Связывание дерева выражений .NET с новой сборкой

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

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

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


person Tamas Czinege    schedule 24.10.2009    source источник


Ответы (2)


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

lambdaExpression.CompileToMethod(myMethodBuilder);
person Tamas Czinege    schedule 24.10.2009
comment
Имейте в виду, что этот метод имеет некоторые ограничения, такие как невозможность компилировать нестатические методы. - person Sam Harwell; 25.10.2009
comment
@ 280Z28: К счастью, My Toy Language не является объектно-ориентированным, так что это не будет проблемой. - person Tamas Czinege; 25.10.2009
comment
Можете ли вы объяснить, как получить соответствующий MethodBuilder - я понимаю, что это было давно :) - person Callum Rogers; 09.06.2010
comment
объектную ориентацию можно стереть, передав экземпляр в качестве первого параметра именованному методу. - person Luiz Felipe; 31.12.2020

Чтобы выдать необработанный IL, вам нужно определить свой собственный AST. Вам нужно получить AssemblyBuilder, затем ModuleBuilder, а затем вы можете определить метод уровня модуля или получить новый TypeBuilder, а теперь и MethodBuilder, чтобы определить метод уровня класса.

Вы сказали, что у вас уже есть лексер и парсер. это означает, что вы можете построить AST. Так что просто пройдитесь по проанализированным выражениям и выдайте свой IL.

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

person Ilya Khaprov    schedule 24.10.2009
comment
Да, это то, чего я пытаюсь избежать. Модель дерева выражений LINQ делает все это за меня, поэтому я хотел бы использовать ее вместо того, чтобы писать свой собственный эмиттер MSIL. - person Tamas Czinege; 24.10.2009
comment
хорошо, вы пытаетесь изучить теорию компилятора, но синтаксический анализатор и лексер - это наименьшие части компилятора. Все самое интересное, что есть в разделах AST и оптимизации, а также в эмиттере кода — всего лишь то, чего вы пытаетесь избежать. - person Ilya Khaprov; 24.10.2009
comment
Существует очень хорошая книга под названием "Expert .NET 2.0 IL Assembler" Сержа Лидина, которая даст вам представление о структуре сборок в MSIL. Его очень легко читать, если вы понимаете основные концепции ассемблера. Я бы также предложил использовать Mono.Cecil в качестве библиотеки для создания вашего IL. Я думаю, вам будет намного проще работать с ней, чем с библиотекой в ​​пространстве имен Emit. В остальном я согласен с вышеприведенным плакатом. Если у вас есть построенный AST, вы должны пройтись по каждому оператору и выдать свой IL. - person ; 24.10.2009
comment
Спасибо, ребята, но я не уверен, что вы понимаете мой вопрос. У меня уже есть абстрактное синтаксическое дерево. Я знаю, как написать эмиттер IL, знаю MSIL, но не хочу, учитывая, что для этого уже есть API. - person Tamas Czinege; 24.10.2009
comment
Вы ... для того, чтобы лучше понять, как работают компиляторы. Что ж, эти выражения (они взяты из Linq и DLR) не предназначены для авторов компиляторов. И вы должны написать компилятор самостоятельно. Они предназначены для динамической генерации кода, поэтому на самом деле у вас есть динамический компилятор, а не только интерпретатор. - person Ilya Khaprov; 24.10.2009