Beispiel #1
0
 public bool Match(XMLLuaSearchGenericFor req, GenericFor real)
 {
     Logger.Debug($"generic_for");
     if (!Match(req.Block, real.Block))
     {
         return(false);
     }
     if (req.Expressions.Count != real.Expressions.Count)
     {
         return(false);
     }
     if (req.Variables.Count != real.Variables.Count)
     {
         return(false);
     }
     for (var i = 0; i < req.Expressions.Count; i++)
     {
         if (!Match(req.Expressions[i], real.Expressions[i]))
         {
             return(false);
         }
     }
     for (var i = 0; i < req.Variables.Count; i++)
     {
         if (req.Variables[i] != real.Variables[i])
         {
             return(false);
         }
     }
     SetSelectionIfSelected(real.Span, req);
     return(true);
 }
Beispiel #2
0
        public async Task ExecuteGenericFor(GenericFor forStat, LuaState state, CancellationToken token)
        {
            var forState = state.WithNewContext();
            var varNames = forStat.Variables.Select(LuaObject.FromString).ToArray();

            var expressions = await _engine.EvaluateExpression(forStat.Expressions, state, token);

            var func  = expressions[0];
            var table = expressions[1];
            var args  = Lua.Args(expressions.Skip(1));

            while (true)
            {
                var result = await func.CallAsync(state.Engine, args, token);

                if (result[0].IsNil())
                {
                    break;
                }

                for (var i = 0; i < varNames.Length; i++)
                {
                    forState.Context.NewIndexRaw(varNames[i], result[i]);
                }

                await _engine.ExecuteStatement(forStat.Block, forState, token);

                args = Lua.Args(new[] { table }.Concat(result));
            }
        }
Beispiel #3
0
        static LuaArguments EvalGenericFor(GenericFor stat, LuaContext Context, out LuaReturnStatus returned)
        {
            returned.broke    = false;
            returned.returned = false;

            LuaArguments args = null;

            foreach (IExpression expr in stat.Expressions)
            {
                if (args == null)
                {
                    args = EvalExpression(expr, Context);
                }
                else
                {
                    args.Concat(EvalExpression(expr, Context));
                }
            }
            LuaObject  f = args[0], s = args[1], var = args[2];
            LuaContext ctx = new LuaContext(Context);

            while (true)
            {
                LuaArguments res = f.Call(s, var);
                for (int i = 0; i < stat.Variables.Count; i++)
                {
                    ctx.SetLocal(stat.Variables[i], res[i]);
                }
                if (res[0].IsNil)
                {
                    break;
                }
                var = res[0];
                LuaArguments obj = EvalBlock(stat.Block, ctx, out returned);
                if (returned.broke)
                {
                    break;
                }
                if (returned.returned)
                {
                    return(obj);
                }
            }

            return(Lua.Return());
        }
Beispiel #4
0
 public void Visit(GenericFor node)
 {
     VisitLuaFunction(node);
 }
        public void Analyze(Function f)
        {
            // Traverse all the nodes in post-order and try to convert jumps to if statements
            var usedFollows = new HashSet <BasicBlock>();

            // Heads of for statements
            var forHeads = new HashSet <BasicBlock>();

            var relocalize = new HashSet <Identifier>();

            // Order the blocks sequentially
            for (int i = 0; i < f.Blocks.Count; i++)
            {
                f.Blocks[i].OrderNumber = i;
            }

            // Step 1: build the AST for ifs/loops based on follow information
            foreach (var node in f.PostorderTraversal(true))
            {
                // Search instructions for identifiers we need to relocalize
                foreach (var inst in node.Instructions)
                {
                    if (inst is Assignment asn)
                    {
                        foreach (var def in inst.GetDefines(true))
                        {
                            if (relocalize.Contains(def))
                            {
                                asn.IsLocalDeclaration = true;
                                relocalize.Remove(def);
                            }
                        }
                    }
                }

                // A for loop is a pretested loop where the follow does not match the head
                if (node.LoopFollow != null && node.LoopFollow != node && node.Predecessors.Count() >= 2 && node.LoopType == LoopType.LoopPretested)
                {
                    var loopInitializer = node.Predecessors.First(x => !node.LoopLatches.Contains(x));

                    // Match a numeric for
                    if (node.Instructions.Last() is Jump loopJump && loopJump.Condition is BinOp loopCondition && loopCondition.OperationType == BinOperationType.OpLoopCompare && node.Instructions[^ 2] is Assignment aaa3 && aaa3.Right != null && aaa3.Right is BinOp)
                    {
                        var nfor = new NumericFor();
                        nfor.Limit = loopCondition.Right;
                        Identifier loopvar = (loopCondition.Left as IdentifierReference).Identifier;
                        var        incinst = node.Instructions[node.Instructions.Count() - 2];
                        nfor.Increment = ((incinst as Assignment).Right as BinOp).Right;

                        // Search the predecessor block for the initial assignments (i.e. the definition)

                        /*for (int i = loopInitializer.Instructions.Count() - 1; i >= 0; i--)
                         * {
                         *  if (loopInitializer.Instructions[i] is Assignment a && a.GetDefines(true).Contains(loopvar))
                         *  {
                         *      nfor.Initial = a;
                         *      //if (!lua51)
                         *      loopInitializer.Instructions.RemoveAt(i);
                         *      break;
                         *  }
                         * }*/

                        // Extract the step variable definition
                        if (loopInitializer.Instructions.Count > 2 && loopInitializer.Instructions[^ 2] is Assignment incassn)
                        {
                            nfor.Increment = incassn.Right;
                            if (incassn.IsLocalDeclaration)
                            {
                                relocalize.Add(incassn.Left[0].Identifier);
                            }
                            loopInitializer.Instructions.RemoveAt(loopInitializer.Instructions.Count - 2);
                        }

                        // Extract the limit variable definition
                        if (loopInitializer.Instructions.Count > 2 && loopInitializer.Instructions[^ 2] is Assignment limitassn)
                        {
                            nfor.Limit = limitassn.Right;
                            if (limitassn.IsLocalDeclaration)
                            {
                                relocalize.Add(limitassn.Left[0].Identifier);
                            }
                            loopInitializer.Instructions.RemoveAt(loopInitializer.Instructions.Count - 2);
                        }

                        // Extract the initializer variable definition
                        if (loopInitializer.Instructions.Count > 1 && loopInitializer.Instructions[loopInitializer.Instructions.Count - 2] is Assignment initassn)
                        {
                            nfor.Initial = initassn;
                            if (initassn.IsLocalDeclaration)
                            {
                                relocalize.Add(initassn.Left[0].Identifier);
                            }
                            loopInitializer.Instructions.RemoveAt(loopInitializer.Instructions.Count - 2);
                        }

                        nfor.Body = node.Successors[1];
                        nfor.Body.MarkCodegenerated(f.Id);
                        if (!usedFollows.Contains(node.LoopFollow))
                        {
                            nfor.Follow = node.LoopFollow;
                            usedFollows.Add(node.LoopFollow);
                            node.LoopFollow.MarkCodegenerated(f.Id);
                        }
                        if (loopInitializer.Instructions.Any() && loopInitializer.Instructions[loopInitializer.Instructions.Count() - 1] is Jump)
                        {
                            loopInitializer.Instructions[loopInitializer.Instructions.Count() - 1] = nfor;
                        }
                        else
                        {
                            loopInitializer.Instructions.Add(nfor);
                        }
                        node.MarkCodegenerated(f.Id);
                        // The head might be the follow of an if statement, so do this to not codegen it
                        usedFollows.Add(node);

                        // Remove any jump instructions from the latches if they exist
                        foreach (var latch in node.LoopLatches)
                        {
                            if (latch.Instructions.Count > 0 && latch.Instructions.Last() is Jump jmp2 && !jmp2.Conditional && jmp2.BlockDest == node)
                            {
                                latch.Instructions.RemoveAt(latch.Instructions.Count - 1);
                            }
                        }
                    }

                    // Match a generic for with a predecessor initializer
                    else if (node.Instructions.Count > 0 && node.Instructions.Last() is Jump loopJump2 && loopJump2.Condition is BinOp loopCondition2 &&
                             loopInitializer.Instructions.Count >= 2 && loopInitializer.Instructions[loopInitializer.Instructions.Count - 2] is Assignment la &&
                             la.Left.Any() && la.Left[0] is IdentifierReference f1 && node.Instructions[0] is Assignment ba && ba.Right is FunctionCall fc &&
                             fc.Function is IdentifierReference fci && fci.Identifier == f1.Identifier)
                    {
                        var gfor = new GenericFor();
                        // Search the predecessor block for the initial assignment which contains the right expression
                        IExpression right = new IExpression();
                        for (int i = loopInitializer.Instructions.Count() - 1; i >= 0; i--)
                        {
                            if (loopInitializer.Instructions[i] is Assignment a)
                            {
                                right = a.Right;
                                loopInitializer.Instructions.RemoveAt(i);
                                break;
                            }
                        }

                        // Loop head has the loop variables
                        if (node.Instructions.First() is Assignment a2)
                        {
                            gfor.Iterator = new Assignment(a2.Left, right);
                            node.Instructions.RemoveAt(0);
                        }
                        else
                        {
                            throw new Exception("Unkown for pattern");
                        }

                        // Body contains more loop bytecode that can be removed
                        //var body = (node.Successors[0].ReversePostorderNumber > node.Successors[1].ReversePostorderNumber) ? node.Successors[0] : node.Successors[1];
                        var body = node.Successors[0];
                        if (body.Instructions[0] is Assignment a3)
                        {
                            body.Instructions.RemoveAt(0);
                        }

                        gfor.Body = body;
                        gfor.Body.MarkCodegenerated(f.Id);
                        if (!usedFollows.Contains(node.LoopFollow))
                        {
                            gfor.Follow = node.LoopFollow;
                            usedFollows.Add(node.LoopFollow);
                            node.LoopFollow.MarkCodegenerated(f.Id);
                        }
                        if (loopInitializer.Instructions.Any() && loopInitializer.Instructions[loopInitializer.Instructions.Count() - 1] is Jump)
                        {
                            loopInitializer.Instructions[loopInitializer.Instructions.Count() - 1] = gfor;
                        }
                        else
                        {
                            loopInitializer.Instructions.Add(gfor);
                        }
                        node.MarkCodegenerated(f.Id);
                        // The head might be the follow of an if statement, so do this to not codegen it
                        usedFollows.Add(node);
                    }
Beispiel #6
0
 public virtual void Visit(GenericFor node)
 {
 }
Beispiel #7
0
        IStatement ParseFor(ParseTreeNode node)
        {
            if (node.Term.Name == "For")
            {
                var block = ParseDoBlock(node.ChildNodes[2]);
                var type  = node.ChildNodes[1].ChildNodes[0];
                if (type.Term.Name == "NumericFor")
                {
                    var cycle = new NumericFor();
                    cycle.Block    = block;
                    cycle.Variable = type.ChildNodes[0].Token.ValueString;
                    cycle.Var      = ParseExpression(type.ChildNodes[1]);
                    cycle.Limit    = ParseExpression(type.ChildNodes[2]);
                    cycle.Step     = new Runtime.Ast.NumberLiteral()
                    {
                        Value = 1
                    };
                    if (type.ChildNodes[3].ChildNodes.Count > 0)
                    {
                        var child = type.ChildNodes[3].ChildNodes[0];
                        cycle.Step = ParseExpression(child);
                    }

                    return(cycle);
                }
                else
                {
                    var cycle = new GenericFor();
                    cycle.Block = block;

                    var nameList = type.ChildNodes[0];
                    var exprList = type.ChildNodes[2];

                    while (true)
                    {
                        var name = nameList.ChildNodes[0].Token.ValueString;
                        cycle.Variables.Add(name);
                        var child = nameList.ChildNodes[1];
                        if (child.ChildNodes.Count > 0)
                        {
                            nameList = child.ChildNodes[0];
                        }
                        else
                        {
                            break;
                        }
                    }

                    while (true)
                    {
                        var expr = ParseExpression(exprList.ChildNodes[0]);
                        cycle.Expressions.Add(expr);
                        var child = exprList.ChildNodes[1];
                        if (child.ChildNodes.Count > 0)
                        {
                            exprList = child.ChildNodes[0];
                        }
                        else
                        {
                            break;
                        }
                    }

                    return(cycle);
                }
            }
            throw new Exception("Invalid For node");
        }