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)); } }
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); }
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); } }
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); }