private void MakeGenericBody(GetMemberInfo getMemInfo, Type instanceType, MemberGroup members, DynamicMetaObject instance) { MemberTracker bestMember = members[0]; if (members.Count > 1) { // if we were given multiple members pick the member closest to the type... Type bestMemberDeclaringType = members[0].DeclaringType; for (int i = 1; i < members.Count; i++) { MemberTracker mt = members[i]; if (!IsTrackerApplicableForType(instanceType, mt)) { continue; } if (members[i].DeclaringType.IsSubclassOf(bestMemberDeclaringType) || !IsTrackerApplicableForType(instanceType, bestMember)) { bestMember = members[i]; bestMemberDeclaringType = members[i].DeclaringType; } } } MakeGenericBodyWorker(getMemInfo, instanceType, bestMember, instance); }
private void MakeSetMemberRule(Type type) { if (MakeOperatorSetMemberBody(type, "SetMember")) { return; } MemberGroup members = Binder.GetMember(Action, type, StringName); // if lookup failed try the strong-box type if available. if (members.Count == 0 && StrongBoxType != null) { type = StrongBoxType; StrongBoxType = null; members = Binder.GetMember(Action, type, StringName); } Expression error; TrackerTypes memberTypes = GetMemberType(members, out error); if (error == null) { switch (memberTypes) { case TrackerTypes.Method: case TrackerTypes.TypeGroup: case TrackerTypes.Type: case TrackerTypes.Constructor: MakeReadOnlyMemberError(type); break; case TrackerTypes.Event: AddToBody(Binder.MakeEventValidation(Rule, members).MakeErrorForRule(Rule, Binder)); break; case TrackerTypes.Field: MakeFieldRule(type, members); break; case TrackerTypes.Property: MakePropertyRule(type, members); break; case TrackerTypes.Custom: MakeGenericBody(type, members[0]); break; case TrackerTypes.All: // no match if (MakeOperatorSetMemberBody(type, "SetMemberAfter")) { return; } MakeMissingMemberError(type); break; default: throw new InvalidOperationException(); } } else { AddToBody(Rule.MakeError(error)); } }
private static MethodInfo[] GetCallableMethods(MemberGroup members) { MethodInfo[] methods = new MethodInfo[members.Count]; for (int i = 0; i < members.Count; i++) { methods[i] = CompilerHelpers.GetCallableMethod(((MethodTracker)members[i]).Method); } return(methods); }
private void MakeTypeBody(Type type, MemberGroup members) { TypeTracker typeTracker = (TypeTracker)members[0]; for (int i = 1; i < members.Count; i++) { typeTracker = TypeGroup.UpdateTypeEntity(typeTracker, (TypeTracker)members[i]); } AddToBody(Rule.MakeReturn(Binder, typeTracker.GetValue(Binder, type))); }
private void MakeTypeBody(GetMemberInfo getMemInfo, Type instanceType, MemberGroup members) { TypeTracker typeTracker = (TypeTracker)members[0]; for (int i = 1; i < members.Count; i++) { typeTracker = TypeGroup.UpdateTypeEntity(typeTracker, (TypeTracker)members[i]); } getMemInfo.Body.FinishCondition(typeTracker.GetValue(getMemInfo.ResolutionFactory, this, instanceType)); }
private MethodInfo[] GetApplicableMembers(Type t, OperatorInfo info) { MemberGroup members = Binder.GetMember(Action, t, info.Name); if (members.Count == 0 && info.AlternateName != null) { members = Binder.GetMember(Action, t, info.AlternateName); } // filter down to just methods return(FilterNonMethods(t, members)); }
/// <summary> /// Gets the members that are visible from the provided type of the specified name. /// /// The default implemetnation first searches the type, then the flattened heirachy of the type, and then /// registered extension methods. /// </summary> public virtual MemberGroup GetMember(MemberRequestKind action, Type type, string name) { IEnumerable <MemberInfo> foundMembers = type.GetInheritedMembers(name); if (!PrivateBinding) { foundMembers = CompilerHelpers.FilterNonVisibleMembers(type, foundMembers); } MemberGroup members = new MemberGroup(foundMembers.ToArray()); // check for generic types w/ arity... string genName = name + ReflectionUtils.GenericArityDelimiter; List <TypeInfo> genTypes = null; foreach (TypeInfo t in type.GetDeclaredNestedTypes()) { if (t.IsPublic && t.Name.StartsWith(genName)) { if (genTypes == null) { genTypes = new List <TypeInfo>(); } genTypes.Add(t); } } if (genTypes != null) { List <MemberTracker> mt = new List <MemberTracker>(members); foreach (TypeInfo t in genTypes) { mt.Add(MemberTracker.FromMemberInfo(t)); } return(MemberGroup.CreateInternal(mt.ToArray())); } if (members.Count == 0) { members = new MemberGroup( type.GetInheritedMembers(name, flattenHierarchy: true).WithBindingFlags(BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance).ToArray() ); if (members.Count == 0) { members = GetAllExtensionMembers(type, name); } } return(members); }
private static Type GetDeclaringMemberType(MemberGroup group) { Type t = typeof(object); foreach (MemberTracker mt in group) { if (t.IsAssignableFrom(mt.DeclaringType)) { t = mt.DeclaringType; } } return(t); }
public virtual ErrorInfo MakeEventValidation(MemberGroup members, Expression eventObject, Expression value, Expression codeContext) { EventTracker ev = (EventTracker)members[0]; // handles in place addition of events - this validates the user did the right thing. return(ErrorInfo.FromValueNoError( Expression.Call( typeof(BinderOps).GetMethod("SetEvent"), Expression.Constant(ev), value ) )); }
public virtual ErrorInfo MakeEventValidation(RuleBuilder rule, MemberGroup members) { EventTracker ev = (EventTracker)members[0]; // handles in place addition of events - this validates the user did the right thing. return(ErrorInfo.FromValueNoError( Expression.Call( typeof(ScriptingRuntimeHelpers).GetMethod("SetEvent"), Expression.Constant(ev), rule.Parameters[1] ) )); }
public virtual ErrorInfo MakeEventValidation(MemberGroup members, DynamicMetaObject eventObject, DynamicMetaObject value, OverloadResolverFactory resolverFactory) { EventTracker ev = (EventTracker)members[0]; // handles in place addition of events - this validates the user did the right thing. return(ErrorInfo.FromValueNoError( Expression.Call( typeof(BinderOps).GetMethod("SetEvent"), AstUtils.Constant(ev), value.Expression ) )); }
/// <summary> /// Gets the extension members of the given name from the provided type. Base classes are also /// searched for their extension members. Once any of the types in the inheritance hierarchy /// provide an extension member the search is stopped. /// </summary> public MemberGroup GetAllExtensionMembers(Type type, string name) { foreach (Type ancestor in type.Ancestors()) { MemberGroup res = GetExtensionMembers(ancestor, name); if (res.Count != 0) { return(res); } } return(MemberGroup.EmptyGroup); }
private MethodInfo[] GetApplicableMembers(Type t, OperatorInfo info) { Assert.NotNull(t, info); MemberGroup members = GetMember(MemberRequestKind.Operation, t, info.Name); if (members.Count == 0 && info.AlternateName != null) { members = GetMember(MemberRequestKind.Operation, t, info.AlternateName); } // filter down to just methods return(FilterNonMethods(t, members)); }
/// <summary> /// Helper that checkes both types to see if either one defines the specified conversion /// method. /// </summary> private DynamicMetaObject TryOneConversion(ConversionResultKind kind, Type toType, Type type, Type fromType, string methodName, bool isImplicit, BindingRestrictions restrictions, DynamicMetaObject arg) { MemberGroup conversions = GetMember(MemberRequestKind.Convert, fromType, methodName); DynamicMetaObject res = TryUserDefinedConversion(kind, toType, type, conversions, isImplicit, restrictions, arg); if (res != null) { return(res); } // then on the type we're trying to convert to conversions = GetMember(MemberRequestKind.Convert, toType, methodName); return(TryUserDefinedConversion(kind, toType, type, conversions, isImplicit, restrictions, arg)); }
private MetaObject MakeDeleteMemberTarget(SetOrDeleteMemberInfo delInfo, MetaObject target) { Type type = target.LimitType; Restrictions restrictions = target.Restrictions; Expression self = target.Expression; // needed for DeleteMember call until DynamicAction goes away OldDynamicAction act = OldDeleteMemberAction.Make( this, delInfo.Name ); if (typeof(TypeTracker).IsAssignableFrom(type)) { restrictions = restrictions.Merge( Restrictions.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(act, 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.FinishCondition(MakeError(MakeUndeletableMemberError(GetDeclaringMemberType(group), delInfo.Name))); } else { delInfo.Body.FinishCondition(MakeError(MakeMissingMemberError(type, delInfo.Name))); } } return(delInfo.Body.GetMetaObject(target)); }
private Expression MakeBodyHelper(Type type, MemberGroup members) { if (!_isStatic) { MakeOperatorGetMemberBody(type, "GetCustomMember"); } Expression error; TrackerTypes memberType = GetMemberType(members, out error); if (error != null) { AddToBody(Rule.MakeError(error)); return(Body); } switch (memberType) { case TrackerTypes.TypeGroup: case TrackerTypes.Type: MakeTypeBody(type, members); break; case TrackerTypes.Method: // turn into a MethodGroup MakeGenericBodyWorker(type, ReflectionCache.GetMethodGroup(StringName, members), _instance ?? Rule.Parameters[0]); break; case TrackerTypes.Event: case TrackerTypes.Field: case TrackerTypes.Property: case TrackerTypes.Constructor: case TrackerTypes.Custom: MakeGenericBody(type, members); break; case TrackerTypes.All: // no members were found if (!_isStatic) { MakeOperatorGetMemberBody(type, "GetBoundMember"); } MakeMissingMemberRuleForGet(type); break; default: throw new InvalidOperationException(memberType.ToString()); } return(Body); }
/// <summary> /// Gets the members that are visible from the provided type of the specified name. /// /// The default implemetnation first searches the type, then the flattened heirachy of the type, and then /// registered extension methods. /// </summary> public virtual MemberGroup GetMember(OldDynamicAction action, Type type, string name) { MemberInfo[] foundMembers = type.GetMember(name); if (!PrivateBinding) { foundMembers = CompilerHelpers.FilterNonVisibleMembers(type, foundMembers); } MemberGroup members = new MemberGroup(foundMembers); // check for generic types w/ arity... Type[] types = type.GetNestedTypes(BindingFlags.Public); string genName = name + ReflectionUtils.GenericArityDelimiter; List <Type> genTypes = null; foreach (Type t in types) { if (t.Name.StartsWith(genName)) { if (genTypes == null) { genTypes = new List <Type>(); } genTypes.Add(t); } } if (genTypes != null) { List <MemberTracker> mt = new List <MemberTracker>(members); foreach (Type t in genTypes) { mt.Add(MemberTracker.FromMemberInfo(t)); } return(MemberGroup.CreateInternal(mt.ToArray())); } if (members.Count == 0) { members = new MemberGroup(type.GetMember(name, BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance)); if (members.Count == 0) { members = GetAllExtensionMembers(type, name); } } return(members); }
private MethodInfo[] GetApplicableMembers(Type t, OperatorInfo info) { Assert.NotNull(t, info); OldDoOperationAction act = OldDoOperationAction.Make(this, info.Operator); MemberGroup members = GetMember(act, t, info.Name); if (members.Count == 0 && info.AlternateName != null) { members = GetMember(act, t, info.AlternateName); } // filter down to just methods return(FilterNonMethods(t, members)); }
/// <summary> /// Helper that checkes both types to see if either one defines the specified conversion /// method. /// </summary> private MetaObject TryOneConversion(ConversionResultKind kind, Type toType, Type type, Type fromType, string methodName, bool isImplicit, Restrictions restrictions, MetaObject arg) { OldConvertToAction action = OldConvertToAction.Make(this, toType, kind); MemberGroup conversions = GetMember(action, fromType, methodName); MetaObject res = TryUserDefinedConversion(kind, toType, type, conversions, isImplicit, restrictions, arg); if (res != null) { return(res); } // then on the type we're trying to convert to conversions = GetMember(action, toType, methodName); return(TryUserDefinedConversion(kind, toType, type, conversions, isImplicit, restrictions, arg)); }
/// <summary> /// Gets the extension members of the given name from the provided type. Base classes are also /// searched for their extension members. Once any of the types in the inheritance hierarchy /// provide an extension member the search is stopped. /// </summary> public MemberGroup GetAllExtensionMembers(Type type, string name) { Type curType = type; do { MemberGroup res = GetExtensionMembers(curType, name); if (res.Count != 0) { return(res); } curType = curType.BaseType; } while (curType != null); return(MemberGroup.EmptyGroup); }
/// <summary> /// Helper that checkes both types to see if either one defines the specified conversion /// method. /// </summary> private bool TryOneConversion(Type toType, Type type, Type fromType, string methodName, bool isImplicit) { MemberGroup conversions = Binder.GetMember(Action, fromType, methodName); if (TryUserDefinedConversion(toType, type, conversions, isImplicit)) { return(true); } // then on the type we're trying to convert to conversions = Binder.GetMember(Action, toType, methodName); if (TryUserDefinedConversion(toType, type, conversions, isImplicit)) { return(true); } return(false); }
private static Expression MakeAmbigiousMatchError(MemberGroup members) { StringBuilder sb = new StringBuilder(); foreach (MethodTracker mi in members) { if (sb.Length != 0) { sb.Append(", "); } sb.Append(mi.MemberType); sb.Append(" : "); sb.Append(mi.ToString()); } return(Ast.New(typeof(AmbiguousMatchException).GetConstructor(new Type[] { typeof(string) }), Ast.Constant(sb.ToString()))); }
protected virtual StandardRule <T> MakeEventValidation(MemberGroup members) { EventTracker ev = (EventTracker)members[0]; // handles in place addition of events - this validates the user did the right thing, probably too Python specific. AddToBody( Rule.MakeReturn( Binder, Ast.Call( typeof(BinderOps).GetMethod("SetEvent"), Ast.RuntimeConstant(ev), Rule.Parameters[1] ) ) ); return(Rule); }
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)); }
/// <summary> /// Gets the extension members of the given name from the provided type. Subclasses of the /// type and their extension members are not searched. /// </summary> public MemberGroup GetExtensionMembers(Type declaringType, string name) { IList <Type> extTypes = GetExtensionTypes(declaringType); List <MemberTracker> members = new List <MemberTracker>(); foreach (Type ext in extTypes) { foreach (MemberInfo mi in ext.GetDeclaredMembers(name).WithBindingFlags(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)) { MemberInfo newMember = mi; if (PrivateBinding || (newMember = CompilerHelpers.TryGetVisibleMember(ext, mi)) != null) { if (IncludeExtensionMember(newMember)) { if (ext != declaringType) { members.Add(MemberTracker.FromMemberInfo(newMember, declaringType)); } else { members.Add(MemberTracker.FromMemberInfo(newMember)); } } } } // TODO: Support indexed getters/setters w/ multiple methods MethodInfo getter = GetExtensionOperator(ext, "Get" + name); MethodInfo setter = GetExtensionOperator(ext, "Set" + name); MethodInfo deleter = GetExtensionOperator(ext, "Delete" + name); if (getter != null || setter != null || deleter != null) { members.Add(new ExtensionPropertyTracker(name, getter, setter, deleter, declaringType)); } } if (members.Count != 0) { return(MemberGroup.CreateInternal(members.ToArray())); } return(MemberGroup.EmptyGroup); }
public TrackerTypes GetMemberType(MemberGroup members, out Expression error) { error = null; TrackerTypes memberType = TrackerTypes.All; for (int i = 0; i < members.Count; i++) { MemberTracker mi = members[i]; if (mi.MemberType != memberType) { if (memberType != TrackerTypes.All) { error = MakeAmbiguousMatchError(members); return(TrackerTypes.All); } memberType = mi.MemberType; } } return(memberType); }
/// <summary> /// Attempts to bind to an operator Call method. /// </summary> private TargetInfo TryGetOperatorTargets(DynamicMetaObject self, DynamicMetaObject[] args, object target) { Type targetType = CompilerHelpers.GetType(target); MemberGroup callMembers = GetMember(MemberRequestKind.Invoke, targetType, "Call"); List<MethodBase> callTargets = new List<MethodBase>(); foreach (MemberTracker mi in callMembers) { if (mi.MemberType == TrackerTypes.Method) { MethodInfo method = ((MethodTracker)mi).Method; if (method.IsSpecialName) { callTargets.Add(method); } } } if (callTargets.Count > 0) { return new TargetInfo(null, ArrayUtils.Insert(self, args), callTargets.ToArray()); } return null; }
private static MethodInfo[] FilterNonMethods(Type t, MemberGroup members) { List <MethodInfo> methods = new List <MethodInfo>(members.Count); foreach (MemberTracker mi in members) { if (mi.MemberType == TrackerTypes.Method) { MethodInfo method = ((MethodTracker)mi).Method; // don't call object methods for None type, but if someone added // methods to null we'd call those. if (method.DeclaringType != typeof(object) || t != typeof(Null)) { methods.Add(method); } } } return(methods.ToArray()); }
/// <summary> /// Checks if any of the members of the MemberGroup provide the applicable conversion and /// if so uses it to build a conversion rule. /// </summary> private bool TryUserDefinedConversion(Type toType, Type type, MemberGroup conversions, bool isImplicit) { Type checkType = GetUnderlyingType(type); foreach (MemberTracker mt in conversions) { if (mt.MemberType != TrackerTypes.Method) { continue; } MethodTracker method = (MethodTracker)mt; if (isImplicit && method.Method.IsDefined(typeof(ExplicitConversionMethodAttribute), true)) { continue; } if (method.Method.ReturnType == toType) // TODO: IsAssignableFrom? IsSubclass? { ParameterInfo[] pis = method.Method.GetParameters(); if (pis.Length == 1 && pis[0].ParameterType.IsAssignableFrom(checkType)) { // we can use this method if (type == checkType) { MakeConversionTarget(method, type, isImplicit); } else { MakeExtensibleConversionTarget(method, type, isImplicit); } return(true); } } } return(false); }
private Statement MakeDeleteMemberTarget() { Type type = CompilerHelpers.GetType(Target); // This goes away when ICustomMembers goes away. if (typeof(ICustomMembers).IsAssignableFrom(type)) { MakeCustomMembersBody(type); return(Body); } if (!MakeOperatorGetMemberBody(type, "DeleteMember")) { MemberGroup group = Binder.GetMember(Action, type, StringName); if (group.Count != 0) { if (group[0].MemberType == TrackerTypes.Property) { MethodInfo del = ((PropertyTracker)group[0]).GetDeleteMethod(ScriptDomainManager.Options.PrivateBinding); if (del != null) { MakePropertyDeleteStatement(del); return(Body); } } MakeUndeletableMemberError(GetDeclaringMemberType(group)); } else { MakeMissingMemberError(type); } } return(Body); }