我正在研究JVM上的自定义编程语言的REPL。 REPL目前能够使用与编译器完全相同的解析器和AST结构读取一行并将其转换为AST。这意味着我可以将REPL中的一行代码转换为AST表示,就好像它是main
方法中的一行代码一样。这个问题是我得到了计算的AST,但没有结果(显然),因为这需要对AST进行实际评估。为此,我想到了两种方法:
AST内部的计算。非常坦率的。每个AST节点都必须有某种eval
方法折叠AST,直到只剩下一个值。运算符可以由编译器完成,方法将被内联。问题:开销和大量eval
实施。
使用字节码进行计算。将AST转换为临时类中的字节码,如下所示:
class REPL$1
{
public static [insert type] res1;
static
{
res1 = [insert REPL input]
}
}
这个问题是,对于每个输入行(或结果),我需要一个单独的类。由于结果在REPL的整个运行时期间可用,因此类需要保持加载状态,并且不能使用Unsafe.defineAnonymousClass
。过了一会儿,这些类会堆积起来并导致OutOfMemory: Permgen
错误。
这两种方法中哪一种更适合REPL,JVM上的其他REPL(主要是scala
)如何解决这个问题呢?