5 个版本

使用旧的 Rust 2015

0.5.3 2023年6月22日
0.5.2 2023年6月18日
0.5.1 2020年10月10日
0.5.0 2020年7月28日
0.4.0 2020年7月3日

#58 in 编程语言

50 每月下载量

MIT 许可证

48KB
1K SLoC

BF 即时编译器

这是一个非常过度设计的,用 rust 编写的 BrainFuck 解释器/优化 JIT 编译器。

用法

  fucker [--int] <program>
  fucker (-d | --debug) <program>
  fucker (-h | --help)

Options:
  -h --help     Show this screen.
  -d --debug    Display intermediate language.
  --int         Use an interpreter instead of the JIT compiler.

什么是 BrainFuck?

BrainFuck 是一种旨在既具有图灵完备性又易于编译的谜之编程语言。环境为程序员提供了一个 30,000 个单元的无符号字节数组和一个数据指针。只有 8 个单字符命令

  • + : 将当前内存单元增加 1(带有环绕溢出)
  • - : 将当前内存单元减 1(带有环绕下溢)
  • > : 将数据指针移到下一个内存单元
  • < : 将数据指针移到上一个内存单元
  • . : 以 ASCII 字符输出当前内存单元
  • , : 从 stdin 读取一个 ASCII 字符
  • [ : 如果当前内存单元为 0,则跳转到匹配的 ]
  • ] : 如果当前内存单元不为 0,则跳转到匹配的 [

实现

优化

这里最直接的方法是对指令进行行程编码。在执行之前,可以组合连续的 +->< 命令。内部通过编译到一个中间语言来实现,该语言存储为一个 Instr 向量

pub struct Program {
    pub data: Vec<Instr>,
}

pub enum Instr {
    Incr(u8),
    Decr(u8),
    Next(usize),
    Prev(usize),
    Print,
    Read,
    BeginLoop(usize),
    EndLoop(usize),
}

在不进行其他优化(除非你计算执行前的注释剥离)的情况下,这本身在与 BrainFuck Mandelbrot 集渲染器进行基准测试时实现了 ~3 倍的速度提升。

下一步是什么?更复杂的 BrainFuck 程序是从高级宏语言生成的。从 BrainFuck 反编译回这种语言可能使我能够执行更智能的代码。

JIT 编译

虽然无法直接阅读BrainFuck代码,但BrainFuck可能是最简单的图灵完备语言。这使得它成为探索即时编译的理想候选者。

我们定义在Instr中的前六个指令在x86-64上实现起来相当直接。


+:

add    BYTE PTR [r10],n

其中

  • r10用作数据指针
  • n与在Instr枚举中Incr持有的值相同

-><都同样简单。


PrintRead稍微复杂一些,但不需要我们自己做任何控制流。

基准测试

mandelbrot.bf上运行。

使用Intel Core i5-3230M进行测试。

版本 运行时间
原始解释器 56.824秒
优化解释器 19.055秒
优化即时编译 1.450秒

依赖项

~3.5–5.5MB
~95K SLoC