Пример #1
0
        public void EnterMethodDefinition(
            ScopeBuilder /*!*/ locals,
            MSA.Expression /*!*/ selfParameter,
            MSA.ParameterExpression /*!*/ runtimeScopeVariable,
            MSA.Expression blockParameter,
            string /*!*/ methodName,
            Parameters parameters)
        {
            Assert.NotNull(locals, selfParameter, runtimeScopeVariable);

            MethodScope method = new MethodScope(
                locals,
                selfParameter,
                runtimeScopeVariable,
                blockParameter,
                methodName,
                parameters
                );

            method.Parent              = _currentElement;
            method.ParentRescue        = _currentRescue;
            method.ParentLoop          = _currentLoop;
            method.ParentBlock         = _currentBlock;
            method.ParentVariableScope = _currentVariableScope;
            method.ParentMethod        = _currentMethod;

            _currentElement       = method;
            _currentRescue        = null;
            _currentLoop          = null;
            _currentBlock         = null;
            _currentVariableScope = method;
            _currentMethod        = method;
        }
Пример #2
0
        private void DoStatementEnter(XmlNode node)
        {
            var loopEntryBlock = new CFGBlock();

            if (!CurrentBlock.BreaksOutOfScope)
            {
                loopEntryBlock = ConnectNewBlockTo(CurrentBlock, EdgeType.Normal);
            }
            Graph.AddVertex(loopEntryBlock);
            CurrentBlock = loopEntryBlock;

            CFGBlock conditionBlock = new CFGBlock {
                AstEntryNode = node
            };
            CFGBlock loopDoneBlock = ConnectNewBlockTo(conditionBlock, EdgeType.False);

            ConnectBlocks(conditionBlock, loopEntryBlock, EdgeType.True);

            var loopScope = new LoopScope(loopEntryBlock)
            {
                LoopBodyStartBlock  = loopEntryBlock,
                LoopConditionBlock  = conditionBlock,
                ContinueDestination = conditionBlock,
                EndBlock            = loopDoneBlock,
            };

            scopeHandler.EnterLoop(loopScope);
            DoNotVisitChildren(Conditional.GetCondNode(node));
        }
Пример #3
0
        public void EnterLoop(MSA.Expression /*!*/ redoVariable, MSA.Expression /*!*/ resultVariable, MSA.LabelTarget /*!*/ breakLabel, MSA.LabelTarget /*!*/ continueLabel)
        {
            Assert.NotNull(redoVariable, resultVariable, breakLabel, continueLabel);

            LoopScope loop = new LoopScope(redoVariable, resultVariable, breakLabel, continueLabel);

            loop.Parent     = _currentElement;
            loop.ParentLoop = _currentLoop;

            _currentElement = _currentLoop = loop;
        }
Пример #4
0
        public void LeaveBlockDefinition()
        {
            Debug.Assert(_currentElement == _currentBlock);
            BlockScope oldBlock = _currentBlock;

            _currentElement       = oldBlock.Parent;
            _currentRescue        = oldBlock.ParentRescue;
            _currentLoop          = oldBlock.ParentLoop;
            _currentVariableScope = oldBlock.ParentVariableScope;
            _currentBlock         = oldBlock.ParentBlock;
        }
Пример #5
0
        public void LeaveMethodDefinition()
        {
            Debug.Assert(_currentElement == _currentMethod);
            MethodScope oldMethod = _currentMethod;

            _currentElement       = oldMethod.Parent;
            _currentRescue        = oldMethod.ParentRescue;
            _currentLoop          = oldMethod.ParentLoop;
            _currentBlock         = oldMethod.ParentBlock;
            _currentVariableScope = oldMethod.ParentVariableScope;
            _currentMethod        = oldMethod.ParentMethod;
        }
Пример #6
0
        private void WhileOrForeachStatementEnter(XmlNode node)
        {
            CFGBlock conditionBlock = new CFGBlock();

            if (!CurrentBlock.BreaksOutOfScope)
            {
                conditionBlock = ConnectNewBlockTo(CurrentBlock, EdgeType.Normal);
            }

            CFGBlock loopBodyBlock;
            CFGBlock loopExitBlock;

            if (node.LocalName == AstConstants.Nodes.Stmt_Foreach)
            {
                loopBodyBlock = ConnectNewBlockTo(conditionBlock, EdgeType.Normal);
                loopExitBlock = ConnectNewBlockTo(conditionBlock, EdgeType.Normal);
            }
            else
            {
                loopBodyBlock = ConnectNewBlockTo(conditionBlock, EdgeType.True);
                loopExitBlock = ConnectNewBlockTo(conditionBlock, EdgeType.False);
            }


            conditionBlock.AstEntryNode = node;

            var whileLoopScope = new LoopScope(conditionBlock)
            {
                LoopConditionBlock  = conditionBlock,
                LoopBodyStartBlock  = loopBodyBlock,
                ContinueDestination = conditionBlock,
                EndBlock            = loopExitBlock
            };

            scopeHandler.EnterLoop(whileLoopScope);

            if (node.LocalName == AstConstants.Nodes.Stmt_Foreach)
            {
                DoNotVisitChildren(node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.Expr));
                DoNotVisitChildren(node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.KeyVar));
                DoNotVisitChildren(node.GetSubNode(AstConstants.Subnode + ":" + AstConstants.Subnodes.ValueVar));
            }
            else
            {
                DoNotVisitChildren(Conditional.GetCondNode(node));
            }


            CurrentBlock = loopBodyBlock;
        }
Пример #7
0
        private void ForStatementEnter(XmlNode node)
        {
            CFGBlock forLoopInit = new CFGBlock();

            if (!CurrentBlock.BreaksOutOfScope)
            {
                forLoopInit = ConnectNewBlockTo(CurrentBlock, EdgeType.Normal);
            }
            forLoopInit.AstEntryNode = ForLoop.GetInitNode(node);
            DoNotVisitChildren(forLoopInit.AstEntryNode);

            CFGBlock conditionBlock = ConnectNewBlockTo(forLoopInit, EdgeType.Normal);

            conditionBlock.AstEntryNode = node;
            DoNotVisitChildren(Conditional.GetCondNode(node));

            CFGBlock loopUpdateBlock = new CFGBlock {
                AstEntryNode = ForLoop.GetLoopNode(node)
            };

            DoNotVisitChildren(loopUpdateBlock.AstEntryNode);

            var edge = new TaggedEdge <CFGBlock, EdgeTag>(loopUpdateBlock, conditionBlock, new EdgeTag(EdgeType.Normal));

            Graph.AddVerticesAndEdge(edge);

            CFGBlock loopBodyBlock = ConnectNewBlockTo(conditionBlock, EdgeType.True);
            CFGBlock loopDoneBlock = ConnectNewBlockTo(conditionBlock, EdgeType.False);

            var loopScope = new LoopScope(forLoopInit)
            {
                LoopConditionBlock  = loopUpdateBlock,
                LoopBodyStartBlock  = loopBodyBlock,
                LoopUpdateBlock     = loopUpdateBlock,
                ContinueDestination = loopUpdateBlock,
                EndBlock            = loopDoneBlock
            };

            scopeHandler.EnterLoop(loopScope);

            CurrentBlock = loopBodyBlock;
        }
Пример #8
0
        public void EnterBlockDefinition(
            ScopeBuilder /*!*/ locals,
            MSA.Expression /*!*/ bfcVariable,
            MSA.Expression /*!*/ selfVariable,
            MSA.Expression /*!*/ runtimeScopeVariable,
            MSA.LabelTarget /*!*/ redoLabel)
        {
            Assert.NotNull(locals, bfcVariable, selfVariable);
            Assert.NotNull(redoLabel);

            BlockScope block = new BlockScope(locals, selfVariable, runtimeScopeVariable, bfcVariable, redoLabel);

            block.Parent              = _currentElement;
            block.ParentRescue        = _currentRescue;
            block.ParentLoop          = _currentLoop;
            block.ParentBlock         = _currentBlock;
            block.ParentVariableScope = _currentVariableScope;

            _currentElement       = block;
            _currentRescue        = null;
            _currentLoop          = null;
            _currentBlock         = block;
            _currentVariableScope = block;
        }
Пример #9
0
        private static Expression GenerateForLoop(LoopScope loopScope, Token tStart, ParameterExpression loopVar, Expression loopStart, Expression loopEnd, Expression loopStep)
        {
            const string csVar = "#var";
            const string csEnd = "#end";
            const string csStep = "#step";
            ParameterExpression internLoopVar = Expression.Variable(loopVar.Type, csVar);
            ParameterExpression endVar = Expression.Variable(loopEnd.Type, csEnd);
            ParameterExpression stepVar = Expression.Variable(loopStep.Type, csStep);
            LabelTarget labelLoop = Expression.Label("#loop");

            // Erzeuge CodeBlock
            loopScope.InsertExpression(0, Expression.Assign(loopVar, internLoopVar));

            // Erzeuge den Schleifenblock
            return Expression.Block(new ParameterExpression[] { internLoopVar, endVar, stepVar },
                Expression.Assign(internLoopVar, ConvertExpression(loopScope.Runtime, tStart, loopStart, internLoopVar.Type)),
                Expression.Assign(endVar, loopEnd),
                Expression.Assign(stepVar, loopStep),

                Expression.Label(labelLoop),

                Expression.IfThenElse(
                    BinaryOperationExpression(loopScope.Runtime, tStart, ExpressionType.OrElse,
                        BinaryOperationExpression(loopScope.Runtime, tStart, ExpressionType.AndAlso,
                            ConvertExpression(loopScope.Runtime, tStart, BinaryOperationExpression(loopScope.Runtime, tStart, ExpressionType.GreaterThan, stepVar, Expression.Constant(0, typeof(int))), typeof(bool)),
                            ConvertExpression(loopScope.Runtime, tStart, BinaryOperationExpression(loopScope.Runtime, tStart, ExpressionType.LessThanOrEqual, internLoopVar, endVar), typeof(bool))
                        ),
                        BinaryOperationExpression(loopScope.Runtime, tStart, ExpressionType.AndAlso,
                            ConvertExpression(loopScope.Runtime, tStart, BinaryOperationExpression(loopScope.Runtime, tStart, ExpressionType.LessThanOrEqual, stepVar, Expression.Constant(0, typeof(int))), typeof(bool)),
                            ConvertExpression(loopScope.Runtime, tStart, BinaryOperationExpression(loopScope.Runtime, tStart, ExpressionType.GreaterThanOrEqual, internLoopVar, endVar), typeof(bool))
                        )
                    ),
                    loopScope.ExpressionBlock,
                    Expression.Goto(loopScope.BreakLabel)
                ),
                Expression.Label(loopScope.ContinueLabel),

                Expression.Assign(internLoopVar, ConvertExpression(loopScope.Runtime, tStart, BinaryOperationExpression(loopScope.Runtime, tStart, ExpressionType.Add, internLoopVar, stepVar), internLoopVar.Type)),

                Expression.Goto(labelLoop),
                Expression.Label(loopScope.BreakLabel)
            );
        }
Пример #10
0
        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);
        }
Пример #11
0
        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));
            }
        }
Пример #12
0
        public void LeaveMethodDefinition() {
            Debug.Assert(_currentElement == _currentMethod);
            MethodScope oldMethod = _currentMethod;

            _currentElement = oldMethod.Parent;
            _currentRescue = oldMethod.ParentRescue;
            _currentLoop = oldMethod.ParentLoop;
            _currentBlock = oldMethod.ParentBlock;
            _currentVariableScope = oldMethod.ParentVariableScope;
            _currentMethod = oldMethod.ParentMethod;
        }
Пример #13
0
        public void EnterMethodDefinition(
            ScopeBuilder/*!*/ locals, 
            MSA.Expression/*!*/ selfParameter,
            MSA.ParameterExpression/*!*/ runtimeScopeVariable,
            MSA.Expression blockParameter,
            string/*!*/ methodName,
            Parameters parameters) {
            Assert.NotNull(locals, selfParameter, runtimeScopeVariable);

            MethodScope method = new MethodScope(
                locals,
                selfParameter, 
                runtimeScopeVariable, 
                blockParameter, 
                methodName, 
                parameters
            );

            method.Parent = _currentElement;
            method.ParentRescue = _currentRescue;
            method.ParentLoop = _currentLoop;
            method.ParentBlock = _currentBlock;
            method.ParentVariableScope = _currentVariableScope;
            method.ParentMethod = _currentMethod;

            _currentElement = method;
            _currentRescue = null;
            _currentLoop = null;
            _currentBlock = null;
            _currentVariableScope = method;
            _currentMethod = method;
        }
Пример #14
0
        public void LeaveBlockDefinition() {
            Debug.Assert(_currentElement == _currentBlock);
            BlockScope oldBlock = _currentBlock;

            _currentElement = oldBlock.Parent;
            _currentRescue = oldBlock.ParentRescue;
            _currentLoop = oldBlock.ParentLoop;
            _currentVariableScope = oldBlock.ParentVariableScope;
            _currentBlock = oldBlock.ParentBlock;
        }
Пример #15
0
        public void EnterBlockDefinition(
            ScopeBuilder/*!*/ locals,
            MSA.Expression/*!*/ bfcVariable,
            MSA.Expression/*!*/ selfVariable,
            MSA.ParameterExpression/*!*/ runtimeScopeVariable, 
            MSA.LabelTarget/*!*/ redoLabel) {
            Assert.NotNull(locals, bfcVariable, selfVariable);
            Assert.NotNull(redoLabel);

            BlockScope block = new BlockScope(locals, selfVariable, runtimeScopeVariable, bfcVariable, redoLabel);
            block.Parent = _currentElement;
            block.ParentRescue = _currentRescue;
            block.ParentLoop = _currentLoop;
            block.ParentBlock = _currentBlock;
            block.ParentVariableScope = _currentVariableScope;
            
            _currentElement = block;
            _currentRescue = null;
            _currentLoop = null;
            _currentBlock = block;
            _currentVariableScope = block;
        }
Пример #16
0
 public void LeaveLoop() {
     Debug.Assert(_currentElement == _currentLoop);
     _currentElement = _currentLoop.Parent;
     _currentLoop = _currentLoop.ParentLoop;
 }
Пример #17
0
 public BreakOutOfLoopScopeError(SourceLocation location, LoopScope scope) : base(location)
 {
     _scope = scope;
 }
Пример #18
0
        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);
        }
Пример #19
0
        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);
        }
Пример #20
0
 public void LeaveLoop()
 {
     Debug.Assert(_currentElement == _currentLoop);
     _currentElement = _currentLoop.Parent;
     _currentLoop    = _currentLoop.ParentLoop;
 }
Пример #21
0
    /// <summary>
    /// Compiles the source text into a module.
    /// </summary>
    /// <param name="sourceText">The source text.</param>
    /// <param name="module">The source module.</param>
    /// <returns>The compiled module.</returns>
    public static Module Compile(string sourceText, string module = "")
    {
        var parser = new Parser(sourceText, module);

        // -------------------------------------------------------------------------

        LexicalScope scope = new FunctionScope(null)
        {
            Token = parser.Next
        };

        void EnterFunctionScope(Token token)
        {
            scope = new FunctionScope(scope)
            {
                Token = token
            };
        }

        void EnterBlockScope(Token token)
        {
            scope = new BlockScope(scope)
            {
                Token = token
            };
        }

        void EnterLoopScope(Token token)
        {
            scope = new LoopScope(scope)
            {
                Token = token
            };
        }

        void LeaveScope()
        {
            scope = scope.Scope;
            Debug.Assert(scope != null);
        }

        // -------------------------------------------------------------------------

        Slot MakeSlot(string name)
        {
            foreach (var found in scope.SlotsInScope)
            {
                if (found.Name == name)
                {
                    throw parser.Error($"'{name}' is already defined in this scope");
                }
            }

            var slot = new Slot {
                Name = name, Scope = scope
            };

            scope.Slots.Add(slot);
            return(slot);
        }

        Slot FindSlot(string name)
        {
            foreach (var found in scope.SlotsInScope)
            {
                if (found.Name == name)
                {
                    return(found);
                }
            }

            throw parser.Error($"Undefined '{name}'");
        }

        // -------------------------------------------------------------------------

        // Identifier declaration
        parser.Syntax.Declaration(Token.Word).Do((token, context) => new Identifier(MakeSlot(token.Text))
        {
            Token = token,
            Scope = scope,
        });

        // -------------------------------------------------------------------------

        // Grouping: ( expr )
        // Function expression: ( ) => expr_or_block
        // Function expression: ( ...ident ) => expr_or_block
        // Function expression: ( ident , ... ) => expr_or_block
        parser.Syntax.Primitive("(").Do((token, context) => {
            var isFunction =
                parser.Match(")", "=>") ||
                parser.Match(Token.Word, ",") ||
                parser.Match(Token.Word, ")", "=>") ||
                parser.Match("...", Token.Word, ")", "=>");

            if (isFunction)
            {
                var expression = new FunctionExpression {
                    Token = token,
                    Scope = scope,
                };

                EnterFunctionScope(token);
                {
                    parser.RepeatZeroOrMoreWithSeparatorUntil(")", ",", delegate {
                        var isRestParameter = parser.Optional("...");

                        if (parser.Declaration(context) is Identifier parameter)
                        {
                            var index = expression.Parameters.Count;
                            expression.Parameters.Add(parameter);

                            parameter.Slot.Kind     = SlotKind.Parameter;
                            parameter.Slot.ReadOnly = true; // <- parameters are always read-only

                            if (isRestParameter)
                            {
                                parameter.Slot.Source      = SlotSource.ArgumentSlice;
                                parameter.Slot.SourceIndex = index;
                                parser.Next.Require(")", "The rest parameter must be the last");
                            }
                            else
                            {
                                parameter.Slot.Source      = SlotSource.Argument;
                                parameter.Slot.SourceIndex = index;
                            }
                        }
                        else
                        {
                            throw parser.Error("Expected a parameter name");
                        }
                    });

                    var arrow = parser.Required("=>");

                    if (parser.Optional("{") is Token begin)
                    {
                        expression.Body = new Block {
                            Token = begin,
                            Scope = scope,
                        };

                        parser.RepeatZeroOrMoreUntil("}", delegate {
                            expression.Body.Statements.Add(parser.Statement(context) as Statement);
                        });
                    }
                    else if (parser.Expression(context) is Expression value)
                    {
                        expression.Body = new Block {
                            Token      = arrow,
                            Scope      = scope,
                            Statements =
                            {
                                new ReturnStatement {
                                    Token = arrow,
                                    Scope = scope,
                                    Value = value,
                                },
                            },
                        };
                    }
                    else
                    {
                        throw parser.Error("Expected an expression after '=>'");
                    }
                }
Пример #22
0
        private static Expression GenerateForLoop(LoopScope loopScope, Token tStart, List<ParameterExpression> loopVars, Expression[] explist)
        {
            const string csFunc = "#f";
            const string csState = "#s";
            const string csVar = "#var";

            ParameterExpression varTmp = Expression.Variable(typeof(LuaResult), "#tmp");
            ParameterExpression varFunc = Expression.Variable(explist.Length > 0 && typeof(Delegate).GetTypeInfo().IsAssignableFrom(explist[0].Type.GetTypeInfo()) ? explist[0].Type : typeof(object), csFunc);
            ParameterExpression varState = Expression.Variable(typeof(object), csState);
            ParameterExpression varVar = Expression.Variable(typeof(object), csVar);

            // local var1, ..., varn = tmp;
            for (int i = 0; i < loopVars.Count; i++)
                loopScope.InsertExpression(i, Expression.Assign(loopVars[i], ConvertExpression(loopScope.Runtime, tStart, GetResultExpression(loopScope.Runtime, tStart, varTmp, i), loopVars[i].Type)));
            return Expression.Block(new ParameterExpression[] { varTmp, varFunc, varState, varVar },
                // fill the local loop variables initial
                // local #f, #s, #var = explist
                Expression.Assign(varTmp, GetLuaResultExpression(loopScope, tStart, explist)),
                Expression.Assign(varFunc, ConvertExpression(loopScope.Runtime, tStart, GetResultExpression(loopScope.Runtime, tStart, varTmp, 0), varFunc.Type)),
                Expression.Assign(varState, GetResultExpression(loopScope.Runtime, tStart, varTmp, 1)),
                Expression.Assign(varVar, GetResultExpression(loopScope.Runtime, tStart, varTmp, 2)),

                Expression.Label(loopScope.ContinueLabel),

                // local tmp = f(s, var)
                Expression.Assign(varTmp, InvokeExpression(loopScope, tStart, varFunc, InvokeResult.LuaResult,
                    new ArgumentsList(varState, varVar), true)
                ),

                // var = tmp[0]
                Expression.Assign(varVar, GetResultExpression(loopScope.Runtime, tStart, varTmp, 0)),

                // if var == nil then goto break;
                Expression.IfThenElse(Expression.Equal(varVar, Expression.Constant(null, typeof(object))),
                    Expression.Goto(loopScope.BreakLabel),
                    loopScope.ExpressionBlock), // LoopBody

                Expression.Goto(loopScope.ContinueLabel),
                Expression.Label(loopScope.BreakLabel)
            );
        }
Пример #23
0
        public void EnterLoop(MSA.Expression/*!*/ redoVariable, MSA.Expression/*!*/ resultVariable, MSA.LabelTarget/*!*/ breakLabel, MSA.LabelTarget/*!*/ continueLabel) {
            Assert.NotNull(redoVariable, resultVariable, breakLabel, continueLabel);

            LoopScope loop = new LoopScope(redoVariable, resultVariable, breakLabel, continueLabel);

            loop.Parent = _currentElement;
            loop.ParentLoop = _currentLoop;

            _currentElement = _currentLoop = loop;
        }
Пример #24
0
        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)
                ));
        }
Пример #25
0
 public ContinueOutOfLoopScopeError(SourceLocation location, LoopScope scope)
     : base(location)
 {
     _scope = scope;
 }