Пример #1
0
            public override DynamicMetaObject BindDeleteMember(DeleteMemberBinder binder)
            {
                ContractUtils.RequiresNotNull(binder, nameof(binder));

                // Value can be null, let it true if it is
                var index = Value !.Class.GetValueIndex(binder.Name, binder.IgnoreCase, Value);

                Expression tryDelete = Expression.Call
                                       (
                    _expandoTryDeleteValue,
                    GetLimitedSelf(),
                    Expression.Constant(Value.Class, typeof(object)),
                    AstUtils.Constant(index),
                    Expression.Constant(binder.Name),
                    AstUtils.Constant(binder.IgnoreCase)
                                       );
                var fallback = binder.FallbackDeleteMember(this);

                var target = new DynamicMetaObject
                             (
                    Expression.IfThen(Expression.Not(tryDelete), fallback.Expression),
                    fallback.Restrictions
                             );

                return(AddDynamicTestAndDefer(binder, Value.Class, null, target));
            }
Пример #2
0
            public override DynamicMetaObject BindSetMember(SetMemberBinder binder, DynamicMetaObject value)
            {
                ArgumentNullException.ThrowIfNull(binder);
                ArgumentNullException.ThrowIfNull(value);

                ExpandoClass klass;
                int          index;

                ExpandoClass?originalClass = GetClassEnsureIndex(binder.Name, binder.IgnoreCase, Value, out klass, out index);

                return(AddDynamicTestAndDefer(
                           binder,
                           klass,
                           originalClass,
                           new DynamicMetaObject(
                               Expression.Call(
                                   s_expandoTrySetValue,
                                   GetLimitedSelf(),
                                   Expression.Constant(klass, typeof(object)),
                                   AstUtils.Constant(index),
                                   Expression.Convert(value.Expression, typeof(object)),
                                   Expression.Constant(binder.Name),
                                   AstUtils.Constant(binder.IgnoreCase)
                                   ),
                               BindingRestrictions.Empty
                               )
                           ));
            }
Пример #3
0
            public override DynamicMetaObject BindSetMember(SetMemberBinder binder, DynamicMetaObject value)
            {
                ContractUtils.RequiresNotNull(binder, nameof(binder));
                ContractUtils.RequiresNotNull(value, nameof(value));

                var originalClass = GetClassEnsureIndex(binder.Name, binder.IgnoreCase, Value !, out var @class, out var index);

                return(AddDynamicTestAndDefer
                       (
                           binder,
                           @class,
                           originalClass,
                           new DynamicMetaObject
                           (
                               Expression.Call
                               (
                                   _expandoTrySetValue,
                                   GetLimitedSelf(),
                                   Expression.Constant(@class, typeof(object)),
                                   AstUtils.Constant(index),
                                   Expression.Convert(value.Expression, typeof(object)),
                                   Expression.Constant(binder.Name),
                                   AstUtils.Constant(binder.IgnoreCase)
                               ),
                               BindingRestrictions.Empty
                           )
                       ));
            }
Пример #4
0
            private DynamicMetaObject BindGetOrInvokeMember(DynamicMetaObjectBinder binder, string name, bool ignoreCase, DynamicMetaObject fallback, Func <DynamicMetaObject, DynamicMetaObject>?fallbackInvoke)
            {
                // Value can be null, let it true if it is
                var @class = Value !.Class;

                //try to find the member, including the deleted members
                var index = @class.GetValueIndex(name, ignoreCase, Value);

                var value = Expression.Parameter(typeof(object), "value");

                Expression tryGetValue = Expression.Call
                                         (
                    _expandoTryGetValue,
                    GetLimitedSelf(),
                    Expression.Constant(@class, typeof(object)),
                    AstUtils.Constant(index),
                    Expression.Constant(name),
                    AstUtils.Constant(ignoreCase),
                    value
                                         );

                var result = new DynamicMetaObject(value, BindingRestrictions.Empty);

                if (fallbackInvoke != null)
                {
                    result = fallbackInvoke(result);
                }

                result = new DynamicMetaObject
                         (
                    Expression.Block
                    (
                        ReadOnlyCollectionEx.Create(value),
                        ReadOnlyCollectionEx.Create <Expression>
                        (
                            Expression.Condition
                            (
                                tryGetValue,
                                result.Expression,
                                fallback.Expression,
                                typeof(object)
                            )
                        )
                    ),
                    result.Restrictions.Merge(fallback.Restrictions)
                         );

                return(AddDynamicTestAndDefer(binder, Value.Class, null, result));
            }
Пример #5
0
            private DynamicMetaObject BindGetOrInvokeMember(DynamicMetaObjectBinder binder, string name, bool ignoreCase, DynamicMetaObject fallback, Func <DynamicMetaObject, DynamicMetaObject> fallbackInvoke)
            {
                ExpandoClass klass = Value.Class;

                //try to find the member, including the deleted members
                int index = klass.GetValueIndex(name, ignoreCase, Value);

                ParameterExpression value = Expression.Parameter(typeof(object), "value");

                Expression tryGetValue = Expression.Call(
                    typeof(RuntimeOps).GetMethod(nameof(RuntimeOps.ExpandoTryGetValue)),
                    GetLimitedSelf(),
                    Expression.Constant(klass, typeof(object)),
                    AstUtils.Constant(index),
                    Expression.Constant(name),
                    AstUtils.Constant(ignoreCase),
                    value
                    );

                var result = new DynamicMetaObject(value, BindingRestrictions.Empty);

                if (fallbackInvoke != null)
                {
                    result = fallbackInvoke(result);
                }

                result = new DynamicMetaObject(
                    Expression.Block(
                        new TrueReadOnlyCollection <ParameterExpression>(value),
                        Expression.Condition(
                            tryGetValue,
                            result.Expression,
                            fallback.Expression,
                            typeof(object)
                            )
                        ),
                    result.Restrictions.Merge(fallback.Restrictions)
                    );

                return(AddDynamicTestAndDefer(binder, Value.Class, null, result));
            }
Пример #6
0
            /// <summary>
            /// Helper method for generating expressions that assign byRef call
            /// parameters back to their original variables.
            /// </summary>
            private static Expression ReferenceArgAssign(Expression callArgs, Expression[] args)
            {
                ReadOnlyCollectionBuilder <Expression> block = null;

                for (int i = 0; i < args.Length; i++)
                {
                    ParameterExpression variable = args[i] as ParameterExpression;
                    ContractUtils.Requires(variable != null, nameof(args));

                    if (variable.IsByRef)
                    {
                        if (block == null)
                        {
                            block = new ReadOnlyCollectionBuilder <Expression>();
                        }

                        block.Add(
                            Expression.Assign(
                                variable,
                                Expression.Convert(
                                    Expression.ArrayIndex(
                                        callArgs,
                                        AstUtils.Constant(i)
                                        ),
                                    variable.Type
                                    )
                                )
                            );
                    }
                }

                if (block != null)
                {
                    return(Expression.Block(block));
                }
                else
                {
                    return(AstUtils.Empty);
                }
            }
Пример #7
0
            private static Expression ReferenceArgAssign(Expression callArgs, Expression[] args)
            {
                ReadOnlyCollectionBuilder <Expression> block = null;

                for (var i = 0; i < args.Length; i++)
                {
                    var variable = args[i] as ParameterExpression;
                    if (variable == null && variable == null)
                    {
                        throw new ArgumentException("Invalid argument value", nameof(args));
                    }

                    if (variable.IsByRef)
                    {
                        (block ?? (block = new ReadOnlyCollectionBuilder <Expression>())).Add
                        (
                            Expression.Assign
                            (
                                variable,
                                Expression.Convert
                                (
                                    Expression.ArrayIndex
                                    (
                                        callArgs,
                                        AstUtils.Constant(i)
                                    ),
                                    variable.Type
                                )
                            )
                        );
                    }
                }

                if (block != null)
                {
                    return(Expression.Block(block));
                }

                return(AstUtils.Empty);
            }
Пример #8
0
            public override DynamicMetaObject BindDeleteMember(DeleteMemberBinder binder)
            {
                ArgumentNullException.ThrowIfNull(binder);

                int index = Value.Class.GetValueIndex(binder.Name, binder.IgnoreCase, Value);

                Expression tryDelete = Expression.Call(
                    s_expandoTryDeleteValue,
                    GetLimitedSelf(),
                    Expression.Constant(Value.Class, typeof(object)),
                    AstUtils.Constant(index),
                    Expression.Constant(binder.Name),
                    AstUtils.Constant(binder.IgnoreCase)
                    );
                DynamicMetaObject fallback = binder.FallbackDeleteMember(this);

                DynamicMetaObject target = new DynamicMetaObject(
                    Expression.IfThen(Expression.Not(tryDelete), fallback.Expression),
                    fallback.Restrictions
                    );

                return(AddDynamicTestAndDefer(binder, Value.Class, null, target));
            }
Пример #9
0
            public override DynamicMetaObject BindDeleteMember(DeleteMemberBinder binder)
            {
                ContractUtils.RequiresNotNull(binder, nameof(binder));

                int index = Value.Class.GetValueIndex(binder.Name, binder.IgnoreCase, Value);

                Expression tryDelete = Expression.Call(
                    typeof(RuntimeOps).GetMethod(nameof(RuntimeOps.ExpandoTryDeleteValue)),
                    GetLimitedSelf(),
                    Expression.Constant(Value.Class, typeof(object)),
                    AstUtils.Constant(index),
                    Expression.Constant(binder.Name),
                    AstUtils.Constant(binder.IgnoreCase)
                    );
                DynamicMetaObject fallback = binder.FallbackDeleteMember(this);

                DynamicMetaObject target = new DynamicMetaObject(
                    Expression.IfThen(Expression.Not(tryDelete), fallback.Expression),
                    fallback.Restrictions
                    );

                return(AddDynamicTestAndDefer(binder, Value.Class, null, target));
            }
Пример #10
0
        /// <summary>
        /// Creates the <see cref="Expression"/> representing the binding restrictions.
        /// </summary>
        /// <returns>The expression tree representing the restrictions.</returns>
        public Expression ToExpression()
        {
            // We could optimize this better, e.g. common subexpression elimination
            // But for now, it's good enough.

            if (this == Empty)
            {
                return(AstUtils.Constant(true));
            }

            var testBuilder = new TestBuilder();

            // Visit the tree, left to right.
            // Use an explicit stack so we don't stack overflow.
            //
            // Left-most node is on top of the stack, so we always expand the
            // left most node each iteration.
            var stack = new Stack <BindingRestrictions>();

            stack.Push(this);
            do
            {
                var top = stack.Pop();
                var m   = top as MergedRestriction;
                if (m != null)
                {
                    stack.Push(m.Right);
                    stack.Push(m.Left);
                }
                else
                {
                    testBuilder.Append(top);
                }
            } while (stack.Count > 0);

            return(testBuilder.ToExpression());
        }
Пример #11
0
        //TODO enable sharing of these custom delegates
        private Delegate CreateCustomDelegate(Type delegateType)
        {
            //PerfTrack.NoteEvent(PerfTrack.Categories.Compiler, "Synchronously compiling a custom delegate");

            var  method             = delegateType.GetMethod("Invoke");
            var  paramInfos         = method.GetParameters();
            var  parameters         = new ParameterExpression[paramInfos.Length];
            var  parametersAsObject = new Expression[paramInfos.Length];
            bool hasByRef           = false;

            for (int i = 0; i < paramInfos.Length; i++)
            {
                ParameterExpression parameter = Expression.Parameter(paramInfos[i].ParameterType, paramInfos[i].Name);
                hasByRef              = hasByRef || paramInfos[i].ParameterType.IsByRef;
                parameters[i]         = parameter;
                parametersAsObject[i] = Expression.Convert(parameter, typeof(object));
            }

            var data = Expression.NewArrayInit(typeof(object), parametersAsObject);
            var dlg  = new Func <object[], object>(Run);

            var dlgExpr = AstUtils.Constant(dlg);


            var argsParam = Expression.Parameter(typeof(object[]), "$args");

            Expression body;

            if (method.ReturnType == typeof(void))
            {
                body = Expression.Block(typeof(void), Expression.Invoke(dlgExpr, argsParam));
            }
            else
            {
                body = Expression.Convert(Expression.Invoke(dlgExpr, argsParam), method.ReturnType);
            }


            if (hasByRef)
            {
                List <Expression> updates = new List <Expression>();
                for (int i = 0; i < paramInfos.Length; i++)
                {
                    if (paramInfos[i].ParameterType.IsByRef)
                    {
                        updates.Add(
                            Expression.Assign(
                                parameters[i],
                                Expression.Convert(
                                    Expression.ArrayAccess(argsParam, Expression.Constant(i)),
                                    paramInfos[i].ParameterType.GetElementType()
                                    )
                                )
                            );
                    }
                }

                body = Expression.TryFinally(body, Expression.Block(typeof(void), updates));
            }

            body = Expression.Block(
                method.ReturnType,
                new[] { argsParam },
                Expression.Assign(argsParam, data),
                body
                );

            var lambda = Expression.Lambda(delegateType, body, parameters);

            //return System.Linq.Expressions.Compiler.LambdaCompiler.Compile(lambda, null);
            throw new NotImplementedException("byref delegate");
        }