예제 #1
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))
                );
            }
        }
예제 #2
0
        public DynamicMetaObject ConvertWorker(DynamicMetaObjectBinder binder, Type toType, ConversionResultKind kind) {
            if (toType.IsSubclassOf(typeof(Delegate))) {
                return MakeDelegateTarget(binder, toType, Restrict(typeof(Method)));
            }

            return FallbackConvert(binder);
        }
예제 #3
0
        internal static bool IsNoThrow(DynamicMetaObjectBinder action) {
            PythonGetMemberBinder gmb = action as PythonGetMemberBinder;
            if (gmb != null) {
                return gmb.IsNoThrow;
            }

            return false;
        }
예제 #4
0
                    public Expression Dynamic(DynamicMetaObjectBinder binder, Type retType, Expression arg0, Expression arg1, Expression arg2, Expression arg3)
            {
                if(retType == typeof(object))
                    return new TotemDynamicExpression4(binder, this, arg0, arg1, arg2, arg3);
                else if(retType == typeof(bool))
                    return new TotemDynamicExpression4<bool>(binder, this, arg0, arg1, arg2, arg3);

                return ReduceDynamic(binder, retType, arg0, arg1, arg2, arg3);
            }
예제 #5
0
        public DynamicMetaObject ConvertWorker(DynamicMetaObjectBinder binder, Type toType, ConversionResultKind kind) {
            PerfTrack.NoteEvent(PerfTrack.Categories.Binding, "BuiltinFunc Convert " + toType);
            PerfTrack.NoteEvent(PerfTrack.Categories.BindingTarget, "BuiltinFunc Convert");

            if (toType.IsSubclassOf(typeof(Delegate))) {
                return MakeDelegateTarget(binder, toType, Restrict(LimitType));
            }

            return FallbackConvert(binder);
        }
예제 #6
0
        public DynamicMetaObject ConvertWorker(DynamicMetaObjectBinder binder, Type type, Type retType, ConversionResultKind kind) {
            PerfTrack.NoteEvent(PerfTrack.Categories.Binding, "Conversion " + type.FullName);
            PerfTrack.NoteEvent(PerfTrack.Categories.BindingTarget, "Conversion");
            ValidationInfo typeTest = BindingHelpers.GetValidationInfo(this, Value.PythonType);

            return BindingHelpers.AddDynamicTestAndDefer(
                binder,
                TryPythonConversion(binder, type) ?? FallbackConvert(binder),
                new DynamicMetaObject[] { this },
                typeTest,
                retType
            );
        }
예제 #7
0
        /*!*/
        public MSAst.Expression Dynamic(DynamicMetaObjectBinder/*!*/ binder, Type/*!*/ retType, MSAst.Expression/*!*/ arg0)
        {
            if (retType == typeof(object))
            {
                throw new NotImplementedException();
                //return new TotemDynamicExpression1(binder, this, arg0);
            }
            else if (retType == typeof(bool))
            {
                throw new NotImplementedException();
                //return new TotemDynamicExpression1<bool>(binder, this, arg0);
            }

            return ReduceDynamic(binder, retType, arg0);
        }
        private DynamicMetaObject/*!*/ InvokeWorker(DynamicMetaObjectBinder/*!*/ call, Expression/*!*/ codeContext, DynamicMetaObject/*!*/[] args) {
            PerfTrack.NoteEvent(PerfTrack.Categories.Binding, "BuiltinMethodDesc Invoke " + Value.DeclaringType + "." + Value.__name__ + " w/ " + args.Length + " args");
            PerfTrack.NoteEvent(PerfTrack.Categories.BindingTarget, "BuiltinMethodDesc Invoke");

            CallSignature signature = BindingHelpers.GetCallSignature(call);
            BindingRestrictions selfRestrict = BindingRestrictions.GetInstanceRestriction(Expression, Value).Merge(Restrictions);

            selfRestrict = selfRestrict.Merge(
                BindingRestrictions.GetExpressionRestriction(
                    MakeFunctionTest(
                        Ast.Call(
                            typeof(PythonOps).GetMethod("GetBuiltinMethodDescriptorTemplate"),
                            Ast.Convert(Expression, typeof(BuiltinMethodDescriptor))
                        )
                    )
                )
            );

            return Value.Template.MakeBuiltinFunctionCall(
                call,
                codeContext,
                this,
                args,
                false,  // no self
                selfRestrict,
                (newArgs) => {
                    BindingTarget target;
                    PythonContext state = PythonContext.GetPythonContext(call);

                    DynamicMetaObject res = state.Binder.CallMethod(
                        new PythonOverloadResolver(
                            state.Binder,
                            newArgs,
                            signature,
                            codeContext
                        ),
                        Value.Template.Targets,
                        selfRestrict,
                        Value.Template.Name,
                        NarrowingLevel.None,
                        Value.Template.IsBinaryOperator ? PythonNarrowing.BinaryOperator : NarrowingLevel.All,
                        out target
                    );

                    return BindingHelpers.CheckLightThrow(call, res, target);
                });            
        }
예제 #9
0
            public FunctionBinderHelper(DynamicMetaObjectBinder call, MetaTotemFunction function, Expression codeContext, DynamicMetaObject[] args)
            {
                PerfTrack.NoteEvent(PerfTrack.Categories.Binding, "TotemFunction Invoke " + function.Value.FunctionCompatibility + " w/ " + args.Length + " args");
                PerfTrack.NoteEvent(PerfTrack.Categories.BindingTarget, "TotemFunction");

                _call = call;
                _func = function;
                _args = args;
                _originalArgs = args;
                _temps = new List<ParameterExpression>();
                _codeContext = codeContext;

                // Remove the passed in instance argument if present
                int instanceIndex = Signature.IndexOf(ArgumentType.Instance);
                if (instanceIndex > -1)
                    _args = ArrayUtils.RemoveAt(_args, instanceIndex);
            }
예제 #10
0
        private DynamicMetaObject/*!*/ InvokeWorker(DynamicMetaObjectBinder/*!*/ call, DynamicMetaObject/*!*/[]/*!*/ args, Expression/*!*/ codeContext) {
            if (this.NeedsDeferral()) {
                return call.Defer(ArrayUtils.Insert(this, args));
            }

            for (int i = 0; i < args.Length; i++) {
                if (args[i].NeedsDeferral()) {
                    return call.Defer(ArrayUtils.Insert(this, args));
                }
            }

            if (IsStandardDotNetType(call)) {
                return MakeStandardDotNetTypeCall(call, codeContext, args);
            }

            return MakePythonTypeCall(call, codeContext, args);
        }
예제 #11
0
        internal static DynamicMetaObject/*!*/ FilterShowCls(Expression/*!*/ codeContext, DynamicMetaObjectBinder/*!*/ action, DynamicMetaObject/*!*/ res, Expression/*!*/ failure) {
            if (action is IPythonSite) {
                return new DynamicMetaObject(
                    Ast.Condition(
                        Ast.Call(
                            typeof(PythonOps).GetMethod("IsClsVisible"),
                            codeContext
                        ),
                        AstUtils.Convert(res.Expression, typeof(object)),
                        AstUtils.Convert(failure, typeof(object))

                    ),
                    res.Restrictions
                );
            }

            return res;
        }
예제 #12
0
        private DynamicMetaObject/*!*/ InvokeWorker(DynamicMetaObjectBinder/*!*/ call, DynamicMetaObject/*!*/[]/*!*/ args, Expression/*!*/ codeContext) {
            PerfTrack.NoteEvent(PerfTrack.Categories.Binding, "Type Invoke " + Value.UnderlyingSystemType.FullName + args.Length);
            PerfTrack.NoteEvent(PerfTrack.Categories.BindingTarget, "Type Invoke");
            if (this.NeedsDeferral()) {
                return call.Defer(ArrayUtils.Insert(this, args));
            }

            for (int i = 0; i < args.Length; i++) {
                if (args[i].NeedsDeferral()) {
                    return call.Defer(ArrayUtils.Insert(this, args));
                }
            }

            if (IsStandardDotNetType(call)) {
                return MakeStandardDotNetTypeCall(call, codeContext, args);
            }

            return MakePythonTypeCall(call, codeContext, args);
        }
예제 #13
0
        public Expression Dynamic(DynamicMetaObjectBinder binder, Type retType, Expression[] args)
        {
            Assert.NotNull(binder, retType, args);
            Assert.NotNullItems(args);

            switch(args.Length)
            {
                                    case 1: return Dynamic(binder, retType, args[0]);
                                    case 2: return Dynamic(binder, retType, args[0], args[1]);
                                    case 3: return Dynamic(binder, retType, args[0], args[1], args[2]);
                                    case 4: return Dynamic(binder, retType, args[0], args[1], args[2], args[3]);
                            }

            if(retType == typeof(object))
            {
                return new TotemDynamicExpressionN(binder, this, args);
            }

            return ReduceDynamic(binder, retType, args);
        }
예제 #14
0
        internal static DynamicMetaObject/*!*/ FilterShowCls(Expression/*!*/ codeContext, DynamicMetaObjectBinder/*!*/ action, DynamicMetaObject/*!*/ res, Expression/*!*/ failure) {
            if (action is IPythonSite) {
                Type resType = BindingHelpers.GetCompatibleType(res.Expression.Type, failure.Type);

                return new DynamicMetaObject(
                    Ast.Condition(
                        Ast.Call(
                            typeof(PythonOps).GetMethod("IsClsVisible"),
                            codeContext
                        ),
                        AstUtils.Convert(res.Expression, resType),
                        AstUtils.Convert(failure, resType)

                    ),
                    res.Restrictions
                );
            }

            return res;
        }
예제 #15
0
        private DynamicMetaObject/*!*/ InvokeWorker(DynamicMetaObjectBinder/*!*/ call, Expression/*!*/ codeContext, DynamicMetaObject/*!*/[]/*!*/ args) {
            PerfTrack.NoteEvent(PerfTrack.Categories.Binding, "BuiltinFunc Invoke " + Value.DeclaringType.FullName + "." + Value.Name + " with " + args.Length + " args " + Value.IsUnbound);
            PerfTrack.NoteEvent(PerfTrack.Categories.BindingTarget, "BuiltinFunction " + Value.Targets.Count + ", " + Value.Targets[0].GetParameters().Length);
            PerfTrack.NoteEvent(PerfTrack.Categories.BindingSlow, "BuiltinFunction " + BindingHelpers.GetCallSignature(call));

            if (this.NeedsDeferral()) {
                return call.Defer(ArrayUtils.Insert(this, args));
            }

            for (int i = 0; i < args.Length; i++) {
                if (args[i].NeedsDeferral()) {
                    return call.Defer(ArrayUtils.Insert(this, args));
                }
            }

            if (Value.IsUnbound) {
                return MakeSelflessCall(call, codeContext, args);
            } else {
                return MakeSelfCall(call, codeContext, args);
            }
        }
예제 #16
0
 /// <summary>
 /// Helper method for generating a MetaObject which calls a
 /// specific method on Dynamic that returns a result
 /// </summary>
 private DynamicMetaObject CallMethodWithResult(string methodName, DynamicMetaObjectBinder binder, Expression[] args, Fallback fallback)
 {
     return(CallMethodWithResult(methodName, binder, args, fallback, null));
 }
예제 #17
0
        private DynamicMetaObject /*!*/ MakeConvertRuleForCall(DynamicMetaObjectBinder /*!*/ convertToAction, Type toType, DynamicMetaObject /*!*/ self, string name, string returner, Func <DynamicMetaObject> fallback, Func <Expression, Expression> resultConverter)
        {
            PythonType     pt = ((IPythonObject)self.Value).PythonType;
            PythonTypeSlot pts;
            CodeContext    context = PythonContext.GetPythonContext(convertToAction).SharedContext;
            ValidationInfo valInfo = BindingHelpers.GetValidationInfo(this, pt);

            if (pt.TryResolveSlot(context, name, out pts) && !IsBuiltinConversion(context, pts, name, pt))
            {
                ParameterExpression tmp = Ast.Variable(typeof(object), "func");

                Expression callExpr = resultConverter(
                    Ast.Call(
                        PythonOps.GetConversionHelper(returner, GetResultKind(convertToAction)),
                        Ast.Dynamic(
                            PythonContext.GetPythonContext(convertToAction).InvokeNone,
                            typeof(object),
                            PythonContext.GetCodeContext(convertToAction),
                            tmp
                            )
                        )
                    );

                if (typeof(Extensible <>).MakeGenericType(toType).IsAssignableFrom(self.GetLimitType()))
                {
                    // if we're doing a conversion to the underlying type and we're an
                    // Extensible<T> of that type:

                    // if an extensible type returns it's self in a conversion, then we need
                    // to actually return the underlying value.  If an extensible just keeps
                    // returning more instances  of it's self a stack overflow occurs - both
                    // behaviors match CPython.
                    callExpr = AstUtils.Convert(AddExtensibleSelfCheck(convertToAction, toType, self, callExpr), typeof(object));
                }

                return(BindingHelpers.AddDynamicTestAndDefer(
                           convertToAction,
                           new DynamicMetaObject(
                               Ast.Condition(
                                   MakeTryGetTypeMember(
                                       PythonContext.GetPythonContext(convertToAction),
                                       pts,
                                       self.Expression,
                                       tmp
                                       ),
                                   callExpr,
                                   AstUtils.Convert(
                                       ConversionFallback(convertToAction),
                                       typeof(object)
                                       )
                                   ),
                               self.Restrict(self.GetRuntimeType()).Restrictions
                               ),
                           new DynamicMetaObject[] { this },
                           valInfo,
                           tmp
                           ));
            }

            return(fallback());
        }
        private static DynamicMetaObject/*!*/ MakeBinaryOperatorResult(DynamicMetaObject/*!*/[]/*!*/ types, DynamicMetaObjectBinder/*!*/ operation, PythonOperationKind op, SlotOrFunction/*!*/ fCand, SlotOrFunction/*!*/ rCand, PythonTypeSlot fSlot, PythonTypeSlot rSlot, DynamicMetaObject errorSuggestion) {
            Assert.NotNull(operation, fCand, rCand);

            SlotOrFunction fTarget, rTarget;
            PythonContext state = PythonContext.GetPythonContext(operation);

            ConditionalBuilder bodyBuilder = new ConditionalBuilder(operation);

            if ((op & PythonOperationKind.InPlace) != 0) {
                // in place operator, see if there's a specific method that handles it.
                SlotOrFunction function = SlotOrFunction.GetSlotOrFunction(PythonContext.GetPythonContext(operation), Symbols.OperatorToSymbol(op), types);

                // we don't do a coerce for in place operators if the lhs implements __iop__
                if (!MakeOneCompareGeneric(function, false, types, MakeCompareReturn, bodyBuilder, typeof(object))) {
                    // the method handles it and always returns a useful value.
                    return bodyBuilder.GetMetaObject(types);
                }
            }

            if (!SlotOrFunction.GetCombinedTargets(fCand, rCand, out fTarget, out rTarget) &&
                fSlot == null &&
                rSlot == null &&
                !ShouldCoerce(state, op, types[0], types[1], false) &&
                !ShouldCoerce(state, op, types[1], types[0], false) &&
                bodyBuilder.NoConditions) {
                return MakeRuleForNoMatch(operation, op, errorSuggestion, types);
            }

            if (ShouldCoerce(state, op, types[0], types[1], false) &&
                (op != PythonOperationKind.Mod || !MetaPythonObject.GetPythonType(types[0]).IsSubclassOf(TypeCache.String))) {
                // need to try __coerce__ first.
                DoCoerce(state, bodyBuilder, op, types, false);
            }

            if (MakeOneTarget(PythonContext.GetPythonContext(operation), fTarget, fSlot, bodyBuilder, false, types)) {
                if (ShouldCoerce(state, op, types[1], types[0], false)) {
                    // need to try __coerce__ on the reverse first                    
                    DoCoerce(state, bodyBuilder, op, new DynamicMetaObject[] { types[1], types[0] }, true);
                }

                if (rSlot != null) {
                    MakeSlotCall(PythonContext.GetPythonContext(operation), types, bodyBuilder, rSlot, true);
                    bodyBuilder.FinishCondition(MakeBinaryThrow(operation, op, types).Expression, typeof(object));
                } else if (MakeOneTarget(PythonContext.GetPythonContext(operation), rTarget, rSlot, bodyBuilder, false, types)) {
                    // need to fallback to throwing or coercion
                    bodyBuilder.FinishCondition(MakeBinaryThrow(operation, op, types).Expression, typeof(object));
                }
            }

            return bodyBuilder.GetMetaObject(types);
        }
예제 #19
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
            // }
            // {
            //   Option<object> result;
            //   result = TryGetMember(payload, out result)
            //   result.HasValue ? fallbackInvoke(result.Value) : fallbackResult
            // }
            //
            var result   = Expression.Parameter(typeof(Option <object>), null);
            var callArgs = new Expression[] { Expression.Convert(Expression, typeof(T)), Constant(binder) }.Concat(args);

            var resultDmo = new DynamicMetaObject(Expression.MakeMemberAccess(
                                                      result,
                                                      typeof(Option <object>).GetProperty("Value")
                                                      ), BindingRestrictions.Empty);

            // Need to add a conversion if calling TryConvert
            if (binder.ReturnType != typeof(object))
            {
                Debug.Assert(binder is ConvertBinder && fallbackInvoke == null);

                var convert = Expression.Convert(resultDmo.Expression, binder.ReturnType);
                // will always be a cast or unbox
                Debug.Assert(convert.Method == null);

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

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

            var callDynamic = new DynamicMetaObject(
                Expression.Block(
                    new[] { result },
                    Expression.Assign(
                        result,
                        Expression.Invoke(
                            Expression.MakeMemberAccess(
                                Expression.Constant(_runtime),
                                typeof(DynamicObjectRuntime <T>).GetProperty(methodName)),
                            callArgs
                            )),
                    Expression.Condition(
                        Expression.MakeMemberAccess(
                            result,
                            typeof(Option <object>).GetProperty("HasValue")
                            ),
                        resultDmo.Expression,
                        fallbackResult.Expression,
                        binder.ReturnType
                        )
                    ),
                GetRestrictions().Merge(resultDmo.Restrictions).Merge(fallbackResult.Restrictions)
                );

            return(callDynamic);
        }
예제 #20
0
 internal static BuiltinFunction.BindingResult CheckLightThrow(DynamicMetaObjectBinder call, DynamicMetaObject res, BindingTarget target)
 {
     return(new BuiltinFunction.BindingResult(target, CheckLightThrowMO(call, res, target)));
 }
        private static DynamicMetaObject/*!*/ MakeUnaryNotOperation(DynamicMetaObjectBinder/*!*/ operation, DynamicMetaObject/*!*/ self, Type retType, DynamicMetaObject errorSuggestion) {
            self = self.Restrict(self.GetLimitType());

            SlotOrFunction nonzero = SlotOrFunction.GetSlotOrFunction(PythonContext.GetPythonContext(operation), "__nonzero__", self);
            SlotOrFunction length = SlotOrFunction.GetSlotOrFunction(PythonContext.GetPythonContext(operation), "__len__", self);

            Expression notExpr;

            if (!nonzero.Success && !length.Success) {
                // no __len__ or __nonzero__, for None this is always false, everything else is True.  If we have
                // an error suggestion though we'll go with that.
                if (errorSuggestion == null) {
                    notExpr = (self.GetLimitType() == typeof(DynamicNull)) ? AstUtils.Constant(true) : AstUtils.Constant(false);
                } else {
                    notExpr = errorSuggestion.Expression;
                }
            } else {
                SlotOrFunction target = nonzero.Success ? nonzero : length;

                notExpr = target.Target.Expression;

                if (nonzero.Success) {
                    // call non-zero and negate it
                    if (notExpr.Type == typeof(bool)) {
                        notExpr = Ast.Equal(notExpr, AstUtils.Constant(false));
                    } else {
                        notExpr = Ast.Call(
                            typeof(PythonOps).GetMethod("Not"),
                            AstUtils.Convert(notExpr, typeof(object))
                        );
                    }
                } else {
                    // call len, compare w/ zero
                    if (notExpr.Type == typeof(int)) {
                        notExpr = Ast.Equal(notExpr, AstUtils.Constant(0));
                    } else {
                        notExpr =
                            Ast.Equal(
                                DynamicExpression.Dynamic(
                                    PythonContext.GetPythonContext(operation).Operation(
                                        PythonOperationKind.Compare
                                    ),
                                    typeof(int),
                                    notExpr,
                                    AstUtils.Constant(0)
                                ),
                                AstUtils.Constant(0)
                            );
                    }
                }
            }

            if (retType == typeof(object) && notExpr.Type == typeof(bool)) {
                notExpr = BindingHelpers.AddPythonBoxing(notExpr);
            }

            return new DynamicMetaObject(
                notExpr,
                self.Restrictions.Merge(nonzero.Target.Restrictions.Merge(length.Target.Restrictions))
            );
        }
예제 #22
0
        internal static DynamicMetaObject Bind(
            DynamicMetaObjectBinder action,
            RuntimeBinder binder,
            IEnumerable <DynamicMetaObject> args,
            IEnumerable <CSharpArgumentInfo> arginfos,
            DynamicMetaObject onBindingError)
        {
            List <Expression>   parameters   = new List <Expression>();
            BindingRestrictions restrictions = BindingRestrictions.Empty;
            ICSharpInvokeOrInvokeMemberBinder callPayload = action as ICSharpInvokeOrInvokeMemberBinder;
            ParameterExpression tempForIncrement          = null;
            IEnumerator <CSharpArgumentInfo> arginfosEnum = arginfos == null ? null : arginfos.GetEnumerator();

            int index = 0;

            foreach (DynamicMetaObject o in args)
            {
                // 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 = null;
                if (arginfosEnum != null && arginfosEnum.MoveNext())
                {
                    info = arginfosEnum.Current;
                }

                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.
                    tempForIncrement = Expression.Variable(o.Value != null ? o.Value.GetType() : typeof(object), "t0");
                    parameters.Add(tempForIncrement);
                }
                else
                {
                    parameters.Add(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 float && float.IsNaN((float)o.Value)) ||
                        o.Value is double && double.IsNaN((double)o.Value))
                    {
                        // We cannot create an equality restriction for NaN, because equality is implemented
                        // in such a way that NaN != NaN and the rule we make would be unsatisfiable.
                    }
                    else
                    {
                        Expression e = Expression.Equal(o.Expression, Expression.Constant(o.Value, o.Expression.Type));
                        r            = BindingRestrictions.GetExpressionRestriction(e);
                        restrictions = restrictions.Merge(r);
                    }
                }

                ++index;
            }

            // Get the bound expression.
            try
            {
                DynamicMetaObject deferredBinding;
                Expression        expression = binder.Bind(action, parameters, args.ToArray(), 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 = Enumerable.First(args);

                    Expression assignTemp = Expression.Assign(
                        tempForIncrement,
                        Expression.Convert(arg0.Expression, arg0.Value.GetType()));
                    Expression assignResult = Expression.Assign(
                        arg0.Expression,
                        Expression.Convert(tempForIncrement, arg0.Expression.Type));
                    List <Expression> expressions = new List <Expression>();

                    expressions.Add(assignTemp);
                    expressions.Add(expression);
                    expressions.Add(assignResult);

                    expression = Expression.Block(new ParameterExpression[] { tempForIncrement }, expressions);
                }

                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.FirstOrDefault())
                               ),
                           restrictions
                           ));
            }
        }
예제 #23
0
        private DynamicMetaObject /*!*/ MakeDynamicMemberAccess(DynamicMetaObjectBinder /*!*/ member, string /*!*/ name, MemberAccess access, DynamicMetaObject /*!*/[] /*!*/ args)
        {
            DynamicMetaObject self = Restrict(typeof(OldInstance));
            Expression        target;

            ParameterExpression tmp = Ast.Variable(typeof(object), "result");

            switch (access)
            {
            case MemberAccess.Invoke:

                target = Ast.Block(
                    new ParameterExpression[] { tmp },
                    Ast.Condition(
                        Expression.Not(
                            Expression.TypeIs(
                                Expression.Assign(
                                    tmp,
                                    Ast.Call(
                                        typeof(PythonOps).GetMethod(nameof(PythonOps.OldInstanceTryGetBoundCustomMember)),
                                        AstUtils.Constant(PythonContext.GetPythonContext(member).SharedContext),
                                        self.Expression,
                                        AstUtils.Constant(name)
                                        )
                                    ),
                                typeof(OperationFailed)
                                )
                            ),
                        ((InvokeMemberBinder)member).FallbackInvoke(new DynamicMetaObject(tmp, BindingRestrictions.Empty), args, null).Expression,
                        AstUtils.Convert(
                            ((InvokeMemberBinder)member).FallbackInvokeMember(this, args).Expression,
                            typeof(object)
                            )
                        )
                    );
                break;

            case MemberAccess.Get:
                target = Ast.Block(
                    new ParameterExpression[] { tmp },
                    Ast.Condition(
                        Expression.Not(
                            Expression.TypeIs(
                                Expression.Assign(
                                    tmp,
                                    Ast.Call(
                                        typeof(PythonOps).GetMethod(nameof(PythonOps.OldInstanceTryGetBoundCustomMember)),
                                        AstUtils.Constant(PythonContext.GetPythonContext(member).SharedContext),
                                        self.Expression,
                                        AstUtils.Constant(name)
                                        )
                                    ),
                                typeof(OperationFailed)
                                )
                            ),
                        tmp,
                        AstUtils.Convert(
                            FallbackGet(member, args),
                            typeof(object)
                            )
                        )
                    );
                break;

            case MemberAccess.Set:
                target = Ast.Call(
                    typeof(PythonOps).GetMethod(nameof(PythonOps.OldInstanceSetCustomMember)),
                    AstUtils.Constant(PythonContext.GetPythonContext(member).SharedContext),
                    self.Expression,
                    AstUtils.Constant(name),
                    AstUtils.Convert(args[1].Expression, typeof(object))
                    );
                break;

            case MemberAccess.Delete:
                target = Ast.Call(
                    typeof(PythonOps).GetMethod(nameof(PythonOps.OldInstanceDeleteCustomMember)),
                    AstUtils.Constant(PythonContext.GetPythonContext(member).SharedContext),
                    self.Expression,
                    AstUtils.Constant(name)
                    );
                break;

            default:
                throw new InvalidOperationException();
            }

            return(new DynamicMetaObject(
                       target,
                       self.Restrictions.Merge(BindingRestrictions.Combine(args))
                       ));
        }
예제 #24
0
 public virtual MSAst.Expression/*!*/ Dynamic(DynamicMetaObjectBinder/*!*/ binder, Type/*!*/ retType, MSAst.Expression/*!*/ arg0, MSAst.Expression/*!*/ arg1) {
     return MSAst.Expression.Dynamic(binder, retType, arg0, arg1);
 }
예제 #25
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 str = args[index];

                // TODO: ANything w/ __iter__ that's not an IList<object>
                if (!(str.Value is IList <object>) && str.Value is IEnumerable)
                {
                    // The DefaultBinder only handles types that implement IList<object>.  Here we have a
                    // string.  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.MakeTupleFromSequence)),
                            Expression.Convert(args[index].Expression, typeof(object))
                            ),
                        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(str.Expression, str.GetLimitType()))
                                   )
                               ));
                }
            }
            return(null);
        }
예제 #26
0
        internal static DynamicMetaObject Call(DynamicMetaObjectBinder /*!*/ call, DynamicMetaObject target, DynamicMetaObject /*!*/[] /*!*/ args)
        {
            Assert.NotNull(call, args);
            Assert.NotNullItems(args);

            if (target.NeedsDeferral())
            {
                return(call.Defer(ArrayUtils.Insert(target, args)));
            }

            foreach (DynamicMetaObject mo in args)
            {
                if (mo.NeedsDeferral())
                {
                    RestrictTypes(args);

                    return(call.Defer(
                               ArrayUtils.Insert(target, args)
                               ));
                }
            }

            DynamicMetaObject self = target.Restrict(target.GetLimitType());

            ValidationInfo valInfo   = BindingHelpers.GetValidationInfo(target);
            PythonType     pt        = DynamicHelpers.GetPythonType(target.Value);
            PythonContext  pyContext = PythonContext.GetPythonContext(call);

            // look for __call__, if it's present dispatch to it.  Otherwise fall back to the
            // default binder
            PythonTypeSlot callSlot;

            if (!typeof(Delegate).IsAssignableFrom(target.GetLimitType()) &&
                pt.TryResolveSlot(pyContext.SharedContext, "__call__", out callSlot))
            {
                ConditionalBuilder cb = new ConditionalBuilder(call);

                callSlot.MakeGetExpression(
                    pyContext.Binder,
                    PythonContext.GetCodeContext(call),
                    self,
                    GetPythonType(self),
                    cb
                    );

                if (!cb.IsFinal)
                {
                    cb.FinishCondition(GetCallError(call, self));
                }

                Expression[] callArgs = ArrayUtils.Insert(
                    PythonContext.GetCodeContext(call),
                    cb.GetMetaObject().Expression,
                    DynamicUtils.GetExpressions(args)
                    );

                Expression body = DynamicExpression.Dynamic(
                    PythonContext.GetPythonContext(call).Invoke(
                        BindingHelpers.GetCallSignature(call)
                        ),
                    typeof(object),
                    callArgs
                    );

                body = Ast.TryFinally(
                    Ast.Block(
                        Ast.Call(typeof(PythonOps).GetMethod(nameof(PythonOps.FunctionPushFrame)), Ast.Constant(pyContext)),
                        body
                        ),
                    Ast.Call(typeof(PythonOps).GetMethod(nameof(PythonOps.FunctionPopFrame)))
                    );

                return(BindingHelpers.AddDynamicTestAndDefer(
                           call,
                           new DynamicMetaObject(body, self.Restrictions.Merge(BindingRestrictions.Combine(args))),
                           args,
                           valInfo
                           ));
            }

            return(null);
        }
예제 #27
0
            /// <summary>
            /// Helper method for generating a MetaObject which calls a
            /// specific method on Dynamic that returns a result
            /// </summary>
            private DynamicMetaObject CallMethodWithResult(string methodName, DynamicMetaObjectBinder binder, Expression[] args, Fallback fallback, Fallback fallbackInvoke)
            {
                //
                // First, call fallback to do default binding
                // This produces either an error or a call to a .NET member
                //
                DynamicMetaObject fallbackResult = fallback(null);

                //
                // Build a new expression like:
                // {
                //   object result;
                //   TryGetMember(payload, out result) ? fallbackInvoke(result) : fallbackResult
                // }
                //
                var result = Expression.Parameter(typeof(object), null);

                var callArgs = new Expression[args.Length + 2];

                Array.Copy(args, 0, callArgs, 1, args.Length);
                callArgs[0] = Constant(binder);
                callArgs[callArgs.Length - 1] = result;

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

                // Need to add a conversion if calling TryConvert
                if (binder.ReturnType != typeof(object))
                {
                    Debug.Assert(binder is ConvertBinder && fallbackInvoke == null);

                    var convert = Expression.Convert(resultMO.Expression, binder.ReturnType);
                    // will always be a cast or unbox
                    Debug.Assert(convert.Method == null);

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

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

                var callDynamic = new DynamicMetaObject(
                    Expression.Block(
                        new[] { result },
                        Expression.Condition(
                            Expression.Call(
                                GetLimitedSelf(),
                                typeof(DynamicObject).GetMethod(methodName),
                                callArgs
                                ),
                            resultMO.Expression,
                            fallbackResult.Expression,
                            binder.ReturnType
                            )
                        ),
                    GetRestrictions().Merge(resultMO.Restrictions).Merge(fallbackResult.Restrictions)
                    );

                //
                // Now, call fallback again using our new MO as the error
                // When we do this, one of two things can happen:
                //   1. Binding will succeed, and it will ignore our call to
                //      the dynamic method, OR
                //   2. Binding will fail, and it will use the MO we created
                //      above.
                //
                return(fallback(callDynamic));
            }
예제 #28
0
 public ConditionalBuilder(DynamicMetaObjectBinder /*!*/ action)
 {
     _action = action;
 }
예제 #29
0
 public virtual MSAst.Expression /*!*/ Dynamic(DynamicMetaObjectBinder /*!*/ binder, Type /*!*/ retType, MSAst.Expression /*!*/ arg0)
 {
     return(MSAst.Expression.Dynamic(binder, retType, arg0));
 }
예제 #30
0
        private DynamicMetaObject/*!*/ InvokeWorker(DynamicMetaObjectBinder/*!*/ invoke, Expression/*!*/ codeContext, DynamicMetaObject/*!*/[] args) {
            PerfTrack.NoteEvent(PerfTrack.Categories.Binding, "OldClass Invoke");

            DynamicMetaObject self = Restrict(typeof(OldInstance));

            Expression[] exprArgs = new Expression[args.Length + 1];
            for (int i = 0; i < args.Length; i++) {
                exprArgs[i + 1] = args[i].Expression;
            }

            ParameterExpression tmp = Ast.Variable(typeof(object), "callFunc");

            exprArgs[0] = tmp;
            return new DynamicMetaObject(
                // we could get better throughput w/ a more specific rule against our current custom old class but
                // this favors less code generation.

                Ast.Block(
                    new ParameterExpression[] { tmp },
                    Ast.Condition(
                        Ast.Call(
                            typeof(PythonOps).GetMethod("OldInstanceTryGetBoundCustomMember"),
                            codeContext,
                            self.Expression,
                            AstUtils.Constant("__call__"),
                            tmp
                        ),
                        Ast.Block(
                            Utils.Try(
                                Ast.Call(typeof(PythonOps).GetMethod("FunctionPushFrameCodeContext"), codeContext),
                                Ast.Assign(
                                    tmp,
                                    Ast.Dynamic(
                                        PythonContext.GetPythonContext(invoke).Invoke(
                                            BindingHelpers.GetCallSignature(invoke)
                                        ),
                                        typeof(object),
                                        ArrayUtils.Insert(codeContext, exprArgs)
                                    )
                                )
                            ).Finally(
                                Ast.Call(typeof(PythonOps).GetMethod("FunctionPopFrame"))
                            ),
                            tmp
                        ),
                        Utils.Convert(
                            BindingHelpers.InvokeFallback(invoke, codeContext, this, args).Expression,
                            typeof(object)
                        )
                    )
                ),
                self.Restrictions.Merge(BindingRestrictions.Combine(args))
            );
        }        
예제 #31
0
        private DynamicMetaObject /*!*/ MakeMemberAccess(DynamicMetaObjectBinder /*!*/ member, string name, MemberAccess access, params DynamicMetaObject /*!*/[] /*!*/ args)
        {
            DynamicMetaObject self = Restrict(typeof(OldInstance));

            CustomInstanceDictionaryStorage dict;
            int key = GetCustomStorageSlot(name, out dict);

            if (key == -1)
            {
                PerfTrack.NoteEvent(PerfTrack.Categories.Binding, "OldInstance " + access + " NoOptimized");
                return(MakeDynamicMemberAccess(member, name, access, args));
            }

            ParameterExpression tmp = Ast.Variable(typeof(object), "dict");
            Expression          target;

            ValidationInfo test = new ValidationInfo(
                Ast.NotEqual(
                    Ast.Assign(
                        tmp,
                        Ast.Call(
                            typeof(PythonOps).GetMethod(nameof(PythonOps.OldInstanceGetOptimizedDictionary)),
                            self.Expression,
                            AstUtils.Constant(dict.KeyVersion)
                            )
                        ),
                    AstUtils.Constant(null)
                    )
                );

            PerfTrack.NoteEvent(PerfTrack.Categories.Binding, "OldInstance " + access + " Optimized");
            switch (access)
            {
            case MemberAccess.Invoke:
                ParameterExpression value = Ast.Variable(typeof(object), "value");
                target = Ast.Block(
                    new[] { value },
                    Ast.Condition(
                        Ast.Call(
                            typeof(PythonOps).GetMethod(nameof(PythonOps.TryOldInstanceDictionaryGetValueHelper)),
                            tmp,
                            Ast.Constant(key),
                            AstUtils.Convert(Expression, typeof(object)),
                            value
                            ),
                        AstUtils.Convert(
                            ((InvokeMemberBinder)member).FallbackInvoke(new DynamicMetaObject(value, BindingRestrictions.Empty), args, null).Expression,
                            typeof(object)
                            ),
                        AstUtils.Convert(
                            ((InvokeMemberBinder)member).FallbackInvokeMember(self, args).Expression,
                            typeof(object)
                            )
                        )
                    );
                break;

            case MemberAccess.Get:
                // BUG: There's a missing Fallback path here that's always been present even
                // in the version that used rules.
                target = Ast.Call(
                    typeof(PythonOps).GetMethod(nameof(PythonOps.OldInstanceDictionaryGetValueHelper)),
                    tmp,
                    AstUtils.Constant(key),
                    AstUtils.Convert(Expression, typeof(object))
                    );
                break;

            case MemberAccess.Set:
                target = Ast.Call(
                    typeof(PythonOps).GetMethod(nameof(PythonOps.OldInstanceDictionarySetExtraValue)),
                    tmp,
                    AstUtils.Constant(key),
                    AstUtils.Convert(args[1].Expression, typeof(object))
                    );
                break;

            case MemberAccess.Delete:
                target = Ast.Call(
                    typeof(PythonOps).GetMethod(nameof(PythonOps.OldInstanceDeleteCustomMember)),
                    AstUtils.Constant(PythonContext.GetPythonContext(member).SharedContext),
                    AstUtils.Convert(Expression, typeof(OldInstance)),
                    AstUtils.Constant(name)
                    );
                break;

            default:
                throw new InvalidOperationException();
            }

            return(BindingHelpers.AddDynamicTestAndDefer(
                       member,
                       new DynamicMetaObject(
                           target,
                           BindingRestrictions.Combine(args).Merge(self.Restrictions)
                           ),
                       args,
                       test,
                       tmp
                       ));
        }
예제 #32
0
        private DynamicMetaObject/*!*/ MakeConvertToIEnumerable(DynamicMetaObjectBinder/*!*/ conversion, Type toType, Type genericType) {
            ParameterExpression tmp = Ast.Variable(toType, "res");
            DynamicMetaObject self = Restrict(typeof(OldInstance));

            return new DynamicMetaObject(
                Ast.Block(
                    new ParameterExpression[] { tmp },
                    Ast.Condition(
                        Ast.NotEqual(
                            Ast.Assign(
                                tmp,
                                Ast.Call(
                                    typeof(PythonOps).GetMethod("OldInstanceConvertToIEnumerableOfTNonThrowing").MakeGenericMethod(genericType),
                                    AstUtils.Constant(PythonContext.GetPythonContext(conversion).SharedContext),
                                    self.Expression                                   
                                )
                            ),
                            AstUtils.Constant(null)
                        ),
                        tmp,
                        AstUtils.Convert(
                            AstUtils.Convert(
                                FallbackConvert(conversion).Expression,
                                typeof(object)
                            ),
                            toType
                        )
                    )
                ),
                self.Restrictions
            );                       
        }
예제 #33
0
 internal static DynamicMetaObject /*!*/ AddDynamicTestAndDefer(DynamicMetaObjectBinder /*!*/ operation, DynamicMetaObject /*!*/ res, DynamicMetaObject /*!*/[] args, ValidationInfo typeTest, params ParameterExpression[] temps)
 {
     return(AddDynamicTestAndDefer(operation, res, args, typeTest, null, temps));
 }
예제 #34
0
 private static BinaryExpression/*!*/ MakeOneConvert(DynamicMetaObjectBinder/*!*/ conversion, DynamicMetaObject/*!*/ self, string name, ParameterExpression/*!*/ tmp) {
     return Ast.NotEqual(
         Ast.Assign(
             tmp,
             Ast.Call(
                 typeof(PythonOps).GetMethod("OldInstanceConvertNonThrowing"),
                 AstUtils.Constant(PythonContext.GetPythonContext(conversion).SharedContext),
                 self.Expression,
                 AstUtils.Constant(name)
             )
         ),
         AstUtils.Constant(null)
     );
 }
예제 #35
0
        internal static DynamicMetaObject /*!*/ FilterShowCls(DynamicMetaObject /*!*/ codeContext, DynamicMetaObjectBinder /*!*/ action, DynamicMetaObject /*!*/ res, Expression /*!*/ failure)
        {
            if (action is IPythonSite)
            {
                return(new DynamicMetaObject(
                           Ast.Condition(
                               Ast.Call(
                                   typeof(PythonOps).GetMethod("IsClsVisible"),
                                   codeContext.Expression
                                   ),
                               AstUtils.Convert(res.Expression, typeof(object)),
                               AstUtils.Convert(failure, typeof(object))

                               ),
                           res.Restrictions
                           ));
            }

            return(res);
        }
예제 #36
0
        private DynamicMetaObject/*!*/ MakeMemberAccess(DynamicMetaObjectBinder/*!*/ member, string name, MemberAccess access, params DynamicMetaObject/*!*/[]/*!*/ args) {
            DynamicMetaObject self = Restrict(typeof(OldInstance));

            CustomOldClassDictionaryStorage dict;
            int key = GetCustomStorageSlot(name, out dict);
            if (key == -1) {
                PerfTrack.NoteEvent(PerfTrack.Categories.Binding, "OldInstance " + access + " NoOptimized"); 
                return MakeDynamicMemberAccess(member, name, access, args);
            }

            ParameterExpression tmp = Ast.Variable(typeof(object), "dict");
            Expression target;

            ValidationInfo test = new ValidationInfo(
                Ast.NotEqual(
                    Ast.Assign(
                        tmp, 
                        Ast.Call(
                            typeof(PythonOps).GetMethod("OldInstanceGetOptimizedDictionary"),
                            self.Expression,
                            AstUtils.Constant(dict.KeyVersion)
                        )
                    ), 
                    AstUtils.Constant(null)
                )
            );
            PerfTrack.NoteEvent(PerfTrack.Categories.Binding, "OldInstance " + access + " Optimized"); 
            switch (access) {
                case MemberAccess.Invoke:
                    ParameterExpression value = Ast.Variable(typeof(object), "value");
                    target = Ast.Block(
                        new[] { value },
                        Ast.Condition(
                            Ast.Call(
                                typeof(PythonOps).GetMethod("TryOldInstanceDictionaryGetValueHelper"),
                                tmp,
                                Ast.Constant(key),
                                AstUtils.Convert(Expression, typeof(object)),
                                value
                            ),
                            AstUtils.Convert(
                                ((InvokeMemberBinder)member).FallbackInvoke(new DynamicMetaObject(value, BindingRestrictions.Empty), args, null).Expression,
                                typeof(object)
                            ),
                            AstUtils.Convert(
                                ((InvokeMemberBinder)member).FallbackInvokeMember(self, args).Expression,
                                typeof(object)
                            )
                        )
                    );
                    break;
                case MemberAccess.Get:
                    // BUG: There's a missing Fallback path here that's always been present even
                    // in the version that used rules.
                    target = Ast.Call(
                        typeof(PythonOps).GetMethod("OldInstanceDictionaryGetValueHelper"),
                        tmp,
                        AstUtils.Constant(key),
                        AstUtils.Convert(Expression, typeof(object))
                    );
                    break;
                case MemberAccess.Set:
                    target = Ast.Call(
                        typeof(PythonOps).GetMethod("OldInstanceDictionarySetExtraValue"),
                        tmp,
                        AstUtils.Constant(key),
                        AstUtils.Convert(args[1].Expression, typeof(object))
                    );
                    break;
                case MemberAccess.Delete:
                    target = Ast.Call(
                        typeof(PythonOps).GetMethod("OldInstanceDeleteCustomMember"),
                        AstUtils.Constant(PythonContext.GetPythonContext(member).SharedContext),
                        AstUtils.Convert(Expression, typeof(OldInstance)),
                        AstUtils.Constant(name)
                    );
                    break;
                default:
                    throw new InvalidOperationException();
            }

            return BindingHelpers.AddDynamicTestAndDefer(
                member,
                new DynamicMetaObject(
                    target,
                    BindingRestrictions.Combine(args).Merge(self.Restrictions)
                ),
                args,
                test,
                tmp
            );                            
        }
        private static DynamicMetaObject/*!*/ MakeSimpleOperation(DynamicMetaObject/*!*/[]/*!*/ types, DynamicMetaObjectBinder/*!*/ binder, PythonOperationKind operation, DynamicMetaObject errorSuggestion) {
            RestrictTypes(types);

            SlotOrFunction fbinder;
            SlotOrFunction rbinder;
            PythonTypeSlot fSlot;
            PythonTypeSlot rSlot;
            GetOperatorMethods(types, operation, PythonContext.GetPythonContext(binder), out fbinder, out rbinder, out fSlot, out rSlot);

            return MakeBinaryOperatorResult(types, binder, operation, fbinder, rbinder, fSlot, rSlot, errorSuggestion);
        }
예제 #38
0
        private static Expression FallbackGet(DynamicMetaObjectBinder member, DynamicMetaObject[] args) {
            GetMemberBinder sa = member as GetMemberBinder;
            if (sa != null) {
                return sa.FallbackGetMember(args[0]).Expression;
            }

            return ((PythonGetMemberBinder)member).Fallback(args[0], PythonContext.GetCodeContextMO(member)).Expression;
        }
예제 #39
0
 public virtual MSAst.Expression/*!*/ Dynamic(DynamicMetaObjectBinder/*!*/ binder, Type/*!*/ retType, IList<MSAst.Expression/*!*/>/*!*/ args) {
     Assert.NotNull(binder, retType, args);
     Assert.NotNullItems(args);
     return MSAst.Expression.Dynamic(binder, retType, args);
 }
예제 #40
0
 static DynamicMetaObject \u200C‍‌‬‫‪​‪‏‎​‮‏‮‪‌‎‌‎‬‫‪‎‏‌‌‮‫‎‌‮([In] DynamicMetaObjectBinder obj0, [In] DynamicMetaObject obj1, [In] DynamicMetaObject[] obj2)
 {
     // ISSUE: unable to decompile the method.
 }
예제 #41
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), "NotImplemented"),
                    res.Restrictions
                    );
            }
            else if (target.Overload != null)
            {
                // Add profiling information for this builtin function, if applicable
                IPythonSite pythonSite = (call as IPythonSite);
                if (pythonSite != null)
                {
                    var pc = pythonSite.Context;
                    var po = pc.Options as PythonOptions;
                    if (po != null && 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);
        }
예제 #42
0
 public BinderMappingInfo(DynamicMetaObjectBinder binder, IList<ParameterMappingInfo> mappingInfo) {
     Binder = binder;
     MappingInfo = mappingInfo;
 }
예제 #43
0
 internal DynamicMetaObject /*!*/ CreateMetaObject(DynamicMetaObjectBinder /*!*/ action)
 {
     return(CreateMetaObject(action, action.ReturnType));
 }
예제 #44
0
 public BinderMappingInfo(DynamicMetaObjectBinder binder, params ParameterMappingInfo[] mappingInfos)
     : this(binder, (IList<ParameterMappingInfo>)mappingInfos) {
 }
예제 #45
0
        public DynamicMetaObject ConvertWorker(DynamicMetaObjectBinder binder, Type type, Type retType, ConversionResultKind kind) {
            if (!type.IsEnum) {
                switch (Type.GetTypeCode(type)) {
                    case TypeCode.Boolean:
                        return MakeConvertToBool(binder);
                    case TypeCode.Int32:
                        return MakeConvertToCommon(binder, type, retType, "__int__");
                    case TypeCode.Double:
                        return MakeConvertToCommon(binder, type, retType, "__float__");
                    case TypeCode.String:
                        return MakeConvertToCommon(binder, type, retType, "__str__");
                    case TypeCode.Object:
                        if (type == typeof(BigInteger)) {
                            return MakeConvertToCommon(binder, type, retType, "__long__");
                        } else if (type == typeof(Complex64)) {
                            return MakeConvertToCommon(binder, type, retType, "__complex__");
                        } else if (type == typeof(IEnumerable)) {
                            return MakeConvertToIEnumerable(binder);
                        } else if (type == typeof(IEnumerator)) {
                            return MakeConvertToIEnumerator(binder);
                        } else if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IEnumerable<>)) {
                            return MakeConvertToIEnumerable(binder, type, type.GetGenericArguments()[0]);
                        } else if (type.IsSubclassOf(typeof(Delegate))) {
                            return MakeDelegateTarget(binder, type, Restrict(typeof(OldInstance)));
                        }

                        break;
                }
            }

            return FallbackConvert(binder);
        }
예제 #46
0
        internal static DynamicMetaObject FallbackWorker(PythonContext context, DynamicMetaObject /*!*/ self, DynamicMetaObject /*!*/ codeContext, string name, GetMemberOptions options, DynamicMetaObjectBinder action, DynamicMetaObject errorSuggestion)
        {
            if (self.NeedsDeferral())
            {
                return(action.Defer(self));
            }
            PythonOverloadResolverFactory resolverFactory = new PythonOverloadResolverFactory(context.Binder, codeContext.Expression);

            PerfTrack.NoteEvent(PerfTrack.Categories.BindingTarget, "FallbackGet");

            bool isNoThrow = ((options & GetMemberOptions.IsNoThrow) != 0) ? true : false;
            Type limitType = self.GetLimitType();

            if (limitType == typeof(DynamicNull) || PythonBinder.IsPythonType(limitType))
            {
                // look up in the PythonType so that we can
                // get our custom method names (e.g. string.startswith)
                PythonType argType = DynamicHelpers.GetPythonTypeFromType(limitType);

                // if the name is defined in the CLS context but not the normal context then
                // we will hide it.
                if (argType.IsHiddenMember(name))
                {
                    DynamicMetaObject baseRes = PythonContext.GetPythonContext(action).Binder.GetMember(
                        name,
                        self,
                        resolverFactory,
                        isNoThrow,
                        errorSuggestion
                        );
                    Expression failure = GetFailureExpression(limitType, self, name, isNoThrow, action);

                    return(BindingHelpers.FilterShowCls(codeContext, action, baseRes, failure));
                }
            }

            var res = context.Binder.GetMember(name, self, resolverFactory, isNoThrow, errorSuggestion);

            if (res is ErrorMetaObject)
            {
                // see if we can bind to any extension methods...
                var codeCtx    = (CodeContext)codeContext.Value;
                var extMethods = codeCtx.ModuleContext.ExtensionMethods;

                if (extMethods != null)
                {
                    // try again w/ the extension method binder
                    res = extMethods.GetBinder(context).GetMember(name, self, resolverFactory, isNoThrow, errorSuggestion);
                }

                // and add any restrictions (we need an empty restriction even if it's an error so later adds work)
                res = new DynamicMetaObject(
                    res.Expression,
                    res.Restrictions.Merge(extMethods.GetRestriction(codeContext.Expression))
                    );
            }

            // Default binder 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 = new DynamicMetaObject(
                    AstUtils.Convert(res.Expression, typeof(object)),
                    res.Restrictions
                    );
            }

            return(res);
        }
예제 #47
0
        private DynamicMetaObject/*!*/ MakeConvertToIEnumerable(DynamicMetaObjectBinder/*!*/ conversion) {
            ParameterExpression tmp = Ast.Variable(typeof(IEnumerable), "res");
            DynamicMetaObject self = Restrict(typeof(OldInstance));

            return new DynamicMetaObject(
                Ast.Block(
                    new ParameterExpression[] { tmp },
                    Ast.Condition(
                        Ast.NotEqual(
                            Ast.Assign(
                                tmp,
                                Ast.Call(
                                    typeof(PythonOps).GetMethod("OldInstanceConvertToIEnumerableNonThrowing"),
                                    AstUtils.Constant(PythonContext.GetPythonContext(conversion).SharedContext),
                                    self.Expression
                                )
                            ),
                            AstUtils.Constant(null)
                        ),
                        tmp,
                        AstUtils.Convert(
                            AstUtils.Convert(  // first to object (incase it's a throw), then to IEnumerable
                                FallbackConvert(conversion).Expression,
                                typeof(object)
                            ),
                            typeof(IEnumerable)
                        )
                    )
                ),
                self.Restrictions
            );
        }
예제 #48
0
 private static Expression /*!*/ GetFailureExpression(Type /*!*/ limitType, DynamicMetaObject self, string name, bool isNoThrow, DynamicMetaObjectBinder action)
 {
     return(isNoThrow ?
            Ast.Field(null, typeof(OperationFailed).GetField("Value")) :
            DefaultBinder.MakeError(
                PythonContext.GetPythonContext(action).Binder.MakeMissingMemberError(
                    limitType,
                    self,
                    name
                    ),
                typeof(object)
                ).Expression);
 }
예제 #49
0
 private DynamicMetaObject/*!*/ MakeConvertToCommon(DynamicMetaObjectBinder/*!*/ conversion, Type toType, Type retType, string name) {
     // TODO: support trys
     ParameterExpression tmp = Ast.Variable(typeof(object), "convertResult");
     DynamicMetaObject self = Restrict(typeof(OldInstance));
     return new DynamicMetaObject(
         Ast.Block(
             new ParameterExpression[] { tmp },
             Ast.Condition(
                 MakeOneConvert(conversion, self, name, tmp),
                 Expression.Convert(
                     tmp,
                     retType
                 ),
                 FallbackConvert(conversion).Expression
             )
         ),
         self.Restrictions
     );
 }
예제 #50
0
        /// <summary>
        /// Creating a Python type involves calling __new__ and __init__.  We resolve them
        /// and generate calls to either the builtin funcions directly or embed sites which
        /// call the slots at runtime.
        /// </summary>
        private DynamicMetaObject /*!*/ MakePythonTypeCall(DynamicMetaObjectBinder /*!*/ call, Expression /*!*/ codeContext, DynamicMetaObject /*!*/[] /*!*/ args)
        {
            ValidationInfo valInfo = MakeVersionCheck();

            DynamicMetaObject self = new RestrictedMetaObject(
                AstUtils.Convert(Expression, LimitType),
                BindingRestrictionsHelpers.GetRuntimeTypeRestriction(Expression, LimitType),
                Value
                );
            CallSignature  sig = BindingHelpers.GetCallSignature(call);
            ArgumentValues ai  = new ArgumentValues(sig, self, args);
            NewAdapter     newAdapter;
            InitAdapter    initAdapter;

            if (TooManyArgsForDefaultNew(call, args))
            {
                return(MakeIncorrectArgumentsForCallError(call, ai, valInfo));
            }
            else if (Value.UnderlyingSystemType.IsGenericTypeDefinition)
            {
                return(MakeGenericTypeDefinitionError(call, ai, valInfo));
            }
            else if (Value.HasAbstractMethods(PythonContext.GetPythonContext(call).SharedContext))
            {
                return(MakeAbstractInstantiationError(call, ai, valInfo));
            }

            DynamicMetaObject translated = BuiltinFunction.TranslateArguments(call, codeContext, self, args, false, Value.Name);

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

            GetAdapters(ai, call, codeContext, out newAdapter, out initAdapter);
            PythonContext state = PythonContext.GetPythonContext(call);

            // get the expression for calling __new__
            DynamicMetaObject createExpr = newAdapter.GetExpression(state.Binder);

            if (createExpr.Expression.Type == typeof(void))
            {
                return(BindingHelpers.AddDynamicTestAndDefer(
                           call,
                           createExpr,
                           args,
                           valInfo
                           ));
            }

            Expression          res;
            BindingRestrictions additionalRestrictions = BindingRestrictions.Empty;

            if (!Value.IsSystemType && (!(newAdapter is DefaultNewAdapter) || HasFinalizer(call)))
            {
                // we need to dynamically check the return value to see if it's a subtype of
                // the type that we are calling.  If it is then we need to call __init__/__del__
                // for the actual returned type.
                res = Expression.Dynamic(
                    Value.GetLateBoundInitBinder(sig),
                    typeof(object),
                    ArrayUtils.Insert(
                        codeContext,
                        Expression.Convert(createExpr.Expression, typeof(object)),
                        DynamicUtils.GetExpressions(args)
                        )
                    );
                additionalRestrictions = createExpr.Restrictions;
            }
            else
            {
                // just call the __init__ method, built-in types currently have
                // no wacky return values which don't return the derived type.

                // then get the statement for calling __init__
                ParameterExpression allocatedInst = Ast.Variable(createExpr.GetLimitType(), "newInst");
                Expression          tmpRead       = allocatedInst;
                DynamicMetaObject   initCall      = initAdapter.MakeInitCall(
                    state.Binder,
                    new RestrictedMetaObject(
                        AstUtils.Convert(allocatedInst, Value.UnderlyingSystemType),
                        createExpr.Restrictions
                        )
                    );

                List <Expression> body = new List <Expression>();
                Debug.Assert(!HasFinalizer(call));

                // add the call to init if we need to
                if (initCall.Expression != tmpRead)
                {
                    // init can fail but if __new__ returns a different type
                    // no exception is raised.
                    DynamicMetaObject initStmt = initCall;

                    if (body.Count == 0)
                    {
                        body.Add(
                            Ast.Assign(allocatedInst, createExpr.Expression)
                            );
                    }

                    if (!Value.UnderlyingSystemType.IsAssignableFrom(createExpr.Expression.Type))
                    {
                        // return type of object, we need to check the return type before calling __init__.
                        body.Add(
                            AstUtils.IfThen(
                                Ast.TypeIs(allocatedInst, Value.UnderlyingSystemType),
                                initStmt.Expression
                                )
                            );
                    }
                    else
                    {
                        // just call the __init__ method, no type check necessary (TODO: need null check?)
                        body.Add(initStmt.Expression);
                    }
                }

                // and build the target from everything we have
                if (body.Count == 0)
                {
                    res = createExpr.Expression;
                }
                else
                {
                    body.Add(allocatedInst);
                    res = Ast.Block(body);
                }
                res = Ast.Block(new ParameterExpression[] { allocatedInst }, res);

                additionalRestrictions = initCall.Restrictions;
            }

            return(BindingHelpers.AddDynamicTestAndDefer(
                       call,
                       new DynamicMetaObject(
                           res,
                           self.Restrictions.Merge(additionalRestrictions)
                           ),
                       ArrayUtils.Insert(this, args),
                       valInfo
                       ));
        }
예제 #51
0
        private DynamicMetaObject/*!*/ MakeConvertToBool(DynamicMetaObjectBinder/*!*/ conversion) {
            DynamicMetaObject self = Restrict(typeof(OldInstance));

            ParameterExpression tmp = Ast.Variable(typeof(bool?), "tmp");
            DynamicMetaObject fallback = FallbackConvert(conversion);
            Type resType = BindingHelpers.GetCompatibleType(typeof(bool), fallback.Expression.Type);

            return new DynamicMetaObject(
                Ast.Block(
                    new ParameterExpression[] { tmp },
                    Ast.Condition(
                        Ast.NotEqual(
                            Ast.Assign(
                                tmp,
                                Ast.Call(
                                    typeof(PythonOps).GetMethod("OldInstanceConvertToBoolNonThrowing"),
                                    AstUtils.Constant(PythonContext.GetPythonContext(conversion).SharedContext),
                                    self.Expression
                                )
                            ),
                            AstUtils.Constant(null)
                        ),
                        AstUtils.Convert(tmp, resType),
                        AstUtils.Convert(fallback.Expression, resType)
                    )
                ),
                self.Restrictions
            );
        }
예제 #52
0
        private InitAdapter /*!*/ GetInitAdapter(ArgumentValues /*!*/ ai, PythonTypeSlot /*!*/ init, DynamicMetaObjectBinder /*!*/ call, Expression /*!*/ codeContext)
        {
            PythonContext state = PythonContext.GetPythonContext(call);

            if (Value.IsMixedNewStyleOldStyle())
            {
                return(new MixedInitAdapter(ai, state, codeContext));
            }
            else if ((init == InstanceOps.Init && !HasFinalizer(call)) || (Value == TypeCache.PythonType && ai.Arguments.Length == 2))
            {
                return(new DefaultInitAdapter(ai, state, codeContext));
            }
            else if (init is BuiltinMethodDescriptor)
            {
                return(new BuiltinInitAdapter(ai, ((BuiltinMethodDescriptor)init).Template, state, codeContext));
            }
            else if (init is BuiltinFunction)
            {
                return(new BuiltinInitAdapter(ai, (BuiltinFunction)init, state, codeContext));
            }
            else
            {
                return(new SlotInitAdapter(init, ai, state, codeContext));
            }
        }
예제 #53
0
        private DynamicMetaObject/*!*/ MakeDynamicMemberAccess(DynamicMetaObjectBinder/*!*/ member, string/*!*/ name, MemberAccess access, DynamicMetaObject/*!*/[]/*!*/ args) {
            DynamicMetaObject self = Restrict(typeof(OldInstance));
            Expression target;

            ParameterExpression tmp = Ast.Variable(typeof(object), "result");

            switch (access) {
                case MemberAccess.Invoke:

                    target = Ast.Block(
                        new ParameterExpression[] { tmp },
                        Ast.Condition(
                            Ast.Call(
                                typeof(PythonOps).GetMethod("OldInstanceTryGetBoundCustomMember"),
                                Ast.Constant(PythonContext.GetPythonContext(member).SharedContext),
                                self.Expression,
                                AstUtils.Constant(name),
                                tmp
                            ),
                            ((InvokeMemberBinder)member).FallbackInvoke(new DynamicMetaObject(tmp, BindingRestrictions.Empty), args, null).Expression,
                            AstUtils.Convert(                            
                                ((InvokeMemberBinder)member).FallbackInvokeMember(this, args).Expression,
                                typeof(object)
                            )
                        )
                    );
                    break;
                case MemberAccess.Get:                    
                    target = Ast.Block(
                        new ParameterExpression[] { tmp },
                        Ast.Condition(
                            Ast.Call(
                                typeof(PythonOps).GetMethod("OldInstanceTryGetBoundCustomMember"),
                                AstUtils.Constant(PythonContext.GetPythonContext(member).SharedContext),
                                self.Expression,
                                AstUtils.Constant(name),
                                tmp
                            ),
                            tmp,
                            AstUtils.Convert(
                                FallbackGet(member, args),
                                typeof(object)
                            )
                        )
                    );                    
                    break;
                case MemberAccess.Set:
                    target = Ast.Call(
                        typeof(PythonOps).GetMethod("OldInstanceSetCustomMember"),
                        AstUtils.Constant(PythonContext.GetPythonContext(member).SharedContext),
                        self.Expression,
                        AstUtils.Constant(name),
                        AstUtils.Convert(args[1].Expression, typeof(object))
                    );
                    break;
                case MemberAccess.Delete:
                    target = Ast.Call(
                        typeof(PythonOps).GetMethod("OldInstanceDeleteCustomMember"),
                        AstUtils.Constant(PythonContext.GetPythonContext(member).SharedContext),
                        self.Expression,
                        AstUtils.Constant(name)
                    );
                    break;
                default:
                    throw new InvalidOperationException();
            }

            return new DynamicMetaObject(
                target,
                self.Restrictions.Merge(BindingRestrictions.Combine(args))
            );
        }
예제 #54
0
        private NewAdapter /*!*/ GetNewAdapter(ArgumentValues /*!*/ ai, PythonTypeSlot /*!*/ newInst, DynamicMetaObjectBinder /*!*/ call, Expression /*!*/ codeContext)
        {
            PythonContext state = PythonContext.GetPythonContext(call);

            if (Value.IsMixedNewStyleOldStyle())
            {
                return(new MixedNewAdapter(ai, state, codeContext));
            }
            else if (newInst == InstanceOps.New)
            {
                return(new DefaultNewAdapter(ai, Value, state, codeContext));
            }
            else if (newInst is ConstructorFunction)
            {
                return(new ConstructorNewAdapter(ai, Value, state, codeContext));
            }
            else if (newInst is BuiltinFunction)
            {
                return(new BuiltinNewAdapter(ai, Value, ((BuiltinFunction)newInst), state, codeContext));
            }

            return(new NewAdapter(ai, state, codeContext));
        }
예제 #55
0
        private static ConstantExpression Constant(DynamicMetaObjectBinder binder)
        {
            Type t = binder.GetType();

            return(Expression.Constant(binder, t));
        }
예제 #56
0
 private bool HasDefaultNewAndInit(DynamicMetaObjectBinder /*!*/ action)
 {
     return(HasDefaultNew(action) && HasDefaultInit(action));
 }
예제 #57
0
        /// <summary>
        /// Helper method for generating a MetaObject which calls a
        /// specific method on DynamicObject that returns a result.
        ///
        /// args is either an array of arguments to be passed
        /// to the method as an object[] or NoArgs to signify that
        /// the target method takes no parameters.
        /// </summary>
        private DynamicMetaObject BuildCallMethodWithResult(string methodName, DynamicMetaObjectBinder binder, Expression[] args, DynamicMetaObject fallbackResult, Fallback fallbackInvoke)
        {
            if (!IsOverridden(methodName))
            {
                return(fallbackResult);
            }

            //
            // Build a new expression like:
            // {
            //   object result;
            //   TryGetMember(payload, out result) ? fallbackInvoke(result) : fallbackResult
            // }
            //
            var result = Expression.Parameter(typeof(object), null);
            ParameterExpression callArgs = methodName != "TryBinaryOperation" ? Expression.Parameter(typeof(object[]), null) : Expression.Parameter(typeof(object), null);
            var callArgsValue            = GetConvertedArgs(args);

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

            // Need to add a conversion if calling TryConvert
            if (binder.ReturnType != typeof(object))
            {
                Debug.Assert(binder is ConvertBinder && fallbackInvoke == null);

                var convert = Expression.Convert(resultMO.Expression, binder.ReturnType);
                // will always be a cast or unbox
                Debug.Assert(convert.Method == null);

                // Prepare a good exception message in case the convert will fail
                string convertFailed = string.Format(
                    "The result type '{0}' of the dynamic binding produced by the object with type '{1}' for the binder '{2}' is not compati         ble with the result type '{3}' expected by the call site.",
                    "{0}",
                    this.Value.GetType(),
                    binder.GetType(),
                    binder.ReturnType
                    );

                var checkedConvert = Expression.Condition(
                    Expression.TypeIs(resultMO.Expression, binder.ReturnType),
                    convert,
                    Expression.Throw(
                        Expression.New(typeof(InvalidCastException).GetConstructor(new Type[] { typeof(string) }),
                                       Expression.Call(
                                           typeof(string).GetMethod("Format", new Type[] { typeof(string), typeof(object) }),
                                           Expression.Constant(convertFailed),
                                           Expression.Condition(
                                               Expression.Equal(resultMO.Expression, Expression.Constant(null)),
                                               Expression.Constant("null"),
                                               Expression.Call(
                                                   resultMO.Expression,
                                                   typeof(object).GetMethod("GetType")
                                                   ),
                                               typeof(object)
                                               )
                                           )
                                       ),
                        binder.ReturnType
                        ),
                    binder.ReturnType
                    );

                resultMO = new DynamicMetaObject(checkedConvert, resultMO.Restrictions);
            }

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

            var callDynamic = new DynamicMetaObject(
                Expression.Block(
                    new[] { result, callArgs },
                    methodName != "TryBinaryOperation" ? Expression.Assign(callArgs, Expression.NewArrayInit(typeof(object), callArgsValue)) : Expression.Assign(callArgs, callArgsValue[0]),
                    Expression.Condition(
                        Expression.Call(
                            GetLimitedSelf(),
                            ValueType.GetMethod(methodName),
                            BuildCallArgs(
                                binder,
                                args,
                                callArgs,
                                result
                                )
                            ),
                        Expression.Block(
                            methodName != "TryBinaryOperation" ? ReferenceArgAssign(callArgs, args) : Expression.Empty(),
                            resultMO.Expression
                            ),
                        fallbackResult.Expression,
                        binder.ReturnType
                        )
                    ),
                GetRestrictions().Merge(resultMO.Restrictions).Merge(fallbackResult.Restrictions)
                );

            return(callDynamic);
        }
예제 #58
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
                       ));
        }
예제 #59
0
 private DynamicMetaObject /*!*/ MakeConvertRuleForCall(DynamicMetaObjectBinder /*!*/ convertToAction, Type toType, DynamicMetaObject /*!*/ self, string name, string returner)
 {
     return(MakeConvertRuleForCall(convertToAction, toType, self, name, returner, () => FallbackConvert(convertToAction), (x) => x));
 }
예제 #60
0
        private DynamicMetaObject /*!*/ InvokeWorker(DynamicMetaObjectBinder /*!*/ invoke, Expression /*!*/ codeContext, DynamicMetaObject /*!*/[] args)
        {
            PerfTrack.NoteEvent(PerfTrack.Categories.Binding, "OldClass Invoke");

            DynamicMetaObject self = Restrict(typeof(OldInstance));

            Expression[] exprArgs = new Expression[args.Length + 1];
            for (int i = 0; i < args.Length; i++)
            {
                exprArgs[i + 1] = args[i].Expression;
            }

            ParameterExpression tmp = Ast.Variable(typeof(object), "callFunc");

            exprArgs[0] = tmp;
            return(new DynamicMetaObject(
                       // we could get better throughput w/ a more specific rule against our current custom old class but
                       // this favors less code generation.

                       Ast.Block(
                           new ParameterExpression[] { tmp },
                           Ast.Condition(
                               Expression.Not(
                                   Expression.TypeIs(
                                       Expression.Assign(
                                           tmp,
                                           Ast.Call(
                                               typeof(PythonOps).GetMethod(nameof(PythonOps.OldInstanceTryGetBoundCustomMember)),
                                               codeContext,
                                               self.Expression,
                                               AstUtils.Constant("__call__")
                                               )
                                           ),
                                       typeof(OperationFailed)
                                       )
                                   ),
                               Ast.Block(
                                   Utils.Try(
                                       Ast.Call(typeof(PythonOps).GetMethod(nameof(PythonOps.FunctionPushFrameCodeContext)), codeContext),
                                       Ast.Assign(
                                           tmp,
                                           DynamicExpression.Dynamic(
                                               PythonContext.GetPythonContext(invoke).Invoke(
                                                   BindingHelpers.GetCallSignature(invoke)
                                                   ),
                                               typeof(object),
                                               ArrayUtils.Insert(codeContext, exprArgs)
                                               )
                                           )
                                       ).Finally(
                                       Ast.Call(typeof(PythonOps).GetMethod(nameof(PythonOps.FunctionPopFrame)))
                                       ),
                                   tmp
                                   ),
                               Utils.Convert(
                                   BindingHelpers.InvokeFallback(invoke, codeContext, this, args).Expression,
                                   typeof(object)
                                   )
                               )
                           ),
                       self.Restrictions.Merge(BindingRestrictions.Combine(args))
                       ));
        }