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