/// <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);
            }
        }
Esempio n. 2
0
 static object AddTest(object a, object b)
 {
     return(Primitives.add(a, b));
 }