Exemplo n.º 1
0
        private void GenerateDeclaration(IlProcessor il, ref Instruction start, ref Instruction current, ParseTreeNode node)
        {
            string name;

            switch (node.Term.Name)
            {
            case "VarStmt":
                var declarators = node.ChildNodes[1].ChildNodes;
                foreach (var dec in declarators)
                {
                    GenerateDeclaration(il, ref start, ref current, dec);
                }
                break;

            case "VarExpr":
                name = node.ChildNodes[0].Token.ValueString;
                il.Add(ref current, Instruction.Create(OpCodes.Ldarg_0));
                il.Add(ref current, Instruction.Create(OpCodes.Ldstr, name));
                if (node.ChildNodes.Count > 1)
                {
                    GenerateExpression(il, ref start, ref current, node.ChildNodes[1].ChildNodes[1]);
                }
                else
                {
                    il.Add(ref current, Instruction.Create(OpCodes.Call, undefined));
                }
                il.Add(ref current, Instruction.Create(OpCodes.Callvirt, function_local_dec));
                break;

            default:
                throw new InvalidOperationException("Term " + node.Term.Name + " is not a declaration statement");
            }
        }
Exemplo n.º 2
0
        private void GenerateConst(IlProcessor il, Instruction start, ref Instruction current, ParseTreeNode node)
        {
            var obj = node.Token.Value;

            if (node.Token.Terminal is KeyTerm)
            {
                switch ((string)obj)
                {
                case "true":
                    il.Add(ref current, Instruction.Create(OpCodes.Ldc_I4_1));
                    il.Add(ref current, Instruction.Create(OpCodes.Newobj, bool_ctor));
                    break;

                case "false":
                    il.Add(ref current, Instruction.Create(OpCodes.Ldc_I4_0));
                    il.Add(ref current, Instruction.Create(OpCodes.Newobj, bool_ctor));
                    break;

                case "null":
                    il.Add(ref current, Instruction.Create(OpCodes.Call, @null));
                    break;

                case "undefined":
                    il.Add(ref current, Instruction.Create(OpCodes.Call, undefined));
                    break;

                default:
                    throw new InvalidOperationException("Unknown keyword " + obj);
                }
            }
            else if (obj is string)
            {
                il.Add(ref current, Instruction.Create(OpCodes.Ldstr, (string)obj));
                il.Add(ref current, Instruction.Create(OpCodes.Newobj, string_ctor));
            }
            else if (obj is int || obj is long)
            {
                il.Add(ref current, Instruction.Create(OpCodes.Ldc_I8, Convert.ToInt64(obj)));
                il.Add(ref current, Instruction.Create(OpCodes.Newobj, number_ctor_long));
            }
            else
            {
                throw new InvalidOperationException("Unknown constant type " + obj.GetType());
            }
        }
Exemplo n.º 3
0
        private void GenerateExpression(IlProcessor il, ref Instruction start, ref Instruction current, ParseTreeNode node)
        {
            string       name;
            LocalBuilder pn;
            var          prev = start;

            switch (node.Term.Name)
            {
            case "ConstExpr":
                GenerateConst(il, start, ref current, node.ChildNodes[0]);
                break;

            case "BinExpr":
                GenerateExpression(il, ref start, ref current, node.ChildNodes[0]);     // left
                GenerateExpression(il, ref start, ref current, node.ChildNodes[2]);     // right
                var keySymbol = node.ChildNodes[1].Token.ValueString;
                switch (keySymbol)
                {
                case "+":
                    il.Add(ref current, Instruction.Create(OpCodes.Call, value_add));
                    break;

                case "-":
                    il.Add(ref current, Instruction.Create(OpCodes.Call, value_sub));
                    break;

                case "<":
                    il.Add(ref current, Instruction.Create(OpCodes.Call, value_lt));
                    break;

                case ">":
                    il.Add(ref current, Instruction.Create(OpCodes.Call, value_gt));
                    break;

                case "==":
                    il.Add(ref current, Instruction.Create(OpCodes.Call, value_eq));
                    break;

                case "!=":
                    il.Add(ref current, Instruction.Create(OpCodes.Call, value_neq));
                    break;

                case "*":
                    il.Add(ref current, Instruction.Create(OpCodes.Call, value_mul));
                    break;

                case "/":
                    il.Add(ref current, Instruction.Create(OpCodes.Call, value_div));
                    break;

                case "<=":
                    il.Add(ref current, Instruction.Create(OpCodes.Call, value_lte));
                    break;

                case ">=":
                    il.Add(ref current, Instruction.Create(OpCodes.Call, value_gte));
                    break;

                default:
                    throw new InvalidOperationException("Unknown bin expression key symbol " + keySymbol);
                }
                break;

            case "TerExpr":     // a < b ? c : d
                Label trueLabel = il.DefineLabel(),
                      endLabel  = il.DefineLabel();
                GenerateExpression(il, ref start, ref current, node.ChildNodes[0]);     // a < b
                il.Add(ref current, Instruction.Create(OpCodes.Call, value_istrue));
                il.Add(ref current, Instruction.Create(OpCodes.Brtrue, trueLabel));

                GenerateExpression(il, ref start, ref current, node.ChildNodes[3]);     // d
                il.Add(ref current, Instruction.Create(OpCodes.Br, endLabel));

                il.Add(ref current, Instruction.Create(Specials.Label, trueLabel));
                GenerateExpression(il, ref start, ref current, node.ChildNodes[2]);     // c
                il.Add(ref current, Instruction.Create(Specials.Label, endLabel));
                break;

            case "FunctionCallExpr":
                pn = GetSVar(arguments);
                il.Add(ref prev, Instruction.Create(OpCodes.Newobj, arguments_ctor));
                il.Add(ref prev, Instruction.Create(OpCodes.Stloc, pn));
                foreach (var arg in node.ChildNodes[1].ChildNodes)
                {
                    il.Add(ref prev, Instruction.Create(OpCodes.Ldloc, pn));
                    if (arg.ChildNodes.Count == 1)
                    {
                        il.Add(ref prev, Instruction.Create(OpCodes.Ldnull));
                    }
                    else
                    {
                        il.Add(ref prev, Instruction.Create(OpCodes.Ldstr, arg.ChildNodes[0].Token.ValueString));
                    }
                    GenerateExpression(il, ref start, ref prev, arg.ChildNodes[arg.ChildNodes.Count - 1]);
                    il.Add(ref prev, Instruction.Create(OpCodes.Callvirt, arguments_add));
                }
                start = prev;
                GenerateExpression(il, ref start, ref current, node.ChildNodes[0]);
                il.Add(ref current, Instruction.Create(OpCodes.Ldloc, pn));
                il.Add(ref current, Instruction.Create(OpCodes.Callvirt, execute));
                break;

            case "AssignExpr":
                switch (node.ChildNodes[0].Term.Name)
                {
                case "identifier":
                    pn = GetSVar(value);
                    if (node.ChildNodes.Count == 3)         // a = b / a += b etc.
                    {
                        GenerateExpression(il, ref start, ref start, node.ChildNodes[2]);
                        il.Add(ref start, Instruction.Create(OpCodes.Stloc, pn));
                        il.Add(ref current, Instruction.Create(OpCodes.Ldarg_0));
                        il.Add(ref current, Instruction.Create(OpCodes.Ldstr, node.ChildNodes[0].Token.ValueString));
                        il.Add(ref current, Instruction.Create(OpCodes.Ldloc, pn));
                        il.Add(ref current, Instruction.Create(OpCodes.Callvirt, function_local_set));
                        il.Add(ref current, Instruction.Create(OpCodes.Ldloc, pn));
                    }
                    else
                    {
                        var pn2 = GetSVar(value);
                        il.Add(ref current, Instruction.Create(OpCodes.Ldarg_0));
                        il.Add(ref current, Instruction.Create(OpCodes.Ldstr, node.ChildNodes[0].Token.ValueString));
                        il.Add(ref current, Instruction.Create(OpCodes.Callvirt, function_local_get));
                        il.Add(ref current, Instruction.Create(OpCodes.Dup));
                        il.Add(ref current, Instruction.Create(OpCodes.Stloc, pn));
                        // Increment/decrement and restore
                        if (node.ChildNodes[1].Token.ValueString == "++")
                        {
                            il.Add(ref current, Instruction.Create(OpCodes.Call, value_incr));
                        }
                        else if (node.ChildNodes[1].Token.ValueString == "--")
                        {
                            il.Add(ref current, Instruction.Create(OpCodes.Call, value_decr));
                        }
                        else
                        {
                            throw new InvalidOperationException("??");
                        }
                        il.Add(ref current, Instruction.Create(OpCodes.Stloc, pn2));
                        il.Add(ref current, Instruction.Create(OpCodes.Ldarg_0));
                        il.Add(ref current, Instruction.Create(OpCodes.Ldstr, node.ChildNodes[0].Token.ValueString));
                        il.Add(ref current, Instruction.Create(OpCodes.Ldloc, pn2));
                        il.Add(ref current, Instruction.Create(OpCodes.Callvirt, function_local_set));
                        il.Add(ref current, Instruction.Create(OpCodes.Ldloc, pn));
                    }
                    break;

                case "MemberExpr":
                    pn = GetSVar(value);
                    if (node.ChildNodes.Count == 3)         // a = b / a += b etc.
                    {
                        GenerateExpression(il, ref start, ref start, node.ChildNodes[2]);
                        il.Add(ref start, Instruction.Create(OpCodes.Stloc, pn));
                        GenerateExpression(il, ref start, ref current, node.ChildNodes[0].ChildNodes[0]);
                        il.Add(ref current, Instruction.Create(OpCodes.Ldstr, node.ChildNodes[0].ChildNodes[2].Token.ValueString));
                        il.Add(ref current, Instruction.Create(OpCodes.Ldloc, pn));
                        il.Add(ref current, Instruction.Create(OpCodes.Callvirt, set_prop));
                        il.Add(ref current, Instruction.Create(OpCodes.Ldloc, pn));
                    }
                    else
                    {
                        var pn2 = GetSVar(value);
                        GenerateExpression(il, ref start, ref start, node.ChildNodes[2]);
                    }
                    break;

                case "ArrOpExpr":
                    pn = GetSVar(value);
                    if (node.ChildNodes.Count == 3)         // a = b / a += b etc.
                    {
                        GenerateExpression(il, ref start, ref start, node.ChildNodes[2]);
                        il.Add(ref start, Instruction.Create(OpCodes.Stloc, pn));
                        GenerateExpression(il, ref start, ref current, node.ChildNodes[0].ChildNodes[0]);
                        GenerateExpression(il, ref start, ref current, node.ChildNodes[0].ChildNodes[1]);
                        il.Add(ref current, Instruction.Create(OpCodes.Ldloc, pn));
                        il.Add(ref current, Instruction.Create(OpCodes.Callvirt, value_lookup_set));
                        il.Add(ref current, Instruction.Create(OpCodes.Ldloc, pn));
                    }
                    else
                    {
                        var pn2 = GetSVar(value);
                        GenerateExpression(il, ref start, ref start, node.ChildNodes[2]);
                    }
                    break;

                default:
                    throw new InvalidOperationException("Invalid QualifiedName term " + node.ChildNodes[0].Term.Name);
                }
                break;

            case "identifier":
                name = node.Token.ValueString;
                il.Add(ref current, Instruction.Create(OpCodes.Ldarg_0));
                il.Add(ref current, Instruction.Create(OpCodes.Ldstr, name));
                il.Add(ref current, Instruction.Create(OpCodes.Callvirt, function_local_get));
                break;

            case "FuncDefExpr":
                if (node.ChildNodes[1] != null && node.ChildNodes[1].Token != null && node.ChildNodes[1].Token.Text == "=>")
                {
                    name = "anonymous";
                    var mName = MakeFunctionName(name);
                    IEnumerable <ParseTreeNode> bodyNodes;
                    ParseTreeNodeList           parameters;
                    if (node.ChildNodes[2].Term.Name == "Block")
                    {
                        bodyNodes = node.ChildNodes[2].ChildNodes[0].ChildNodes;
                    }
                    else if (node.ChildNodes[2].Term.Name.Contains("Stmt"))
                    {
                        bodyNodes = new ParseTreeNode[] { node.ChildNodes[2] };
                    }
                    else
                    {
                        var flowCtrlStmtNode = new ParseTreeNode(grammar.FlowControlStmt, new SourceSpan());
                        flowCtrlStmtNode.ChildNodes.Add(new ParseTreeNode(new Token(grammar.@return, new SourceLocation(), "return", "return")));
                        flowCtrlStmtNode.ChildNodes.Add(node.ChildNodes[2]);
                        bodyNodes = new ParseTreeNode[] { flowCtrlStmtNode };
                    }
                    if (node.ChildNodes[0].Term.Name == "identifier")
                    {
                        parameters = new ParseTreeNodeList();
                        var param = new ParseTreeNode(grammar.Parameter, node.ChildNodes[0].Span);
                        param.ChildNodes.Add(node.ChildNodes[0]);
                        parameters.Add(param);
                    }
                    else
                    {
                        parameters = node.ChildNodes[0].ChildNodes;
                    }
                    GenerateFunction(il, ref start, ref current, name, mName, parameters, bodyNodes);
                }
                else
                {
                    if (node.ChildNodes[1].ChildNodes.Count == 1)
                    {
                        name = node.ChildNodes[1].ChildNodes[0].Token.ValueString;
                    }
                    else
                    {
                        name = "anonymous";
                    }
                    var mName = MakeFunctionName(name);
                    GenerateFunction(il, ref start, ref current, name, mName, node.ChildNodes[2].ChildNodes, node.ChildNodes[3].ChildNodes[0].ChildNodes);
                }
                break;

            case "MemberExpr":
                GenerateExpression(il, ref start, ref current, node.ChildNodes[0]);
                il.Add(ref current, Instruction.Create(OpCodes.Ldstr, node.ChildNodes[2].Token.ValueString));
                il.Add(ref current, Instruction.Create(OpCodes.Callvirt, get_prop));
                break;

            case "ObjLitExpr":
                pn = GetSVar(map);
                il.Add(ref prev, Instruction.Create(OpCodes.Newobj, map_ctor));
                il.Add(ref prev, Instruction.Create(OpCodes.Stloc, pn));
                if (node.ChildNodes.Count > 0)
                {
                    foreach (var prop in node.ChildNodes[0].ChildNodes)
                    {
                        il.Add(ref prev, Instruction.Create(OpCodes.Ldloc, pn));
                        il.Add(ref prev, Instruction.Create(OpCodes.Ldstr, prop.ChildNodes[0].Token.ValueString));
                        il.Add(ref prev, Instruction.Create(OpCodes.Newobj, string_ctor));
                        GenerateExpression(il, ref start, ref prev, prop.ChildNodes[1]);
                        il.Add(ref prev, Instruction.Create(OpCodes.Callvirt, map_add));
                    }
                }
                il.Add(ref current, Instruction.Create(OpCodes.Ldloc, pn));
                start = prev;
                break;

            case "ArrLitExpr":
                pn = GetSVar(array);
                il.Add(ref prev, Instruction.Create(OpCodes.Newobj, array_ctor));
                il.Add(ref prev, Instruction.Create(OpCodes.Stloc, pn));
                if (node.ChildNodes.Count > 0)
                {
                    foreach (var elm in node.ChildNodes[0].ChildNodes)
                    {
                        il.Add(ref prev, Instruction.Create(OpCodes.Ldloc, pn));
                        GenerateExpression(il, ref start, ref prev, elm);
                        il.Add(ref prev, Instruction.Create(OpCodes.Callvirt, array_add));
                    }
                }
                il.Add(ref current, Instruction.Create(OpCodes.Ldloc, pn));
                start = prev;
                break;

            case "ArrOpExpr":
                GenerateExpression(il, ref start, ref current, node.ChildNodes[0]);
                GenerateExpression(il, ref start, ref current, node.ChildNodes[1]);
                il.Add(ref current, Instruction.Create(OpCodes.Callvirt, value_lookup_get));
                break;

            default:
                throw new InvalidOperationException("Term " + node.Term.Name + " is not a valid expression term");
            }
        }
Exemplo n.º 4
0
        private void GenerateStatement(IlProcessor il, ref Instruction current, ParseTreeNode node)
        {
            var          label = CreateStatementLabel(il);
            var          start = current;
            LocalBuilder pn = null, pn2 = null;

            il.Add(ref current, Instruction.Create(OpCodes.Nop));
            switch (node.Term.Name)
            {
            case "VarStmt":
                GenerateDeclaration(il, ref start, ref current, node);
                break;

            case "FuncDefStmt":
                var name  = node.ChildNodes[1].Token.ValueString;
                var mName = MakeFunctionName(name);
                il.Add(ref current, Instruction.Create(OpCodes.Ldarg_0));
                il.Add(ref current, Instruction.Create(OpCodes.Ldstr, name));
                GenerateFunction(il, ref start, ref current, name, mName, node.ChildNodes[2].ChildNodes, node.ChildNodes[3].ChildNodes[0].ChildNodes);
                il.Add(ref current, Instruction.Create(OpCodes.Callvirt, function_local_dec));
                break;

            case "FlowControlStmt":
                var keyword = node.ChildNodes[0].Token.ValueString;
                switch (keyword)
                {
                case "return":
                    if (node.ChildNodes.Count > 1)
                    {
                        GenerateExpression(il, ref start, ref current, node.ChildNodes[1]);
                    }
                    else
                    {
                        il.Add(ref current, Instruction.Create(OpCodes.Call, undefined));
                    }
                    il.Add(ref current, Instruction.Create(OpCodes.Ret));
                    break;

                case "continue":
                    il.Add(ref current, Instruction.Create(OpCodes.Br, GetLoopDec().ContinueLabel));
                    break;

                case "break":
                    il.Add(ref current, Instruction.Create(OpCodes.Br, GetLoopDec().BreakLabel));
                    break;

                default:
                    throw new InvalidOperationException("Unknown flow control keyword " + keyword);
                }
                break;

            case "ExprStmt":
                GenerateExpression(il, ref start, ref current, node.ChildNodes[0]);
                il.Add(ref current, Instruction.Create(OpCodes.Pop));
                break;

            case "IfElseStmt":
                pn = GetSVar(sys_bool);
                var endLabel = il.DefineLabel();
                GenerateExpression(il, ref start, ref current, node.ChildNodes[1].ChildNodes[0]);
                il.Add(ref current, Instruction.Create(OpCodes.Call, value_istrue));
                il.Add(ref current, Instruction.Create(OpCodes.Ldc_I4_0));
                il.Add(ref current, Instruction.Create(OpCodes.Ceq));
                il.Add(ref current, Instruction.Create(OpCodes.Stloc, pn));
                il.Add(ref current, Instruction.Create(OpCodes.Ldloc, pn));

                if (node.ChildNodes.Count == 5)
                {
                    var elseLabel = il.DefineLabel();
                    il.Add(ref current, Instruction.Create(OpCodes.Brtrue, elseLabel));
                    GenerateStatement(il, ref current, node.ChildNodes[2]);
                    il.Add(ref current, Instruction.Create(OpCodes.Br, endLabel));

                    il.Add(ref current, Instruction.Create(Specials.Label, elseLabel));
                    GenerateStatement(il, ref current, node.ChildNodes[4]);
                }
                else
                {
                    il.Add(ref current, Instruction.Create(OpCodes.Brtrue, endLabel));
                    GenerateStatement(il, ref current, node.ChildNodes[2]);
                }
                il.Add(ref current, Instruction.Create(Specials.Label, endLabel));

                break;

            case "ForStmt":
                AddLoopDec(il);
                // Push new scope
                pn = GetVar(scope);

                il.Add(ref start, Instruction.Create(Specials.BeginTotemScope, pn));

                // Initializer
                il.Add(ref current, Instruction.Create(OpCodes.Nop));
                var initializer = node.ChildNodes[1];
                if (initializer.ChildNodes.Count != 0)
                {
                    initializer = initializer.ChildNodes[0];
                    if (initializer.ChildNodes.Count == 1)
                    {
                        GenerateExpression(il, ref start, ref current, initializer.ChildNodes[0]);
                        il.Add(ref current, Instruction.Create(OpCodes.Pop));
                    }
                    else
                    {
                        foreach (var dec in initializer.ChildNodes[1].ChildNodes)
                        {
                            GenerateDeclaration(il, ref start, ref current, dec);
                        }
                    }
                }
                var conditionLabel = il.DefineLabel();
                var bodyLabel      = il.DefineLabel();
                endLabel = il.DefineLabel();
                il.Add(ref current, Instruction.Create(OpCodes.Br, conditionLabel));

                // Body
                il.Add(ref current, Instruction.Create(Specials.Label, bodyLabel));
                GenerateStatement(il, ref current, node.ChildNodes[4]);
                il.Add(ref current, Instruction.Create(OpCodes.Nop));

                // Increment
                Instruction incr      = il.Add(ref current, Instruction.Create(Specials.Label, GetLoopDec().ContinueLabel));
                var         increment = node.ChildNodes[3];
                if (increment.ChildNodes.Count != 0)
                {
                    GenerateExpression(il, ref start, ref current, increment.ChildNodes[0]);
                }

                // Condition
                il.Add(ref current, Instruction.Create(Specials.Label, conditionLabel));
                var condition = node.ChildNodes[2];
                if (condition.ChildNodes.Count == 0)
                {
                    il.Add(ref current, Instruction.Create(OpCodes.Ldc_I4_1));
                    il.Add(ref current, Instruction.Create(OpCodes.Call, bool_ctor));     // Create TotemBool true
                }
                else
                {
                    GenerateExpression(il, ref start, ref current, condition.ChildNodes[0]);
                }
                il.Add(ref current, Instruction.Create(OpCodes.Call, value_istrue));
                il.Add(ref current, Instruction.Create(OpCodes.Brtrue, bodyLabel));
                il.Add(ref current, Instruction.Create(Specials.Label, GetLoopDec().BreakLabel));
                il.Add(ref current, Instruction.Create(OpCodes.Leave, endLabel));

                pn2 = GetSVar(Load(typeof(bool)));

                // Pop scope
                il.Add(ref current, Instruction.Create(Specials.EndTotemScope, pn));
                RemLoopDec();
                RelVar(pn);
                il.Add(ref current, Instruction.Create(Specials.Label, endLabel));
                break;

            case "Block":
                foreach (var stmt in node.ChildNodes[0].ChildNodes)
                {
                    GenerateStatement(il, ref current, stmt);
                }
                break;

            default:
                throw new InvalidOperationException("Term " + node.Term.Name + " is not a statement");
            }
            RelSVars();
            il.Add(ref current, Instruction.Create(Specials.Label, label));
        }
Exemplo n.º 5
0
        private void GenerateFunction(IlProcessor il, ref Instruction start, ref Instruction current, string name, string mName, ParseTreeNodeList parameters, IEnumerable <ParseTreeNode> body)
        {
            var fn   = module.DefineType(nsp + "." + mName, r.TypeAttributes.Public | r.TypeAttributes.Sealed, function);
            var ctor = fn.DefineConstructor(r.MethodAttributes.Public, r.CallingConventions.Standard, new IKType[] { Load(typeof(TotemScope)), Load(typeof(string)), arr_parameters });

            ctor.DefineParameter(0, r.ParameterAttributes.In, "env");
            ctor.DefineParameter(1, r.ParameterAttributes.In, "name");
            ctor.DefineParameter(2, r.ParameterAttributes.In, "parameters");
            var ctorIl = ctor.GetILGenerator();

            ctorIl.Emit(OpCodes.Ldarg_0);
            ctorIl.Emit(OpCodes.Ldarg_1);
            ctorIl.Emit(OpCodes.Ldarg_2);
            ctorIl.Emit(OpCodes.Ldarg_3);
            ctorIl.Emit(OpCodes.Call, function_ctor);
            ctorIl.Emit(OpCodes.Ret);

            var fnc = fn.DefineMethod("TotemRun", r.MethodAttributes.Family | r.MethodAttributes.HideBySig | r.MethodAttributes.Virtual, r.CallingConventions.Standard, value, IKType.EmptyTypes);

            using (var fnil = fnc.GetILProcessor())
            {
                functionPoints.Push(new FunctionPoints
                {
                    Avail            = new HashSet <LocalBuilder>(),
                    SVars            = new HashSet <LocalBuilder>(),
                    MethodDefinition = fnc,
                    Il = fnil
                });
                GenerateFunction(fnil, body);
                fnil.Emit(OpCodes.Nop);
                fnil.Emit(OpCodes.Call, undefined);
                fnil.Emit(OpCodes.Ret);
                functionPoints.Pop();
            }
            fn.CreateType();

            var pn   = GetSVar(arr_parameters);
            var prev = start;

            il.Add(ref prev, Instruction.Create(OpCodes.Ldc_I4, parameters.Count));
            il.Add(ref prev, Instruction.Create(OpCodes.Newarr, Generator.parameter));
            il.Add(ref prev, Instruction.Create(OpCodes.Stloc, pn));
            for (var i = 0; i < parameters.Count; i++)
            {
                var param = parameters[i];
                il.Add(ref prev, Instruction.Create(OpCodes.Ldloc, pn));
                il.Add(ref prev, Instruction.Create(OpCodes.Ldc_I4, i));
                il.Add(ref prev, Instruction.Create(OpCodes.Ldstr, param.ChildNodes[0].Token.ValueString));
                if (param.ChildNodes.Count > 1)
                {
                    GenerateExpression(il, ref start, ref prev, param.ChildNodes[1].ChildNodes[1]);
                }
                else
                {
                    il.Add(ref prev, Instruction.Create(OpCodes.Call, undefined));
                }
                il.Add(ref prev, Instruction.Create(OpCodes.Newobj, parameter_ctor));
                il.Add(ref prev, Instruction.Create(OpCodes.Stelem_Ref));
            }
            start = prev;
            il.Add(ref current, Instruction.Create(OpCodes.Ldarg_0));
            il.Add(ref current, Instruction.Create(OpCodes.Callvirt, function_env));
            il.Add(ref current, Instruction.Create(OpCodes.Ldstr, name));
            il.Add(ref current, Instruction.Create(OpCodes.Ldloc, pn));
            il.Add(ref current, Instruction.Create(OpCodes.Newobj, ctor));
        }