コード例 #1
0
ファイル: Parser.cs プロジェクト: strogo/neolua
        private static void ParseExpressionStatement(Scope scope, LuaLexer code, bool lLocal)
        {
            List<ParameterExpression> registerLocals = null;
            List<PrefixMemberInfo> prefixes = new List<PrefixMemberInfo>();

            // parse the assgiee list (var0, var1, var2, ...)
            while (true)
            {
                if (lLocal) // parse local variables
                {
                    Token tVar;
                    Type typeVar;
                    ParseIdentifierAndType(scope, code, out tVar, out typeVar);

                    ParameterExpression exprVar = scope.LookupExpression(tVar.Value, true) as ParameterExpression;
                    if (exprVar == null)
                    {
                        exprVar = Expression.Variable(typeVar, tVar.Value);
                        if (registerLocals == null)
                            registerLocals = new List<ParameterExpression>();
                        registerLocals.Add(exprVar);
                    }
                    else if (exprVar.Type != typeVar)
                        throw ParseError(tVar, Properties.Resources.rsParseTypeRedef);

                    prefixes.Add(new PrefixMemberInfo(tVar, exprVar, null, null, null));
                }
                else // parse a assignee
                {
                    // parse as a prefix
                    prefixes.Add(ParsePrefix(scope, code));
                }

                // is there another prefix
                if (code.Current.Typ == LuaToken.Comma)
                    code.Next();
                else
                    break;
            }

            // Optional assign
            if (code.Current.Typ == LuaToken.Assign)
            {
                code.Next();

                // parse all expressions
                IEnumerator<Expression> expr = ParseExpressionList(scope, code).GetEnumerator();
                expr.MoveNext();

                if (prefixes.Count == 1) // one expression, one variable?
                {
                    scope.AddExpression(
                        prefixes[0].GenerateSet(scope, expr.Current != null ? expr.Current : Expression.Constant(null, typeof(object)))
                    );
                }
                else if (expr.Current == null) // No expression, assign null
                {
                    for (int i = 0; i < prefixes.Count; i++)
                        scope.AddExpression(prefixes[i].GenerateSet(scope, Expression.Constant(null, typeof(object))));
                }
                else // assign on an unknown number of expressions
                {
                    #region -- unknown number --
                    List<ParameterExpression> assignTempVars = new List<ParameterExpression>();
                    List<Expression> assignExprs = new List<Expression>();
                    int iExpressionVarOffset;

                    // Safe the prefixes in variables
                    for (int k = 0; k < prefixes.Count; k++)
                    {
                        var p = prefixes[k];
                        if (p.Member != null || prefixes[k].Indices != null)
                        {
                            p.Instance = ParseExpressionStatementExchangeToTempVar(assignTempVars, assignExprs, p.Instance);

                            if (p.Indices != null)
                            {
                                for (int l = 0; l < p.Indices.Length; l++)
                                    p.Indices[l] = ParseExpressionStatementExchangeToTempVar(assignTempVars, assignExprs, p.Indices[l]);
                            }
                        }
                    }

                    // collect the results of the expressions
                    iExpressionVarOffset = assignTempVars.Count;
                    do
                    {
                        ParseExpressionStatementExchangeToTempVar(assignTempVars, assignExprs, expr.Current);
                    } while (expr.MoveNext());

                    // Assign the Result to the prefixes
                    int i = 0;
                    int j = 0;
                    ParameterExpression lastVariable = null;
                    while (i < prefixes.Count)
                    {
                        if (i < assignTempVars.Count - iExpressionVarOffset) // are the variables
                        {
                            if (i == assignTempVars.Count - iExpressionVarOffset - 1 && assignTempVars[i + iExpressionVarOffset].Type == typeof(LuaResult)) // check if the last expression is a LuaResult
                            {
                                lastVariable = assignTempVars[i + iExpressionVarOffset];
                                assignExprs.Add(prefixes[i].GenerateSet(scope, GetResultExpression(scope.Runtime, code.Current, lastVariable, j++)));
                            }
                            else
                            {
                                assignExprs.Add(prefixes[i].GenerateSet(scope, assignTempVars[i + iExpressionVarOffset]));
                            }
                        }
                        else if (lastVariable != null) // we enroll the last expression
                        {
                            assignExprs.Add(prefixes[i].GenerateSet(scope, GetResultExpression(scope.Runtime, code.Current, lastVariable, j++)));
                        }
                        else // no variable left
                        {
                            assignExprs.Add(prefixes[i].GenerateSet(scope, Expression.Default(typeof(object))));
                        }
                        i++;
                    }

                    // add the block
                    scope.AddExpression(Expression.Block(assignTempVars, assignExprs));

                    #endregion
                }

                // Führe die restlichen Expressions aus
                while (expr.MoveNext())
                    scope.AddExpression(expr.Current);
            }
            else if (!lLocal)
            {
                for (int i = 0; i < prefixes.Count; i++)
                {
                    if (prefixes[i].Arguments == null) // do not execute getMember
                        throw ParseError(prefixes[i].Position, Properties.Resources.rsParseAssignmentExpected);

                    scope.AddExpression(prefixes[i].GenerateGet(scope, InvokeResult.None));
                }
            }

            // register the variables
            if (registerLocals != null)
            {
                for (int i = 0; i < registerLocals.Count; i++)
                    scope.RegisterVariable(registerLocals[i]);
            }
        }
コード例 #2
0
ファイル: Parser.cs プロジェクト: strogo/neolua
        private static void ParseForEachLoop(Scope scope, LuaLexer code)
        {
            ParameterExpression varEnumerable = Expression.Variable(typeof(System.Collections.IEnumerable), "#enumerable");
            ParameterExpression varEnumerator = Expression.Variable(typeof(System.Collections.IEnumerator), "#enumerator");

            // foreach name in exp do block end;
            code.Next(); // foreach

            // fetch the loop variable
            LoopScope loopScope = new LoopScope(scope);
            Token tLoopVar;
            Type typeLoopVar;
            ParseIdentifierAndType(scope, code, out tLoopVar, out typeLoopVar);
            ParameterExpression loopVar = loopScope.RegisterVariable(typeLoopVar, tLoopVar.Value);

            // get the enumerable expression
            FetchToken(LuaToken.KwIn, code);
            Expression exprEnum = Lua.EnsureType(ParseExpression(scope, code, InvokeResult.None, scope.EmitExpressionDebug), typeof(object));

            // parse the loop body
            FetchToken(LuaToken.KwDo, code);
            ParseBlock(loopScope, code);
            FetchToken(LuaToken.KwEnd, code);

            loopScope.InsertExpression(0, Expression.Assign(loopVar, ConvertExpression(scope.Runtime, tLoopVar, Expression.Property(varEnumerator, Lua.EnumeratorCurrentPropertyInfo), loopVar.Type)));
            scope.AddExpression(
                Expression.Block(new ParameterExpression[] { varEnumerable, varEnumerator, loopVar },
                // local enumerable = exprEnum as IEnumerator
                Expression.Assign(varEnumerable, Expression.TypeAs(exprEnum, typeof(System.Collections.IEnumerable))),

                // if enumerable == nil then error
                Expression.IfThen(Expression.Equal(varEnumerable, Expression.Constant(null, typeof(object))), Lua.ThrowExpression(Properties.Resources.rsExpressionNotEnumerable)),

                // local enum = exprEnum.GetEnumerator()
                Expression.Assign(varEnumerator, Expression.Call(varEnumerable, Lua.EnumerableGetEnumeratorMethodInfo)),

                // while enum.MoveNext() do
                Expression.Label(loopScope.ContinueLabel),
                Expression.IfThenElse(Expression.Call(varEnumerator, Lua.EnumeratorMoveNextMethodInfo), Expression.Empty(), Expression.Goto(loopScope.BreakLabel)),

                //   loopVar = enum.Current
                loopScope.ExpressionBlock,

                // end;
                Expression.Goto(loopScope.ContinueLabel),
                Expression.Label(loopScope.BreakLabel)
                ));
        }
コード例 #3
0
ファイル: Parser.cs プロジェクト: strogo/neolua
        private static void ParseBreak(Scope scope, LuaLexer code)
        {
            FetchToken(LuaToken.KwBreak, code);

            // Erzeuge die Expression
            scope.AddExpression(Expression.Goto(scope.LookupLabel(null, csBreakLabel)));

            // Optionales Semicolon
            FetchToken(LuaToken.Semicolon, code, true);
        }
コード例 #4
0
ファイル: Parser.cs プロジェクト: strogo/neolua
        private static void ParseDoLoop(Scope scope, LuaLexer code)
        {
            // doloop ::= do '(' name { ',' name } = expr { ',' expr }  ')' block end

            // create empty block, that can used as an loop
            Scope outerScope = new Scope(scope);
            Expression[] exprFinally = null;

            // fetch do
            FetchToken(LuaToken.KwDo, code);
            if (code.Current.Typ == LuaToken.BracketOpen) // look for disposable variables
            {
                code.Next();
                ParseExpressionStatement(outerScope, code, true);

                // Build finally-Block for the declared variables
                exprFinally = (
                    from c in outerScope.Variables
                    select Expression.IfThen(
                        Expression.TypeIs(c, typeof(IDisposable)),
                        Expression.Call(Expression.Convert(c, typeof(IDisposable)), Lua.DisposeDisposeMethodInfo)
                    )).ToArray();

                FetchToken(LuaToken.BracketClose, code);
            }

            LoopScope loopScope = new LoopScope(outerScope);

            // Add the Contine label after the declaration
            loopScope.AddExpression(Expression.Label(loopScope.ContinueLabel));
            // parse the block
            ParseBlock(loopScope, code);
            // create the break label
            loopScope.AddExpression(Expression.Label(loopScope.BreakLabel));

            FetchToken(LuaToken.KwEnd, code);

            if (exprFinally != null && exprFinally.Length > 0)
            {
                outerScope.AddExpression(
                    Expression.TryFinally(
                        loopScope.ExpressionBlock,
                        Expression.Block(exprFinally)
                    )
                );
                scope.AddExpression(outerScope.ExpressionBlock);
            }
            else
                scope.AddExpression(loopScope.ExpressionBlock);
        }
コード例 #5
0
ファイル: Parser.cs プロジェクト: strogo/neolua
        private static void ParseWhileLoop(Scope scope, LuaLexer code)
        {
            // while expr do block end;
            LoopScope loopScope = new LoopScope(scope);

            // get the expression
            FetchToken(LuaToken.KwWhile, code);

            loopScope.AddExpression(Expression.Label(loopScope.ContinueLabel));
            loopScope.AddExpression(
                Expression.IfThenElse(
                    ConvertExpression(scope.Runtime, code.Current, ParseExpression(scope, code, InvokeResult.Object, scope.EmitExpressionDebug), typeof(bool)),
                    Expression.Empty(),
                    Expression.Goto(loopScope.BreakLabel)
                )
            );

            // append the block
            FetchToken(LuaToken.KwDo, code);
            ParseBlock(loopScope, code);
            FetchToken(LuaToken.KwEnd, code);

            // goto continue
            loopScope.AddExpression(Expression.Goto(loopScope.ContinueLabel));
            loopScope.AddExpression(Expression.Label(loopScope.BreakLabel));

            scope.AddExpression(loopScope.ExpressionBlock);
        }
コード例 #6
0
ファイル: Parser.cs プロジェクト: strogo/neolua
        private static void ParseBlock(Scope scope, LuaLexer code)
        {
            // Lese die Statement
            int iLastDebugInfo = -1;
            bool lLoop = true;
            while (lLoop)
            {
                bool lDebugInfoEmitted = false;

                if ((scope.EmitDebug & LuaDebugLevel.Line) != 0) // debug info for line
                {
                    if (code.Current.Start.Line != iLastDebugInfo)
                    {
                        iLastDebugInfo = code.Current.Start.Line;
                        scope.AddExpression(GetDebugInfo(code.Current, code.Current));
                        lDebugInfoEmitted = true;
                    }
                }

                switch (code.Current.Typ)
                {
                    case LuaToken.Eof: // End of file
                        lLoop = false;
                        break;

                    case LuaToken.KwReturn: //  The return-statement is only allowed on the end of a scope
                        ParseReturn(scope, code);
                        break;

                    case LuaToken.KwBreak: // The break-statement is only allowed on the end of a scope
                        ParseBreak(scope, code);
                        lLoop = false;
                        break;

                    case LuaToken.Semicolon: // End of statement => ignore
                        code.Next();
                        break;

                    default:
                        if (!lDebugInfoEmitted && (scope.EmitDebug & LuaDebugLevel.Expression) != 0) // Start every statement with a debug point
                            scope.AddExpression(GetDebugInfo(code.Current, code.Current));

                        if (!ParseStatement(scope, code)) // Parse normal statements
                            lLoop = false;
                        break;
                }
            }
            if (scope.EmitDebug != LuaDebugLevel.None)
                scope.AddExpression(Expression.ClearDebugInfo(code.Current.Start.Document)); // Clear debug info
        }
コード例 #7
0
ファイル: Parser.cs プロジェクト: strogo/neolua
        private static Expression ParseTableConstructor(Scope scope, LuaLexer code)
        {
            // table ::= '{' [field] { fieldsep field } [fieldsep] '}'
            // fieldsep ::= ',' | ';'
            FetchToken(LuaToken.BracketCurlyOpen, code);

            if (code.Current.Typ != LuaToken.BracketCurlyClose)
            {
                int iIndex = 1;
                Scope scopeTable = new Scope(scope);

                // Create the variable for the table
                ParameterExpression tableVar = scopeTable.RegisterVariable(typeof(LuaTable), "#table");
                scopeTable.AddExpression(Expression.Assign(tableVar, CreateEmptyTableExpression()));

                // fiest field
                ParseTableField(tableVar, scopeTable, code, ref iIndex);

                // collect more table fields
                while (code.Current.Typ == LuaToken.Comma || code.Current.Typ == LuaToken.Semicolon)
                {
                    code.Next();

                    // Optional last separator
                    if (code.Current.Typ == LuaToken.BracketCurlyClose)
                        break;

                    // Parse the field
                    ParseTableField(tableVar, scopeTable, code, ref iIndex);
                }

                scopeTable.AddExpression(tableVar);
                scopeTable.ExpressionBlockType = typeof(LuaTable);

                // Closing bracket
                FetchToken(LuaToken.BracketCurlyClose, code);

                return scopeTable.ExpressionBlock;
            }
            else
            {
                FetchToken(LuaToken.BracketCurlyClose, code);
                return CreateEmptyTableExpression();
            }
        }
コード例 #8
0
ファイル: Parser.cs プロジェクト: strogo/neolua
        private static void ParseTableField(ParameterExpression tableVar, Scope scope, LuaLexer code, ref int iIndex)
        {
            // field ::= '[' exp ']' '=' exp | Name '=' exp | exp
            if (code.Current.Typ == LuaToken.BracketSquareOpen)
            {
                // Parse the index
                code.Next();
                var index = ParseExpression(scope, code, InvokeResult.Object, scope.EmitExpressionDebug);
                FetchToken(LuaToken.BracketSquareClose, code);
                FetchToken(LuaToken.Assign, code);

                // Expression that results in a value
                scope.AddExpression(
                    IndexSetExpression(scope.Runtime, code.Current, tableVar, new Expression[] { index },
                        ParseExpression(scope, code, InvokeResult.Object, scope.EmitExpressionDebug)
                    )
                );

            }
            else if (code.Current.Typ == LuaToken.Identifier && code.LookAhead.Typ == LuaToken.Assign)
            {
                // Read the identifier
                Token tMember = code.Current;
                code.Next();
                FetchToken(LuaToken.Assign, code);

                // Expression
                scope.AddExpression(
                    IndexSetExpression(scope.Runtime, code.Current, tableVar, new Expression[] { Expression.Constant(tMember.Value) },
                        ParseExpression(scope, code, InvokeResult.Object, scope.EmitExpressionDebug)
                    )
                );
            }
            else
            {
                Token tStart = code.Current;
                Expression expr = ParseExpression(scope, code, InvokeResult.None, scope.EmitExpressionDebug);

                // Last assign, enroll parameter
                if (code.Current.Typ == LuaToken.BracketCurlyClose && LuaEmit.IsDynamicType(expr.Type))
                {
                    scope.AddExpression(
                        Expression.Call(Lua.TableSetObjectsMethod,
                            tableVar,
                            Expression.Convert(expr, typeof(object)),
                            Expression.Constant(iIndex, typeof(int))
                        )
                    );
                }
                else // Normal index set
                {
                    scope.AddExpression(
                        IndexSetExpression(scope.Runtime, code.Current, tableVar, new Expression[] { Expression.Constant(iIndex++, typeof(object)) }, expr)
                    );
                }
            }
        }
コード例 #9
0
ファイル: Parser.cs プロジェクト: strogo/neolua
        private static void ParseRepeatLoop(Scope scope, LuaLexer code)
        {
            LoopScope loopScope = new LoopScope(scope);

            // continue label
            loopScope.AddExpression(Expression.Label(loopScope.ContinueLabel));

            // loop content
            FetchToken(LuaToken.KwRepeat, code);
            ParseBlock(loopScope, code);

            // get the loop expression
            FetchToken(LuaToken.KwUntil, code);
            loopScope.AddExpression(
                Expression.IfThenElse(
                    ConvertExpression(scope.Runtime, code.Current, ParseExpression(scope, code, InvokeResult.Object, scope.EmitExpressionDebug), typeof(bool)),
                    Expression.Empty(),
                    Expression.Goto(loopScope.ContinueLabel)
                )
            );

            loopScope.AddExpression(Expression.Label(loopScope.BreakLabel));

            scope.AddExpression(loopScope.ExpressionBlock);
        }
コード例 #10
0
ファイル: Parser.cs プロジェクト: strogo/neolua
        private static void ParseReturn(Scope scope, LuaLexer code)
        {
            // eat return
            code.Next();

            // Build the return expression for all parameters
            Expression exprReturnValue;

            if (IsExpressionStart(code)) // there is a return value
            {
                if (scope.ReturnType == typeof(LuaResult))
                {
                    exprReturnValue = GetLuaResultExpression(scope, code.Current, ParseExpressionList(scope, code).ToArray());
                }
                else if (scope.ReturnType.IsArray)
                {
                    Type typeArray = scope.ReturnType.GetElementType();
                    exprReturnValue = Expression.NewArrayInit(
                        typeArray,
                        from c in ParseExpressionList(scope, code) select ConvertExpression(scope.Runtime, code.Current, c, typeArray));
                }
                else
                {
                    List<Expression> exprList = new List<Expression>(ParseExpressionList(scope, code));

                    if (exprList.Count == 1)
                        exprReturnValue = ConvertExpression(scope.Runtime, code.Current, exprList[0], scope.ReturnType);
                    else
                    {
                        ParameterExpression tmpVar = Expression.Variable(scope.ReturnType);
                        exprList[0] = Expression.Assign(tmpVar, ConvertExpression(scope.Runtime, code.Current, exprList[0], scope.ReturnType));
                        exprList.Add(tmpVar);
                        exprReturnValue = Expression.Block(scope.ReturnType, new ParameterExpression[] { tmpVar }, exprList);
                    }
                }
            }
            else // use the default-value
            {
                if (scope.ReturnType == typeof(LuaResult))
                    exprReturnValue = Expression.Property(null, Lua.ResultEmptyPropertyInfo);
                else if (scope.ReturnType.IsArray)
                    exprReturnValue = Expression.NewArrayInit(scope.ReturnType.GetElementType());
                else
                    exprReturnValue = Expression.Default(scope.ReturnType);
            }

            if (code.Current.Typ == LuaToken.Semicolon)
                code.Next();

            scope.AddExpression(Expression.Goto(scope.LookupLabel(scope.ReturnType, csReturnLabel), exprReturnValue));
        }
コード例 #11
0
ファイル: Parser.cs プロジェクト: strogo/neolua
        private static void ParseLabel(Scope scope, LuaLexer code)
        {
            // ::identifier::
            FetchToken(LuaToken.ColonColon, code);

            // Erzeuge das Label
            scope.AddExpression(Expression.Label(scope.LookupLabel(null, FetchToken(LuaToken.Identifier, code).Value)));

            FetchToken(LuaToken.ColonColon, code);
        }
コード例 #12
0
ファイル: Parser.cs プロジェクト: strogo/neolua
        private static void ParseIfStatement(Scope scope, LuaLexer code)
        {
            // if expr then block { elseif expr then block } [ else block ] end
            FetchToken(LuaToken.KwIf, code);
            var expr = ConvertExpression(scope.Runtime, code.Current, ParseExpression(scope, code, InvokeResult.Object, scope.EmitExpressionDebug), typeof(bool));
            FetchToken(LuaToken.KwThen, code);

            scope.AddExpression(Expression.IfThenElse(expr, ParseIfElseBlock(scope, code), ParseElseStatement(scope, code)));
        }
コード例 #13
0
ファイル: Parser.cs プロジェクト: strogo/neolua
        private static void ParseGoto(Scope scope, LuaLexer code)
        {
            // goto Identifier
            FetchToken(LuaToken.KwGoto, code);

            var t = FetchToken(LuaToken.Identifier, code);
            scope.AddExpression(Expression.Goto(scope.LookupLabel(null, t.Value)));
        }
コード例 #14
0
ファイル: Parser.cs プロジェクト: strogo/neolua
        private static void ParseFunction(Scope scope, LuaLexer code, bool lLocal)
        {
            FetchToken(LuaToken.KwFunction, code);

            if (lLocal) // Local function, only one identifier is allowed
            {
                var t = FetchToken(LuaToken.Identifier, code);
                ParameterExpression funcVar = null;
                Expression exprFunction = ParseLamdaDefinition(scope, code, t.Value, false,
                    typeDelegate => funcVar = scope.RegisterVariable(typeDelegate, t.Value)
                );
                scope.AddExpression(Expression.Assign(funcVar, exprFunction));
            }
            else // Function that is assigned to a table. A chain of identifiers is allowed.
            {
                Expression assignee = null;
                Token tCurrent = FetchToken(LuaToken.Identifier, code);
                string sMember = tCurrent.Value;

                // Collect the chain of members
                while (code.Current.Typ == LuaToken.Dot)
                {
                    code.Next();

                    // Create the get-member for the current assignee
                    assignee = ParseFunctionAddChain(scope, tCurrent, assignee, sMember);
                    sMember = FetchToken(LuaToken.Identifier, code).Value;
                }
                // add a method to the table. methods get a hidden parameter and will bo marked
                bool lMethodMember;
                if (code.Current.Typ == LuaToken.Colon)
                {
                    code.Next();

                    // add the last member to the assignee chain
                    assignee = ParseFunctionAddChain(scope, tCurrent, assignee, sMember);
                    // fetch the method name
                    sMember = FetchToken(LuaToken.Identifier, code).Value;
                    lMethodMember = true;
                }
                else
                {
                    if (assignee == null)
                        assignee = scope.LookupExpression(csEnv); // create a global function
                    lMethodMember = false;
                }

                // generate lambda
                scope.AddExpression(MemberSetExpression(scope.Runtime, tCurrent, assignee, sMember, lMethodMember, ParseLamdaDefinition(scope, code, sMember, lMethodMember, null)));
            }
        }
コード例 #15
0
ファイル: Parser.cs プロジェクト: strogo/neolua
        private static void ParseForLoop(Scope scope, LuaLexer code)
        {
            // for name
            FetchToken(LuaToken.KwFor, code);
            Token tLoopVar;
            Type typeLoopVar;
            ParseIdentifierAndType(scope, code, out tLoopVar, out typeLoopVar);
            if (code.Current.Typ == LuaToken.Assign)
            {
                // = exp, exp [, exp] do block end
                FetchToken(LuaToken.Assign, code);
                Expression loopStart = ParseExpression(scope, code, InvokeResult.Object, scope.EmitExpressionDebug);
                FetchToken(LuaToken.Comma, code);
                Expression loopEnd = ParseExpression(scope, code, InvokeResult.Object, scope.EmitExpressionDebug);
                Expression loopStep;
                if (code.Current.Typ == LuaToken.Comma)
                {
                    code.Next();
                    loopStep = ParseExpression(scope, code, InvokeResult.Object, scope.EmitExpressionDebug);
                }
                else
                    loopStep = Expression.Constant(1, loopStart.Type);

                LoopScope loopScope = new LoopScope(scope);
                ParameterExpression loopVarParameter = loopScope.RegisterVariable(typeLoopVar == typeof(object) ? LuaEmit.LiftType(LuaEmit.LiftType(loopStart.Type, loopEnd.Type), loopStep.Type) : typeLoopVar, tLoopVar.Value);

                FetchToken(LuaToken.KwDo, code);
                ParseBlock(loopScope, code);
                FetchToken(LuaToken.KwEnd, code);
                scope.AddExpression(GenerateForLoop(loopScope, tLoopVar, loopVarParameter, loopStart, loopEnd, loopStep));
            }
            else
            {
                // {, name} in explist do block end

                // fetch all loop variables
                LoopScope loopScope = new LoopScope(scope);
                List<ParameterExpression> loopVars = new List<ParameterExpression>();
                loopVars.Add(loopScope.RegisterVariable(typeLoopVar, tLoopVar.Value));
                while (code.Current.Typ == LuaToken.Comma)
                {
                    code.Next();
                    ParseIdentifierAndType(scope, code, out tLoopVar, out typeLoopVar);
                    loopVars.Add(loopScope.RegisterVariable(typeLoopVar, tLoopVar.Value));
                }

                // get the loop expressions
                FetchToken(LuaToken.KwIn, code);
                Expression[] explist = ParseExpressionList(scope, code).ToArray();

                // parse the loop body
                FetchToken(LuaToken.KwDo, code);
                ParseBlock(loopScope, code);
                FetchToken(LuaToken.KwEnd, code);

                scope.AddExpression(GenerateForLoop(loopScope, tLoopVar, loopVars, explist));
            }
        }