问题 编译为字节码的动机是什么?


我正在使用自己的玩具编程语言。现在我正在解释AST的源语言,我想知道编译一个字节码然后解释它有什么好处可以提供给我。

现在我有三件事:

  • 遍历语法树数百次可能比运行阵列中的指令慢,特别是如果阵列支持O(1)随机访问(即上下跳过10条指令)。
  • 在类型化的执行环境中,我有一些运行时成本,因为我的AST是打字的,而且我经常遍历它(即我有10种类型的节点,我需要检查我现在要执行的类型)。也许编译成无类型的字节码可能有助于改善这一点,因为在类型检查和编译之后,我会有一个无类型的值和代码。
  • 编译为字节代码可以提供更好的可移植性。

我的观点是否正确?编译到字节码背后有什么其他动机?


11227
2017-07-11 13:19


起源

通过运行解释器,它可以提高代码的可移植性 - Luis
@Luis,是的,这已经在我的脑海里,我忘了补充.. - sinan
@Luis:那是假的。序列化的AST可以同样便携。字节码实际上可能不是便携式的; Python字节码特定于每个版本的解释器。 - Fred Foo
它比解释AST更容易 - 字节码应该足够低。将高级语言编译为字节码比直接解释高级语言更简单。例如,不是维护具有复杂语义的环境,而是通过名称等查找变量,而只需通过简单的加载和存储指令访问简单的堆栈帧。 - SK-logic


答案:


速度是主要原因;解释AST在实践中太慢了。

使用字节码的另一个原因是它可以简单地序列化(存储在磁盘上),以便您可以分发它。这就是Java所做的。


5
2017-07-11 13:22



嗯,基本上就是这样。我希望能找到一些其他有趣的动机。 - sinan
“这就是Java所做的”。 python不? - Dani Springer
@DaniSpringer Python模块以源代码形式分发并在本地编译。 - Aaron Brick
什么时候Java编译成字节码,如果不是本地的? - Dani Springer


生成字节代码(或任何其他“易于解释”的形式,如线程代码)的要点基本上是性能。

对于AST解释器来决定接下来要做什么,它需要遍历树,检查节点,确定节点类型,检查任何操作数的类型,验证合法性,并确定AST指定运算符的哪种特殊情况适用(它说“+”,但它意味着16位添加或字符串连接?),在它最终执行某些操作之前。

如果采取最终操作并生成某种易于解释的结构,则在“执行”时,解释器可以仅关注执行操作而无需进行所有检查/特殊情况确定。

最近的另一个借口是,如果为许多众所周知的虚拟机(JVM,MSIL,Parrot等)中的任何一个生成字节代码,您甚至不必编写解释器代码。对于JVM和MSIL,您还可以获得与它们相关的JIT编译器的好处,并仔细设计您的语言,兼容大型库,这是Java和C#的真正吸引力。


6
2017-07-15 22:40