Befunge 的设计目标之一是难以编译。但是,它很容易解释。可以用传统语言编写解释器,比如 C。要将 Befunge 程序翻译成等效的机器代码,可以将 Befunge 代码硬编码到 C 解释器中,然后将生成的 C 程序编译为机器代码。或者“编译”是否意味着排除这种翻译的更受限制的东西?
3 回答
由于p
. 就 JIT 而言,与现有的所有动态语言相比,这简直是小菜一碟。我致力于一些快速的实现。
marsh
通过成为线程解释器来提高速度。为了加快指令调度,它必须为每个方向创建 4 个解释器副本。我通过将程序存储在 80x32 空间而不是 80x25 空间来优化边界检查和查找
bejit
我观察到大部分程序时间都花在了四处走动上。bejit
在解释时记录跟踪,如果在同一方向上击中相同位置,我们将跳转到跟踪记录的内部字节码格式。当p
对我们跟踪的程序源执行写入时,我们删除所有跟踪并返回到解释器。在实践中,这可以使执行mandel.bf
速度提高 3 倍。它还开辟了窥视孔优化,其中示踪剂可以应用恒定传播。这在 Befunge 中特别有用,因为常量是由多条指令构建的
我的 python 实现在执行之前编译整个程序,因为 Python 函数的字节码是不可变的。这开辟了整个程序分析的可能性
funge.py
将 befunge 指令跟踪到 CPython 字节码中。它必须在堆栈顶部保留一个 int 来跟踪堆栈高度,因为 CPython 不处理堆栈下溢。我最初希望创建一个通用的 python 字节码优化器,但我最终意识到以缺少跳转偏移的中间格式进行优化会更有效。除此之外,数组比链表更快的常见建议在 CPython 中并不适用,因为数组是指针数组,而链表只会将这些指针分散开来。所以我创建了funge2.py
(wfunge.py
是 funge.py 的一个端口,为http://bugs.python.org/issue26647做准备)
funge2.py
将指令跟踪到控制流图中。不幸的是,我们没有 JVM 和 CIL 要求的静态堆栈调整,所以优化有点困难。funge2.py 进行常量折叠、循环展开、一些堆栈深度跟踪以减少堆栈深度检查,并且我正在添加更多(跳转到跳转优化、更智能的堆栈深度杂耍、不跳转或跳转弹出或 dup - 跳跃结合)
当 funge2 开始优化 Befunge 时,它是一个非常简单的 IR
- 加载常量
- 二元运算(+、-、*、/、%、>)
- 不是
- 流行音乐
- 重复
- 交换
- printint/printchar/printstr(最后一个用于当常量折叠使这些确定性时)
- getint/getchar
- 自述文件
- 写内存
- 跳跃
- 跳跃
- 出口
这似乎并不难编译
要将 Befunge 程序翻译成等效的机器代码,可以将 Befunge 代码硬编码到 C 解释器中,并将生成的 C 程序编译为机器代码。
是的,当然。这可以应用于任何解释器,无论是否深奥的语言,在某些定义下,这可以称为编译器。
但这并不是 Befunge 上下文中“编译”的含义——我认为称其为“编译器”在很大程度上忽略了编译的意义,即将某些(高级)语言中的代码转换为语义其他(低级)语言的等效代码。这里没有进行这样的转换。
根据这个定义,Befunge 确实是一种很难以这种方式转换的语言,因为给定一条指令很难知道——在编译时——下一条指令是什么。
p
由于andg
命令,Befunge 很难编译。使用这些,您可以在运行时放置和获取命令,即编写自更改代码。
您无法将其直接转换为汇编,更不用说二进制代码了。
如果您将 Befunge 程序嵌入解释器代码并对其进行编译,那么您仍在编译解释器,而不是 Befunge 程序...