Exemplo n.º 1
0
        private static Expression /*!*/ AddExtensibleSelfCheck(DynamicMetaObjectBinder /*!*/ convertToAction, Type toType, DynamicMetaObject /*!*/ self, Expression /*!*/ callExpr)
        {
            ParameterExpression  tmp     = Ast.Variable(callExpr.Type, "tmp");
            ConversionResultKind resKind = GetResultKind(convertToAction);
            Type retType = (resKind == ConversionResultKind.ExplicitTry || resKind == ConversionResultKind.ImplicitTry) ? typeof(object) : toType;

            callExpr = Ast.Block(
                new ParameterExpression[] { tmp },
                Ast.Block(
                    Ast.Assign(tmp, callExpr),
                    Ast.Condition(
                        Ast.Equal(tmp, self.Expression),
                        AstUtils.Convert(
                            Ast.Property(
                                AstUtils.Convert(self.Expression, self.GetLimitType()),
                                self.GetLimitType().GetProperty("Value")
                                ),
                            retType
                            ),
                        Ast.Dynamic(
                            new PythonConversionBinder(
                                PythonContext.GetPythonContext(convertToAction),
                                toType,
                                GetResultKind(convertToAction)
                                ),
                            retType,
                            tmp
                            )
                        )
                    )
                );
            return(callExpr);
        }
        public DynamicMetaObject ConvertTo(Type toType, ConversionResultKind kind, DynamicMetaObject arg, OverloadResolverFactory resolverFactory, DynamicMetaObject errorSuggestion)
        {
            ContractUtils.RequiresNotNull(toType, "toType");
            ContractUtils.RequiresNotNull(arg, "arg");

            Type knownType = arg.GetLimitType();

            // try all the conversions - first look for conversions against the expression type,
            // these can be done w/o any additional tests.  Then look for conversions against the
            // restricted type.
            BindingRestrictions typeRestrictions = arg.Restrictions.Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(arg.Expression, arg.GetLimitType()));

            DynamicMetaObject res =
                TryConvertToObject(toType, arg.Expression.Type, arg, typeRestrictions) ??
                TryAllConversions(resolverFactory, toType, kind, arg.Expression.Type, typeRestrictions, arg) ??
                TryAllConversions(resolverFactory, toType, kind, arg.GetLimitType(), typeRestrictions, arg) ??
                errorSuggestion ??
                MakeErrorTarget(toType, kind, typeRestrictions, arg);

            if ((kind == ConversionResultKind.ExplicitTry || kind == ConversionResultKind.ImplicitTry) && toType.IsValueType)
            {
                res = new DynamicMetaObject(
                    AstUtils.Convert(
                        res.Expression,
                        typeof(object)
                        ),
                    res.Restrictions
                    );
            }
            return(res);
        }
Exemplo n.º 3
0
        private DynamicMetaObject /*!*/ MakeToBoolConversion(DynamicMetaObject /*!*/ self)
        {
            DynamicMetaObject res;

            if (self.HasValue)
            {
                self = self.Restrict(self.GetRuntimeType());
            }

            // Optimization: if we already boxed it to a bool, and now
            // we're unboxing it, remove the unnecessary box.
            if (self.Expression.NodeType == ExpressionType.Convert && self.Expression.Type == typeof(object))
            {
                var convert = (UnaryExpression)self.Expression;
                if (convert.Operand.Type == typeof(bool))
                {
                    return(new DynamicMetaObject(convert.Operand, self.Restrictions));
                }
            }

            if (self.GetLimitType() == typeof(DynamicNull))
            {
                // None has no __nonzero__ and no __len__ but it's always false
                res = MakeNoneToBoolConversion(self);
            }
            else if (self.GetLimitType() == typeof(bool))
            {
                // nothing special to convert from bool to bool
                res = self;
            }
            else if (typeof(IStrongBox).IsAssignableFrom(self.GetLimitType()))
            {
                // Explictly block conversion of References to bool
                res = MakeStrongBoxToBoolConversionError(self);
            }
            else if (self.GetLimitType().IsPrimitive || self.GetLimitType().IsEnum)
            {
                // optimization - rather than doing a method call for primitives and enums generate
                // the comparison to zero directly.
                res = MakePrimitiveToBoolComparison(self);
            }
            else
            {
                // anything non-null that doesn't fall under one of the above rules is true.  So we
                // fallback to the base Python conversion which will check for __nonzero__ and
                // __len__.  The fallback is handled by our ConvertTo site binder.
                return
                    (PythonProtocol.ConvertToBool(this, self) ??
                     new DynamicMetaObject(
                         AstUtils.Constant(true),
                         self.Restrictions
                         ));
            }

            return(res);
        }
Exemplo n.º 4
0
            public override DynamicMetaObject /*!*/ FallbackInvoke(DynamicMetaObject /*!*/ target, DynamicMetaObject /*!*/[] /*!*/ args,
                                                                   DynamicMetaObject errorSuggestion)
            {
                // Used in combination with GetMember to compose InvokeMember operation.
                // Gets here only if the target is not a callable meta-object.

                var metaBuilder = new MetaObjectBuilder(this, target, args);
                var callArgs    = new CallArguments(_context, target, args, CallInfo);

                metaBuilder.AddTypeRestriction(target.GetLimitType(), target.Expression);

                RubyOverloadResolver.NormalizeArguments(metaBuilder, callArgs, 0, 0);
                if (!metaBuilder.Error)
                {
                    // no arguments => just return the target:
                    metaBuilder.Result = target.Expression;
                }
                else
                {
                    // any arguments found (expected none):
                    metaBuilder.SetMetaResult(errorSuggestion, false);
                }

                return(metaBuilder.CreateMetaObject(this));
            }
Exemplo n.º 5
0
        /// <summary>
        /// Provides default binding for performing a call on the specified meta objects.
        /// </summary>
        /// <param name="signature">The signature describing the call</param>
        /// <param name="target">The meta object to be called.</param>
        /// <param name="args">
        /// Additional meta objects are the parameters for the call as specified by the CallSignature in the CallAction.
        /// </param>
        /// <param name="resolverFactory">Overload resolver factory.</param>
        /// <param name="errorSuggestion">The result should the object be uncallable.</param>
        /// <returns>A MetaObject representing the call or the error.</returns>
        public DynamicMetaObject Call(CallSignature signature, DynamicMetaObject errorSuggestion, OverloadResolverFactory resolverFactory, DynamicMetaObject target, params DynamicMetaObject[] args)
        {
            ContractUtils.RequiresNotNullItems(args, nameof(args));
            ContractUtils.RequiresNotNull(resolverFactory, nameof(resolverFactory));

            TargetInfo targetInfo = GetTargetInfo(target, args);

            if (targetInfo != null)
            {
                // we're calling a well-known MethodBase
                DynamicMetaObject res = MakeMetaMethodCall(signature, resolverFactory, targetInfo);
                if (res.Expression.Type.IsValueType())
                {
                    res = new DynamicMetaObject(
                        AstUtils.Convert(res.Expression, typeof(object)),
                        res.Restrictions
                        );
                }

                return(res);
            }
            else
            {
                // we can't call this object
                return(errorSuggestion ?? MakeCannotCallRule(target, target.GetLimitType()));
            }
        }
Exemplo n.º 6
0
        protected internal override DynamicMetaObject GetBoundValue(OverloadResolverFactory resolverFactory, ActionBinder binder, Type type, DynamicMetaObject instance)
        {
            if (instance != null && IsStatic)
            {
                return(null);
            }

            if (GetIndexParameters().Length > 0)
            {
                // need to bind to a value or parameters to get the value.
                return(binder.ReturnMemberTracker(type, BindToInstance(instance)));
            }

            MethodInfo getter = GetGetMethod(true);

            if (getter == null || getter.ContainsGenericParameters)
            {
                // no usable getter
                return(null);
            }

            // TODO (tomat): this used to use getter.ReflectedType, is it still correct?
            getter = CompilerHelpers.TryGetCallableMethod(instance.GetLimitType(), getter);

            var defaultBinder = (DefaultBinder)binder;

            if (binder.PrivateBinding || CompilerHelpers.IsVisible(getter))
            {
                return(defaultBinder.MakeCallExpression(resolverFactory, getter, instance));
            }

            // private binding is just a call to the getter method...
            return(DefaultBinder.MakeError(defaultBinder.MakeNonPublicMemberGetError(resolverFactory, this, type, instance), BindingRestrictions.Empty, typeof(object)));
        }
Exemplo n.º 7
0
        DynamicMetaObject MakeGetMemberTarget(GetMemberInfo info, DynamicMetaObject target)
        {
            var type         = target.GetLimitType();
            var restrictions = target.Restrictions;
            var self         = target;

            target = target.Restrict(target.GetLimitType());
            var members = MemberGroup.EmptyGroup;

            // メンバ取得対象が TypeTracker である場合
            if (typeof(TypeTracker).IsAssignableFrom(type))
            {
                restrictions = restrictions.Merge(BindingRestrictions.GetInstanceRestriction(target.Expression, target.Value));
                var tg = target.Value as TypeGroup;
                if (tg == null || tg.TypesByArity.ContainsKey(0))
                {
                    var targetedType = ((TypeTracker)target.Value).Type;
                    members = GetMember(MemberRequestKind.Get, targetedType, info.Name);
                    if (members.Count > 0)
                    {
                        type = targetedType;
                        self = null;
                    }
                }
            }
            // 通常のメンバ一覧を検索
            if (members.Count == 0)
            {
                members = GetMember(MemberRequestKind.Get, type, info.Name);
            }
            // インターフェイスの場合、object メンバを検索
            if (members.Count == 0 && type.IsInterface)
            {
                members = GetMember(MemberRequestKind.Get, type = typeof(object), info.Name);
            }
            // プロパティ・フィールド用に StrongBox を展開し、そこから検索
            var expandedSelf = self;

            if (members.Count == 0 && typeof(IStrongBox).IsAssignableFrom(type) && expandedSelf != null)
            {
                expandedSelf = new DynamicMetaObject(Expression.Field(AstUtils.Convert(expandedSelf.Expression, type), type.GetField("Value")), expandedSelf.Restrictions, ((IStrongBox)expandedSelf.Value).Value);
                type         = type.GetGenericArguments()[0];
                members      = GetMember(MemberRequestKind.Get, type, info.Name);
            }
            MakeBodyHelper(info, self, expandedSelf, type, members);
            return(info.Body.GetMetaObject(restrictions));
        }
Exemplo n.º 8
0
 private ErrorInfo MakeInvalidSplatteeError(BindingTarget target) {
     return ErrorInfo.FromException(
         Ast.Call(typeof(BinderOps).GetMethod("InvalidSplatteeError"), 
             AstUtils.Constant(target.Name),
             AstUtils.Constant(Binder.GetTypeName(_invalidSplattee.GetLimitType()))
         )
     );
 }
Exemplo n.º 9
0
        public static string /*!*/ GetPythonTypeName(DynamicMetaObject /*!*/ value)
        {
            if (value.HasValue)
            {
                return(PythonOps.GetPythonTypeName(value.Value));
            }

            return(DynamicHelpers.GetPythonTypeFromType(value.GetLimitType()).Name);
        }
Exemplo n.º 10
0
        public static PythonType /*!*/ GetPythonType(DynamicMetaObject /*!*/ value)
        {
            if (value.HasValue)
            {
                return(DynamicHelpers.GetPythonType(value.Value));
            }

            return(DynamicHelpers.GetPythonTypeFromType(value.GetLimitType()));
        }
Exemplo n.º 11
0
        private DynamicMetaObject TryComparisonMethod(OperatorInfo info, OverloadResolverFactory resolverFactory, DynamicMetaObject target, DynamicMetaObject[] args)
        {
            MethodInfo[] targets = GetApplicableMembers(target.GetLimitType(), info);
            if (targets.Length > 0)
            {
                return(TryMakeBindingTarget(resolverFactory, targets, args, BindingRestrictions.Empty));
            }

            return(null);
        }
Exemplo n.º 12
0
        protected static DynamicMetaObject GetMemberFallback(DynamicMetaObject self, DynamicMetaObjectBinder member, DynamicMetaObject codeContext)
        {
            if (member is PythonGetMemberBinder gmb)
            {
                return(gmb.Fallback(self, codeContext));
            }

            GetMemberBinder gma = (GetMemberBinder)member;

            return(gma.FallbackGetMember(self.Restrict(self.GetLimitType())));
        }
Exemplo n.º 13
0
        private static DynamicMetaObject /*!*/ MakePrimitiveToBoolComparison(DynamicMetaObject /*!*/ self)
        {
            object zeroVal = Activator.CreateInstance(self.GetLimitType());

            return(new DynamicMetaObject(
                       Ast.NotEqual(
                           AstUtils.Constant(zeroVal),
                           self.Expression
                           ),
                       self.Restrictions
                       ));
        }
Exemplo n.º 14
0
        /// <summary>
        /// Python's Invoke is a non-standard action.  Here we first try to bind through a Python
        /// internal interface (IPythonInvokable) which supports CallSigantures.  If that fails
        /// and we have an IDO then we translate to the DLR protocol through a nested dynamic site -
        /// this includes unsplatting any keyword / position arguments.  Finally if it's just a plain
        /// old .NET type we use the default binder which supports CallSignatures.
        /// </summary>
        public override DynamicMetaObject /*!*/ Bind(DynamicMetaObject /*!*/ target, DynamicMetaObject /*!*/[] /*!*/ args)
        {
            Debug.Assert(args.Length > 0);

            DynamicMetaObject cc           = target;
            DynamicMetaObject actualTarget = args[0];

            args = ArrayUtils.RemoveFirst(args);

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

            return(BindWorker(cc, actualTarget, args));
        }
        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 = PythonContext.GetPythonContext(action).Binder.GetMember(name, self, resolverFactory, isNoThrow, errorSuggestion);

            // 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);
        }
Exemplo n.º 16
0
        public DynamicMetaObject DeleteMember(string name, DynamicMetaObject target, OverloadResolverFactory resolutionFactory, DynamicMetaObject errorSuggestion)
        {
            ContractUtils.RequiresNotNull(name, "name");
            ContractUtils.RequiresNotNull(target, "target");

            return(MakeDeleteMemberTarget(
                       new SetOrDeleteMemberInfo(
                           name,
                           resolutionFactory
                           ),
                       target.Restrict(target.GetLimitType()),
                       errorSuggestion
                       ));
        }
Exemplo n.º 17
0
        private DynamicMetaObject MakeSetMemberTarget(SetOrDeleteMemberInfo memInfo, DynamicMetaObject target, DynamicMetaObject value, DynamicMetaObject errorSuggestion)
        {
            Type type = target.GetLimitType();
            DynamicMetaObject self = target;

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

            memInfo.Body.Restrictions = target.Restrictions;

            if (typeof(TypeTracker).IsAssignableFrom(type))
            {
                type = ((TypeTracker)target.Value).Type;
                self = null;

                memInfo.Body.Restrictions = memInfo.Body.Restrictions.Merge(
                    BindingRestrictions.GetInstanceRestriction(target.Expression, target.Value)
                    );
            }

            MakeSetMemberRule(memInfo, type, self, value, errorSuggestion);

            return(memInfo.Body.GetMetaObject(target, value));
        }
Exemplo n.º 18
0
        private DynamicMetaObject TryInvertedComparison(OperatorInfo info, OverloadResolverFactory resolverFactory, DynamicMetaObject target, DynamicMetaObject[] args)
        {
            ExpressionType revOp   = GetInvertedOperator(info.Operator);
            OperatorInfo   revInfo = OperatorInfo.GetOperatorInfo(revOp);

            Debug.Assert(revInfo != null);

            // try the 1st type's opposite function result negated
            MethodBase[] targets = GetApplicableMembers(target.GetLimitType(), revInfo);
            if (targets.Length > 0)
            {
                return(TryMakeInvertedBindingTarget(resolverFactory, targets, args));
            }

            return(null);
        }
Exemplo n.º 19
0
        private DynamicMetaObject MakeDeleteMemberTarget(SetOrDeleteMemberInfo delInfo, DynamicMetaObject target, DynamicMetaObject errorSuggestion)
        {
            Type type = target.GetLimitType();
            BindingRestrictions restrictions = target.Restrictions;
            DynamicMetaObject   self         = target;

            if (typeof(TypeTracker).IsAssignableFrom(type))
            {
                restrictions = restrictions.Merge(
                    BindingRestrictions.GetInstanceRestriction(target.Expression, target.Value)
                    );

                type = ((TypeTracker)target.Value).Type;
                self = null;
            }

            delInfo.Body.Restrictions = restrictions;

            if (self == null || !MakeOperatorDeleteMemberBody(delInfo, self, type, "DeleteMember"))
            {
                MemberGroup group = GetMember(MemberRequestKind.Delete, type, delInfo.Name);
                if (group.Count != 0)
                {
                    if (group[0].MemberType == TrackerTypes.Property)
                    {
                        MethodInfo del = ((PropertyTracker)group[0]).GetDeleteMethod(PrivateBinding);
                        if (del != null)
                        {
                            MakePropertyDeleteStatement(delInfo, self, del);
                            return(delInfo.Body.GetMetaObject(target));
                        }
                    }

                    delInfo.Body.FinishError(errorSuggestion ?? MakeError(MakeUndeletableMemberError(GetDeclaringMemberType(group), delInfo.Name), typeof(void)));
                }
                else
                {
                    delInfo.Body.FinishError(errorSuggestion ?? MakeError(MakeMissingMemberErrorForDelete(type, self, delInfo.Name), typeof(void)));
                }
            }

            return(delInfo.Body.GetMetaObject(target));
        }
 private static DynamicMetaObject MakeUnaryOperation(DynamicMetaObjectBinder binder, DynamicMetaObject self, TotemOperationKind symbol, DynamicMetaObject errorSuggestion, Type retType)
 {
     self = self.Restrict(self.GetLimitType());
     throw new NotImplementedException();
 }
        private static DynamicMetaObject MakeEnumeratorOperation(PythonOperationBinder operation, DynamicMetaObject self) {
            if (self.GetLimitType() == typeof(string)) {
                self = self.Restrict(self.GetLimitType());

                return new DynamicMetaObject(
                    Expression.Call(
                        typeof(PythonOps).GetMethod("StringEnumerator"),
                        self.Expression
                    ),
                    self.Restrictions
                );
            } else if (self.GetLimitType() == typeof(PythonDictionary)) {
                self = self.Restrict(self.GetLimitType());

                return new DynamicMetaObject(
                    Expression.Call(
                        typeof(PythonOps).GetMethod("MakeDictionaryKeyEnumerator"),
                        self.Expression
                    ),
                    self.Restrictions
                );
            } else if (self.Value is IEnumerable ||
                       typeof(IEnumerable).IsAssignableFrom(self.GetLimitType())) {
                self = self.Restrict(self.GetLimitType());

                return new DynamicMetaObject(
                    Expression.Call(
                        Expression.Convert(
                            self.Expression,
                            typeof(IEnumerable)
                        ),
                        typeof(IEnumerable).GetMethod("GetEnumerator")
                    ),
                    self.Restrictions
                );

            } else if (self.Value is IEnumerator ||                                 // check for COM object (and fast check when we have values)
                       typeof(IEnumerator).IsAssignableFrom(self.GetLimitType())) { // check if we don't have a value
                DynamicMetaObject ieres = self.Restrict(self.GetLimitType());

#if !SILVERLIGHT
                if (ComOps.IsComObject(self.Value)) {
                    ieres = new DynamicMetaObject(
                         self.Expression,
                         ieres.Restrictions.Merge(
                            BindingRestrictions.GetExpressionRestriction(
                                Ast.TypeIs(self.Expression, typeof(IEnumerator))
                            )
                        )
                    );
                }
#endif

                return ieres;
            }

            ParameterExpression tmp = Ast.Parameter(typeof(IEnumerator), "enum");
            DynamicMetaObject res = self.BindConvert(new ConversionBinder(BinderState.GetBinderState(operation), typeof(IEnumerator), ConversionResultKind.ExplicitTry));
            return new DynamicMetaObject(                
                Expression.Block(
                    new[] { tmp },
                    Ast.Condition(
                        Ast.NotEqual(
                            Ast.Assign(tmp, res.Expression),
                            AstUtils.Constant(null)
                        ),
                        tmp,
                        Ast.Call(
                            typeof(PythonOps).GetMethod("ThrowTypeErrorForBadIteration"),
                            BinderState.GetCodeContext(operation),
                            self.Expression
                        )
                    )
                ),
                res.Restrictions
            );
        }
Exemplo n.º 22
0
 internal static bool IsIndexless(DynamicMetaObject /*!*/ arg)
 {
     return(arg.GetLimitType() != typeof(OldInstance));
 }
Exemplo n.º 23
0
 private static DynamicMetaObject MakeIMembersListRule(Expression codeContext, DynamicMetaObject target) {
     return new DynamicMetaObject(
         Ast.Call(
             typeof(BinderOps).GetMethod("GetStringMembers"),
             Ast.Call(
                 AstUtils.Convert(target.Expression, typeof(IMembersList)),
                 typeof(IMembersList).GetMethod("GetMemberNames"),
                 codeContext
             )
         ),
         BindingRestrictionsHelpers.GetRuntimeTypeRestriction(target.Expression, target.GetLimitType()).Merge(target.Restrictions)
     );
 }
Exemplo n.º 24
0
        private static DynamicMetaObject MakeUnaryOperation(DynamicMetaObjectBinder binder, DynamicMetaObject self, string symbol, DynamicMetaObject errorSuggestion) {
            self = self.Restrict(self.GetLimitType());

            SlotOrFunction func = SlotOrFunction.GetSlotOrFunction(PythonContext.GetPythonContext(binder), symbol, self);

            if (!func.Success) {
                // we get the error message w/ {0} so that PythonBinderHelper.TypeError formats it correctly
                return errorSuggestion ?? TypeError(binder, MakeUnaryOpErrorMessage(symbol, "{0}"), self);
            }

            return func.Target;
        }
Exemplo n.º 25
0
        private static bool IsIndexType(PythonContext/*!*/ state, DynamicMetaObject/*!*/ obj) {
            bool numeric = true;
            if (obj.GetLimitType() != typeof(MissingParameter) &&
                !PythonOps.IsNumericType(obj.GetLimitType())) {

                PythonType curType = MetaPythonObject.GetPythonType(obj);
                PythonTypeSlot dummy;

                if (!curType.TryResolveSlot(state.SharedContext, "__index__", out dummy)) {
                    numeric = false;
                }
            }
            return numeric;
        }
Exemplo n.º 26
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
                       ));
        }
Exemplo n.º 27
0
        private static DynamicMetaObject MakeCallSignatureResult(MethodBase[] methods, DynamicMetaObject target)
        {
            List <string> arrres = new List <string>();

            if (methods != null)
            {
                foreach (MethodBase mb in methods)
                {
                    StringBuilder res   = new StringBuilder();
                    string        comma = "";
                    foreach (ParameterInfo param in mb.GetParameters())
                    {
                        res.Append(comma);
                        res.Append(param.ParameterType.Name);
                        res.Append(" ");
                        res.Append(param.Name);
                        comma = ", ";
                    }
                    arrres.Add(res.ToString());
                }
            }

            return(new DynamicMetaObject(
                       AstUtils.Constant(arrres.ToArray()),
                       BindingRestrictionsHelpers.GetRuntimeTypeRestriction(target.Expression, target.GetLimitType()).Merge(target.Restrictions)
                       ));
        }
Exemplo n.º 28
0
        private static Expression/*!*/ AddExtensibleSelfCheck(DynamicMetaObjectBinder/*!*/ convertToAction, Type toType, DynamicMetaObject/*!*/ self, Expression/*!*/ callExpr) {
            ParameterExpression tmp = Ast.Variable(callExpr.Type, "tmp");
            ConversionResultKind resKind = GetResultKind(convertToAction);
            Type retType = (resKind == ConversionResultKind.ExplicitTry || resKind == ConversionResultKind.ImplicitTry) ? typeof(object) : toType;

            callExpr = Ast.Block(
                new ParameterExpression[] { tmp },
                Ast.Block(
                    Ast.Assign(tmp, callExpr),
                    Ast.Condition(
                        Ast.Equal(tmp, self.Expression),
                        AstUtils.Convert(
                            Ast.Property(
                                AstUtils.Convert(self.Expression, self.GetLimitType()),
                                self.GetLimitType().GetProperty("Value")
                            ),
                            retType
                        ),
                        Ast.Dynamic(
                            new PythonConversionBinder(
                                PythonContext.GetPythonContext(convertToAction),
                                toType,
                                GetResultKind(convertToAction)
                            ),
                            retType,
                            tmp
                        )
                    )
                )
            );
            return callExpr;
        }
Exemplo n.º 29
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();
        }
Exemplo n.º 30
0
 private static Expression/*!*/ AddExtensibleSelfCheck(ConvertBinder/*!*/ convertToAction, DynamicMetaObject/*!*/ self, Expression/*!*/ callExpr) {
     ParameterExpression tmp = Ast.Variable(callExpr.Type, "tmp");
     callExpr = Ast.Block(
         new ParameterExpression[] { tmp },
         Ast.Block(
             Ast.Assign(tmp, callExpr),
             Ast.Condition(
                 Ast.Equal(tmp, self.Expression),
                 Ast.Property(
                     AstUtils.Convert(self.Expression, self.GetLimitType()),
                     self.GetLimitType().GetProperty("Value")
                 ),
                 Binders.Convert(
                     BinderState.GetBinderState(convertToAction),
                     convertToAction.Type,
                     ConversionResultKind.ExplicitCast,
                     tmp
                 )
             )
         )
     );
     return callExpr;
 }
Exemplo n.º 31
0
        private DynamicMetaObject MakeGetMemberTarget(GetMemberInfo getMemInfo, DynamicMetaObject target)
        {
            Type targetType = target.GetLimitType();
            BindingRestrictions restrictions = target.Restrictions;
            DynamicMetaObject   self         = target;

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

            // Specially recognized types: TypeTracker, NamespaceTracker, and StrongBox.
            // TODO: TypeTracker and NamespaceTracker should technically be IDO's.
            MemberGroup members = MemberGroup.EmptyGroup;

            if (typeof(TypeTracker).IsAssignableFrom(targetType))
            {
                restrictions = restrictions.Merge(
                    BindingRestrictions.GetInstanceRestriction(target.Expression, target.Value)
                    );

                TypeGroup tg = target.Value as TypeGroup;
                if (tg == null || tg.TryGetNonGenericType(out Type _))
                {
                    members = GetMember(MemberRequestKind.Get, ((TypeTracker)target.Value).Type, getMemInfo.Name);
                    if (members.Count > 0)
                    {
                        // we have a member that's on the type associated w/ the tracker, return that...
                        targetType = ((TypeTracker)target.Value).Type;
                        self       = null;
                    }
                }
            }

            if (members.Count == 0)
            {
                // Get the members
                members = GetMember(MemberRequestKind.Get, targetType, getMemInfo.Name);
            }

            if (members.Count == 0)
            {
                if (typeof(TypeTracker).IsAssignableFrom(targetType))
                {
                    // Throws an exception if we don't have a non-generic type, and if we do report an error now.  This matches
                    // the rule version of the default binder but should probably be removed long term.
                    EnsureTrackerRepresentsNonGenericType((TypeTracker)target.Value);
                }
                else if (targetType.IsInterface)
                {
                    // all interfaces have object members
                    targetType = typeof(object);
                    members    = GetMember(MemberRequestKind.Get, targetType, getMemInfo.Name);
                }
            }

            DynamicMetaObject propSelf = self;

            // if lookup failed try the strong-box type if available.
            if (members.Count == 0 && typeof(IStrongBox).IsAssignableFrom(targetType) && propSelf != null)
            {
                // properties/fields need the direct value, methods hold onto the strong box.
                propSelf = new DynamicMetaObject(
                    Expression.Field(AstUtils.Convert(propSelf.Expression, targetType), targetType.GetInheritedFields("Value").First()),
                    propSelf.Restrictions,
                    ((IStrongBox)propSelf.Value).Value
                    );

                targetType = targetType.GetGenericArguments()[0];

                members = GetMember(
                    MemberRequestKind.Get,
                    targetType,
                    getMemInfo.Name
                    );
            }

            MakeBodyHelper(getMemInfo, self, propSelf, targetType, members);

            getMemInfo.Body.Restrictions = restrictions;
            return(getMemInfo.Body.GetMetaObject(target));
        }
Exemplo n.º 32
0
        /// <summary>
        /// Transforms a call into a Python GetMember/Invoke.  This isn't quite the correct semantic as
        /// we shouldn't be returning Python members (e.g. object.__repr__) to non-Python callers.  This
        /// can go away as soon as all of the classes implement the full fidelity of the protocol
        /// </summary>
        internal static DynamicMetaObject/*!*/ GenericCall(InvokeMemberBinder/*!*/ action, DynamicMetaObject target, DynamicMetaObject/*!*/[]/*!*/ args) {
            if (target.NeedsDeferral()) {
                return action.Defer(args);
            }

            return new DynamicMetaObject(
                Invoke(
                    BinderState.GetCodeContext(action),
                    BinderState.GetBinderState(action),
                    typeof(object),
                    GetCallSignature(action),
                    ArrayUtils.Insert(
                        Binders.Get(
                            BinderState.GetCodeContext(action),
                            BinderState.GetBinderState(action),
                            typeof(object),
                            action.Name,
                            target.Expression
                        ),
                        DynamicUtils.GetExpressions(args)
                    )
                ),
                BindingRestrictions.Combine(args).Merge(target.Restrict(target.GetLimitType()).Restrictions)
            );
        }
Exemplo n.º 33
0
 private DynamicMetaObject GetForeignObject(DynamicMetaObject self)
 {
     return(new DynamicMetaObject(
                Expression.Dynamic(
                    _context.CompatGetMember(Name, IsNoThrow),
                    typeof(object),
                    self.Expression
                    ),
                self.Restrictions.Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(self.Expression, self.GetLimitType()))
                ));
 }
Exemplo n.º 34
0
        private DynamicMetaObject/*!*/ MakeConvertRuleForCall(ConvertBinder/*!*/ convertToAction, DynamicMetaObject/*!*/ self, SymbolId symbolId, string returner) {
            PythonType pt = ((IPythonObject)self.Value).PythonType;
            PythonTypeSlot pts;
            CodeContext context = BinderState.GetBinderState(convertToAction).Context;

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

                Expression callExpr = Ast.Call(
                    PythonOps.GetConversionHelper(returner, GetResultKind(convertToAction)),
                    Ast.Dynamic(
                        new PythonInvokeBinder(
                            BinderState.GetBinderState(convertToAction),
                            new CallSignature(0)
                        ),
                        typeof(object),
                        BinderState.GetCodeContext(convertToAction),
                        tmp
                    )
                );

                if (typeof(Extensible<>).MakeGenericType(convertToAction.Type).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, self, callExpr), typeof(object));
                }

                return new DynamicMetaObject(
                    Ast.Block(
                        new ParameterExpression[] { tmp },
                        Ast.Condition(
                            BindingHelpers.CheckTypeVersion(
                                self.Expression,
                                pt.Version
                            ),
                            Ast.Condition(
                                MakeTryGetTypeMember(
                                    BinderState.GetBinderState(convertToAction),
                                    pts,
                                    self.Expression,
                                    tmp
                                ),
                                callExpr,
                                AstUtils.Convert(
                                    ConversionFallback(convertToAction),
                                    typeof(object)
                                )
                            ),
                            convertToAction.Defer(this).Expression
                        )
                    ),
                    self.Restrict(self.GetRuntimeType()).Restrictions
                );
            }

            return convertToAction.FallbackConvert(this);
        }
Exemplo n.º 35
0
            /// <summary>
            /// Called when the user is expanding a dictionary - we copy the user
            /// dictionary and verify that it contains only valid string names.
            /// </summary>
            private DynamicMetaObject/*!*/ MakeDictionaryCopy(DynamicMetaObject/*!*/ userDict) {
                Debug.Assert(_dict == null);

                userDict = userDict.Restrict(userDict.GetLimitType());
                _temps.Add(_dict = Ast.Variable(typeof(PythonDictionary), "$dict"));                

                EnsureInit();

                string methodName;
                if (typeof(PythonDictionary).IsAssignableFrom(userDict.GetLimitType())) {
                    methodName = "CopyAndVerifyPythonDictionary";
                } else if (typeof(IDictionary).IsAssignableFrom(userDict.GetLimitType())) {
                    methodName = "CopyAndVerifyDictionary";
                } else {
                    methodName = "CopyAndVerifyUserMapping";
                }

                _init.Add(
                    Ast.Assign(
                        _dict,
                        Ast.Call(
                            typeof(PythonOps).GetMethod(methodName),
                            GetFunctionParam(),
                            AstUtils.Convert(userDict.Expression, userDict.GetLimitType())
                        )
                    )
                );
                return userDict;
            }
Exemplo n.º 36
0
        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))
            );
        }
Exemplo n.º 37
0
        private static DynamicMetaObject/*!*/ MakeHashOperation(PythonOperationBinder/*!*/ operation, DynamicMetaObject/*!*/ self) {
            self = self.Restrict(self.GetLimitType());

            PythonContext state = PythonContext.GetPythonContext(operation);
            SlotOrFunction func = SlotOrFunction.GetSlotOrFunction(state, "__hash__", self);
            DynamicMetaObject res = func.Target;

            if (func.IsNull) {
                // Python 2.6 setting __hash__ = None makes the type unhashable
                res = new DynamicMetaObject(
                    operation.Throw(
                        Expression.Call(
                            typeof(PythonOps).GetMethod("TypeErrorForUnhashableObject"),
                            self.Expression
                        ),
                        typeof(int)
                    ),
                    res.Restrictions
                );
            } else if (func.ReturnType != typeof(int)) {
                if (func.ReturnType == typeof(BigInteger)) {
                    // Python 2.5 defines the result of returning a long as hashing the long
                    res = new DynamicMetaObject(
                        HashBigInt(operation, res.Expression),
                        res.Restrictions
                    );
                } else if (func.ReturnType == typeof(object)) {
                    // need to get the integer value here...
                    ParameterExpression tempVar = Ast.Parameter(typeof(object), "hashTemp");

                    res = new DynamicMetaObject(
                            Expression.Block(
                                new[] { tempVar },
                                Expression.Assign(tempVar, res.Expression),
                                Expression.Condition(
                                    Expression.TypeIs(tempVar, typeof(int)),
                                    Expression.Convert(tempVar, typeof(int)),
                                    Expression.Condition(
                                        Expression.TypeIs(tempVar, typeof(BigInteger)),
                                        HashBigInt(operation, tempVar),
                                        HashConvertToInt(state, tempVar)
                                    )
                                )
                            ),
                            res.Restrictions
                        );
                } else {
                    // need to convert unknown value to object
                    res = new DynamicMetaObject(
                        HashConvertToInt(state, res.Expression),
                        res.Restrictions
                    );
                }
            }

            return res;
        }
Exemplo n.º 38
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);
        }
Exemplo n.º 39
0
        private static DynamicMetaObject MakeEnumeratorOperation(PythonOperationBinder operation, DynamicMetaObject self) {
            if (self.GetLimitType() == typeof(string)) {
                self = self.Restrict(self.GetLimitType());

                return new DynamicMetaObject(
                    Expression.Call(
                        typeof(PythonOps).GetMethod("StringEnumerator"),
                        self.Expression
                    ),
                    self.Restrictions
                );
            } else if (self.GetLimitType() == typeof(Bytes)) {
                self = self.Restrict(self.GetLimitType());

                if (operation.Context.PythonOptions.Python30) {
                    return new DynamicMetaObject(
                        Expression.Call(
                            typeof(PythonOps).GetMethod("BytesIntEnumerator"),
                            self.Expression
                        ),
                        self.Restrictions
                    );
                } else {
                    return new DynamicMetaObject(
                        Expression.Call(
                            typeof(PythonOps).GetMethod("BytesEnumerator"),
                            self.Expression
                        ),
                        self.Restrictions
                    );
                }
            } else if ((self.Value is IEnumerable ||
                    typeof(IEnumerable).IsAssignableFrom(self.GetLimitType())) && !(self.Value is PythonGenerator)) {
                self = self.Restrict(self.GetLimitType());

                return new DynamicMetaObject(
                    Expression.Call(
                        typeof(PythonOps).GetMethod("GetEnumeratorFromEnumerable"),
                        Expression.Convert(
                            self.Expression,
                            typeof(IEnumerable)
                        )
                    ),
                    self.Restrictions
                );

            } else if (self.Value is IEnumerator ||                              // check for COM object (and fast check when we have values)
                    typeof(IEnumerator).IsAssignableFrom(self.GetLimitType())) { // check if we don't have a value
                DynamicMetaObject ieres = new DynamicMetaObject(
                    MakeEnumeratorResult(
                        Ast.Convert(
                            self.Expression,
                            typeof(IEnumerator)
                        )
                    ),
                    self.Restrict(self.GetLimitType()).Restrictions
                );

#if FEATURE_COM
                if (Microsoft.Scripting.ComInterop.ComBinder.IsComObject(self.Value)) {
                    ieres = new DynamicMetaObject(
                         MakeEnumeratorResult(
                                Expression.Convert(
                                 self.Expression,
                                 typeof(IEnumerator)
                             )
                         ),
                         ieres.Restrictions.Merge(
                            BindingRestrictions.GetExpressionRestriction(
                                Ast.TypeIs(self.Expression, typeof(IEnumerator))
                            )
                        )
                    );
                }
#endif

                return ieres;
            }

            ParameterExpression tmp = Ast.Parameter(typeof(IEnumerator), "enum");
            IPythonConvertible pyConv = self as IPythonConvertible;
            PythonConversionBinder convBinder = PythonContext.GetPythonContext(operation).Convert(typeof(IEnumerator), ConversionResultKind.ExplicitTry);

            DynamicMetaObject res;
            if (pyConv != null) {
                res = pyConv.BindConvert(convBinder);
            } else {
                res = convBinder.Bind(self, new DynamicMetaObject[0]);
            }

            return new DynamicMetaObject(
                Expression.Block(
                    new[] { tmp },
                    Ast.Condition(
                        Ast.NotEqual(
                            Ast.Assign(tmp, res.Expression),
                            AstUtils.Constant(null)
                        ),
                        MakeEnumeratorResult(tmp),
                        Ast.Call(
                            typeof(PythonOps).GetMethod("ThrowTypeErrorForBadIteration"),
                            PythonContext.GetCodeContext(operation),
                            self.Expression
                        )
                    )
                ),
                res.Restrictions
            );
        }
Exemplo n.º 40
0
        private static DynamicMetaObject/*!*/ MakeUnaryNotOperation(DynamicMetaObjectBinder/*!*/ operation, DynamicMetaObject/*!*/ self, Type/*!*/ retType) {
            self = self.Restrict(self.GetLimitType());

            SlotOrFunction nonzero = SlotOrFunction.GetSlotOrFunction(PythonContext.GetPythonContext(operation), Symbols.NonZero, self);
            SlotOrFunction length = SlotOrFunction.GetSlotOrFunction(PythonContext.GetPythonContext(operation), Symbols.Length, self);

            Expression notExpr;

            if (!nonzero.Success && !length.Success) {
                // always False or True for None
                notExpr = (self.GetLimitType() == typeof(DynamicNull)) ? AstUtils.Constant(true) : AstUtils.Constant(false);
            } 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(
                                Ast.Dynamic(
                                    PythonContext.GetPythonContext(operation).Operation(
                                        PythonOperationKind.Compare
                                    ),
                                    typeof(int),
                                    notExpr,
                                    AstUtils.Constant(0)
                                ),
                                AstUtils.Constant(0)
                            );
                    }
                }
            }

            Debug.Assert(notExpr.Type == typeof(bool));

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

            return new DynamicMetaObject(
                notExpr,
                self.Restrictions.Merge(nonzero.Target.Restrictions.Merge(length.Target.Restrictions))
            );
        }
Exemplo n.º 41
0
 private static bool IsSequence(DynamicMetaObject/*!*/ metaObject) {
     if (typeof(List).IsAssignableFrom(metaObject.GetLimitType()) ||
         typeof(PythonTuple).IsAssignableFrom(metaObject.GetLimitType()) ||
         typeof(String).IsAssignableFrom(metaObject.GetLimitType())) {
         return true;
     }
     return false;
 }
Exemplo n.º 42
0
        /// <summary>
        /// Creates a nested dynamic site which uses the unpacked arguments.
        /// </summary>
        internal DynamicMetaObject InvokeForeignObject(DynamicMetaObject target, DynamicMetaObject[] args)
        {
            // need to unpack any dict / list arguments...
            CallInfo            callInfo;
            List <Expression>   metaArgs;
            Expression          test;
            BindingRestrictions restrictions;

            TranslateArguments(target, args, out callInfo, out metaArgs, out test, out restrictions);

            Debug.Assert(metaArgs.Count > 0);

            return(BindingHelpers.AddDynamicTestAndDefer(
                       this,
                       new DynamicMetaObject(
                           DynamicExpression.Dynamic(
                               _context.CompatInvoke(callInfo),
                               typeof(object),
                               metaArgs.ToArray()
                               ),
                           restrictions.Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(target.Expression, target.GetLimitType()))
                           ),
                       args,
                       new ValidationInfo(test)
                       ));
        }
Exemplo n.º 43
0
        internal DynamicMetaObject FallbackConvert(Type returnType, DynamicMetaObject self, DynamicMetaObject errorSuggestion)
        {
            Type type             = Type;
            DynamicMetaObject res = null;

            switch (Type.GetTypeCode(type))
            {
            case TypeCode.Boolean:
                res = MakeToBoolConversion(self);
                break;

            case TypeCode.Char:
                res = TryToCharConversion(self);
                break;

            case TypeCode.String:
                if (self.GetLimitType() == typeof(Bytes) && !_context.PythonOptions.Python30)
                {
                    res = new DynamicMetaObject(
                        Ast.Call(
                            typeof(PythonOps).GetMethod("MakeString"),
                            AstUtils.Convert(self.Expression, typeof(IList <byte>))
                            ),
                        BindingRestrictionsHelpers.GetRuntimeTypeRestriction(self.Expression, typeof(Bytes))
                        );
                }
                break;

            case TypeCode.Object:
                // !!! Deferral?
                if (type.IsArray && self.Value is PythonTuple && type.GetArrayRank() == 1)
                {
                    res = MakeToArrayConversion(self, type);
                }
                else if (type.IsGenericType && !type.IsAssignableFrom(CompilerHelpers.GetType(self.Value)))
                {
                    Type genTo = type.GetGenericTypeDefinition();

                    // Interface conversion helpers...
                    if (genTo == typeof(IList <>))
                    {
                        if (self.LimitType == typeof(string))
                        {
                            res = new DynamicMetaObject(
                                Ast.Call(
                                    typeof(PythonOps).GetMethod("MakeByteArray"),
                                    AstUtils.Convert(self.Expression, typeof(string))
                                    ),
                                BindingRestrictions.GetTypeRestriction(
                                    self.Expression,
                                    typeof(string)
                                    )
                                );
                        }
                        else
                        {
                            res = TryToGenericInterfaceConversion(self, type, typeof(IList <object>), typeof(ListGenericWrapper <>));
                        }
                    }
                    else if (genTo == typeof(IDictionary <,>))
                    {
                        res = TryToGenericInterfaceConversion(self, type, typeof(IDictionary <object, object>), typeof(DictionaryGenericWrapper <,>));
                    }
                    else if (genTo == typeof(IEnumerable <>))
                    {
                        res = TryToGenericInterfaceConversion(self, type, typeof(IEnumerable), typeof(IEnumerableOfTWrapper <>));
                    }
                }
                else if (type == typeof(IEnumerable))
                {
                    if (!typeof(IEnumerable).IsAssignableFrom(self.GetLimitType()) && IsIndexless(self))
                    {
                        res = ConvertToIEnumerable(this, self.Restrict(self.GetLimitType()));
                    }
                }
                else if (type == typeof(IEnumerator))
                {
                    if (!typeof(IEnumerator).IsAssignableFrom(self.GetLimitType()) &&
                        !typeof(IEnumerable).IsAssignableFrom(self.GetLimitType()) &&
                        IsIndexless(self))
                    {
                        res = ConvertToIEnumerator(this, self.Restrict(self.GetLimitType()));
                    }
                }
                break;
            }

            if (type.IsEnum && Enum.GetUnderlyingType(type) == self.GetLimitType())
            {
                // numeric type to enum, this is ok if the value is zero
                object value = Activator.CreateInstance(type);

                return(new DynamicMetaObject(
                           Ast.Condition(
                               Ast.Equal(
                                   AstUtils.Convert(self.Expression, Enum.GetUnderlyingType(type)),
                                   AstUtils.Constant(Activator.CreateInstance(self.GetLimitType()))
                                   ),
                               AstUtils.Constant(value),
                               Ast.Call(
                                   typeof(PythonOps).GetMethod("TypeErrorForBadEnumConversion").MakeGenericMethod(type),
                                   AstUtils.Convert(self.Expression, typeof(object))
                                   )
                               ),
                           self.Restrictions.Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(self.Expression, self.GetLimitType())),
                           value
                           ));
            }

            return(res ?? EnsureReturnType(returnType, Context.Binder.ConvertTo(Type, ResultKind, self, _context.SharedOverloadResolverFactory, errorSuggestion)));
        }
Exemplo n.º 44
0
            ///-------------------------------------------------------------------------------------------------
            /// <summary>
            /// Called when the user is expanding a dictionary - we copy the user
            /// dictionary and verify that it contains only valid string names.
            /// </summary>
            ///
            /// <remarks>   Aleksander, 19.05.2013. </remarks>
            ///
            /// <param name="userDict"> Dictionary of users. </param>
            ///
            /// <returns>   . </returns>
            ///-------------------------------------------------------------------------------------------------
            private DynamicMetaObject MakeDictionaryCopy(DynamicMetaObject userDict)
            {
                Debug.Assert(_dict == null);

                userDict = userDict.Restrict(userDict.GetLimitType());
                _temps.Add(_dict = Expression.Variable(typeof(TotemDictionary), "$dict"));

                EnsureInit();

                MethodInfo method;
                if (typeof(TotemDictionary).IsAssignableFrom(userDict.GetLimitType()))
                    method = AstMethods.CopyAndVerifyTotemDictionary;
                else if (typeof(IDictionary).IsAssignableFrom(userDict.GetLimitType()))
                    method = AstMethods.CopyAndVerifyDictionary;
                else
                    method = AstMethods.CopyAndVerifyUserMapping;

                _init.Add(
                    Expression.Assign(
                        _dict,
                        Expression.Call(
                            method,
                            GetFunctionParam(),
                            Utils.Convert(userDict.Expression, userDict.GetLimitType())
                        )
                    )
                );
                return userDict;
            }
Exemplo n.º 45
0
        /// <summary>
        /// Creates a nested dynamic site which uses the unpacked arguments.
        /// </summary>
        protected DynamicMetaObject InvokeForeignObject(DynamicMetaObject target, DynamicMetaObject[] args) {
            // need to unpack any dict / list arguments...
            List<ArgumentInfo> newArgs;
            List<Expression> metaArgs;
            Expression test;
            BindingRestrictions restrictions;
            TranslateArguments(target, args, out newArgs, out metaArgs, out test, out restrictions);

            Debug.Assert(metaArgs.Count > 0);

            return BindingHelpers.AddDynamicTestAndDefer(
                this,
                new DynamicMetaObject(
                    Expression.Dynamic(
                        new CompatibilityInvokeBinder(_state, newArgs.ToArray()),
                        typeof(object),
                        metaArgs.ToArray()
                    ),
                    restrictions.Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(target.Expression, target.GetLimitType()))
                ),
                args,
                new ValidationInfo(test, null)
            );
        }
        private static DynamicMetaObject/*!*/ MakeHashOperation(PythonOperationBinder/*!*/ operation, DynamicMetaObject/*!*/ self) {
            self = self.Restrict(self.GetLimitType());

            BinderState state = BinderState.GetBinderState(operation);
            SlotOrFunction func = SlotOrFunction.GetSlotOrFunction(state, Symbols.Hash, self);
            DynamicMetaObject res = func.Target;

            if (func.ReturnType != typeof(int)) {
                if (func.ReturnType == typeof(BigInteger)) {
                    // Python 2.5 defines the result of returning a long as hashing the long
                    res = new DynamicMetaObject(
                        HashBigInt(operation, res.Expression),
                        res.Restrictions
                    );
                } else if (func.ReturnType == typeof(object)) {
                    // need to get the integer value here...
                    ParameterExpression tempVar = Ast.Parameter(typeof(object), "hashTemp");

                    res = new DynamicMetaObject(
                            Expression.Block(
                                new [] { tempVar },
                                Expression.Assign(tempVar, res.Expression),
                                Expression.Condition(
                                    Expression.TypeIs(tempVar, typeof(int)),
                                    Expression.Convert(tempVar, typeof(int)),
                                    Expression.Condition(
                                        Expression.TypeIs(tempVar, typeof(BigInteger)),
                                        HashBigInt(operation, tempVar),
                                        HashConvertToInt(state, tempVar)
                                    )
                                )
                            ),
                            res.Restrictions
                        );
                } else {
                    // need to convert unknown value to object
                    res = new DynamicMetaObject(
                        HashConvertToInt(state, res.Expression),
                        res.Restrictions
                    );
                }
            }

            return res;
        }
Exemplo n.º 47
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());
        }
Exemplo n.º 48
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);
        }
        public override Candidate SelectBestConversionFor(DynamicMetaObject /*!*/ arg, ParameterWrapper /*!*/ candidateOne,
                                                          ParameterWrapper /*!*/ candidateTwo, NarrowingLevel level)
        {
            Type typeOne    = candidateOne.Type;
            Type typeTwo    = candidateTwo.Type;
            Type actualType = arg.GetLimitType();

            if (actualType == typeof(DynamicNull))
            {
                // if nil is passed as a block argument prefers BlockParam over a missing block:
                if (typeOne == typeof(BlockParam) && typeTwo == typeof(MissingBlockParam))
                {
                    Debug.Assert(!candidateOne.ProhibitNull);
                    return(Candidate.One);
                }

                if (typeOne == typeof(MissingBlockParam) && typeTwo == typeof(BlockParam))
                {
                    Debug.Assert(!candidateTwo.ProhibitNull);
                    return(Candidate.Two);
                }
            }
            else
            {
                if (typeOne == actualType)
                {
                    if (typeTwo == actualType)
                    {
                        // prefer non-nullable reference type over nullable:
                        if (!actualType.IsValueType)
                        {
                            if (candidateOne.ProhibitNull)
                            {
                                return(Candidate.One);
                            }
                            else if (candidateTwo.ProhibitNull)
                            {
                                return(Candidate.Two);
                            }
                        }
                    }
                    else
                    {
                        return(Candidate.One);
                    }
                }
                else if (typeTwo == actualType)
                {
                    return(Candidate.Two);
                }
            }

            // prefer integer type over enum:
            if (typeOne.IsEnum && Enum.GetUnderlyingType(typeOne) == typeTwo)
            {
                return(Candidate.Two);
            }

            if (typeTwo.IsEnum && Enum.GetUnderlyingType(typeTwo) == typeOne)
            {
                return(Candidate.One);
            }

            return(base.SelectBestConversionFor(arg, candidateOne, candidateTwo, level));
        }
Exemplo n.º 50
0
        private static DynamicMetaObject/*!*/ MakeUnaryOperation(OperationBinder/*!*/ operation, DynamicMetaObject/*!*/ self) {
            self = self.Restrict(self.GetLimitType());

            SlotOrFunction func = SlotOrFunction.GetSlotOrFunction(BinderState.GetBinderState(operation), Symbols.OperatorToSymbol(operation.Operation), self);

            if (!func.Success) {
                // we get the error message w/ {0} so that PythonBinderHelper.TypeError formats it correctly
                return TypeError(operation, MakeUnaryOpErrorMessage(operation.Operation.ToString(), "{0}"), self);
            }

            return func.Target;
        }