public override DynamicMetaObject FallbackDeleteMember(DynamicMetaObject self, DynamicMetaObject errorSuggestion) {
            if (self.NeedsDeferral()) {
                return Defer(self);
            }

            return Binder.Binder.DeleteMember(Name, self, AstUtils.Constant(Binder.Context));
        }
 protected override DynamicMetaObject SetBoundValue(OverloadResolverFactory factory, ActionBinder binder, Type type, DynamicMetaObject value, DynamicMetaObject instance, DynamicMetaObject errorSuggestion) {
     return new DynamicMetaObject(
         Expression.Condition(
             Ast.Call(
                 typeof(PythonOps).GetMethod("SlotTrySetValue"),
                 ((PythonOverloadResolverFactory)factory)._codeContext,
                 AstUtils.Constant(GetSlot(), typeof(PythonTypeSlot)),
                 AstUtils.Convert(
                     instance.Expression,
                     typeof(object)
                 ),
                 AstUtils.Constant(DynamicHelpers.GetPythonTypeFromType(type)),
                 value.Expression
             ),
             AstUtils.Convert(value.Expression, typeof(object)),
             errorSuggestion != null ?
                 errorSuggestion.Expression :
                 Expression.Throw(
                     Expression.Call(
                         typeof(PythonOps).GetMethod("AttributeErrorForMissingAttribute", new Type[] { typeof(object), typeof(string) }),
                         instance.Expression,
                         Expression.Constant(Name)
                     ),
                     typeof(object)
                 )
         ),
         BindingRestrictions.Empty
     );
 }
示例#3
0
        public override DynamicMetaObject FallbackBinaryOperation(
            DynamicMetaObject target,
            DynamicMetaObject arg,
            DynamicMetaObject errorSuggestion)
        {
            DynamicMetaObject left = target;
            DynamicMetaObject right = arg;

            if (Operation != ExpressionType.LessThan)
                throw new NotImplementedException();

            if (left.LimitType != right.LimitType)
            {
                throw new Exception(String.Format(
                    "attempt to compare {0} with {1}",
                    left.LimitType.Name, right.LimitType.Name));
            }

            if (left.LimitType != typeof(string) &&
                left.LimitType != typeof(double))
            {
                throw new Exception(String.Format(
                    "attempt to compare two {0} values",
                    left.LimitType.Name));
            }

            return _binder.DoOperation(Operation, left, right);
        }
示例#4
0
        public override DynamicMetaObject/*!*/ BindInvokeMember(InvokeMemberBinder/*!*/ action, DynamicMetaObject/*!*/[]/*!*/ args) {
            DynamicMetaObject errorSuggestion = null;
            if (_baseMetaObject != null) {
                errorSuggestion = _baseMetaObject.BindInvokeMember(action, args);
            }
            
            CodeContext context = BinderState.GetBinderState(action).Context;
            IPythonObject sdo = Value;
            PythonTypeSlot foundSlot;

            if (TryGetGetAttribute(context, sdo.PythonType, out foundSlot)) {
                // we'll always fetch the value, go ahead and invoke afterwards.
                return BindingHelpers.GenericCall(action, this, args);
            }

            bool isOldStyle;
            bool systemTypeResolution;
            foundSlot = FindSlot(context, action.Name, sdo, out isOldStyle, out systemTypeResolution);
            if (foundSlot != null && !systemTypeResolution) {
                // we found the member in the type dictionary, not a .NET type, go ahead and
                // do the get & invoke.
                return BindingHelpers.GenericCall(action, this, args);
            }

            // it's a normal .NET member, let the calling language handle it how it usually does
            return action.FallbackInvokeMember(this, args, errorSuggestion);
        }
示例#5
0
        public static bool TryBindGetMember(GetMemberBinder binder, DynamicMetaObject instance, out DynamicMetaObject result, bool delayInvocation) {
            ContractUtils.RequiresNotNull(binder, "binder");
            ContractUtils.RequiresNotNull(instance, "instance");

            if (TryGetMetaObject(ref instance)) {
                //
                // Demand Full Trust to proceed with the binding.
                //

                new PermissionSet(PermissionState.Unrestricted).Demand();

                var comGetMember = new ComGetMemberBinder(binder, delayInvocation);
                result = instance.BindGetMember(comGetMember);
                if (result.Expression.Type.IsValueType) {
                    result = new DynamicMetaObject(
                        Expression.Convert(result.Expression, typeof(object)),
                        result.Restrictions
                    );
                }
                return true;
            } else {
                result = null;
                return false;
            }
        }
示例#6
0
        public static DynamicMetaObject BindCatchAllPrimitive(DynamicMetaObject target, DynamicMetaObject[] args, Type returnType)
        {
            var method = typeof(BonsaiPrimitives).GetMethodsWith<CatchAllPrimitiveAttribute>(
                (mi, capi) =>
                       capi.Type == null || (
                           target.LimitType.IsAssignableFrom(capi.Type) || (
                               capi.Type.IsGenericTypeDefinition &&
                               target.LimitType.IsGenericType &&
                               capi.Type.GetGenericArguments().Length == target.LimitType.GetGenericArguments().Length &&
                               capi.Type.MakeGenericType(target.LimitType.GetGenericArguments()).IsAssignableFrom(target.LimitType))))
                .FirstOrDefault();

            // assume that if the method is generic than the matched type is also generic and it gets the same parameters
            if (method != null && method.IsGenericMethodDefinition)
                method = method.MakeGenericMethod(target.LimitType.GetGenericArguments());

            if (method != null) {
                return new DynamicMetaObject(
                       Expression.Convert(
                           Expression.Call(
                               null,
                               method,
                               new Expression[] {
                                    Expression.Convert(target.Expression, method.GetParameters()[0].ParameterType),
                                    args[0].Expression,
                                    Expression.NewArrayInit(
                                        typeof(object),
                                        args.Subarray(1).Select(a => Expression.Convert(a.Expression, typeof(object))))
                                }),
                           returnType),
                       BindingRestrictions.GetTypeRestriction(target.Expression, target.Value.GetType()));
            } else {
                throw new Exception("Binding failed");
            }
        }
        public override DynamicMetaObject FallbackDeleteMember(DynamicMetaObject self, DynamicMetaObject errorSuggestion) {
            if (self.NeedsDeferral()) {
                return Defer(self);
            }

            return Context.Binder.DeleteMember(Name, self, new PythonOverloadResolverFactory(_context.Binder, AstUtils.Constant(Context.SharedContext)));
        }
        public override DynamicMetaObject BindSetIndex(SetIndexBinder binder, DynamicMetaObject[] indexes, DynamicMetaObject value) {
            //
            // Demand Full Trust to proceed with the binding.
            //

            new PermissionSet(PermissionState.Unrestricted).Demand();

            ComMethodDesc method;
            var target = _callable.DispatchComObject;
            var name = _callable.MemberName;

            bool holdsNull = value.Value == null && value.HasValue;
            if (target.TryGetPropertySetter(name, out method, value.LimitType, holdsNull) ||
                target.TryGetPropertySetterExplicit(name, out method, value.LimitType, holdsNull)) {

                bool[] isByRef = ComBinderHelpers.ProcessArgumentsForCom(ref indexes);
                isByRef = isByRef.AddLast(false);
                var result = BindComInvoke(method, indexes.AddLast(value), binder.CallInfo, isByRef);

                // Make sure to return the value; some languages need it.
                return new DynamicMetaObject(
                    Expression.Block(result.Expression, Expression.Convert(value.Expression, typeof(object))),
                    result.Restrictions
                );
            }

            return base.BindSetIndex(binder, indexes, value);
        }
示例#9
0
        /// <summary>
        /// Creating a standard .NET type is easy - we just call it's constructor with the provided
        /// arguments.
        /// </summary>
        private DynamicMetaObject/*!*/ MakeStandardDotNetTypeCall(DynamicMetaObjectBinder/*!*/ call, Expression/*!*/ codeContext, DynamicMetaObject/*!*/[]/*!*/ args) {
            CallSignature signature = BindingHelpers.GetCallSignature(call);
            BinderState state = BinderState.GetBinderState(call);
            MethodBase[] ctors = CompilerHelpers.GetConstructors(Value.UnderlyingSystemType, state.Binder.PrivateBinding);

            if (ctors.Length > 0) {
                return state.Binder.CallMethod(
                    new ParameterBinderWithCodeContext(state.Binder, codeContext),
                    ctors,
                    args,
                    signature,
                    Restrictions.Merge(BindingRestrictions.GetInstanceRestriction(Expression, Value))
                );
            } else {
                return new DynamicMetaObject(
                   Ast.Throw(
                       Ast.New(
                           typeof(ArgumentTypeException).GetConstructor(new Type[] { typeof(string) }),
                           Ast.Constant("Cannot create instances of " + Value.Name)
                       )
                   ),
                   Restrictions.Merge(BindingRestrictions.GetInstanceRestriction(Expression, Value))
                );
            }
        }
示例#10
0
        internal ComInvokeBinder(
                CallInfo callInfo, 
                DynamicMetaObject[] args,
                bool[] isByRef,
                BindingRestrictions restrictions, 
                Expression method, 
                Expression dispatch, 
                ComMethodDesc methodDesc
                ) {

            Debug.Assert(callInfo != null, "arguments");
            Debug.Assert(args != null, "args");
            Debug.Assert(isByRef != null, "isByRef");
            Debug.Assert(method != null, "method");
            Debug.Assert(dispatch != null, "dispatch");

            Debug.Assert(TypeUtils.AreReferenceAssignable(typeof(ComMethodDesc), method.Type), "method");
            Debug.Assert(TypeUtils.AreReferenceAssignable(typeof(IDispatch), dispatch.Type), "dispatch");

            _method = method;
            _dispatch = dispatch;
            _methodDesc = methodDesc;

            _callInfo = callInfo;
            _args = args;
            _isByRef = isByRef;
            _restrictions = restrictions;

            // Set Instance to some value so that CallBinderHelper has the right number of parameters to work with
            _instance = dispatch;
        }
示例#11
0
        public static DynamicMetaObject TryBind(RubyContext/*!*/ context, GetMemberBinder/*!*/ binder, DynamicMetaObject/*!*/ target) {
            Assert.NotNull(context, target);
            var metaBuilder = new MetaObjectBuilder();
            var contextExpression = AstUtils.Constant(context);

            RubyClass targetClass = context.GetImmediateClassOf(target.Value);
            MethodResolutionResult method;
            RubyMemberInfo methodMissing = null;

            using (targetClass.Context.ClassHierarchyLocker()) {
                metaBuilder.AddTargetTypeTest(target.Value, targetClass, target.Expression, context, contextExpression);

                method = targetClass.ResolveMethodForSiteNoLock(binder.Name, RubyClass.IgnoreVisibility);
                if (method.Found) {
                    methodMissing = targetClass.ResolveMethodForSiteNoLock(Symbols.MethodMissing, RubyClass.IgnoreVisibility).Info;
                }
            }
            
            if (method.Found) {
                // we need to create a bound member:
                metaBuilder.Result = AstUtils.Constant(new RubyMethod(target.Value, method.Info, binder.Name));
            } else {
                // TODO:
                // We need to throw an exception if we don't find method_missing so that our version update optimization works: 
                // This limits interop with other languages. 
                //                   
                // class B           CLR type with method 'foo'
                // class C < B       Ruby class
                // x = C.new
                //
                // 1. x.GET("foo") from Ruby
                //    No method found or CLR method found -> fallback to Python
                //    Python might see its method foo or might just fallback to .NET, 
                //    in any case it will add rule [1] with restriction on type of C w/o Ruby version check.
                // 2. B.define_method("foo") 
                //    This doesn't update C due to the optimization (there is no overridden method foo in C).
                // 3. x.GET("foo") from Ruby
                //    This will not invoke the binder since the rule [1] is still valid.
                //
                object symbol = SymbolTable.StringToId(binder.Name);
                RubyCallAction.BindToMethodMissing(metaBuilder, 
                    new CallArguments(
                        new DynamicMetaObject(contextExpression, BindingRestrictions.Empty, context),
                        new[] { 
                            target,
                            new DynamicMetaObject(AstUtils.Constant(symbol), BindingRestrictions.Empty, symbol) 
                        },
                        RubyCallSignature.Simple(1)
                    ),
                    binder.Name,
                    methodMissing,
                    method.IncompatibleVisibility,
                    false
                );
            }

            // TODO: we should return null if we fail, we need to throw exception for now:
            return metaBuilder.CreateMetaObject(binder, DynamicMetaObject.EmptyMetaObjects);
        }
        public DynamicMetaObject/*!*/ Invoke(PythonInvokeBinder/*!*/ pythonInvoke, Expression/*!*/ codeContext, DynamicMetaObject/*!*/ target, DynamicMetaObject/*!*/[]/*!*/ args) {
            DynamicMetaObject translated = BuiltinFunction.TranslateArguments(pythonInvoke, codeContext, target, args, false, Value.Name);
            if (translated != null) {
                return translated;
            }

            return InvokeWorker(pythonInvoke, args, codeContext);
        }
        public override DynamicMetaObject/*!*/ FallbackInvokeMember(DynamicMetaObject/*!*/ self, DynamicMetaObject/*!*/[]/*!*/ args, DynamicMetaObject/*!*/ onBindingError) {
            var result = TryBind(_context, this, self, args);
            if (result != null) {
                return result;
            }

            // TODO: return ((DefaultBinder)_context.Binder).GetMember(Name, self, Ast.Null(typeof(CodeContext)), true);
            throw new NotImplementedException();
        }
示例#14
0
        public override DynamicMetaObject/*!*/ FallbackGetMember(DynamicMetaObject/*!*/ self, DynamicMetaObject/*!*/ onBindingError) {
            var result = TryBind(_context, this, self);
            if (result != null) {
                return result; 
            }

            // TODO: remove CodeContext
            return ((DefaultBinder)_context.Binder).GetMember(Name, self, AstUtils.Constant(null, typeof(CodeContext)), true);
        }
        public override DynamicMetaObject/*!*/ FallbackCreateInstance(DynamicMetaObject/*!*/ target, DynamicMetaObject/*!*/[]/*!*/ args, DynamicMetaObject errorSuggestion) {
            var result = TryBind(_context, this, target, args);
            if (result != null) {
                return result;
            }

            throw new NotImplementedException();
            // TODO:
            //return ((DefaultBinder)_context.Binder).Create(.GetMember(Name, self, Ast.Null(typeof(CodeContext)), true);
        }
示例#16
0
        DynamicMetaObject IPythonOperable.BindOperation(PythonOperationBinder action, DynamicMetaObject[] args) {
            PerfTrack.NoteEvent(PerfTrack.Categories.Binding, "BuiltinFunc Operation " + action.Operation);
            PerfTrack.NoteEvent(PerfTrack.Categories.BindingTarget, "BuiltinFunc Operation");
            switch (action.Operation) {
                case PythonOperationKind.CallSignatures:
                    return PythonProtocol.MakeCallSignatureOperation(this, Value.Targets);
            }

            return null;
        }
示例#17
0
 public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) {
     return new DynamicMetaObject(
         Expression.Call(
             typeof(String).GetMethod("Concat", new Type[] { typeof(object), typeof(object) }),
             Expression.Constant("FallbackInvoke"),
             target.Expression
         ),
         BindingRestrictionsHelpers.GetRuntimeTypeRestriction(target)
     );
 }
        /// <summary>
        /// Performs the binding of the dynamic set member operation.
        /// </summary>
        /// <param name="target">The target of the dynamic set member operation.</param>
        /// <param name="args">An array of arguments of the dynamic set member operation.</param>
        /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
        public sealed override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObject[] args) {
            ContractUtils.RequiresNotNull(target, "target");
            ContractUtils.RequiresNotNull(args, "args");
            ContractUtils.Requires(args.Length == 1, "args");

            var arg0 = args[0];
            ContractUtils.RequiresNotNull(arg0, "args");

            return target.BindSetMember(this, arg0);
        }
示例#19
0
        public override DynamicMetaObject/*!*/ BindOperation(OperationBinder/*!*/ action, DynamicMetaObject/*!*/[]/*!*/ args) {
            switch (action.Operation) {
                case StandardOperators.CallSignatures:
                    return MakeCallSignatureRule(this);
                case StandardOperators.IsCallable:
                    return MakeIsCallableRule(this);
            }

            return base.BindOperation(action, args);
        }
示例#20
0
 public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) {
     return errorSuggestion ?? new DynamicMetaObject(
         Expression.Throw(
             Expression.New(
                 typeof(NotSupportedException).GetConstructor(new[] { typeof(string) }),
                 Expression.Constant(Strings.CannotCall)
             )
         ),
         target.Restrictions.Merge(BindingRestrictions.Combine(args))
     );
 }
示例#21
0
        /// <summary>
        /// Python's Invoke is a non-standard action.  Here we first try to bind through a Python
        /// internal interface (IPythonInvokable) which supports CallSigantures.  If that fails
        /// and we have an IDO then we translate to the DLR protocol through a nested dynamic site -
        /// this includes unsplatting any keyword / position arguments.  Finally if it's just a plain
        /// old .NET type we use the default binder which supports CallSignatures.
        /// </summary>
        public override DynamicMetaObject/*!*/ Bind(DynamicMetaObject/*!*/ target, DynamicMetaObject/*!*/[]/*!*/ args) {
            Debug.Assert(args.Length > 0);

            DynamicMetaObject cc = target;
            DynamicMetaObject actualTarget = args[0];
            args = ArrayUtils.RemoveFirst(args);

            Debug.Assert(cc.GetLimitType() == typeof(CodeContext));

            return BindWorker(cc, actualTarget, args);
        }
        public static DynamicMetaObject/*!*/ Operation(BinaryOperationBinder/*!*/ operation, DynamicMetaObject target, DynamicMetaObject arg, DynamicMetaObject errorSuggestion) {
            PerfTrack.NoteEvent(PerfTrack.Categories.Binding, "Fallback BinaryOperator " + target.LimitType.FullName + " " + operation.Operation + " " + arg.LimitType.FullName);
            PerfTrack.NoteEvent(PerfTrack.Categories.BindingTarget, operation.Operation.ToString());

            DynamicMetaObject[] args = new[] { target, arg };
            if (BindingHelpers.NeedsDeferral(args)) {
                return operation.Defer(target, arg);
            }

            ValidationInfo valInfo = BindingHelpers.GetValidationInfo(args);

            PythonOperationKind? pyOperator = null;
            switch (operation.Operation) {
                case ExpressionType.Add: pyOperator = PythonOperationKind.Add; break;
                case ExpressionType.And: pyOperator = PythonOperationKind.BitwiseAnd; break;
                case ExpressionType.Divide: pyOperator = PythonOperationKind.Divide; break;
                case ExpressionType.ExclusiveOr: pyOperator = PythonOperationKind.ExclusiveOr; break;
                case ExpressionType.Modulo: pyOperator = PythonOperationKind.Mod; break;
                case ExpressionType.Multiply: pyOperator = PythonOperationKind.Multiply; break;
                case ExpressionType.Or: pyOperator = PythonOperationKind.BitwiseOr; break;
                case ExpressionType.Power: pyOperator = PythonOperationKind.Power; break;
                case ExpressionType.RightShift: pyOperator = PythonOperationKind.RightShift; break;
                case ExpressionType.LeftShift: pyOperator = PythonOperationKind.LeftShift; break;
                case ExpressionType.Subtract: pyOperator = PythonOperationKind.Subtract; break;

                case ExpressionType.AddAssign: pyOperator = PythonOperationKind.InPlaceAdd; break;
                case ExpressionType.AndAssign: pyOperator = PythonOperationKind.InPlaceBitwiseAnd; break;
                case ExpressionType.DivideAssign: pyOperator = PythonOperationKind.InPlaceDivide; break;
                case ExpressionType.ExclusiveOrAssign: pyOperator = PythonOperationKind.InPlaceExclusiveOr; break;
                case ExpressionType.ModuloAssign: pyOperator = PythonOperationKind.InPlaceMod; break;
                case ExpressionType.MultiplyAssign: pyOperator = PythonOperationKind.InPlaceMultiply; break;
                case ExpressionType.OrAssign: pyOperator = PythonOperationKind.InPlaceBitwiseOr; break;
                case ExpressionType.PowerAssign: pyOperator = PythonOperationKind.InPlacePower; break;
                case ExpressionType.RightShiftAssign: pyOperator = PythonOperationKind.InPlaceRightShift; break;
                case ExpressionType.LeftShiftAssign: pyOperator = PythonOperationKind.InPlaceLeftShift; break;
                case ExpressionType.SubtractAssign: pyOperator = PythonOperationKind.InPlaceSubtract; break;

                case ExpressionType.Equal: pyOperator = PythonOperationKind.Equal; break;
                case ExpressionType.GreaterThan: pyOperator = PythonOperationKind.GreaterThan; break;
                case ExpressionType.GreaterThanOrEqual: pyOperator = PythonOperationKind.GreaterThanOrEqual; break;
                case ExpressionType.LessThan: pyOperator = PythonOperationKind.LessThan; break;
                case ExpressionType.LessThanOrEqual: pyOperator = PythonOperationKind.LessThanOrEqual; break;
                case ExpressionType.NotEqual: pyOperator = PythonOperationKind.NotEqual; break;
            }

            DynamicMetaObject res = null;
            if (pyOperator != null) {
                res = MakeBinaryOperation(operation, args, pyOperator.Value, errorSuggestion);
            } else {
                res = operation.FallbackBinaryOperation(target, arg);
            }

            return BindingHelpers.AddDynamicTestAndDefer(operation, BindingHelpers.AddPythonBoxing(res), args, valInfo);
        }
        public override DynamicMetaObject BindInvoke(InvokeBinder binder, DynamicMetaObject[] args) {
            ContractUtils.RequiresNotNull(binder, "binder");

            ComMethodDesc method;
            if (_self.TryGetGetItem(out method)) {

                bool[] isByRef = ComBinderHelpers.ProcessArgumentsForCom(ref args);
                return BindComInvoke(args, method, binder.CallInfo, isByRef);
            }

            return base.BindInvoke(binder, args);
        }
示例#24
0
        // Ruby binders:
        internal CallArguments(RubyContext context, DynamicMetaObject/*!*/ scopeOrContextOrTargetOrArgArray, DynamicMetaObject/*!*/[]/*!*/ args, RubyCallSignature signature)
        {
            Assert.NotNull(scopeOrContextOrTargetOrArgArray);
            Assert.NotNullItems(args);

            ArgumentArray argArray = scopeOrContextOrTargetOrArgArray.Value as ArgumentArray;
            if (argArray != null) {
                Debug.Assert(args.Length == 0 && argArray.Count >= 1);

                // build meta-objects for arguments wrapped in the array:
                args = new DynamicMetaObject[argArray.Count - 1];
                for (int i = 0; i < args.Length; i++) {
                    args[i] = argArray.GetMetaObject(scopeOrContextOrTargetOrArgArray.Expression, 1 + i);
                }
                scopeOrContextOrTargetOrArgArray = argArray.GetMetaObject(scopeOrContextOrTargetOrArgArray.Expression, 0);
            }

            Debug.Assert(signature.HasScope == scopeOrContextOrTargetOrArgArray.Value is RubyScope);
            Debug.Assert((context == null && !signature.HasScope) == scopeOrContextOrTargetOrArgArray.Value is RubyContext);

            if (context != null) {
                // bound site:
                _context = new DynamicMetaObject(AstUtils.Constant(context), BindingRestrictions.Empty, context);
                if (signature.HasScope) {
                    _scope = scopeOrContextOrTargetOrArgArray;
                    _hasScopeOrContextArg = true;
                } else {
                    _target = scopeOrContextOrTargetOrArgArray;
                }
            } else if (signature.HasScope) {
                // unbound site with scope:
                _context = new DynamicMetaObject(
                    Methods.GetContextFromScope.OpCall(scopeOrContextOrTargetOrArgArray.Expression), BindingRestrictions.Empty,
                    ((RubyScope)scopeOrContextOrTargetOrArgArray.Value).RubyContext
                );
                _scope = scopeOrContextOrTargetOrArgArray;
                _hasScopeOrContextArg = true;
                _target = null;
            } else {
                // unbound site with context:
                _context = scopeOrContextOrTargetOrArgArray;
                _hasScopeOrContextArg = true;
                _target = null;
            }

            Debug.Assert(_target != null || args.Length > 0);

            _args = args;
            _copyArgsOnWrite = true;
            _signature = signature;

            Debug.Assert(!signature.HasSplattedArgument || GetSplattedArgument() != null);
        }
示例#25
0
        public override DynamicMetaObject FallbackSetMember(DynamicMetaObject self, DynamicMetaObject value, DynamicMetaObject onBindingError) {
            if (self.NeedsDeferral()) {
                return Defer(self, value);
            }
#if !SILVERLIGHT
            DynamicMetaObject com;
            if (System.Dynamic.ComBinder.TryBindSetMember(this, self, value, out com)) {
                return com;
            }
#endif
            return Binder.Binder.SetMember(Name, self, value, Ast.Constant(Binder.Context));
        }
示例#26
0
        public override DynamicMetaObject/*!*/ Bind(DynamicMetaObject/*!*/ context, DynamicMetaObject/*!*/[]/*!*/ args) {
            var callArgs = new CallArguments(context, args, Signature);
            
            // TODO: COM interop
            if (IsForeignMetaObject(callArgs.MetaTarget)) {
                return InteropBind(callArgs);
            }

            var metaBuilder = new MetaObjectBuilder();
            Build(metaBuilder, callArgs);
            return metaBuilder.CreateMetaObject(this);
        }
        /// <summary>
        /// Performs the binding of the dynamic set index operation.
        /// </summary>
        /// <param name="target">The target of the dynamic set index operation.</param>
        /// <param name="args">An array of arguments of the dynamic set index operation.</param>
        /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
        public sealed override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObject[] args) {
            ContractUtils.RequiresNotNull(target, "target");
            ContractUtils.RequiresNotNull(args, "args");
            ContractUtils.Requires(args.Length >= 2, "args");

            DynamicMetaObject value = args[args.Length - 1];
            DynamicMetaObject[] indexes = args.RemoveLast();

            ContractUtils.RequiresNotNull(value, "args");
            ContractUtils.RequiresNotNullItems(indexes, "args");

            return target.BindSetIndex(this, indexes, value);
        }
 internal override void MakeGetExpression(PythonBinder/*!*/ binder, Expression/*!*/ codeContext, DynamicMetaObject instance, DynamicMetaObject/*!*/ owner, ConditionalBuilder/*!*/ builder) {
     if (instance != null) {
         builder.FinishCondition(
             Ast.Call(
                 typeof(PythonOps).GetMethod("MakeBoundBuiltinFunction"),
                 AstUtils.Constant(_template),
                 instance.Expression
             )
         );
     } else {
         builder.FinishCondition(AstUtils.Constant(this));
     }
 }
        public override DynamicMetaObject FallbackBinaryOperation(DynamicMetaObject target, DynamicMetaObject arg, DynamicMetaObject errorSuggestion)
        {
            if (!target.HasValue && !arg.HasValue)
                return Defer(target, arg);
            else if (!target.HasValue)
                return Defer(target);
            else if (!arg.HasValue)
                return Defer(arg);

            if (Operation == ExpressionType.GreaterThan)
            {
                return new DynamicMetaObject(
                    AstUtils.LightDynamic(
                        _context.BinaryOperation(ExpressionType.LessThan),
                        arg.Expression,
                        target.Expression
                    ),
                    BindingRestrictions.Empty
                );
            }

            if (target.Value == null)
            {
                var tNull = TotemNull.Get(_context);
                target = new DynamicMetaObject(
                    Expression.Constant(tNull, typeof(TotemNull)),
                    BindingRestrictions.GetExpressionRestriction(
                        Expression.ReferenceEqual(target.Expression, AstUtils.Constant(null))
                    ),
                    tNull
                );
            }

            var targetType = target.LimitType;
            if (target.GetType() != typeof(TotemType.MetaObject))
            {
                var type = _context.GetTypeHandler(targetType);
                if (type != null)
                {
                    return type.GetMetaObject(target.Expression, target.Restrictions, target.Value).BindBinaryOperation(this, arg);
                }
            }

            // we get the error message w/ {0}, {1} so that TypeError formats it correctly
            return errorSuggestion ?? TotemProtocol.TypeError(
                this,
                MakeBinaryOpErrorMessage(Operation, "{0}", "{1}"),
                target,
                arg
            );
        }
示例#30
0
        // this helper prepares arguments for COM binding by transforming ByVal StongBox arguments
        // into ByRef expressions that represent the argument's Value fields.
        internal static bool[] ProcessArgumentsForCom(ref DynamicMetaObject[] args) {
            Debug.Assert(args != null);

            DynamicMetaObject[] newArgs = new DynamicMetaObject[args.Length];
            bool[] isByRefArg = new bool[args.Length];

            for (int i = 0; i < args.Length; i++) {
                DynamicMetaObject curArgument = args[i];

                // set new arg infos to their original values or set default ones
                // we will do this fixup early so that we can assume we always have
                // arginfos in COM binder.

                if (IsByRef(curArgument)) {
                    newArgs[i] = curArgument;
                    isByRefArg[i] = true;
                } else {
                    if (IsStrongBoxArg(curArgument)) {
                        var restrictions = curArgument.Restrictions.Merge(
                            GetTypeRestrictionForDynamicMetaObject(curArgument)
                        );

                        // we have restricted this argument to LimitType so we can convert and conversion will be trivial cast.
                        Expression boxedValueAccessor = Expression.Field(
                            Helpers.Convert(
                                curArgument.Expression,
                                curArgument.LimitType
                            ),
                            curArgument.LimitType.GetField("Value")
                        );

                        IStrongBox value = curArgument.Value as IStrongBox;
                        object boxedValue = value != null ? value.Value : null;

                        newArgs[i] = new DynamicMetaObject(
                            boxedValueAccessor,
                            restrictions,
                            boxedValue
                        );

                        isByRefArg[i] = true;
                    } else {
                        newArgs[i] = curArgument;
                        isByRefArg[i] = false;
                    }
                }
            }

            args = newArgs;
            return isByRefArg;
        }
示例#31
0
 public DynamicMetaObject GetMetaObject(Expression parameter, int index)
 {
     return(DynamicMetaObject.Create(this.GetArgument(index), Expression.Call(_GetArgMethod, Utils.Convert(parameter, typeof(ArgumentArray)), Utils.Constant(index))));
 }
示例#32
0
 internal override void MakeGetExpression(PythonBinder /*!*/ binder, Expression /*!*/ codeContext, DynamicMetaObject instance, DynamicMetaObject /*!*/ owner, ConditionalBuilder /*!*/ builder)
 {
     builder.FinishCondition(Ast.Constant(this));
 }
示例#33
0
        /// <summary>
        /// Helper for generating the call to a builtin function.  This is used for calls from built-in method
        /// descriptors and built-in functions w/ and w/o a bound instance.
        ///
        /// This provides all sorts of common checks on top of the call while the caller provides a delegate
        /// to do the actual call.  The common checks include:
        ///     check for generic-only methods
        ///     reversed operator support
        ///     transforming arguments so the default binder can understand them (currently user defined mapping types to PythonDictionary)
        ///     returning NotImplemented from binary operators
        ///     Warning when calling certain built-in functions
        ///
        /// </summary>
        /// <param name="call">The call binder we're doing the call for</param>
        /// <param name="codeContext">An expression which points to the code context</param>
        /// <param name="function">the meta object for the built in function</param>
        /// <param name="hasSelf">true if we're calling with an instance</param>
        /// <param name="args">The arguments being passed to the function</param>
        /// <param name="functionRestriction">A restriction for the built-in function, method desc, etc...</param>
        /// <param name="bind">A delegate to perform the actual call to the method.</param>
        internal DynamicMetaObject /*!*/ MakeBuiltinFunctionCall(DynamicMetaObjectBinder /*!*/ call, Expression /*!*/ codeContext, DynamicMetaObject /*!*/ function, DynamicMetaObject /*!*/[] args, bool hasSelf, BindingRestrictions /*!*/ functionRestriction, Func <DynamicMetaObject /*!*/[] /*!*/, BindingResult /*!*/> bind)
        {
            DynamicMetaObject res = null;

            // if we have a user defined operator for **args then transform it into a PythonDictionary
            DynamicMetaObject translated = TranslateArguments(call, codeContext, new DynamicMetaObject(function.Expression, functionRestriction, function.Value), args, hasSelf, Name);

            if (translated != null)
            {
                return(translated);
            }

            // swap the arguments if we have a reversed operator
            if (IsReversedOperator)
            {
                ArrayUtils.SwapLastTwo(args);
            }

            // do the appropriate calling logic
            BindingResult result = bind(args);

            // validate the result
            BindingTarget target = result.Target;

            res = result.MetaObject;

            if (target.Overload != null && target.Overload.IsProtected)
            {
                // report an error when calling a protected member
                res = new DynamicMetaObject(
                    BindingHelpers.TypeErrorForProtectedMember(
                        target.Overload.DeclaringType,
                        target.Overload.Name
                        ),
                    res.Restrictions
                    );
            }
            else if (IsBinaryOperator && args.Length == 2 && IsThrowException(res.Expression))
            {
                // Binary Operators return NotImplemented on failure.
                res = new DynamicMetaObject(
                    Ast.Property(null, typeof(PythonOps), nameof(PythonOps.NotImplemented)),
                    res.Restrictions
                    );
            }
            else if (target.Overload != null)
            {
                // Add profiling information for this builtin function, if applicable
                if (call is IPythonSite pythonSite)
                {
                    var pc = pythonSite.Context;
                    if (pc.Options is PythonOptions po && po.EnableProfiler)
                    {
                        Profiler profiler = Profiler.GetProfiler(pc);
                        res = new DynamicMetaObject(
                            profiler.AddProfiling(res.Expression, target.Overload.ReflectionInfo),
                            res.Restrictions
                            );
                    }
                }
            }

            // add any warnings that are applicable for calling this function
            WarningInfo info;

            if (target.Overload != null && BindingWarnings.ShouldWarn(PythonContext.GetPythonContext(call), target.Overload, out info))
            {
                res = info.AddWarning(codeContext, res);
            }

            // finally add the restrictions for the built-in function and return the result.
            res = new DynamicMetaObject(
                res.Expression,
                functionRestriction.Merge(res.Restrictions)
                );

            // The function can return something typed to boolean or int.
            // If that happens, we need to apply Python's boxing rules.
            if (res.Expression.Type.IsValueType)
            {
                res = BindingHelpers.AddPythonBoxing(res);
            }
            else if (res.Expression.Type == typeof(void))
            {
                res = new DynamicMetaObject(
                    Expression.Block(
                        res.Expression,
                        Expression.Constant(null)
                        ),
                    res.Restrictions
                    );
            }

            return(res);
        }
示例#34
0
 public override DynamicMetaObject BindSetMember(SetMemberBinder binder, DynamicMetaObject value)
 {
     Requires.NotNull(binder);
     return(binder.Defer(WrapSelf(), value));
 }
示例#35
0
 public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion) => null;
示例#36
0
 public override DynamicMetaObject BindBinaryOperation(BinaryOperationBinder binder, DynamicMetaObject arg)
 {
     return(IsOverridden("TryBinaryOperation")
         ? CallMethodWithResult("TryBinaryOperation", binder, GetArgs(arg), e => binder.FallbackBinaryOperation(this, arg, e))
         : base.BindBinaryOperation(binder, arg));
 }
示例#37
0
 public DynamicMetaObject /*!*/ Invoke(PythonInvokeBinder /*!*/ pythonInvoke, Expression /*!*/ codeContext, DynamicMetaObject /*!*/ target, DynamicMetaObject /*!*/[] /*!*/ args)
 {
     return(InvokeWorker(pythonInvoke, args));
 }
        /// <summary>
        /// Updates the <see cref="Expression"/> tree for the operands of the specified operation.
        /// </summary>
        /// <param name="operation">The operation to evalutes.</param>
        /// <param name="thisOperand">The first operand.</param>
        /// <param name="otherOperand">The second operand.</param>
        /// <param name="thisExpression">The <see cref="Expression"/> for the first operand.</param>
        /// <param name="otherExpression">The <see cref="Expression"/> for the second operand.</param>
        private static void GetBinaryOperandExpressions(ExpressionType operation, DynamicMetaObject thisOperand, DynamicMetaObject otherOperand, ref Expression thisExpression, ref Expression otherExpression)
        {
            JsonValue thisValue  = thisOperand.Value as JsonValue;
            JsonValue otherValue = otherOperand.Value as JsonValue;

            Type thisType  = thisValue.Read().GetType();
            Type otherType = otherValue != null?otherValue.Read().GetType() : otherOperand.Value.GetType();

            Type coercedType;

            if (JsonValueDynamicMetaObject.TryCoerceType(operation, thisType, otherType, out coercedType))
            {
                thisType = otherType = coercedType;
            }
            else if (JsonValueDynamicMetaObject.TryCoerceSpecialTypes(thisOperand, otherOperand, out coercedType))
            {
                thisType = otherType = coercedType;
            }

            thisExpression = Expression.Convert(thisExpression, thisOperand.LimitType);
            thisExpression = Expression.Convert(Expression.Call(thisExpression, ReadAsMethodInfo, new Expression[] { Expression.Constant(thisType) }), thisType);

            otherExpression = Expression.Convert(otherExpression, otherOperand.LimitType);
            if (otherValue != null)
            {
                otherExpression = Expression.Convert(Expression.Call(otherExpression, ReadAsMethodInfo, new Expression[] { Expression.Constant(otherType) }), otherType);
            }
            else if (otherOperand.LimitType != otherType)
            {
                otherExpression = Expression.Convert(otherExpression, otherType);
            }
        }
示例#39
0
        private DynamicMetaObject InvokeWorker(DynamicMetaObjectBinder /*!*/ callAction, DynamicMetaObject /*!*/[] args)
        {
            PerfTrack.NoteEvent(PerfTrack.Categories.Binding, "Method Invoke " + args.Length);
            PerfTrack.NoteEvent(PerfTrack.Categories.BindingTarget, "Method");

            CallSignature       signature    = BindingHelpers.GetCallSignature(callAction);
            DynamicMetaObject   self         = Restrict(typeof(Method));
            BindingRestrictions restrictions = self.Restrictions;

            DynamicMetaObject func = GetMetaFunction(self);
            DynamicMetaObject call;

            if (Value.im_self == null)
            {
                // restrict to null self (Method is immutable so this is an invariant test)
                restrictions = restrictions.Merge(
                    BindingRestrictions.GetExpressionRestriction(
                        Ast.Equal(
                            GetSelfExpression(self),
                            AstUtils.Constant(null)
                            )
                        )
                    );

                if (args.Length == 0)
                {
                    // this is an error, we pass null which will throw the normal error
                    call = new DynamicMetaObject(
                        Ast.Call(
                            typeof(PythonOps).GetMethod("MethodCheckSelf"),
                            PythonContext.GetCodeContext(callAction),
                            self.Expression,
                            AstUtils.Constant(null)
                            ),
                        restrictions
                        );
                }
                else
                {
                    // this may or may not be an error
                    call = new DynamicMetaObject(
                        Ast.Block(
                            MakeCheckSelf(callAction, signature, args),
                            DynamicExpression.Dynamic(
                                PythonContext.GetPythonContext(callAction).Invoke(
                                    BindingHelpers.GetCallSignature(callAction)
                                    ).GetLightExceptionBinder(callAction.SupportsLightThrow()),
                                typeof(object),
                                ArrayUtils.Insert(PythonContext.GetCodeContext(callAction), DynamicUtils.GetExpressions(ArrayUtils.Insert(func, args)))
                                )
                            ),
                        BindingRestrictions.Empty
                        );

                    /*call = func.Invoke(callAction, ArrayUtils.Insert(func, args));
                     * call =  new MetaObject(
                     *  Ast.Comma(
                     *      Ast.Call(
                     *          typeof(PythonOps).GetMethod("MethodCheckSelf"),
                     *          self.Expression,
                     *          args[0].Expression
                     *      ),
                     *      call.Expression
                     *  ),
                     *  call.Restrictions
                     * );*/
                }
            }
            else
            {
                // restrict to non-null self (Method is immutable so this is an invariant test)
                restrictions = restrictions.Merge(
                    BindingRestrictions.GetExpressionRestriction(
                        Ast.NotEqual(
                            GetSelfExpression(self),
                            AstUtils.Constant(null)
                            )
                        )
                    );

                DynamicMetaObject   im_self = GetMetaSelf(self);
                DynamicMetaObject[] newArgs = ArrayUtils.Insert(func, im_self, args);
                CallSignature       newSig  = new CallSignature(ArrayUtils.Insert(new Argument(ArgumentType.Simple), signature.GetArgumentInfos()));


                call = new DynamicMetaObject(
                    DynamicExpression.Dynamic(
                        PythonContext.GetPythonContext(callAction).Invoke(
                            newSig
                            ).GetLightExceptionBinder(callAction.SupportsLightThrow()),
                        typeof(object),
                        ArrayUtils.Insert(PythonContext.GetCodeContext(callAction), DynamicUtils.GetExpressions(newArgs))
                        ),
                    BindingRestrictions.Empty
                    );

                /*
                 * call = func.Invoke(
                 *  new CallBinder(
                 *      PythonContext.GetBinderState(callAction),
                 *      newSig
                 *  ),
                 *  newArgs
                 * );*/
            }

            if (call.HasValue)
            {
                return(new DynamicMetaObject(
                           call.Expression,
                           restrictions.Merge(call.Restrictions),
                           call.Value
                           ));
            }
            else
            {
                return(new DynamicMetaObject(
                           call.Expression,
                           restrictions.Merge(call.Restrictions)
                           ));
            }
        }
示例#40
0
 public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion)
 {
     throw new NotImplementedException();
 }
 public override DynamicMetaObject FallbackDeleteIndex(DynamicMetaObject target, DynamicMetaObject[] indexes, DynamicMetaObject errorSuggestion)
 {
     throw new NotImplementedException();
 }
示例#42
0
 public override DynamicMetaObject BindSetIndex(SetIndexBinder binder, DynamicMetaObject[] indexes, DynamicMetaObject value)
 {
     return(IsOverridden("TrySetIndex")
         ? CallMethodReturnLast("TrySetIndex", binder, GetArgArray(indexes, value), e => binder.FallbackSetIndex(this, indexes, value, e))
         : base.BindSetIndex(binder, indexes, value));
 }
示例#43
0
 public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion)
 {
     return(_context.Binder.Invoke(
                Signature,
                errorSuggestion,
                new TjsOverloadResolverFactory(_context.Binder),
                target,
                args
                ));
 }
示例#44
0
 public DynamicMetaObject /*!*/ Invoke(PythonInvokeBinder /*!*/ pythonInvoke, Expression /*!*/ codeContext, DynamicMetaObject /*!*/ target, DynamicMetaObject /*!*/[] /*!*/ args)
 {
     return(MakeCallRule(pythonInvoke, codeContext, args));
 }
示例#45
0
 public override DynamicMetaObject /*!*/ BindSetMember(SetMemberBinder /*!*/ member, DynamicMetaObject /*!*/ value)
 {
     return(MakeSetMember(member.Name, value));
 }
示例#46
0
 public override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObject[] args)
 {
     return(PythonProtocol.Index(this, PythonIndexType.SetSlice, ArrayUtils.Insert(target, args)));
 }
        /// <summary>
        /// Implements getter for dynamic indexer by index (JsonArray).
        /// </summary>
        /// <param name="binder">An instance of the <see cref="SetIndexBinder"/> that represents the details of the dynamic operation.</param>
        /// <param name="indexes">An array of <see cref="DynamicMetaObject"/> instances - indexes for the set index operation.</param>
        /// <param name="value">The <see cref="DynamicMetaObject"/> representing the value for the set index operation.</param>
        /// <returns>The new <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
        public override DynamicMetaObject BindSetIndex(SetIndexBinder binder, DynamicMetaObject[] indexes, DynamicMetaObject value)
        {
            if (binder == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("binder"));
            }

            if (indexes == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("indexes"));
            }

            if (value == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("value"));
            }

            Expression indexExpression;

            if (!JsonValueDynamicMetaObject.TryGetIndexExpression(indexes, out indexExpression))
            {
                return(new DynamicMetaObject(indexExpression, this.DefaultRestrictions));
            }

            MethodInfo methodInfo = indexExpression.Type == typeof(string) ? SetValueByKeyMethodInfo : SetValueByIndexMethodInfo;

            Expression[] args = new Expression[] { indexExpression, Expression.Convert(value.Expression, typeof(object)) };

            return(this.GetMethodMetaObject(methodInfo, args));
        }
        /// <summary>
        /// Performs the binding of the dynamic binary operation.
        /// </summary>
        /// <param name="binder">An instance of the <see cref="BinaryOperationBinder"/> that represents the details of the dynamic operation.</param>
        /// <param name="arg">An instance of the <see cref="DynamicMetaObject"/> representing the right hand side of the binary operation.</param>
        /// <returns>The new <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
        public override DynamicMetaObject BindBinaryOperation(BinaryOperationBinder binder, DynamicMetaObject arg)
        {
            if (binder == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("binder"));
            }

            if (arg == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("arg"));
            }

            Expression thisExpression  = this.Expression;
            Expression otherExpression = arg.Expression;
            Expression operExpression  = null;

            JsonValue otherValue = arg.Value as JsonValue;
            JsonValue thisValue  = this.Value as JsonValue;

            OperationSupport supportValue = JsonValueDynamicMetaObject.GetBinaryOperationSupport(binder.Operation, thisValue, arg.Value);

            if (supportValue == OperationSupport.Supported)
            {
                if (otherValue != null)
                {
                    if (thisValue is JsonPrimitive && otherValue is JsonPrimitive)
                    {
                        //// operation on primitive types.

                        JsonValueDynamicMetaObject.GetBinaryOperandExpressions(binder.Operation, this, arg, ref thisExpression, ref otherExpression);
                    }
                    else
                    {
                        //// operation on JsonValue types.

                        thisExpression  = Expression.Convert(thisExpression, typeof(JsonValue));
                        otherExpression = Expression.Convert(otherExpression, typeof(JsonValue));
                    }
                }
                else
                {
                    if (arg.Value != null)
                    {
                        //// operation on JSON primitive and CLR primitive

                        JsonValueDynamicMetaObject.GetBinaryOperandExpressions(binder.Operation, this, arg, ref thisExpression, ref otherExpression);
                    }
                    else
                    {
                        //// operation on JsonValue and null.

                        thisExpression = Expression.Convert(thisExpression, typeof(JsonValue));

                        if (thisValue.JsonType == JsonType.Default)
                        {
                            thisExpression = Expression.Constant(null);
                        }
                    }
                }

                operExpression = JsonValueDynamicMetaObject.GetBinaryOperationExpression(binder.Operation, thisExpression, otherExpression);
            }

            if (operExpression == null)
            {
                operExpression = JsonValueDynamicMetaObject.GetOperationErrorExpression(supportValue, binder.Operation, thisValue, arg.Value);
            }

            operExpression = Expression.Convert(operExpression, typeof(object));

            return(new DynamicMetaObject(operExpression, this.DefaultRestrictions));
        }
示例#49
0
 public DynamicMetaObject GetMember(PythonGetMemberBinder member, DynamicMetaObject codeContext)
 {
     // no codeContext filtering but avoid an extra site by handling this action directly
     return(MakeGetMember(member, codeContext));
 }
示例#50
0
 internal override void MakeGetExpression(PythonBinder /*!*/ binder, Expression /*!*/ codeContext, DynamicMetaObject instance, DynamicMetaObject /*!*/ owner, ConditionalBuilder /*!*/ builder)
 {
     if (instance != null)
     {
         builder.FinishCondition(
             Ast.Call(
                 typeof(PythonOps).GetMethod(nameof(PythonOps.MakeBoundBuiltinFunction)),
                 AstUtils.Constant(_template),
                 instance.Expression
                 )
             );
     }
     else
     {
         builder.FinishCondition(AstUtils.Constant(this));
     }
 }
示例#51
0
        private DynamicMetaObject /*!*/ MakeGetMember(DynamicMetaObjectBinder /*!*/ member, DynamicMetaObject codeContext)
        {
            PerfTrack.NoteEvent(PerfTrack.Categories.Binding, "OldClass GetMember");
            PerfTrack.NoteEvent(PerfTrack.Categories.BindingTarget, "OldClass GetMember");
            DynamicMetaObject self = Restrict(typeof(OldClass));

            Expression target;
            string     memberName = GetGetMemberName(member);

            switch (memberName)
            {
            case "__dict__":
                target = Ast.Block(
                    Ast.Call(
                        typeof(PythonOps).GetMethod("OldClassDictionaryIsPublic"),
                        self.Expression
                        ),
                    Ast.Call(
                        typeof(PythonOps).GetMethod("OldClassGetDictionary"),
                        self.Expression
                        )
                    );
                break;

            case "__bases__":
                target = Ast.Call(
                    typeof(PythonOps).GetMethod("OldClassGetBaseClasses"),
                    self.Expression
                    );
                break;

            case "__name__":
                target = Ast.Call(
                    typeof(PythonOps).GetMethod("OldClassGetName"),
                    self.Expression
                    );
                break;

            default:
                ParameterExpression tmp = Ast.Variable(typeof(object), "lookupVal");
                return(new DynamicMetaObject(
                           Ast.Block(
                               new ParameterExpression[] { tmp },
                               Ast.Condition(
                                   Expression.Not(
                                       Expression.TypeIs(
                                           Expression.Assign(
                                               tmp,
                                               Ast.Call(
                                                   typeof(PythonOps).GetMethod("OldClassTryLookupValue"),
                                                   AstUtils.Constant(PythonContext.GetPythonContext(member).SharedContext),
                                                   self.Expression,
                                                   AstUtils.Constant(memberName)
                                                   )
                                               ),
                                           typeof(OperationFailed)
                                           )
                                       ),
                                   tmp,
                                   AstUtils.Convert(
                                       GetMemberFallback(this, member, codeContext).Expression,
                                       typeof(object)
                                       )
                                   )
                               ),
                           self.Restrictions
                           ));
            }

            return(new DynamicMetaObject(
                       target,
                       self.Restrictions
                       ));
        }
示例#52
0
        /////////////////////////////////////////////////////////////////////////////////

        private static Type GetTypeForErrorMetaObject(DynamicMetaObjectBinder action, DynamicMetaObject arg0)
        {
            // This is similar to ConvertResult but has fewer things to worry about.

            var invokeConstructor = action as CSharpInvokeConstructorBinder;

            if (invokeConstructor != null)
            {
                if (arg0 == null || !(arg0.Value is Type))
                {
                    Debug.Assert(false);
                    return(typeof(object));
                }

                Type result = arg0.Value as Type;

                return(result);
            }

            return(action.ReturnType);
        }
示例#53
0
 public override DynamicMetaObject BindSetIndex(SetIndexBinder binder, DynamicMetaObject[] indexes, DynamicMetaObject value)
 {
     Requires.NotNull(binder);
     return(binder.Defer(WrapSelf(), indexes.AddLast(value)));
 }
示例#54
0
        internal static DynamicMetaObject Bind(
            DynamicMetaObjectBinder action,
            RuntimeBinder binder,
            DynamicMetaObject[] args,
            IEnumerable <CSharpArgumentInfo> arginfos,
            DynamicMetaObject onBindingError)
        {
            Expression[]        parameters   = new Expression[args.Length];
            BindingRestrictions restrictions = BindingRestrictions.Empty;
            ICSharpInvokeOrInvokeMemberBinder callPayload = action as ICSharpInvokeOrInvokeMemberBinder;
            ParameterExpression tempForIncrement          = null;
            IEnumerator <CSharpArgumentInfo> arginfosEnum = (arginfos ?? Array.Empty <CSharpArgumentInfo>()).GetEnumerator();

            for (int index = 0; index < args.Length; ++index)
            {
                DynamicMetaObject o = args[index];
                // Our contract with the DLR is such that we will not enter a bind unless we have
                // values for the meta-objects involved.

                if (!o.HasValue)
                {
                    Debug.Assert(false, "The runtime binder is being asked to bind a metaobject without a value");
                    throw Error.InternalCompilerError();
                }

                CSharpArgumentInfo info = arginfosEnum.MoveNext() ? arginfosEnum.Current : null;

                if (index == 0 && IsIncrementOrDecrementActionOnLocal(action))
                {
                    // We have an inc or a dec operation. Insert the temp local instead.
                    //
                    // We need to do this because for value types, the object will come
                    // in boxed, and we'd need to unbox it to get the original type in order
                    // to increment. The only way to do that is to create a new temporary.
                    object value = o.Value;
                    tempForIncrement = Expression.Variable(value != null ? value.GetType() : typeof(object), "t0");
                    parameters[0]    = tempForIncrement;
                }
                else
                {
                    parameters[index] = o.Expression;
                }

                BindingRestrictions r = DeduceArgumentRestriction(index, callPayload, o, info);
                restrictions = restrictions.Merge(r);

                // Here we check the argument info. If the argument info shows that the current argument
                // is a literal constant, then we also add an instance restriction on the value of
                // the constant.
                if (info != null && info.LiteralConstant)
                {
                    if (o.Value is double && double.IsNaN((double)o.Value))
                    {
                        MethodInfo isNaN = s_DoubleIsNaN ?? (s_DoubleIsNaN = typeof(double).GetMethod("IsNaN"));
                        Expression e     = Expression.Call(null, isNaN, o.Expression);
                        restrictions = restrictions.Merge(BindingRestrictions.GetExpressionRestriction(e));
                    }
                    else if (o.Value is float && float.IsNaN((float)o.Value))
                    {
                        MethodInfo isNaN = s_SingleIsNaN ?? (s_SingleIsNaN = typeof(float).GetMethod("IsNaN"));
                        Expression e     = Expression.Call(null, isNaN, o.Expression);
                        restrictions = restrictions.Merge(BindingRestrictions.GetExpressionRestriction(e));
                    }
                    else
                    {
                        Expression e = Expression.Equal(o.Expression, Expression.Constant(o.Value, o.Expression.Type));
                        r            = BindingRestrictions.GetExpressionRestriction(e);
                        restrictions = restrictions.Merge(r);
                    }
                }
            }

            // Get the bound expression.
            try
            {
                DynamicMetaObject deferredBinding;
                Expression        expression = binder.Bind(action, parameters, args, out deferredBinding);

                if (deferredBinding != null)
                {
                    expression   = ConvertResult(deferredBinding.Expression, action);
                    restrictions = deferredBinding.Restrictions.Merge(restrictions);
                    return(new DynamicMetaObject(expression, restrictions));
                }

                if (tempForIncrement != null)
                {
                    // If we have a ++ or -- payload, we need to do some temp rewriting.
                    // We rewrite to the following:
                    //
                    // temp = (type)o;
                    // temp++;
                    // o = temp;
                    // return o;

                    DynamicMetaObject arg0 = args[0];

                    expression = Expression.Block(
                        new[] { tempForIncrement },
                        Expression.Assign(tempForIncrement, Expression.Convert(arg0.Expression, arg0.Value.GetType())),
                        expression,
                        Expression.Assign(arg0.Expression, Expression.Convert(tempForIncrement, arg0.Expression.Type)));
                }

                expression = ConvertResult(expression, action);

                return(new DynamicMetaObject(expression, restrictions));
            }
            catch (RuntimeBinderException e)
            {
                if (onBindingError != null)
                {
                    return(onBindingError);
                }

                return(new DynamicMetaObject(
                           Expression.Throw(
                               Expression.New(
                                   typeof(RuntimeBinderException).GetConstructor(new Type[] { typeof(string) }),
                                   Expression.Constant(e.Message)
                                   ),
                               GetTypeForErrorMetaObject(action, args.Length == 0 ? null : args[0])
                               ),
                           restrictions
                           ));
            }
        }
示例#55
0
        internal static DynamicMetaObject TranslateArguments(DynamicMetaObjectBinder call, Expression codeContext, DynamicMetaObject function, DynamicMetaObject /*!*/[] args, bool hasSelf, string name)
        {
            if (hasSelf)
            {
                args = ArrayUtils.RemoveFirst(args);
            }

            CallSignature sig = BindingHelpers.GetCallSignature(call);

            if (sig.HasDictionaryArgument())
            {
                int index = sig.IndexOf(ArgumentType.Dictionary);

                DynamicMetaObject dict = args[index];

                if (!(dict.Value is IDictionary) && dict.Value != null)
                {
                    // The DefaultBinder only handles types that implement IDictionary.  Here we have an
                    // arbitrary user-defined mapping type.  We'll convert it into a PythonDictionary
                    // and then have an embedded dynamic site pass that dictionary through to the default
                    // binder.
                    DynamicMetaObject[] dynamicArgs = ArrayUtils.Insert(function, args);

                    dynamicArgs[index + 1] = new DynamicMetaObject(
                        Expression.Call(
                            typeof(PythonOps).GetMethod(nameof(PythonOps.UserMappingToPythonDictionary)),
                            codeContext,
                            args[index].Expression,
                            AstUtils.Constant(name)
                            ),
                        BindingRestrictionsHelpers.GetRuntimeTypeRestriction(dict.Expression, dict.GetLimitType()),
                        PythonOps.UserMappingToPythonDictionary(PythonContext.GetPythonContext(call).SharedContext, dict.Value, name)
                        );

                    if (call is IPythonSite)
                    {
                        dynamicArgs = ArrayUtils.Insert(
                            new DynamicMetaObject(codeContext, BindingRestrictions.Empty),
                            dynamicArgs
                            );
                    }

                    return(new DynamicMetaObject(
                               DynamicExpression.Dynamic(
                                   call,
                                   typeof(object),
                                   DynamicUtils.GetExpressions(dynamicArgs)
                                   ),
                               BindingRestrictions.Combine(dynamicArgs).Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(dict.Expression, dict.GetLimitType()))
                               ));
                }
            }

            if (sig.HasListArgument())
            {
                int index = sig.IndexOf(ArgumentType.List);
                DynamicMetaObject list = args[index];

                if (!(list.Value is IList <object>) && list.Value != null)
                {
                    // The DefaultBinder only handles types that implement IList<object>.  Here we have a
                    // arbitrary user-defined sequence type.  We'll convert it into a tuple and then have
                    // an embedded dynamic site pass that tuple through to the default binder.
                    DynamicMetaObject[] dynamicArgs = ArrayUtils.Insert(function, args);

                    dynamicArgs[index + 1] = new DynamicMetaObject(
                        Expression.Call(
                            typeof(PythonOps).GetMethod(nameof(PythonOps.UserMappingToPythonTuple)),
                            codeContext,
                            args[index].Expression,
                            AstUtils.Constant(name)
                            ),
                        BindingRestrictions.Empty
                        );

                    if (call is IPythonSite)
                    {
                        dynamicArgs = ArrayUtils.Insert(
                            new DynamicMetaObject(codeContext, BindingRestrictions.Empty),
                            dynamicArgs
                            );
                    }

                    return(new DynamicMetaObject(
                               DynamicExpression.Dynamic(
                                   call,
                                   typeof(object),
                                   DynamicUtils.GetExpressions(dynamicArgs)
                                   ),
                               function.Restrictions.Merge(
                                   BindingRestrictions.Combine(args).Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(list.Expression, list.GetLimitType()))
                                   )
                               ));
                }
            }
            return(null);
        }
示例#56
0
 private static bool IsByRef(DynamicMetaObject mo)
 {
     return(mo.Expression is ParameterExpression pe && pe.IsByRef);
 }
示例#57
0
 public BindingResult(BindingTarget target, DynamicMetaObject meta)
 {
     Target     = target;
     MetaObject = meta;
 }
        public override DynamicMetaObject BindSetIndex(SetIndexBinder binder, DynamicMetaObject[] indexes, DynamicMetaObject value)
        {
            ComMethodDesc setItem;

            if (_self.TryGetSetItem(out setItem))
            {
                List <ParameterExpression> temps     = new List <ParameterExpression>();
                List <Expression>          initTemps = new List <Expression>();

                bool[] isByRef = ComBinderHelpers.ProcessArgumentsForCom(setItem, ref indexes, temps, initTemps);
                isByRef = isByRef.AddLast(false);

                // Convert the value to the target type
                DynamicMetaObject updatedValue = new DynamicMetaObject(value.CastOrConvertMethodArgument(
                                                                           value.LimitType,
                                                                           setItem.Name,
                                                                           "SetIndex",
                                                                           temps,
                                                                           initTemps), value.Restrictions);

                var result = BindComInvoke(indexes.AddLast(updatedValue), setItem, binder.CallInfo, isByRef, temps, initTemps);

                // Make sure to return the value; some languages need it.
                return(new DynamicMetaObject(
                           Expression.Block(result.Expression, Expression.Convert(value.Expression, typeof(object))),
                           result.Restrictions
                           ));
            }

            return(base.BindSetIndex(binder, indexes, value));
        }
示例#59
0
        private DynamicMetaObject BuildCallMethodWithResult(string methodName, DynamicMetaObjectBinder binder, Expression[] args, DynamicMetaObject fallbackResult, Fallback fallbackInvoke)
        {
            //
            // Build a new expression like:
            // {
            //   object result;
            //   TryGetMember(payload, out result) ? fallbackInvoke(result) : fallbackResult
            // }
            //
            ParameterExpression result = Expression.Parameter(typeof(object), null);

            IList <Expression> callArgs = new List <Expression>();

            callArgs.Add(Expression.Convert(Expression, typeof(T)));
            callArgs.Add(Constant(binder));
            callArgs.AddRange(args);
            callArgs.Add(result);

            DynamicMetaObject resultMetaObject = new DynamicMetaObject(result, BindingRestrictions.Empty);

            // Need to add a conversion if calling TryConvert
            if (binder.ReturnType != typeof(object))
            {
                UnaryExpression convert = Expression.Convert(resultMetaObject.Expression, binder.ReturnType);
                // will always be a cast or unbox

                resultMetaObject = new DynamicMetaObject(convert, resultMetaObject.Restrictions);
            }

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

            DynamicMetaObject callDynamic = new DynamicMetaObject(
                Expression.Block(
                    new[] { result },
                    Expression.Condition(
                        Expression.Call(
                            Expression.Constant(_proxy),
                            typeof(DynamicProxy <T>).GetMethod(methodName),
                            callArgs
                            ),
                        resultMetaObject.Expression,
                        fallbackResult.Expression,
                        binder.ReturnType
                        )
                    ),
                GetRestrictions().Merge(resultMetaObject.Restrictions).Merge(fallbackResult.Restrictions)
                );

            return(callDynamic);
        }
示例#60
0
        public override DynamicMetaObject FallbackSetMember(DynamicMetaObject target, DynamicMetaObject value, DynamicMetaObject errorSuggestion)
        {
            var result = Context.Binder.SetMember(Name, target, value, errorSuggestion, new TjsOverloadResolverFactory(Context.Binder));

            if (result.Expression.Type.IsValueType)
            {
                result = new DynamicMetaObject(AstUtils.Convert(result.Expression, typeof(object)), result.Restrictions);
            }
            return(result);
        }