2009-10-24 74 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