コード例 #1
0
 protected void AddRestrictions(DynamicMetaObject[] args)
 {
     foreach (var arg in args)
     {
         if (arg.Restrictions != BindingRestrictions.Empty)
         {
             AddRestriction(arg.Restrictions);
         }
         else
         {
             // Runtime check!
             AddRestriction(
                 BindingRestrictions.GetExpressionRestriction(NovaExpression.Binary(arg.Expression,
                                                                                    Expression.Constant(arg.Value), ExpressionType.Equal)));
         }
     }
 }
コード例 #2
0
        internal static dynamic Assign(VariableExpression @var, dynamic value, E type, bool isConst, object rawScope)
        {
            var scope = (NovaScope)rawScope;
            var map   = new Dictionary <ExpressionType, ExpressionType>();

            map[E.AddAssign]         = E.Add;
            map[E.AndAssign]         = E.And;
            map[E.DivideAssign]      = E.Divide;
            map[E.ExclusiveOrAssign] = E.ExclusiveOr;
            map[E.LeftShiftAssign]   = E.LeftShift;
            map[E.ModuloAssign]      = E.Modulo;
            map[E.MultiplyAssign]    = E.Multiply;
            map[E.OrAssign]          = E.Or;
            map[E.PowerAssign]       = E.Power;
            map[E.RightShiftAssign]  = E.RightShift;
            map[E.SubtractAssign]    = E.Subtract;

            var incDecMap = new List <ExpressionType> {
                E.PreIncrementAssign,
                E.PreDecrementAssign,
                E.PostIncrementAssign,
                E.PostDecrementAssign
            };

            if (@var.Name is InstanceReferenceExpression)
            {
                var iref = CompilerServices.CompileExpression(@var.Name as InstanceReferenceExpression, scope);
                var lval = CompilerServices.CompileExpression(iref.LValue, scope);
                if (map.ContainsKey(type))
                {
                    value =
                        CompilerServices.CreateLambdaForExpression(
                            NovaExpression.Binary(
                                Expression.Constant(Resolve(CompilerServices.CompileExpression(iref, scope), scope)),
                                Expression.Constant(value), map[type]))();
                }
                if (incDecMap.Contains(type))
                {
                    var gmArgs = new List <Expression>();
                    gmArgs.Add(Expression.Constant(lval, typeof(object)));
                    if (type == E.PreIncrementAssign || type == E.PreDecrementAssign)
                    {
                        var val = Resolve(CompilerServices.CompileExpression(iref, scope), scope);
                        Assign(@var, 1, type == E.PreIncrementAssign ? E.AddAssign : E.SubtractAssign, false, rawScope);
                        return(val);
                    }
                    Assign(@var, 1, type == E.PostIncrementAssign ? E.AddAssign : E.SubtractAssign, false, rawScope);
                    return(Resolve(CompilerServices.CompileExpression(iref, scope), scope));
                }

                var smArgs = new List <Expression>();
                smArgs.Add(Expression.Constant(lval, typeof(object)));
                smArgs.Add(Expression.Constant(value, typeof(object)));
                return(Dynamic(typeof(object), new InteropBinder.SetMember(iref.Key, scope), smArgs));
            }
            if (@var.HasSym)
            {
                var sym = @var.Sym;

                var symFound = false;
                while (scope.ParentScope != null)
                {
                    scope = scope.ParentScope;
                    if (scope[sym] != null)
                    {
                        symFound = true;
                        break;
                    }
                }
                if (!symFound)
                {
                    scope = (NovaScope)rawScope;
                }

                if (map.ContainsKey(type))
                {
                    var nvalue =
                        CompilerServices.CreateLambdaForExpression(
                            NovaExpression.Binary(Expression.Constant(ResolveSymbol(sym, scope)),
                                                  Expression.Constant(value), map[type]))();
                    scope[sym] = nvalue;
                    return(nvalue);
                }

                if (incDecMap.Contains(type))
                {
                    if (type == E.PreIncrementAssign || type == E.PreDecrementAssign)
                    {
                        var val = ResolveSymbol(sym, scope);
                        Assign(@var, 1, type == E.PreIncrementAssign ? E.AddAssign : E.SubtractAssign, false, rawScope);
                        return(val);
                    }
                    Assign(@var, 1, type == E.PostIncrementAssign ? E.AddAssign : E.SubtractAssign, false, rawScope);
                    return(ResolveSymbol(sym, scope));
                }

                scope[sym] = value;
                if (isConst)
                {
                    scope.Constants.Add(sym.Name);
                }
                return(value);
            }
            string name = CompilerServices.CompileExpression(@var.Name, scope);

            if (name.StartsWith("$") && name != "$:")
            {
                scope = scope.GlobalScope;
                name  = name.Substring(1);
            }
            var found = false;

            if (name.StartsWith("@"))
            {
                if (scope["<nova_context_invokemember>"] != null)
                {
                    var ivar =
                        NovaExpression.Variable(
                            NovaExpression.InstanceRef(NovaExpression.Variable(Expression.Constant("self")),
                                                       Expression.Constant(name.Substring(1))));
                    if (map.ContainsKey(type))
                    {
                        value =
                            CompilerServices.CreateLambdaForExpression(
                                NovaExpression.Binary(ivar, Expression.Constant(value), map[type]))();
                    }
                    var assn = NovaExpression.Assign(NovaExpression.LeftHandValue(ivar), Expression.Constant(value));
                    return(CompilerServices.CompileExpression(assn, scope));
                }
                found = true;
                name  = name.Substring(1);
            }
            if (name == "self")
            {
                if (scope["<nova_context_selfname>"] != null &&
                    scope["<nova_context_selfscope>"] != null &&
                    scope["<nova_context_invokemember>"] != null)
                {
                    name  = scope["<nova_context_selfname>"];
                    scope = scope["<nova_context_selfscope>"];
                    found = true;
                }
            }
            while (scope.ParentScope != null && !found)
            {
                scope = scope.ParentScope;
                if (scope[name] != null)
                {
                    found = true;
                    break;
                }
            }
            if (!found)
            {
                scope = (NovaScope)rawScope;
            }

            if (map.ContainsKey(type))
            {
                var nvalue =
                    CompilerServices.CreateLambdaForExpression(
                        NovaExpression.Binary(Expression.Constant(Resolve(name, scope)), Expression.Constant(value),
                                              map[type]))();
                scope[name] = nvalue;
                return(nvalue);
            }

            if (incDecMap.Contains(type))
            {
                if (type == E.PostIncrementAssign || type == E.PostDecrementAssign)
                {
                    var val = Resolve(name, scope);
                    Assign(@var, 1, type == E.PostIncrementAssign ? E.AddAssign : E.SubtractAssign, false, rawScope);
                    return(val);
                }
                Assign(@var, 1, type == E.PreIncrementAssign ? E.AddAssign : E.SubtractAssign, false, rawScope);
                return(Resolve(name, scope));
            }

            scope[name] = value;
            if (isConst)
            {
                scope.Constants.Add(name);
            }
            return(value);
        }
コード例 #3
0
        internal static dynamic AccessSet(object container, List <FunctionArgument> args, object value, E type,
                                          object rawScope)
        {
            var map = new Dictionary <ExpressionType, ExpressionType>();

            map[E.AddAssign]         = E.Add;
            map[E.AndAssign]         = E.And;
            map[E.DivideAssign]      = E.Divide;
            map[E.ExclusiveOrAssign] = E.ExclusiveOr;
            map[E.LeftShiftAssign]   = E.LeftShift;
            map[E.ModuloAssign]      = E.Modulo;
            map[E.MultiplyAssign]    = E.Multiply;
            map[E.OrAssign]          = E.Or;
            map[E.PowerAssign]       = E.Power;
            map[E.RightShiftAssign]  = E.RightShift;
            map[E.SubtractAssign]    = E.Subtract;

            var incDecMap = new List <ExpressionType> {
                E.PreIncrementAssign,
                E.PreDecrementAssign,
                E.PostIncrementAssign,
                E.PostDecrementAssign
            };

            var names = new List <string>();

            for (var i = 0; i < args.Count; i++)
            {
                names.Add(string.Format("index{0}", i));
            }

            var scope    = rawScope as NovaScope;
            var realArgs = new List <object>();

            args.ForEach(arg => realArgs.Add(CompilerServices.CompileExpression(arg.Value, scope)));


            if (map.ContainsKey(type))
            {
                var nvalue =
                    CompilerServices.CreateLambdaForExpression(
                        NovaExpression.Binary(Expression.Constant(Access(container, args, scope)),
                                              Expression.Constant(value),
                                              map[type]))();
                value = nvalue;
            }

            if (incDecMap.Contains(type))
            {
                if (type == E.PostIncrementAssign || type == E.PostDecrementAssign)
                {
                    var val = Access(container, args, scope);
                    AccessSet(container, args, 1, type == E.PostIncrementAssign ? E.AddAssign : E.SubtractAssign,
                              rawScope);
                    return(val);
                }
                AccessSet(container, args, 1, type == E.PreIncrementAssign ? E.AddAssign : E.SubtractAssign, rawScope);
                return(Access(container, args, scope));
            }

            var eArgs = new List <Expression>();

            eArgs.Add(Expression.Constant(container, typeof(object)));
            realArgs.ForEach(arg => eArgs.Add(Expression.Constant(arg)));
            eArgs.Add(Expression.Constant(value, typeof(object)));
            return(Dynamic(typeof(object),
                           new InteropBinder.SetIndex(scope, new CallInfo(args.Count, names)), eArgs));
        }