2014-02-20 37 views
3

当为另一种语言构建解释器时,通常建议创建一个基于堆栈的虚拟机来解释实际解释器生成的字节码。然后解释器将由两部分组成:翻译器,它将虚拟机的高级语言指令转换为字节码,以及虚拟机本身。替代解释器的基于堆栈的虚拟机

我的问题是:解释型语言有什么替代方案?例如,是否可以(并且实际)跳过虚拟机,并使用C中的函数实现所有指令?在某种程度上,在我看来这应该是可能的,但也许你最终会实现一些最简单的虚拟机,以实现更复杂的功能。还有其他选择吗?

+0

您可以直接发出线程代码,跳绳一个“解释者”部分。 –

+0

@ SK-逻辑:这不会消除解释器,它只是使它微不足道。 –

+0

@IraBaxter,带有直接线程代码,没有解释器,它是100%的机器代码。 –

回答

2

建议制作基于堆栈的VM,因为它们制作起来很简单。

VM的另一种常见类型是基于寄存器的,其中值存储在寄存器而不是堆栈中。

解释器和虚拟机还有许多其他变体。你可以有一个生成解析树的编译器和解释这些的解释器(但是如果它是用递归函数实现的,它可能会认为它仍然是一个基于堆栈的虚拟机)。


它也并不少见做出的编译器,而不是产生某种机器代码(虚拟机或真机),以另一种语言生成代码。对于这些类型的编译器来说,C是一种常见的目标语言,因为C语言及其编译器无处不在。但是你没有VM或解释器了,你只需要一个编译器/翻译器。

1

你的建议是有点可能的。 C并没有真正让你操纵堆栈,当你调用一个函数时,它并不知道它周围的局部变量,所以你需要在堆上分配一块内存来保留一些虚假的“堆栈”空间“用于脚本语言的本地变量,并将其传递给每个函数(或将其填充到全局线程中)。你还需要一个用于脚本语言函数调用的栈的基指针。

一旦你这样做了,你已经完成了大部分的工作来获得基于栈的语言。所以你可以做其余的事情。要为此使用实际的堆栈和基址指针,必须将其下拉到机器语言级别。

如果你的语言是基于寄存器的,它仍然需要一个堆栈来访问局部变量(它只是少用一次),但你不要用它作为指令参数。如果我可能犯罪简化,基于3地址注册的虚拟机就是基于堆栈的虚拟机的特例。

字节码解释器的另一种方法是让指令包含指令ID,然后将其用作函数指针数组索引,每个函数指针实现一条指令。

显然这样做会影响性能。如果你的指令足够简单,你可以通过直接在机器代码中实现它们来节省CPU周期,并且可以忽略函数调用的开销(通常可以忽略),甚至可以使用真正的堆栈而不是假的堆栈。

这一切都取决于您的需求。对于大多数情况,特别是如果这是你的第一个解析器/解释器/虚拟机,我建议使用一组函数指针和一个假堆栈。这很简单,不难调试,并且在现代机器上足够快。您随后可以随时进入并编写一个优化版本,以改变事情。

E.g.一种方法是为函数调用生成足够的机器代码,然后在生成的机器代码中插入一个指向这种函数的指针。所以每个脚本都会成为一个编译代码块,但是您不必编写完整的编译器。从那里开始,你可以通过为它们生成汇编程序来改进个别的关键指令,将不常用的东西作为函数。这有点改善了代码的局部性,这是一个微小的优化,可以提供帮助。但只是其中之一。

哦,大约一个月前,我在博客上一个如何使从一个初学者的角度编译器(以及字节码解释器),它可能会有所帮助:http://orangejuiceliberationfront.com/how-to-write-a-compiler/

相关问题