如何使用Reflection.Emit为编译器创建REPL?

时间:2016-01-11 21:01:45

标签: .net compiler-construction f# read-eval-print-loop

为口译员进行翻译是微不足道的。但是,我想知道编译器如何做同样的事情。我看到LLVM如何为C语言等编译语言提供双向和存在的REPL,但是没有意识到它是如何实现的。

我正在用F#构建一个玩具语言,所以如果我生成带有反射发射的程序集,那么我们想知道它是如何做的(即:如果编译成.NET字节码)

1 个答案:

答案 0 :(得分:1)

编译语言的REPL工作方式通常是它发出代码并立即运行它。当您使用F#Interactive时,F#代码被解析,类型检查和编译(照常),但不是将其保存到文件中,而是将生成的程序集保留在内存中,并立即运行代码。我认为C#REPL实际上将程序集保存到磁盘上,然后立即从那里加载代码。

  • 最简单的入口点可能是.NET中的DynamicMethod类型(请参阅MSDN documentation with a sample。您可以使用它来发出IL代码,将其包装到委托中并调用它。

  • 如果你需要发出类型(不仅仅是方法体),那么你需要DefineDynamicAssembly方法(参见MSDN documentation),它允许你定义具有类型的程序集。

另一种方法是在Roslyn或F#Quotations之上构建您的语言,但如果您已经编译为.NET字节码,那么上面应该可以解决这个问题。