private static Expression CompileObj(Obj obj, Scope scope) { var temp = scope.FreeVariable("obj"); var expressions = new List<Expression> { Expression.Assign(temp, Expression.New(ExpandoConstructor)) }; foreach (var @base in obj.Properties) { var property = @base as Assign; foreach (var name in CompileToNames(property.Variable)) { var expression = Compile(property.Value, scope); expressions.Add(Expression.Dynamic(scope.GetRuntime().SetMemberBinders.Get(name), typeof(object), temp, expression)); } } expressions.Add(temp); return Expression.Block(expressions); }
public static Expression CompileValue(Value node, Scope scope) { var curExpr = Compile(node.Base, scope); foreach (var name in CompileToNames(node.Properties)) { curExpr = Expression.Dynamic(scope.GetRuntime().GetMemberBinders.Get(name), typeof (object), curExpr ); } Helper.IsNotNull(curExpr); return curExpr; }
public static Expression CompileOp(Op op, Scope scope) { var ischain = op.IsChainable && op.First is Op && ((Op)op.First).IsChainable; if (op.Second == null) return CompileUnary(op, scope); if (ischain) return CompileChain(op, scope); if (op.Operator == "?") return CompileExistence(op, scope); var first = Compile(op.First, scope); var second = Compile(op.Second, scope); var operation = GetExpressionType(op.Operator); return Expression.Dynamic( scope.GetRuntime().BinaryOperationBinders.Get(operation), typeof(object), first, second ); }
public static Expression CompileChain(Op op, Scope scope) { //for a chain we need to convert the second param of the first to a local. then we can do two comparisons and merge them with && var first = op.First as Op; var refName = scope.FreeVariableName("ref"); first.Second = first.Second.Cache(refName); var fst = Compile(first, scope); var scd = Compile(new Op {First = first.Second, Second = op.Second, Operator = op.Operator}, scope); return Expression.Dynamic( scope.GetRuntime().BinaryOperationBinders.Get(ExpressionType.And), typeof (object), fst, scd); }
public static Expression CompileCall(Call node, Scope scope) { var args = new List<Expression>(); args.AddRange(node.Arguments.Select(arg => Compile(arg, scope))); return GetMemberInvocaton(node.Variable, scope, (memberObject, name) => { args.Insert(0, memberObject); return Expression.Dynamic(scope.GetRuntime().InvokeMemberBinders.Get(new InvokeMemberBinderKey(name, new CallInfo(node.Arguments.Count))), typeof(object), args); }, (memberObject) => { args.Insert(0, memberObject); return Expression.Dynamic(scope.GetRuntime().InvokeBinders.Get(new CallInfo(node.Arguments.Count)), typeof (object), args); }); }
public static Expression CompileAssign(Assign node, Scope scope) { var variable = node.Variable as Value; var value = node.Value; if (variable != null) { if (variable.IsObject) { var obj = variable.Base as Obj; return CompileObjectAssignment(obj, value, scope); } if (!node.Variable.IsAssignable) throw new InvalidOperationException("Variable is not assignable"); if (!variable.HasProperties) { foreach(var name in CompileToNames(variable)) scope.Add(name, VariableType.Variable); } } var right = Compile(value, scope); return GetMemberInvocaton(node.Variable, scope, (memberObject, name) => Expression.Dynamic(scope.GetRuntime().SetMemberBinders.Get(name), typeof (object), memberObject, right), (memberObject) => Expression.Assign(memberObject, right)); }