2009-10-24 5 views
5

Я пытаюсь написать свою игрушку My Toy Language -> MSIL-компилятор, чтобы лучше понять, как работают компиляторы. Я получил парсинг и лексирование, я построил деревья выражений и использовал API дерева выражений System.Linq.Expressionions, у меня есть рабочий интерпретатор. Теперь я хотел бы испустить некоторые реальные сборки MSIL.Связывание дерева выражений .NET с новой сборкой

Проблема в том, что я не могу понять, как на самом деле построить эти сборки. Класс MethodBuilder принимает только примитивные тела метода MSIL, поэтому мне нужно получить сырую MSIL моего дерева выражений. Вызов Expression.Compile() возвращает рабочего делегата, но я не могу получить его базовый MSIL. Вызов MethodInfo.GetMethodBody() вызывает исключение InvalidOperationException, поскольку он не реализован в этом конкретном дочернем классе.

Как связать делегата с новой сборкой?

ответ

3

Просто нашел. DLR-версия LambdaExpression предоставляет метод CompileToMethod, который делает именно то, что мне нужно.

lambdaExpression.CompileToMethod(myMethodBuilder); 
+0

Имейте в виду, что этот метод имеет некоторые ограничения, такие как невозможность скомпилировать нестатические методы. –

+0

@ 280Z28: К счастью, My Toy Language не является объектно-ориентированным, так что это не проблема. –

+0

Можете ли вы объяснить, как получить соответствующий 'MethodBuilder' - я понимаю, что это было давно :) –

0

Для того, чтобы испускать необработанный ИЛ, вам необходимо определить свой собственный АСТ. Вам нужно получить AssemblyBuilder, а затем ModuleBuilder, а затем вы можете определить метод уровня модуля или получить новый TypeBuilder и теперь MethodBuilder для определения метода уровня класса.

Вы сказали, что у вас уже есть lexer и parser. это означает, что вы можете построить АСТ. Поэтому просто пройдите через разобранные выражения и испустите свой ИЛ.

Даже если вы сгенерировали (по компиляции) код, вы не сможете сделать с ним что-то полезное, поскольку сгенерированный код зависит от инфраструктуры. Например, если вам нужно скомпилировать закрытие, тогда вы должны создать класс или другие файлы для лексических переменных и т. Д. (Например, перенос не лексического управления, который требует использования исключений в .net)

+0

Да, этого я и стараюсь избежать. Модель дерева выражений LINQ делает все это для меня, поэтому я хотел бы использовать это вместо написания своего собственного MSIL-эмиттера. –

+0

ОК, вы пытаетесь изучить теорию компилятора, но парсер и лексер - это наименьшая часть компилятора. Все, что у нас есть в разделах AST и оптимизации, а также в emitter of couse - просто то, что вы пытаетесь избежать. –

+0

Существует действительно хорошая книга, которая называется «Expert .NET 2.0 IL Assembler» Сержа Лидина, что даст вам представление о структура сборок в MSIL. Это очень легко прочитать, если вы понимаете основные концепции ассемблера. Я также предлагаю использовать Mono.Cecil в качестве библиотеки для Emit your IL. Я думаю, вам будет намного легче работать с библиотекой в ​​пространстве имен Emit. В противном случае я согласен с вышеуказанным плакатом. Если у вас есть AST, вы должны проходить через каждое утверждение и испускать свой IL. – 2009-10-24 19:00:39