2009-10-24 25 views
5

为了更好地理解编译器的工作方式,我正在尝试编写我自己的玩具我的玩具语言 - > MSIL编译器。我得到了解析和lexing工作,我已经构建了表达式树并使用System.Linq.Expressions表达式树API,我有一个工作的解释器。现在我想发出一些真正的MSIL程序集。将.NET表达式树链接到一个新程序集

问题是,我无法弄清楚如何实际构建这些程序集。 MethodBuilder类只接受原始MSIL方法体,所以我必须得到我的表达式树的原始MSIL。调用Expression.Compile()会返回一个工作委托,但我无法获取其基础MSIL。调用MethodInfo.GetMethodBody()会引发InvalidOperationException,因为它没有在该特定的子类中实现。

如何将该代表链接到新程序集?

回答

3

刚刚找到它。 LambdaExpression的DLR版本公开了一个CompileToMethod方法,它正是我所需要的。

lambdaExpression.CompileToMethod(myMethodBuilder); 
+0

请注意,此方法有一些限制,例如无法编译非静态方法。 – 2009-10-24 22:50:50

+0

@ 280Z28:幸运的是,我的玩具语言不是面向对象的,所以不会成为问题。 – 2009-10-24 23:01:18

+0

你能解释一下如何得到相应的'MethodBuilder' - 我意识到这是很久以前的:) – 2010-06-08 23:39:33

0

为了发出原始的IL你需要定义你自己的AST。您需要先获取AssemblyBuilder,然后才能获得ModuleBuilder,然后您可以定义模块级别的方法或获取新的TypeBuilder,然后使用MethodBuilder来定义类级别的方法。

你说你已经有了词法分析器和解析器。这意味着你可以建立AST。因此,只需遍历解析的表达式并发出你的IL。

即使您生成(通过编译)代码,您也无法对其执行一些有用的操作,因为生成的代码依赖于基础结构。例如,如果你需要编译闭包,那么你应该创建类或其他商店的词法变量等(如非词汇控制转移,需要在.net中使用例外)

+0

是啊,这就是我试图避免。 LINQ表达式树模型为我做了所有这些,所以我想用它来代替编写我自己的MSIL发射器。 – 2009-10-24 18:39:55

+0

好的,你试图学习编译器理论,但解析器和词法分析器是编译器的最少部分。我们在AST和优化部分以及couse的发射器中获得的所有乐趣 - 只是您尝试避免的事情 – 2009-10-24 18:44:03

+0

Serge Lidin有一本名为'Expert .NET 2.0 IL Assembler'的非常好的书,它可以让您了解MSIL中的组件结构。只要您了解基本的汇编程序概念,阅读起来非常简单。我还建议使用Mono.Cecil作为发布您的IL的库。我想你会发现,比Emit命名空间下的库更容易处理。否则,我同意上面的海报。如果你建立了AST,你应该通过每一个陈述并发出你的IL。 – 2009-10-24 19:00:39

相关问题