예제 #1
0
        /// <summary>
        /// Gets an expression which is used for accessing this slot.  If the slot lookup fails the error expression
        /// is used again.
        ///
        /// The default implementation just calls the TryGetValue method.  Subtypes of PythonTypeSlot can override
        /// this and provide a more optimal implementation.
        /// </summary>
        internal virtual void MakeGetExpression(PythonBinder /*!*/ binder, Expression /*!*/ codeContext, DynamicMetaObject instance, DynamicMetaObject /*!*/ owner, ConditionalBuilder /*!*/ builder)
        {
            ParameterExpression tmp  = Ast.Variable(typeof(object), "slotTmp");
            Expression          call = Ast.Call(
                typeof(PythonOps).GetMethod("SlotTryGetValue"),
                codeContext,
                AstUtils.Convert(AstUtils.WeakConstant(this), typeof(PythonTypeSlot)),
                instance != null ? instance.Expression : AstUtils.Constant(null),
                owner.Expression,
                tmp
                );

            builder.AddVariable(tmp);
            if (!GetAlwaysSucceeds)
            {
                builder.AddCondition(
                    call,
                    tmp
                    );
            }
            else
            {
                builder.FinishCondition(Ast.Block(call, tmp));
            }
        }
예제 #2
0
        /// <summary>
        /// Checks to see if the provided members are always visible for the given type.
        ///
        /// This filters out methods such as GetHashCode and Equals on standard .NET
        /// types that we expose directly as Python types (e.g. object, string, etc...).
        ///
        /// It also filters out the base helper overrides that are added for supporting
        /// super calls on user defined types.
        /// </summary>
        private static bool IsMethodAlwaysVisible(Type /*!*/ type, MemberInfo /*!*/[] /*!*/ methods)
        {
            bool alwaysVisible = true;

            if (PythonBinder.IsPythonType(type))
            {
                // only show methods defined outside of the system types (object, string)
                foreach (MethodInfo mi in methods)
                {
                    if (PythonBinder.IsExtendedType(mi.DeclaringType) ||
                        PythonBinder.IsExtendedType(mi.GetBaseDefinition().DeclaringType) ||
                        PythonHiddenAttribute.IsHidden(mi))
                    {
                        alwaysVisible = false;
                        break;
                    }
                }
            }
            else if (typeof(IPythonObject).IsAssignableFrom(type))
            {
                // check if this is a virtual override helper, if so we
                // may need to filter it out.
                foreach (MethodInfo mi in methods)
                {
                    if (PythonBinder.IsExtendedType(mi.DeclaringType))
                    {
                        alwaysVisible = false;
                        break;
                    }
                }
            }
            return(alwaysVisible);
        }
예제 #3
0
        internal static string GetModuleName(CodeContext /*!*/ context, Type type)
        {
            if (IsRuntimeAssembly(type.Assembly) || PythonBinder.IsPythonType(type))
            {
                Type curType = type;
                while (curType != null)
                {
                    string moduleName;
                    if (PythonContext.GetContext(context).BuiltinModuleNames.TryGetValue(curType, out moduleName))
                    {
                        return(moduleName);
                    }

                    curType = curType.DeclaringType;
                }

                FieldInfo modField = type.GetField("__module__");
                if (modField != null && modField.IsLiteral && modField.FieldType == typeof(string))
                {
                    return((string)modField.GetRawConstantValue());
                }
                return("__builtin__");
            }

            return(type.Namespace + " in " + type.Assembly.FullName);
        }
예제 #4
0
 internal override void MakeGetExpression(PythonBinder/*!*/ binder, Expression/*!*/ codeContext, DynamicMetaObject instance, DynamicMetaObject/*!*/ owner, ConditionalBuilder/*!*/ builder) {
     if (instance != null) {
         builder.FinishCondition(
             Ast.Call(
                 typeof(PythonOps).GetMethod(nameof(PythonOps.MakeBoundBuiltinFunction)),
                 AstUtils.Constant(_template),
                 instance.Expression
             )
         );
     } else {
         builder.FinishCondition(AstUtils.Constant(this));
     }
 }
예제 #5
0
        internal static PythonTypeSlot GetReflectedField(FieldInfo info)
        {
            PythonTypeSlot res;

            NameType nt = NameType.Field;

            if (!PythonBinder.IsExtendedPythonType(info.DeclaringType) &&
                !PythonBinder.IsPythonSupportingType(info.DeclaringType) &&
                !PythonHiddenAttribute.IsHidden(info))
            {
                nt |= NameType.PythonField;
            }

            lock (_fieldCache) {
                if (!_fieldCache.TryGetValue(info, out res))
                {
                    if (nt == NameType.PythonField && info.IsLiteral)
                    {
                        if (info.FieldType == typeof(int))
                        {
                            res = new PythonTypeUserDescriptorSlot(
                                ScriptingRuntimeHelpers.Int32ToObject((int)info.GetRawConstantValue()),
                                true
                                );
                        }
                        else if (info.FieldType == typeof(bool))
                        {
                            res = new PythonTypeUserDescriptorSlot(
                                ScriptingRuntimeHelpers.BooleanToObject((bool)info.GetRawConstantValue()),
                                true
                                );
                        }
                        else
                        {
                            res = new PythonTypeUserDescriptorSlot(
                                info.GetValue(null),
                                true
                                );
                        }
                    }
                    else
                    {
                        res = new ReflectedField(info, nt);
                    }

                    _fieldCache[info] = res;
                }
            }

            return(res);
        }
예제 #6
0
 internal override void MakeGetExpression(PythonBinder /*!*/ binder, Expression /*!*/ codeContext, DynamicMetaObject instance, DynamicMetaObject /*!*/ owner, ConditionalBuilder /*!*/ builder)
 {
     if (Getter.Length != 0 && !Getter[0].IsPublic)
     {
         // fallback to runtime call
         base.MakeGetExpression(binder, codeContext, instance, owner, builder);
     }
     else if (NeedToReturnProperty(instance, Getter))
     {
         builder.FinishCondition(AstUtils.Constant(this));
     }
     else if (Getter[0].ContainsGenericParameters)
     {
         builder.FinishCondition(
             DefaultBinder.MakeError(
                 binder.MakeContainsGenericParametersError(
                     MemberTracker.FromMemberInfo(_info)
                     ),
                 typeof(object)
                 ).Expression
             );
     }
     else if (instance != null)
     {
         builder.FinishCondition(
             AstUtils.Convert(
                 binder.MakeCallExpression(
                     new PythonOverloadResolverFactory(binder, codeContext),
                     Getter[0],
                     instance
                     ).Expression,
                 typeof(object)
                 )
             );
     }
     else
     {
         builder.FinishCondition(
             AstUtils.Convert(
                 binder.MakeCallExpression(
                     new PythonOverloadResolverFactory(binder, codeContext),
                     Getter[0]
                     ).Expression,
                 typeof(object)
                 )
             );
     }
 }
예제 #7
0
        internal static ReflectedEvent GetReflectedEvent(EventTracker tracker)
        {
            ReflectedEvent res;

            lock (_eventCache) {
                if (!_eventCache.TryGetValue(tracker, out res))
                {
                    if (PythonBinder.IsExtendedType(tracker.DeclaringType))
                    {
                        _eventCache[tracker] = res = new ReflectedEvent(tracker, true);
                    }
                    else
                    {
                        _eventCache[tracker] = res = new ReflectedEvent(tracker, false);
                    }
                }
            }
            return(res);
        }
예제 #8
0
        public static string GetTypeName(Type t)
        {
            if (t.IsArray)
            {
                return("Array[" + GetTypeName(t.GetElementType()) + "]");
            }

            string name = PythonBinder.GetTypeNameInternal(t);

            if (name != t.Name)
            {
                return(name);
            }

            int backtickIndex;

            if ((backtickIndex = name.IndexOf(ReflectionUtils.GenericArityDelimiter)) != -1)
            {
                name = name.Substring(0, backtickIndex);
                Type[]        typeOf = t.GetGenericArguments();
                StringBuilder sb     = new StringBuilder(name);
                sb.Append('[');
                bool first = true;
                foreach (Type tof in typeOf)
                {
                    if (first)
                    {
                        first = false;
                    }
                    else
                    {
                        sb.Append(", ");
                    }
                    sb.Append(GetTypeName(tof));
                }
                sb.Append(']');
                name = sb.ToString();
            }
            return(name);
        }
예제 #9
0
 internal override void MakeGetExpression(PythonBinder /*!*/ binder, Expression /*!*/ codeContext, DynamicMetaObject instance, DynamicMetaObject /*!*/ owner, ConditionalBuilder /*!*/ builder)
 {
     if (!_info.IsPublic || _info.DeclaringType.ContainsGenericParameters)
     {
         // fallback to reflection
         base.MakeGetExpression(binder, codeContext, instance, owner, builder);
     }
     else if (instance == null)
     {
         if (_info.IsStatic)
         {
             builder.FinishCondition(AstUtils.Convert(Ast.Field(null, _info), typeof(object)));
         }
         else
         {
             builder.FinishCondition(Ast.Constant(this));
         }
     }
     else
     {
         builder.FinishCondition(
             AstUtils.Convert(
                 Ast.Field(
                     binder.ConvertExpression(
                         instance.Expression,
                         _info.DeclaringType,
                         ConversionResultKind.ExplicitCast,
                         new PythonOverloadResolverFactory(binder, codeContext)
                         ),
                     _info
                     ),
                 typeof(object)
                 )
             );
     }
 }
예제 #10
0
        internal static ReflectedGetterSetter GetReflectedProperty(PropertyTracker pt, MemberGroup allProperties, bool privateBinding)
        {
            ReflectedGetterSetter rp;

            lock (_propertyCache) {
                if (_propertyCache.TryGetValue(pt, out rp))
                {
                    return(rp);
                }

                NameType   nt     = NameType.PythonProperty;
                MethodInfo getter = FilterProtectedGetterOrSetter(pt.GetGetMethod(true), privateBinding);
                MethodInfo setter = FilterProtectedGetterOrSetter(pt.GetSetMethod(true), privateBinding);

                if ((getter != null && PythonHiddenAttribute.IsHidden(getter, true)) ||
                    (setter != null && PythonHiddenAttribute.IsHidden(setter, true)))
                {
                    nt = NameType.Property;
                }

                ExtensionPropertyTracker ept = pt as ExtensionPropertyTracker;
                if (ept == null)
                {
                    ReflectedPropertyTracker rpt = pt as ReflectedPropertyTracker;
                    Debug.Assert(rpt != null);

                    if (PythonBinder.IsExtendedType(pt.DeclaringType) ||
                        PythonHiddenAttribute.IsHidden(rpt.Property, true))
                    {
                        nt = NameType.Property;
                    }

                    if (pt.GetIndexParameters().Length == 0)
                    {
                        List <MethodInfo> getters = new List <MethodInfo>();
                        List <MethodInfo> setters = new List <MethodInfo>();

                        IList <ExtensionPropertyTracker> overriddenProperties = NewTypeMaker.GetOverriddenProperties((getter ?? setter).DeclaringType, pt.Name);
                        foreach (ExtensionPropertyTracker tracker in overriddenProperties)
                        {
                            MethodInfo method = tracker.GetGetMethod(privateBinding);
                            if (method != null)
                            {
                                getters.Add(method);
                            }

                            method = tracker.GetSetMethod(privateBinding);
                            if (method != null)
                            {
                                setters.Add(method);
                            }
                        }

                        foreach (PropertyTracker propTracker in allProperties)
                        {
                            MethodInfo method = propTracker.GetGetMethod(privateBinding);
                            if (method != null)
                            {
                                getters.Add(method);
                            }

                            method = propTracker.GetSetMethod(privateBinding);
                            if (method != null)
                            {
                                setters.Add(method);
                            }
                        }
                        rp = new ReflectedProperty(rpt.Property, getters.ToArray(), setters.ToArray(), nt);
                    }
                    else
                    {
                        rp = new ReflectedIndexer(((ReflectedPropertyTracker)pt).Property, NameType.Property, privateBinding);
                    }
                }
                else
                {
                    rp = new ReflectedExtensionProperty(new ExtensionPropertyInfo(pt.DeclaringType, getter ?? setter), nt);
                }

                _propertyCache[pt] = rp;

                return(rp);
            }
        }
예제 #11
0
 internal override void MakeGetExpression(PythonBinder /*!*/ binder, Expression /*!*/ codeContext, DynamicMetaObject instance, DynamicMetaObject /*!*/ owner, ConditionalBuilder /*!*/ builder)
 {
     builder.FinishCondition(Ast.Constant(this));
 }
예제 #12
0
        /// <summary>
        /// target is the newly initialized value.
        /// args are the arguments to be passed to __init__
        /// </summary>
        public override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObject[] args)
        {
            DynamicMetaObject codeContext = target;
            CodeContext       context     = (CodeContext)codeContext.Value;

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

            ValidationInfo valInfo = BindingHelpers.GetValidationInfo(target);

            Expression          res;
            PythonType          instType         = DynamicHelpers.GetPythonType(target.Value);
            BindingRestrictions initRestrictions = BindingRestrictions.Empty;

            if (IronPython.Modules.Builtin.isinstance(target.Value, _newType) &&
                NeedsInitCall((CodeContext)codeContext.Value, instType, args.Length))
            {
                // resolve __init__
                PythonTypeSlot init;
                instType.TryResolveSlot(context, "__init__", out init);

                if (init is PythonFunction)
                {
                    // avoid creating the bound method, just invoke it directly
                    Expression[] allArgs = new Expression[args.Length + 3];
                    allArgs[0] = codeContext.Expression;
                    allArgs[1] = AstUtils.WeakConstant(init);
                    allArgs[2] = target.Expression;
                    for (int i = 0; i < args.Length; i++)
                    {
                        allArgs[3 + i] = args[i].Expression;
                    }

                    res = DynamicExpression.Dynamic(
                        context.LanguageContext.Invoke(_signature.InsertArgument(Argument.Simple)),
                        typeof(object),
                        allArgs
                        );
                }
                else if (init is BuiltinMethodDescriptor || init is BuiltinFunction)
                {
                    IList <MethodBase> targets;
                    if (init is BuiltinMethodDescriptor)
                    {
                        targets = ((BuiltinMethodDescriptor)init).Template.Targets;
                    }
                    else
                    {
                        targets = ((BuiltinFunction)init).Targets;
                    }

                    PythonBinder binder = context.LanguageContext.Binder;

                    DynamicMetaObject initInvoke = binder.CallMethod(
                        new PythonOverloadResolver(
                            binder,
                            target,
                            args,
                            _signature,
                            codeContext.Expression
                            ),
                        targets,
                        BindingRestrictions.Empty
                        );

                    res = initInvoke.Expression;
                    initRestrictions = initInvoke.Restrictions;
                }
                else
                {
                    // some weird descriptor has been put in place for __init__, we need
                    // to call __get__ on it each time.
                    res = MakeDynamicInitInvoke(
                        context,
                        args,
                        Expression.Call(
                            typeof(PythonOps).GetMethod("GetInitSlotMember"),
                            codeContext.Expression,
                            Expression.Convert(AstUtils.WeakConstant(_newType), typeof(PythonType)),
                            Expression.Convert(AstUtils.WeakConstant(init), typeof(PythonTypeSlot)),
                            AstUtils.Convert(target.Expression, typeof(object))
                            ),
                        codeContext.Expression
                        );
                }
            }
            else
            {
                // returned something that isn't a subclass of the creating type
                // __init__ will not be run.
                res = AstUtils.Empty();
            }

            // check for __del__
            PythonTypeSlot delSlot;

            if (instType.TryResolveSlot(context, "__del__", out delSlot))
            {
                res = Expression.Block(
                    res,
                    Expression.Call(
                        typeof(PythonOps).GetMethod("InitializeForFinalization"),
                        codeContext.Expression,
                        AstUtils.Convert(target.Expression, typeof(object))
                        )
                    );
            }

            return(BindingHelpers.AddDynamicTestAndDefer(
                       this,
                       new DynamicMetaObject(
                           Expression.Block(
                               res,
                               target.Expression
                               ),
                           target.Restrict(target.LimitType).Restrictions.Merge(initRestrictions)
                           ),
                       args,
                       valInfo
                       ));
        }