internal DynamicMethod Compile(Block root)
        {
            DynamicMethod dm = new DynamicMethod("affeMethod", typeof(void),
                                                 new Type[] { this.mHostType },
                                                 this.mHostType);

            this.il = dm.GetILGenerator();

            root = (Block) root.Analyze(this);

            this.mReturnLabel = this.il.DefineLabel();

            if (this.mState != null) {
                this.mStateLocal = this.il.DeclareLocal(typeof(ScriptState));
                this.il.Emit(OpCodes.Ldarg_0);
                this.il.Emit(OpCodes.Ldfld, this.mState);
                this.il.Emit(OpCodes.Stloc, this.mStateLocal);
            }

            foreach (VariableSymbol vs in this.mAutoVars) {
                if (this.mStateLocal != null) {
                    this.il.Emit(OpCodes.Ldloc, this.mStateLocal);
                    this.il.Emit(OpCodes.Ldstr, vs.Name);
                    this.il.Emit(OpCodes.Call,
                                 mStateGet.MakeGenericMethod(new Type[] { vs.Type }));
                } else {
                    this.il.Emit(OpCodes.Call, mGetDefault.MakeGenericMethod(new Type[] { vs.Type }));
                }

                this.il.Emit(OpCodes.Stloc, vs.Local);
            }

            if (this.mState != null)
                this.il.BeginExceptionBlock();

            root.Emit(this);

            if (this.mState != null) {
                this.il.BeginFinallyBlock();

                foreach (VariableSymbol vs in this.mAutoVars) {
                    this.il.Emit(OpCodes.Ldloc, this.mStateLocal);
                    this.il.Emit(OpCodes.Ldstr, vs.Name);
                    this.il.Emit(OpCodes.Ldloc, vs.Local);

                    if (vs.Local.LocalType.IsValueType)
                        this.il.Emit(OpCodes.Box, vs.Local.LocalType);

                    this.il.Emit(OpCodes.Call, mStateSet);
                }

                this.il.EndExceptionBlock();
            }

            this.il.MarkLabel(this.mReturnLabel);

            this.il.Emit(OpCodes.Ret);

            return dm;
        }