2009-10-24 15 views
5

Estoy tratando de escribir mi propio compilador My Toy Language -> MSIL para comprender mejor cómo funcionan los compiladores. Obtuve el análisis y el léxico trabajando, construí los árboles de expresiones y, utilizando la API del árbol de expresiones System.Linq.Expressions, tengo un intérprete en funcionamiento. Ahora me gustaría emitir algunos ensambles MSIL reales.Vinculación de un árbol de expresiones .NET en un nuevo conjunto

El problema es que no puedo entender cómo construir realmente estos ensamblajes. La clase MethodBuilder solo acepta cuerpos de método MSIL en bruto, así que tengo que obtener el MSIL sin formato de mi árbol de expresiones. Llamar al Expression.Compile() devuelve un delegado que funciona, pero no puedo obtener su MSIL subyacente. Llamar al MethodInfo.GetMethodBody() arroja una InvalidOperationException ya que no está implementada en esa clase secundaria específica.

¿Cómo puedo vincular ese delegado en un nuevo ensamblaje?

Respuesta

3

Acabo de encontrarlo. La versión DLR de LambdaExpression expone un método CompileToMethod que hace exactamente lo que necesito.

lambdaExpression.CompileToMethod(myMethodBuilder); 
+0

Tenga en cuenta que este método tiene algunas limitaciones, como la imposibilidad de compilar métodos no estáticos. –

+0

@ 280Z28: Afortunadamente, My Toy Language no está orientado a objetos, por lo que no será un problema. –

+0

¿Puede explicar cómo obtener el 'MethodBuilder' apropiado? Me doy cuenta de que esto fue hace mucho tiempo :) –

0

Para emitir IL sin procesar, necesita definir su propia AST. Necesita obtener AssemblyBuilder y luego ModuleBuilder y luego puede definir el método de nivel de módulo o obtener un nuevo TypeBuilder y ahora MethodBuilder para definir el método de nivel de clase.

Has dicho que ya tienes lexer y analizador. eso significa que puedes construir AST. Así que simplemente recorra las expresiones analizadas y emita su IL.

Incluso si obtiene código generado (por Compile) no podrá hacer algo útil con él ya que el código generado depende de la infraestructura. Por ejemplo, si necesita compilar cierres, debe crear clases o almacenar otras variables léxicas, etc. (como la transferencia de control no léxico que requiere el uso de Excepciones en .net)

+0

Sí, eso es lo que trato de evitar. El modelo LINQ Expression Tree hace todo eso por mí, así que me gustaría utilizarlo en lugar de escribir mi propio emisor MSIL. –

+0

bien, estás tratando de aprender la teoría del compilador, pero el analizador y el lexer son las partes menos compiladas. Toda la diversión que tenemos dentro de las secciones AST y de optimización y en emisor de couse: solo cosas que intentas evitar –

+0

Hay un libro realmente bueno llamado 'Expert .NET 2.0 IL Assembler' de Serge Lidin, que te dará un entendimiento sobre la estructura de las asambleas en MSIL. Es muy fácil de leer siempre y cuando comprenda los conceptos básicos de ensamblador. También sugeriría usar Mono.Cecil como la biblioteca para Emitir tu IL. Creo que será mucho más fácil trabajar con él que con la biblioteca en el espacio de nombres Emitir. De lo contrario, estoy de acuerdo con el cartel de arriba. Si tiene la AST construida, debe recorrer cada enunciado y emitir su IL. –

Cuestiones relacionadas