/// <summary> /// The node has to be transformed before being passed /// </summary> /// <param name="n"></param> /// <returns></returns> public Expression ToExpr(Node n) { switch (n.Label) { case "Empty": return(Noop); case "Return": return((n.Count > 0) ? Expression.Return(GetReturnTarget(), ToExpr(n[0]), typeof(Object)) : Expression.Return(GetReturnTarget(), Expression.Constant(typeof(Object), null))); case "If": return(n.Count > 2 ? Expression.IfThenElse(Expression.Convert(ToExpr(n[0]), typeof(Boolean)), ToExpr(n[1]), ToExpr(n[2])) : Expression.IfThen(Expression.Convert(ToExpr(n[0]), typeof(Boolean)), ToExpr(n[1]))); case "Else": return(ToExpr(n[0])); case "For": return(CompileForLoop(ToExpr(n[0]), ToExpr(n[1]), ToExpr(n[2]), ToExpr(n[3]))); case "VarDecl": { var r = AddBinding(Expression.Variable(typeof(object), n[0].Text)); if (n.Count > 1) { r = Expression.Assign(r, ToExpr(n[1])); } return(r); } case "Block": return(ScopedExpr(() => Expression.Block(n.Nodes.Select(ToExpr)))); case "TertiaryExpr": return(Expression.Condition(ToExpr(n[0]), ToExpr(n[1]), ToExpr(n[2]))); case "BinaryExpr": return(Expression.Call(null, Primitives.GetMethodFromBinaryOperator(n[1].Text), ToExpr(n[0]), ToExpr(n[2]))); case "AssignExpr": return(Expression.Assign(ToExpr(n[0]), ToExpr(n[2]))); case "FieldExpr": return(Expression.Field(ToExpr(n[0]), n[1].Text)); case "IndexExpr": return(CompileIndexExpr(ToExpr(n[0]), ToExpr(n[2]))); case "CallExpr": return(CompileCallExpr(ToExpr(n[0]), n[1].Nodes.Select(ToExpr))); case "MethodCallExpr": { var self = ToExpr(n[0]); var func = Expression.Field(self, n[1].Text); var args = new List <Expression>() { self }; args.AddRange(n[2].Nodes.Select(ToExpr)); return(CompileCallExpr(func, args)); } case "PrefixExpr": switch (n[0].Text) { case "!": return(Expression.Not(ToExpr(n[1]))); case "~": return(Expression.OnesComplement(ToExpr(n[1]))); case "-": return(Expression.Negate(ToExpr(n[1]))); default: throw new Exception("Unrecognized prefix operator " + n[0].Text); } case "NewExpr": return(ScopedExpr(() => { AddBinding("this", Expression.Constant(new JsonObject())); return ToExpr(n[0]); })); case "ParenExpr": return(ToExpr(n[0])); case "AnonFunc": { var ps = n[0].Nodes.Select(x => Expression.Parameter(typeof(Object), x.Text)); return(CreateStatementLambda(ps, () => ToExpr(n[1]))); }; case "Object": throw new NotImplementedException(); case "Array": return(Expression.NewArrayInit(typeof(object), n.Nodes.Select(ToExpr))); case "Identifier": return(Lookup(n.Text)); case "String": return(Expression.Constant(Utilities.Unquote(n.Text))); case "Integer": return(Expression.Convert(Expression.Constant(int.Parse(n.Text)), typeof(Object))); case "Float": return(Expression.Convert(Expression.Constant(float.Parse(n.Text)), typeof(Object))); case "True": return(Expression.Convert(Expression.Constant(true), typeof(Object))); case "False": return(Expression.Convert(Expression.Constant(false), typeof(Object))); case "Null": return(Expression.Constant(null)); default: throw new Exception("Unrecognized node type " + n.Label); } }
static object AddTest(object a, object b) { return(Primitives.add(a, b)); }