private void AddCompatibleOverloads(ClrMethod /*!*/ constructedMethod, ClrMethod /*!*/ genericMethod, DTypeDescs /*!*/ typeArgs, bool exactMatch) { foreach (ClrMethod.Overload overload in genericMethod.Overloads) { // add the overloads that are compatible with typeArgs int gen_count = overload.GenericParamCount; if (exactMatch ? gen_count == typeArgs.Count : gen_count > typeArgs.Count) { bool compatible = true; for (int i = 0; i < gen_count; i++) { DTypeDesc desc = (i < typeArgs.Count ? typeArgs[i] : PrimitiveTypeDesc.SystemObjectTypeDesc); if (!desc.IsCompatibleWithGenericParameter(overload.GenericParameters[i])) { compatible = false; break; } } if (compatible) { // make generic method Type[] real_type_args; if (exactMatch) { real_type_args = typeArgs.GetRealTypes(); } else { real_type_args = new Type[gen_count]; typeArgs.GetRealTypes(real_type_args, 0); for (int i = typeArgs.Count; i < gen_count; i++) { real_type_args[i] = Types.Object[0]; } } MethodInfo info = ((MethodInfo)overload.Method).MakeGenericMethod(real_type_args); ClrMethod.Overload constructed_overload; constructedMethod.AddOverload(info, out constructed_overload); } } } }
/// <summary> /// Creates a constructed method desc for the given type arguments. /// </summary> private ClrMethodDesc ConstructMethodDesc(DTypeDescs /*!*/ typeArgs) { ClrMethod generic_method = ClrMethod; ClrMethod constructed_method = new ClrMethod(generic_method.Name, declaringType, memberAttributes, 1, false); // add overloads which have an exact match AddCompatibleOverloads(constructed_method, generic_method, typeArgs, true); if (constructed_method.Overloads.Count == 0) { // now try overloads whose additional type parameters can by substituted by System.Object AddCompatibleOverloads(constructed_method, generic_method, typeArgs, false); if (constructed_method.Overloads.Count == 0) { // sorry, bad luck PhpException.NoSuitableOverload(generic_method.DeclaringType.FullName, generic_method.FullName); return(null); } } return(constructed_method.ClrMethodDesc); }
/// <summary> /// Dispatches the invocation to a constructed method according to type arguments on the stack. /// </summary> /// <remarks> /// Constructed methods are cached in the <see cref="instantiations"/> dictionary. /// </remarks> private object ArglessPreStub(object instance, PhpStack /*!*/ stack) { // get type arguments from the stack DTypeDescs type_args = new DTypeDescs(stack); ClrMethodDesc method_desc; lock (instantiations) { if (!instantiations.TryGetValue(type_args, out method_desc)) { method_desc = ConstructMethodDesc(type_args); if (method_desc == null) { return(null); } instantiations.Add(type_args, method_desc); } } return(method_desc.ArglessStub(instance, stack)); }
private void AddCompatibleOverloads(ClrMethod/*!*/ constructedMethod, ClrMethod/*!*/ genericMethod, DTypeDescs/*!*/ typeArgs, bool exactMatch) { foreach (ClrMethod.Overload overload in genericMethod.Overloads) { // add the overloads that are compatible with typeArgs int gen_count = overload.GenericParamCount; if (exactMatch ? gen_count == typeArgs.Count : gen_count > typeArgs.Count) { bool compatible = true; for (int i = 0; i < gen_count; i++) { DTypeDesc desc = (i < typeArgs.Count ? typeArgs[i] : PrimitiveTypeDesc.SystemObjectTypeDesc); if (!desc.IsCompatibleWithGenericParameter(overload.GenericParameters[i])) { compatible = false; break; } } if (compatible) { // make generic method Type[] real_type_args; if (exactMatch) real_type_args = typeArgs.GetRealTypes(); else { real_type_args = new Type[gen_count]; typeArgs.GetRealTypes(real_type_args, 0); for (int i = typeArgs.Count; i < gen_count; i++) real_type_args[i] = Types.Object[0]; } MethodInfo info = ((MethodInfo)overload.Method).MakeGenericMethod(real_type_args); ClrMethod.Overload constructed_overload; constructedMethod.AddOverload(info, out constructed_overload); } } } }
/// <summary> /// Creates a constructed method desc for the given type arguments. /// </summary> private ClrMethodDesc ConstructMethodDesc(DTypeDescs/*!*/ typeArgs) { ClrMethod generic_method = ClrMethod; ClrMethod constructed_method = new ClrMethod(generic_method.Name, declaringType, memberAttributes, 1, false); // add overloads which have an exact match AddCompatibleOverloads(constructed_method, generic_method, typeArgs, true); if (constructed_method.Overloads.Count == 0) { // now try overloads whose additional type parameters can by substituted by System.Object AddCompatibleOverloads(constructed_method, generic_method, typeArgs, false); if (constructed_method.Overloads.Count == 0) { // sorry, bad luck PhpException.NoSuitableOverload(generic_method.DeclaringType.FullName, generic_method.FullName); return null; } } return constructed_method.ClrMethodDesc; }
/// <summary> /// Dispatches the invocation to a constructed method according to type arguments on the stack. /// </summary> /// <remarks> /// Constructed methods are cached in the <see cref="instantiations"/> dictionary. /// </remarks> private object ArglessPreStub(object instance, PhpStack/*!*/ stack) { // get type arguments from the stack DTypeDescs type_args = new DTypeDescs(stack); ClrMethodDesc method_desc; lock (instantiations) { if (!instantiations.TryGetValue(type_args, out method_desc)) { method_desc = ConstructMethodDesc(type_args); if (method_desc == null) return null; instantiations.Add(type_args, method_desc); } } return method_desc.ArglessStub(instance, stack); }
internal ConstructedType/*!*/ CreateConstructedType(DTypeDesc/*!*/ genericType, DTypeDesc[]/*!!*/ arguments, int argCount) { ConstructedType result; if (genericType.IsUnknown) { Array.Resize(ref arguments, argCount); result = new ConstructedType(genericType, arguments); } else { DTypeDescs tuple = new DTypeDescs(genericType, arguments, argCount); if (!constructedTypes.TryGetValue(tuple, out result)) { Array.Resize(ref arguments, argCount); result = new ConstructedType(genericType, arguments); constructedTypes.Add(tuple, result); } } return result; }