static Expression CompileNumericFor(Ast.NumericFor stat, LabelTarget returnTarget, Expression Context) { var varValue = ToNumber(CompileSingleExpression(stat.Var, Context)); var limit = ToNumber(CompileSingleExpression(stat.Limit, Context)); var step = ToNumber(CompileSingleExpression(stat.Step, Context)); var var = Expression.Parameter(LuaObject_Type); var scope = Expression.Parameter(LuaContext_Type); var @break = Expression.Label(); var assignScope = Expression.Assign(scope, Expression.New(LuaContext_New_parent, Context)); var assignVar = Expression.Assign(var, varValue); var condition = Expression.Or( Expression.And( Expression.GreaterThan(step, Expression.Constant((LuaObject)0)), Expression.LessThanOrEqual(var, limit)), Expression.And( Expression.LessThanOrEqual(step, Expression.Constant((LuaObject)0)), Expression.GreaterThanOrEqual(var, limit))); var setLocalVar = Expression.Call(scope, LuaContext_SetLocal, Expression.Constant(stat.Variable), var); var innerBlock = CompileBlock(stat.Block, returnTarget, @break, scope); var sum = Expression.Assign(var, Expression.Add(var, step)); var check = Expression.IfThenElse(GetAsBool(condition), Expression.Block(setLocalVar, innerBlock, sum), Expression.Break(@break)); var loop = Expression.Loop(check); var body = Expression.Block(new[] { var, scope }, assignScope, assignVar, loop, Expression.Label(@break)); return(body); }
Ast.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 Ast.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 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 Ast.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"); }
Ast.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 Ast.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 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 Ast.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"); }
Ast.IExpression ParseExpression(ParseTreeNode node) { if (node.Term.Name == "Expression") { ParseTreeNode child = node.ChildNodes[0]; if (child.Token != null && child.Token.Terminal is NumberLiteral) { return(new Ast.NumberLiteral() { Span = child.Span, Value = (child.Token.Value is double?(double)(child.Token.Value) : (int)(child.Token.Value)) }); } else if (child.Token != null && child.Token.Terminal is StringLiteral) { return(new Ast.StringLiteral() { Span = child.Span, Value = (string)(child.Token.Value) }); } else if (child.Token != null && child.Token.Terminal is KeyTerm) { string val = child.Token.ValueString; if (val == "true") { return new Ast.BoolLiteral() { Span = child.Span, Value = true } } ; else if (val == "false") { return new Ast.BoolLiteral() { Span = child.Span, Value = false } } ; else if (val == "nil") { return new Ast.NilLiteral() { Span = child.Span } } ; } else if (child.Term != null && child.Term.Name == "Prefix") { return(ParsePrefix(child)); } else if (child.Term != null && child.Term.Name == "OrOp") { return(ParseOrOp(child)); } else if (child.Term != null && child.Term.Name == "FunctionDef") { return(ParseFunctionDef(child)); } else if (child.Term != null && child.Term.Name == "UnaryExpr") { return(ParseUnaryExpr(child)); } else if (child.Term != null && child.Term.Name == "TableConstruct") { return(ParseTableConstruct(child)); } else if (child.Term != null && child.Term.Name == "OopCall") { return(ParseOopCall(child)); } else if (child.Term != null && child.Term.Name == "Varargs") { return(new Ast.VarargsLiteral()); } } throw new Exception("Invalid Expression node"); } #endregion Ast.Block ParseBlock(ParseTreeNode node) { Ast.Block block = new Ast.Block(); block.Statements = new List <Ast.IStatement>(); foreach (ParseTreeNode child in node.ChildNodes) { switch (child.Term.Name) { case "Assignment": block.Statements.Add(ParseAssign(child)); break; case "LocalAssignment": block.Statements.Add(ParseLocalAssign(child)); break; case "FunctionCall": block.Statements.Add(ParseFunctionCall(child)); break; case "ReturnStat": block.Statements.Add(ParseReturnStat(child)); break; case "BreakStat": block.Statements.Add(new Ast.BreakStat()); break; case "DoBlock": block.Statements.Add(ParseDoBlock(child)); break; case "If": block.Statements.Add(ParseIf(child)); break; case "While": block.Statements.Add(ParseWhile(child)); break; case "Repeat": block.Statements.Add(ParseRepeat(child)); break; case "FunctionDecl": block.Statements.Add(ParseFunctionDecl(child)); break; case "For": block.Statements.Add(ParseFor(child)); break; case "OopCall": block.Statements.Add(ParseOopCall(child)); break; case ";": break; default: throw new NotImplementedException("Node not yet implemented"); } } return(block); } Ast.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 Ast.NumericFor(); cycle.Span = node.Span; 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 Ast.NumberLiteral() { Span = new SourceSpan(cycle.Limit.Span.Location, 0), 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 Ast.GenericFor() { Span = node.Span }; 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"); } }