static Expression CompileGenericFor(Ast.GenericFor stat, LabelTarget returnTarget, Expression Context) { var body = new List <Expression>(); var args = Expression.Parameter(LuaArguments_Type); var f = GetArgument(args, 0); var s = GetArgument(args, 1); var var = GetArgument(args, 2); var fVar = Expression.Parameter(LuaObject_Type); var sVar = Expression.Parameter(LuaObject_Type); var varVar = Expression.Parameter(LuaObject_Type); var scope = Expression.Parameter(LuaContext_Type); var @break = Expression.Label(); body.Add(Expression.Assign(args, Expression.New(LuaArguments_New_void))); foreach (IExpression expr in stat.Expressions) { body.Add(Expression.Call(args, LuaArguments_Concat, CompileExpression(expr, Context))); } body.Add(Expression.Assign(fVar, f)); body.Add(Expression.Assign(sVar, s)); body.Add(Expression.Assign(varVar, var)); body.Add(Expression.Assign(scope, Expression.New(LuaContext_New_parent, Context))); var res = Expression.Parameter(LuaArguments_Type); var buildArgs = Expression.New(LuaArguments_New, Expression.NewArrayInit(typeof(LuaObject), sVar, varVar)); var resAssign = Expression.Assign(res, Expression.Call(fVar, LuaObject_Call, buildArgs)); List <Expression> exprs = new List <Expression>(); exprs.Add(resAssign); for (int i = 0; i < stat.Variables.Count; i++) { var val = GetArgument(res, i); exprs.Add(Expression.Call(scope, LuaContext_SetLocal, Expression.Constant(stat.Variables[i]), val)); } var check = Expression.IfThen(Expression.Property(GetArgument(res, 0), "IsNil"), Expression.Break(@break)); exprs.Add(check); exprs.Add(Expression.Assign(varVar, GetFirstArgument(res))); exprs.Add(CompileBlock(stat.Block, returnTarget, @break, scope)); var loopBody = Expression.Block(new[] { res }, exprs.ToArray()); var loop = Expression.Loop(loopBody); body.Add(loop); body.Add(Expression.Label(@break)); var block = Expression.Block(new[] { args, scope, fVar, sVar, varVar }, body.ToArray()); 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.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"); } }