コード例 #1
0
        internal static PythonTypeSlot /*!*/ GetSlot(MemberGroup group, string name, bool privateBinding)
        {
            if (group.Count == 0)
            {
                return(null);
            }

            group = FilterNewSlots(group);
            TrackerTypes tt = GetMemberType(group);

            switch (tt)
            {
            case TrackerTypes.Method:
                bool checkStatic       = false;
                List <MemberInfo> mems = new List <MemberInfo>();
                foreach (MemberTracker mt in group)
                {
                    MethodTracker metht = (MethodTracker)mt;
                    mems.Add(metht.Method);
                    checkStatic |= metht.IsStatic;
                }

                Type         declType = group[0].DeclaringType;
                MemberInfo[] memArray = mems.ToArray();
                FunctionType ft       = GetMethodFunctionType(declType, memArray, checkStatic);
                return(GetFinalSlotForFunction(GetBuiltinFunction(declType, group[0].Name, name, ft, memArray)));

            case TrackerTypes.Field:
                return(GetReflectedField(((FieldTracker)group[0]).Field));

            case TrackerTypes.Property:
                return(GetReflectedProperty((PropertyTracker)group[0], group, privateBinding));

            case TrackerTypes.Event:
                return(GetReflectedEvent(((EventTracker)group[0])));

            case TrackerTypes.Type:
                TypeTracker type = (TypeTracker)group[0];
                for (int i = 1; i < group.Count; i++)
                {
                    type = TypeGroup.UpdateTypeEntity(type, (TypeTracker)group[i]);
                }

                if (type is TypeGroup)
                {
                    return(new PythonTypeUserDescriptorSlot(type, true));
                }

                return(new PythonTypeUserDescriptorSlot(DynamicHelpers.GetPythonTypeFromType(type.Type), true));

            case TrackerTypes.Constructor:
                return(GetConstructorFunction(group[0].DeclaringType, privateBinding));

            case TrackerTypes.Custom:
                return(((PythonCustomTracker)group[0]).GetSlot());

            default:
                // if we have a new slot in the derived class filter out the
                // members from the base class.
                throw new InvalidOperationException(String.Format("Bad member type {0} on {1}.{2}", tt.ToString(), group[0].DeclaringType, name));
            }
        }
コード例 #2
0
        private bool TryGetLazyValue(string name, bool publish, out object value)
        {
            if (!_cleared)
            {
                MemberInfo[] members = NonHiddenMembers(GetMember(name));
                if (members.Length > 0)
                {
                    // we only support fields, methods, and nested types in modules.
                    switch (members[0].MemberType)
                    {
                    case MemberTypes.Field:
                        Debug.Assert(members.Length == 1);

                        var fieldInfo = (FieldInfo)members[0];
                        if (fieldInfo.IsStatic)
                        {
                            value = ((FieldInfo)members[0]).GetValue(null);
                        }
                        else
                        {
                            throw new InvalidOperationException("instance field declared on module.  Fields should stored as PythonGlobals, should be static readonly, or marked as PythonHidden.");
                        }

                        if (publish)
                        {
                            LazyAdd(name, value);
                        }
                        return(true);

                    case MemberTypes.Method:
                        if (!((MethodInfo)members[0]).IsSpecialName)
                        {
                            var          methods = new MethodInfo[members.Length];
                            FunctionType ft      = FunctionType.ModuleMethod | FunctionType.AlwaysVisible;
                            for (int i = 0; i < members.Length; i++)
                            {
                                var method = (MethodInfo)members[i];
                                if (method.IsStatic)
                                {
                                    ft |= FunctionType.Function;
                                }
                                else
                                {
                                    ft |= FunctionType.Method;
                                }

                                methods[i] = method;
                            }

                            var builtinFunc = BuiltinFunction.MakeMethod(
                                name,
                                methods,
                                members[0].DeclaringType,
                                ft
                                );

                            if ((ft & FunctionType.Method) != 0 && Instance != null)
                            {
                                value = builtinFunc.BindToInstance(Instance);
                            }
                            else
                            {
                                value = builtinFunc;
                            }

                            if (publish)
                            {
                                LazyAdd(name, value);
                            }
                            return(true);
                        }
                        break;

                    case MemberTypes.Property:
                        Debug.Assert(members.Length == 1);

                        var propInfo = (PropertyInfo)members[0];
                        if ((propInfo.GetGetMethod() ?? propInfo.GetSetMethod()).IsStatic)
                        {
                            value = ((PropertyInfo)members[0]).GetValue(null, ArrayUtils.EmptyObjects);
                        }
                        else
                        {
                            throw new InvalidOperationException("instance property declared on module.  Propreties should be declared as static, marked as PythonHidden, or you should use a PythonGlobal.");
                        }

                        if (publish)
                        {
                            LazyAdd(name, value);
                        }

                        return(true);

                    case MemberTypes.NestedType:
                        if (members.Length == 1)
                        {
                            value = DynamicHelpers.GetPythonTypeFromType((Type)members[0]);
                        }
                        else
                        {
                            TypeTracker tt = (TypeTracker)MemberTracker.FromMemberInfo(members[0]);
                            for (int i = 1; i < members.Length; i++)
                            {
                                tt = TypeGroup.UpdateTypeEntity(tt, (TypeTracker)MemberTracker.FromMemberInfo(members[i]));
                            }

                            value = tt;
                        }

                        if (publish)
                        {
                            LazyAdd(name, value);
                        }
                        return(true);
                    }
                }
            }

            value = null;
            return(false);
        }
コード例 #3
0
        private Func <CallSite, TSelfType, CodeContext, object> MakeGetMemberTarget <TSelfType>(string name, object target, CodeContext context)
        {
            Type type = CompilerHelpers.GetType(target);

            // needed for GetMember call until DynamicAction goes away
            if (typeof(TypeTracker).IsAssignableFrom(type))
            {
                // no fast path for TypeTrackers
                PerfTrack.NoteEvent(PerfTrack.Categories.BindingSlow, "GetNoFast TypeTracker");
                return(null);
            }

            MemberGroup members = Context.Binder.GetMember(MemberRequestKind.Get, type, name);

            if (members.Count == 0 && type.IsInterface())
            {
                // all interfaces have object members
                type    = typeof(object);
                members = Context.Binder.GetMember(MemberRequestKind.Get, type, name);
            }

            if (members.Count == 0 && typeof(IStrongBox).IsAssignableFrom(type))
            {
                // no fast path for strong box access
                PerfTrack.NoteEvent(PerfTrack.Categories.BindingSlow, "GetNoFast StrongBox");
                return(null);
            }

            MethodInfo getMem = Context.Binder.GetMethod(type, "GetCustomMember");

            if (getMem != null && getMem.IsSpecialName)
            {
                // no fast path for custom member access
                PerfTrack.NoteEvent(PerfTrack.Categories.BindingSlow, "GetNoFast GetCustomMember " + type);
                return(null);
            }

            Expression   error;
            TrackerTypes memberType = Context.Binder.GetMemberType(members, out error);

            if (error == null)
            {
                PythonType argType  = DynamicHelpers.GetPythonTypeFromType(type);
                bool       isHidden = argType.IsHiddenMember(name);
                if (isHidden)
                {
                    PerfTrack.NoteEvent(PerfTrack.Categories.BindingSlow, "GetNoFast FilteredMember " + memberType);
                    return(null);
                }

                switch (memberType)
                {
                case TrackerTypes.TypeGroup:
                case TrackerTypes.Type:
                    object typeObj;
                    if (members.Count == 1)
                    {
                        typeObj = DynamicHelpers.GetPythonTypeFromType(((TypeTracker)members[0]).Type);
                    }
                    else
                    {
                        TypeTracker typeTracker = (TypeTracker)members[0];
                        for (int i = 1; i < members.Count; i++)
                        {
                            typeTracker = TypeGroup.UpdateTypeEntity(typeTracker, (TypeTracker)members[i]);
                        }
                        typeObj = typeTracker;
                    }

                    return(new FastTypeGet <TSelfType>(type, typeObj).GetTypeObject);

                case TrackerTypes.Method:
                    PythonTypeSlot slot = PythonTypeOps.GetSlot(members, name, _context.DomainManager.Configuration.PrivateBinding);
                    if (slot is BuiltinMethodDescriptor)
                    {
                        return(new FastMethodGet <TSelfType>(type, (BuiltinMethodDescriptor)slot).GetMethod);
                    }
                    else if (slot is BuiltinFunction)
                    {
                        return(new FastSlotGet <TSelfType>(type, slot, DynamicHelpers.GetPythonTypeFromType(type)).GetRetSlot);
                    }
                    return(new FastSlotGet <TSelfType>(type, slot, DynamicHelpers.GetPythonTypeFromType(type)).GetBindSlot);

                case TrackerTypes.Event:
                    if (members.Count == 1 && !((EventTracker)members[0]).IsStatic)
                    {
                        slot = PythonTypeOps.GetSlot(members, name, _context.DomainManager.Configuration.PrivateBinding);
                        return(new FastSlotGet <TSelfType>(type, slot, DynamicHelpers.GetPythonTypeFromType(((EventTracker)members[0]).DeclaringType)).GetBindSlot);
                    }
                    PerfTrack.NoteEvent(PerfTrack.Categories.BindingSlow, "GetNoFast Event " + members.Count + " " + ((EventTracker)members[0]).IsStatic);
                    return(null);

                case TrackerTypes.Property:
                    if (members.Count == 1)
                    {
                        PropertyTracker pt = (PropertyTracker)members[0];
                        if (!pt.IsStatic && pt.GetIndexParameters().Length == 0)
                        {
                            MethodInfo      prop = pt.GetGetMethod();
                            ParameterInfo[] parameters;

                            if (prop != null && (parameters = prop.GetParameters()).Length == 0)
                            {
                                if (prop.ReturnType == typeof(bool))
                                {
                                    return(new FastPropertyGet <TSelfType>(type, CallInstruction.Create(prop, parameters).Invoke).GetPropertyBool);
                                }
                                else if (prop.ReturnType == typeof(int))
                                {
                                    return(new FastPropertyGet <TSelfType>(type, CallInstruction.Create(prop, parameters).Invoke).GetPropertyInt);
                                }
                                else
                                {
                                    return(new FastPropertyGet <TSelfType>(type, CallInstruction.Create(prop, parameters).Invoke).GetProperty);
                                }
                            }
                        }
                    }
                    PerfTrack.NoteEvent(PerfTrack.Categories.BindingSlow, "GetNoFast Property " + members.Count + " " + ((PropertyTracker)members[0]).IsStatic);
                    return(null);

                case TrackerTypes.All:
                    getMem = Context.Binder.GetMethod(type, "GetBoundMember");
                    if (getMem != null && getMem.IsSpecialName)
                    {
                        PerfTrack.NoteEvent(PerfTrack.Categories.BindingSlow, "GetNoFast GetBoundMember " + type);
                        return(null);
                    }

                    if (members.Count == 0)
                    {
                        // we don't yet support fast bindings to extension methods
                        members = context.ModuleContext.ExtensionMethods.GetBinder(_context).GetMember(MemberRequestKind.Get, type, name);
                        if (members.Count == 0)
                        {
                            if (IsNoThrow)
                            {
                                return(new FastErrorGet <TSelfType>(type, name, context.ModuleContext.ExtensionMethods).GetErrorNoThrow);
                            }
                            else if (SupportsLightThrow)
                            {
                                return(new FastErrorGet <TSelfType>(type, name, context.ModuleContext.ExtensionMethods).GetErrorLightThrow);
                            }
                            else
                            {
                                return(new FastErrorGet <TSelfType>(type, name, context.ModuleContext.ExtensionMethods).GetError);
                            }
                        }
                    }
                    return(null);

                default:
                    PerfTrack.NoteEvent(PerfTrack.Categories.BindingSlow, "GetNoFast " + memberType);
                    return(null);
                }
            }
            else
            {
                StringBuilder sb = new StringBuilder();
                foreach (MemberTracker mi in members)
                {
                    if (sb.Length != 0)
                    {
                        sb.Append(", ");
                    }
                    sb.Append(mi.MemberType);
                    sb.Append(" : ");
                    sb.Append(mi.ToString());
                }

                return(new FastErrorGet <TSelfType>(type, sb.ToString(), context.ModuleContext.ExtensionMethods).GetAmbiguous);
            }
        }
コード例 #4
0
        private bool TryGetLazyValue(string name, bool publish, out object value)
        {
            if (!_cleared)
            {
                MemberInfo[] members = NonHiddenMembers(GetMember(name));
                if (members.Length > 0)
                {
                    // we only support fields, methods, and nested types in modules.
                    switch (members[0].MemberType)
                    {
                    case MemberTypes.Field:
                        Debug.Assert(members.Length == 1);

                        value = ((FieldInfo)members[0]).GetValue(null);
                        if (publish)
                        {
                            LazyAdd(name, value);
                        }
                        return(true);

                    case MemberTypes.Method:
                        if (!((MethodInfo)members[0]).IsSpecialName)
                        {
                            value = BuiltinFunction.MakeFunction(
                                name,
                                ArrayUtils.ConvertAll <MemberInfo, MethodInfo>(members, delegate(MemberInfo mi) { return((MethodInfo)mi); }),
                                members[0].DeclaringType
                                );

                            if (publish)
                            {
                                LazyAdd(name, value);
                            }
                            return(true);
                        }
                        break;

                    case MemberTypes.Property:
                        Debug.Assert(members.Length == 1);

                        value = ((PropertyInfo)members[0]).GetValue(null, ArrayUtils.EmptyObjects);

                        if (publish)
                        {
                            LazyAdd(name, value);
                        }

                        return(true);

                    case MemberTypes.NestedType:
                        if (members.Length == 1)
                        {
                            value = DynamicHelpers.GetPythonTypeFromType((Type)members[0]);
                        }
                        else
                        {
                            TypeTracker tt = (TypeTracker)MemberTracker.FromMemberInfo(members[0]);
                            for (int i = 1; i < members.Length; i++)
                            {
                                tt = TypeGroup.UpdateTypeEntity(tt, (TypeTracker)MemberTracker.FromMemberInfo(members[i]));
                            }

                            value = tt;
                        }

                        if (publish)
                        {
                            LazyAdd(name, value);
                        }
                        return(true);
                    }
                }
            }

            value = null;
            return(false);
        }