This project is read-only.

Hello World

In this exercise, we will build a micro code generator that emits the 'Hello World' canonical sample:

static void Main()
{
    Console.WriteLine("Hello World!");
}

Step 1: Create the expression tree
We start by creating an expression tree that represents the console writeline call, i.e. a method invocation expression involving Console.WriteLine and a string literal "hello world":
MethodInvokeExpression invokeConsoleWriteLine = 
    Expr.InvokeMethod(
        typeof(Console),
        "WriteLine",
        BindingFlags.Public | BindingFlags.Static,
        Expr.Prim("Hello World (Toad short)")
    );

Step 2: Create a dynamic method and compile it
    ToadEngine engine = new ToadEngine();
    MethodFactoryBase method = engine.CodeGenerationManager.Assembly.CreateDynamicMethod(
               "Main", typeof(void) );
    engine.CodeGenerationManager.Compile( method,
                new ExpressionStatement(invokeConsoleWriteLine));

Step 3: Bake a delegate and run the code!
    Func m = (Func)method.CreateDelegate(typeof(Func));
    m();

output:
Hello World (Toad short)

What's happening under the hood?

Under the hood, Toad compiles the expression tree in IL. It also applies successively a bunch of visitor that morph the expression tree before translating it into IL. One can turn on a flag to have Pex dump the tree to the console at each step:

    // show the trees
    engine.Options.DisplayCodeDomTree = true;


===== Initial Tree
ExpressionStatement <System.Console.WriteLine("Hello World (Toad short)")>
    MethodInvokeExpression <System.Console.WriteLine("Hello World (Toad short)")>
        null <>
        PrimitiveExpression <"Hello World (Toad short)">
...
===== ExceptionHandlingVisitor
ExpressionStatement <System.Console.WriteLine("Hello World (Toad short)")>
    MethodInvokeExpression <System.Console.WriteLine("Hello World (Toad short)")>
        null <>
        PrimitiveExpression <"Hello World (Toad short)">
...
===== Final tree
BlockStatement <{...}>
    ExpressionStatement <System.Console.WriteLine("Hello World (Toad short)")>
        MethodInvokeExpression <System.Console.WriteLine("Hello World (Toad short)")>
            null <>
            PrimitiveExpression <"Hello World (Toad short)">
    ReturnStatement <return ;>
        null <>
Emit(ldstr,"Hello World (Toad short)");
Emit(call,Void WriteLine(System.String));
Emit(ret);
Hello World (Toad short)


In this sample, the tree is not changed by the visitor. You can see at the end the 'emit' instruction logged and output.
What about debugging?
IL can get messy and confusing so Toad also provide a built-in IL source debugging feature. Let's turn it out:

            ToadEngineOptions options = new ToadEngineOptions();
            options.Debug = true;
            options.LiveDebugging = LiveDebugType.IL;
            ToadEngine engine = new ToadEngine(options);
            MethodFactoryBase method = engine.CodeGenerationManager.Assembly.CreateMethod(...);


When compiling the method, Toad generates an IL file on the side and symbols to bing each instructions. Nop are inserted in the IL stream to tell the debugger to break on each IL instruction (when allowed):

livedebugging.png
What's next?
Let's do something more complicated, like a simple xml serializer compiler.

Last edited May 20, 2007 at 10:57 AM by pelikhan, version 8

Comments

No comments yet.