public void Visit(ASTNode_Application node)
            {
                var delegateType = JITInterpreter_DS.Instance().GetDelegateType(node.actualNodes.Count);

                mTailCallFlags.Push(false);
                node.procedureNode.AcceptVisitor(this);
                mTailCallFlags.Pop();

                mILGenerator.Emit(OpCodes.Castclass, delegateType);
                foreach (var n in node.actualNodes)
                {
                    mTailCallFlags.Push(false);
                    n.AcceptVisitor(this);
                    mTailCallFlags.Pop();
                }

                if (mTailCallFlags.All(b => b))
                {
                    mILGenerator.Emit(OpCodes.Tailcall);
                    mILGenerator.Emit(OpCodes.Callvirt, delegateType.GetMethod("Invoke"));
                    mILGenerator.Emit(OpCodes.Ret);
                }
                else
                {
                    mILGenerator.Emit(OpCodes.Callvirt, delegateType.GetMethod("Invoke"));
                }
            }
            public void Visit(ASTNode_SetVar node)
            {
                if (node.address is GlobalAddress)
                {
                    JITInterpreter_DS.Instance().BeginEmitPopGlobal(mILGenerator, (GlobalAddress)node.address);

                    mTailCallFlags.Push(false);
                    node.rightNode.AcceptVisitor(this);
                    mTailCallFlags.Pop();

                    JITInterpreter_DS.Instance().EndEmitPopGlobal(mILGenerator, (GlobalAddress)node.address);
                }
                else if (node.address is LocalAddress)
                {
                    BeginEmitPopLocal((LocalAddress)node.address);

                    mTailCallFlags.Push(false);
                    node.rightNode.AcceptVisitor(this);
                    mTailCallFlags.Pop();

                    EndEmitPopLocal((LocalAddress)node.address);
                }
                else
                {
                    var context = BeginEmitPopFree((FreeAddress)node.address);

                    mTailCallFlags.Push(false);
                    node.rightNode.AcceptVisitor(this);
                    mTailCallFlags.Pop();

                    EndEmitPopFree((FreeAddress)node.address, context);
                }
                mILGenerator.Emit(OpCodes.Ldnull);
            }
 public static JITInterpreter_DS Instance()
 {
     if (sInstance == null)
     {
         sInstance = new JITInterpreter_DS();
     }
     return(sInstance);
 }
 private void DeclareLocals()
 {
     for (var i = mLambdaNode.formalCount; i < mLambdaNode.locals.Count; ++i)
     {
         var localBuilder = mILGenerator.DeclareLocal(typeof(object));
         if (JITInterpreter_DS.Instance().HasSymbolInfo())
         {
             localBuilder.SetLocalSymInfo(mLambdaNode.locals[i]);
         }
         mLocalBuilders.Add(localBuilder);
     }
 }
            private FieldBuilder EmitLoadFreeEnv(FreeAddress address)
            {
                JITInterpreter_DS.EmitLoadThis(mILGenerator);
                ASTNodeVisitor_JITCompiler visitor = mParent;

                for (int i = 1; i < address.envIndex; ++i)
                {
                    mILGenerator.Emit(OpCodes.Ldfld, visitor.mHeapEnvFieldBuilders[PREV_ENV_FIELD_NAME]);
                    visitor = visitor.mParent;
                }
                return(visitor.mHeapEnvFieldBuilders[visitor.mLambdaNode.locals[address.index]]);
            }
 public void Visit(ASTNode_GetVar node)
 {
     if (node.address is GlobalAddress)
     {
         JITInterpreter_DS.Instance().EmitLoadGlobal(mILGenerator, (GlobalAddress)node.address);
     }
     else if (node.address is LocalAddress)
     {
         EmitLoadLocal((LocalAddress)node.address);
     }
     else
     {
         EmitLoadFree((FreeAddress)node.address);
     }
 }
            private void EndEmitPopLocal(LocalAddress address)
            {
                string localName = mLambdaNode.locals[address.index];

                if (mHeapEnvFieldBuilders.ContainsKey(localName))
                {
                    mILGenerator.Emit(OpCodes.Stfld, mHeapEnvFieldBuilders[localName]);
                }
                else if (address.index < mLambdaNode.formalCount)
                {
                    JITInterpreter_DS.EmitStoreArg(mILGenerator, HasThisArgument(), mArgBuilders[address.index]);
                }
                else
                {
                    JITInterpreter_DS.EmitStoreLocal(mILGenerator, mLocalBuilders[address.index - mLambdaNode.formalCount]);
                }
            }
            private void BeginEmitPopLocal(LocalAddress address)
            {
                string localName = mLambdaNode.locals[address.index];

                if (mHeapEnvFieldBuilders.ContainsKey(localName))
                {
                    JITInterpreter_DS.EmitLoadLocal(mILGenerator, mHeapEnvBuilder);
                }
                else if (address.index < mLambdaNode.formalCount)
                {
                    //
                }
                else
                {
                    //
                }
            }
            private void EmitInitHeapEnv()
            {
                if (!HasHeapEnv())
                {
                    return;
                }

                mHeapEnvBuilder = mILGenerator.DeclareLocal(mHeapEnvTypeBuilder);
                if (JITInterpreter_DS.Instance().HasSymbolInfo())
                {
                    mHeapEnvBuilder.SetLocalSymInfo(HEAP_ENV_LOCAL_NAME);
                }

                var constructor = mHeapEnvTypeBuilder.DefineDefaultConstructor(MethodAttributes.Public);

                mILGenerator.Emit(OpCodes.Newobj, constructor);
                EmitStoreLocal(mILGenerator, mHeapEnvBuilder);

                if (mLambdaNode.childrenFreeAddresses.Where(v => v.envIndex > 0).GetEnumerator().MoveNext())
                {
                    var fieldBuilder = mHeapEnvTypeBuilder.DefineField(PREV_ENV_FIELD_NAME, mEnvTypeBuilder, FieldAttributes.Public);
                    mHeapEnvFieldBuilders[PREV_ENV_FIELD_NAME] = fieldBuilder;
                    JITInterpreter_DS.EmitLoadLocal(mILGenerator, mHeapEnvBuilder);
                    JITInterpreter_DS.EmitLoadThis(mILGenerator);
                    mILGenerator.Emit(OpCodes.Stfld, fieldBuilder);
                }

                var heapLocals = mLambdaNode.childrenFreeAddresses.Where(a => a.envIndex == 0).Select(a => a.index).OrderBy(a => a).ToList();

                foreach (var index in heapLocals)
                {
                    var fieldBuilder = mHeapEnvTypeBuilder.DefineField(mLambdaNode.locals[index], typeof(object), FieldAttributes.Public);
                    mHeapEnvFieldBuilders[mLambdaNode.locals[index]] = fieldBuilder;

                    if (index < mLambdaNode.formalCount)
                    {
                        JITInterpreter_DS.EmitLoadLocal(mILGenerator, mHeapEnvBuilder);
                        JITInterpreter_DS.EmitLoadArg(mILGenerator, HasThisArgument(), mArgBuilders[index]);
                        mILGenerator.Emit(OpCodes.Stfld, fieldBuilder);
                    }
                }
            }
            public ASTNodeVisitor_JITCompiler(ASTNodeVisitor_JITCompiler parent, TypeBuilder envTypeBuilder, ASTNode_Lambda node)
            {
                mParent         = parent;
                mEnvTypeBuilder = envTypeBuilder;
                mLambdaNode     = node;

                mHeapEnvTypeBuilder = envTypeBuilder.DefineNestedType(JITInterpreter_DS.Instance().GenernateUniqueString("nested_class"));

                if (HasThisArgument())
                {
                    MethodBuilder = envTypeBuilder.DefineMethod(
                        JITInterpreter_DS.Instance().GenernateUniqueString("method"),
                        MethodAttributes.Public,
                        CallingConventions.HasThis,
                        typeof(object),
                        Enumerable.Repeat(typeof(object), mLambdaNode.formalCount).ToArray());
                }
                else
                {
                    MethodBuilder = envTypeBuilder.DefineMethod(
                        JITInterpreter_DS.Instance().GenernateUniqueString("static_method"),
                        MethodAttributes.Static | MethodAttributes.Public,
                        CallingConventions.Standard,
                        typeof(object),
                        Enumerable.Repeat(typeof(object), mLambdaNode.formalCount).ToArray());
                }


                mILGenerator = MethodBuilder.GetILGenerator();

                DeclareArguments();
                DeclareLocals();
                EmitInitHeapEnv();

                mTailCallFlags.Push(true);
                mLambdaNode.bodyNode.AcceptVisitor(this);
                mTailCallFlags.Pop();

                mILGenerator.Emit(OpCodes.Ret);
                mHeapEnvTypeBuilder.CreateType();
            }
            public void Visit(ASTNode_Lambda node)
            {
                var methodBuilder = new ASTNodeVisitor_JITCompiler(this, mHeapEnvTypeBuilder, node).MethodBuilder;

                if (methodBuilder.IsStatic)
                {
                    mILGenerator.Emit(OpCodes.Ldnull);
                    mILGenerator.Emit(OpCodes.Ldftn, methodBuilder);
                    mILGenerator.Emit(OpCodes.Newobj,
                                      JITInterpreter_DS.Instance().GetDelegateType(node.formalCount).
                                      GetConstructor(new Type[] { typeof(object), typeof(IntPtr) }));
                }
                else
                {
                    JITInterpreter_DS.EmitLoadLocal(mILGenerator, mHeapEnvBuilder);
                    mILGenerator.Emit(OpCodes.Ldftn, methodBuilder);
                    mILGenerator.Emit(OpCodes.Newobj,
                                      JITInterpreter_DS.Instance().GetDelegateType(node.formalCount)
                                      .GetConstructor(new Type[] { typeof(object), typeof(IntPtr) }));
                }
            }
 public void Visit(ASTNode_Literal node)
 {
     JITInterpreter_DS.Instance().EmitLoadLiteral(mILGenerator, node.value);
 }
 public static JITInterpreter_DS Instance()
 {
     if (sInstance == null) sInstance = new JITInterpreter_DS();
     return sInstance;
 }