/// <summary> /// Parses and executes the specified string /// </summary> public LuaArguments DoString(string Chunk) { FunctionDefinition def = new FunctionDefinition(); def.Arguments = new List<Argument>(); def.Body = p.ParseString(Chunk); var function = LuaCompiler.CompileFunction(def, Expression.Constant(ctx)).Compile(); return function().Call(Lua.Return()); }
public static Expression <Func <LuaObject> > CompileFunction(Ast.FunctionDefinition func, Expression Context) { var exprs = new List <Expression>(); var args = Expression.Parameter(LuaArguments_Type, "args"); var label = Expression.Label(LuaArguments_Type, "exit"); var @break = Expression.Label("break"); var scopeVar = Expression.Parameter(LuaContext_Type, "funcScope"); var assignScope = Expression.Assign(scopeVar, Expression.New(LuaContext_New_parent, Context)); #region Arguments init var len = Expression.Property(args, "Length"); var argLen = Expression.Constant(func.Arguments.Count); var argCount = Expression.Constant(func.Arguments.Count); var i = Expression.Parameter(typeof(int), "i"); var assignI = Expression.Assign(i, Expression.Constant(0)); var names = Expression.Parameter(typeof(string[]), "names"); var assignNames = Expression.Assign(names, Expression.Constant(Array.ConvertAll <Argument, string>(func.Arguments.ToArray(), x => x.Name))); var innerCond = Expression.LessThan(i, argLen); var outerCond = Expression.LessThan(i, len); var innerIf = Expression.Call(scopeVar, LuaContext_SetLocal, Expression.ArrayAccess(names, i), Expression.Property(args, "Item", i)); var varargs = Expression.Property(scopeVar, "Varargs"); var innerElse = Expression.Call(varargs, LuaArguments_Add, Expression.Property(args, "Item", i)); var outerIf = Expression.Block(Expression.IfThenElse(innerCond, innerIf, innerElse), Expression.Assign(i, Expression.Add(i, Expression.Constant(1)))); var outerElse = Expression.Break(@break); var loopBody = Expression.IfThenElse(outerCond, outerIf, outerElse); var loop = Expression.Loop(loopBody); var breakLabel = Expression.Label(@break); #endregion var body = CompileBlock(func.Body, label, null, scopeVar); exprs.Add(assignScope); exprs.Add(assignI); exprs.Add(assignNames); exprs.Add(loop); exprs.Add(breakLabel); exprs.Add(body); exprs.Add(Expression.Label(label, Expression.Constant(VoidArguments))); var funcBody = Expression.Block(new[] { i, names, scopeVar }, exprs.ToArray()); var function = Expression.Lambda <LuaFunction>(funcBody, args); var returnValue = Expression.Lambda <Func <LuaObject> >(Expression.Convert(function, LuaObject_Type), null); return(returnValue); }
Ast.Assignment ParseFunctionDecl(ParseTreeNode node) { if (node.Term.Name == "FunctionDecl") { Ast.IAssignable expr = ParseVariable(node.ChildNodes[1]); ParseTreeNode argsNode = node.ChildNodes[3].ChildNodes[0]; ParseTreeNode chunkNode = node.ChildNodes[4]; Ast.Block block = ParseBlock(chunkNode); Ast.FunctionDefinition def = new Ast.FunctionDefinition(); def.Arguments = new List <Ast.Argument>(); var nameNode = node.ChildNodes[2]; if (nameNode.ChildNodes.Count > 0) { def.Arguments.Add(new Ast.Argument() { Name = "self" }); expr = new Ast.Variable() { Name = nameNode.ChildNodes[0].Token.ValueString, Prefix = expr }; } def.Body = block; if (argsNode.ChildNodes.Count > 0) { argsNode = argsNode.ChildNodes[0]; while (argsNode.ChildNodes.Count > 0) { string ident = argsNode.ChildNodes[0].Token.ValueString; def.Arguments.Add(new Ast.Argument() { Name = ident }); if (argsNode.ChildNodes.Count == 1) { break; } argsNode = argsNode.ChildNodes[1]; } } Ast.Assignment assign = new Ast.Assignment(); assign.Variables.Add(expr); assign.Expressions.Add(def); return(assign); } throw new Exception("Invalid FunctionDecl node"); }
Ast.FunctionDefinition ParseFunctionDef(ParseTreeNode node) { if (node.Term.Name == "FunctionDef") { ParseTreeNode argsNode = node.ChildNodes[1].ChildNodes[0]; ParseTreeNode chunkNode = node.ChildNodes[2]; Ast.Block block = ParseBlock(chunkNode); Ast.FunctionDefinition def = new Ast.FunctionDefinition(); def.Body = block; def.Arguments = new List <Ast.Argument>(); if (argsNode.ChildNodes.Count == 0) { return(def); } if (argsNode.ChildNodes.Count > 0) { argsNode = argsNode.ChildNodes[0]; while (argsNode.ChildNodes.Count > 0) { var argsNodeChild = argsNode.ChildNodes[0]; if (argsNodeChild.Token == null) { def.Arguments.Add(new Ast.Argument() { Name = "...", Span = argsNodeChild.Span }); } else { string ident = argsNodeChild.Token.ValueString; def.Arguments.Add(new Ast.Argument() { Name = ident, Span = argsNodeChild.Span }); } if (argsNode.ChildNodes.Count == 1) { break; } argsNode = argsNode.ChildNodes[1]; } } return(def); } throw new Exception("Invalid FunctionDef node"); }
Ast.LocalAssignment ParseLocalAssign(ParseTreeNode node) { if (node.Term.Name == "LocalAssignment") { Ast.LocalAssignment assign = new Ast.LocalAssignment(); var child = node.ChildNodes[1]; if (child.ChildNodes[0].Term.Name == "LocalFunction") { child = child.ChildNodes[0]; var argsNode = child.ChildNodes[2]; var blockNode = child.ChildNodes[3]; assign.Names.Add(child.ChildNodes[1].Token.ValueString); var func = new Ast.FunctionDefinition(); if (argsNode.ChildNodes.Count > 0) { argsNode = argsNode.ChildNodes[0]; while (argsNode.ChildNodes.Count > 0) { string ident = argsNode.ChildNodes[0].Token.ValueString; func.Arguments.Add(new Ast.Argument() { Name = ident }); if (argsNode.ChildNodes.Count == 1) { break; } argsNode = argsNode.ChildNodes[1]; } } func.Body = ParseBlock(blockNode); assign.Values.Add(func); return(assign); } var left = child.ChildNodes[0]; var right = child.ChildNodes[1]; assign.Names.Add(left.ChildNodes[0].Token.ValueString); left = left.ChildNodes[1]; while (left.ChildNodes.Count > 0) { left = left.ChildNodes[0]; assign.Names.Add(left.ChildNodes[0].Token.ValueString); left = left.ChildNodes[1]; } while (right.ChildNodes.Count > 0) { right = right.ChildNodes[0]; assign.Values.Add(ParseExpression(right.ChildNodes[0])); right = right.ChildNodes[1]; } return(assign); } throw new Exception("Invalid LocalAssignment node"); }
Ast.FunctionDefinition ParseFunctionDef(ParseTreeNode node) { if (node.Term.Name == "FunctionDef") { ParseTreeNode argsNode = node.ChildNodes[1].ChildNodes[0]; ParseTreeNode chunkNode = node.ChildNodes[2]; Ast.Block block = ParseBlock(chunkNode); Ast.FunctionDefinition def = new Ast.FunctionDefinition(); def.Body = block; def.Arguments = new List<Ast.Argument>(); if (argsNode.ChildNodes.Count == 0) return def; if (argsNode.ChildNodes.Count > 0) { argsNode = argsNode.ChildNodes[0]; while (argsNode.ChildNodes.Count > 0) { string ident = argsNode.ChildNodes[0].Token.ValueString; def.Arguments.Add(new Ast.Argument() { Name = ident }); if (argsNode.ChildNodes.Count == 1) break; argsNode = argsNode.ChildNodes[1]; } } return def; } throw new Exception("Invalid FunctionDef node"); }
Ast.Assignment ParseFunctionDecl(ParseTreeNode node) { if (node.Term.Name == "FunctionDecl") { Ast.IAssignable expr = ParseVariable(node.ChildNodes[1]); ParseTreeNode argsNode = node.ChildNodes[3].ChildNodes[0]; ParseTreeNode chunkNode = node.ChildNodes[4]; Ast.Block block = ParseBlock(chunkNode); Ast.FunctionDefinition def = new Ast.FunctionDefinition(); def.Arguments = new List<Ast.Argument>(); var nameNode = node.ChildNodes[2]; if (nameNode.ChildNodes.Count > 0) { def.Arguments.Add(new Ast.Argument() { Name = "self" }); expr = new Ast.Variable() { Name = nameNode.ChildNodes[0].Token.ValueString, Prefix = expr }; } def.Body = block; if (argsNode.ChildNodes.Count > 0) { argsNode = argsNode.ChildNodes[0]; while (argsNode.ChildNodes.Count > 0) { string ident = argsNode.ChildNodes[0].Token.ValueString; def.Arguments.Add(new Ast.Argument() { Name = ident }); if (argsNode.ChildNodes.Count == 1) break; argsNode = argsNode.ChildNodes[1]; } } Ast.Assignment assign = new Ast.Assignment(); assign.Variables.Add(expr); assign.Expressions.Add(def); return assign; } throw new Exception("Invalid FunctionDecl node"); }
Ast.LocalAssignment ParseLocalAssign(ParseTreeNode node) { if (node.Term.Name == "LocalAssignment") { Ast.LocalAssignment assign = new Ast.LocalAssignment(); var child = node.ChildNodes[1]; if (child.ChildNodes[0].Term.Name == "LocalFunction") { child = child.ChildNodes[0]; var argsNode = child.ChildNodes[2]; var blockNode = child.ChildNodes[3]; assign.Names.Add(child.ChildNodes[1].Token.ValueString); var func = new Ast.FunctionDefinition(); if (argsNode.ChildNodes.Count > 0) { argsNode = argsNode.ChildNodes[0]; while (argsNode.ChildNodes.Count > 0) { string ident = argsNode.ChildNodes[0].Token.ValueString; func.Arguments.Add(new Ast.Argument() { Name = ident }); if (argsNode.ChildNodes.Count == 1) break; argsNode = argsNode.ChildNodes[1]; } } func.Body = ParseBlock(blockNode); assign.Values.Add(func); return assign; } var left = child.ChildNodes[0]; var right = child.ChildNodes[1]; assign.Names.Add(left.ChildNodes[0].Token.ValueString); left = left.ChildNodes[1]; while (left.ChildNodes.Count > 0) { left = left.ChildNodes[0]; assign.Names.Add(left.ChildNodes[0].Token.ValueString); left = left.ChildNodes[1]; } while (right.ChildNodes.Count > 0) { right = right.ChildNodes[0]; assign.Values.Add(ParseExpression(right.ChildNodes[0])); right = right.ChildNodes[1]; } return assign; } throw new Exception("Invalid LocalAssignment node"); }
static Expression CompileFunctionDef(FunctionDefinition def, Expression Context) { return Expression.Invoke(CompileFunction(def, Context)); }