internal static MemberInfo Select(TypeReferences typeRefs, MemberInfo[] match, int matches, IReflect[] argIRs, MemberTypes memberType){ Debug.Assert(matches > 1); int candidates = 0; ParameterInfo[][] fparams = new ParameterInfo[matches][]; bool lookForPropertyGetters = memberType == MemberTypes.Method; for (int i = 0; i < matches; i++){ MemberInfo mem = match[i]; if (mem is PropertyInfo && lookForPropertyGetters) mem = ((PropertyInfo)mem).GetGetMethod(true); if (mem == null) continue; if (mem.MemberType == memberType){ if (mem is PropertyInfo) fparams[i] = ((PropertyInfo)mem).GetIndexParameters(); else fparams[i] = ((MethodBase)mem).GetParameters(); candidates++; } } int j = JSBinder.SelectBest(typeRefs, match, matches, argIRs, fparams, null, candidates, argIRs.Length); if (j < 0) return null; return match[j]; }
private static int TypeDistance(TypeReferences typeRefs, Type formal, Type actual, int distFromObject) { if (formal == typeRefs.Object) { return distFromObject; } if (formal.IsEnum) { return (TypeDistance(typeRefs, Enum.GetUnderlyingType(formal), actual) + 10); } return 100; }
internal static PropertyInfo SelectProperty(TypeReferences typeRefs, MemberInfo[] match, object[] args) { if (match == null) { return null; } int length = match.Length; switch (length) { case 0: return null; case 1: return (match[0] as PropertyInfo); } int candidates = 0; PropertyInfo info = null; ParameterInfo[][] fparams = new ParameterInfo[length][]; object[][] aparams = new object[length][]; for (int i = 0; i < length; i++) { MemberInfo info2 = match[i]; if (info2.MemberType == MemberTypes.Property) { MethodInfo getMethod = (info = (PropertyInfo) info2).GetGetMethod(true); if (getMethod == null) { fparams[i] = info.GetIndexParameters(); } else { fparams[i] = getMethod.GetParameters(); } aparams[i] = args; candidates++; } } if (candidates <= 1) { return info; } int index = SelectBest(typeRefs, match, length, null, fparams, aparams, candidates, args.Length); if (index < 0) { return null; } return (PropertyInfo) match[index]; }
private static int TypeDistance(TypeReferences typeRefs, IReflect formal, IReflect actual) { if (formal is TypedArray) { if (actual is TypedArray) { TypedArray array = (TypedArray) formal; TypedArray array2 = (TypedArray) actual; if (array.rank == array2.rank) { if (TypeDistance(typeRefs, array.elementType, array2.elementType) != 0) { return 100; } return 0; } } else if (actual is Type) { TypedArray array3 = (TypedArray) formal; Type type = (Type) actual; if (type.IsArray && (array3.rank == type.GetArrayRank())) { if (TypeDistance(typeRefs, array3.elementType, type.GetElementType()) != 0) { return 100; } return 0; } if ((type == typeRefs.Array) || (type == typeRefs.ArrayObject)) { return 30; } } return 100; } if (actual is TypedArray) { if (formal is Type) { Type type2 = (Type) formal; TypedArray array4 = (TypedArray) actual; if (type2.IsArray && (type2.GetArrayRank() == array4.rank)) { if (TypeDistance(typeRefs, type2.GetElementType(), array4.elementType) != 0) { return 100; } return 0; } if (type2 == typeRefs.Array) { return 30; } if (type2 == typeRefs.Object) { return 50; } } return 100; } if (formal is ClassScope) { if (!(actual is ClassScope)) { return 100; } if (!((ClassScope) actual).IsSameOrDerivedFrom((ClassScope) formal)) { return 100; } return 0; } if (!(actual is ClassScope)) { return TypeDistance(typeRefs, Microsoft.JScript.Convert.ToType(typeRefs, formal), Microsoft.JScript.Convert.ToType(typeRefs, actual)); } if (!(formal is Type)) { return 100; } if (!((ClassScope) actual).IsPromotableTo((Type) formal)) { return 100; } return 0; }
internal static ConstructorInfo SelectConstructor(TypeReferences typeRefs, MemberInfo[] match, ref object[] args, string[] namedParameters) { if (match == null) { return null; } int length = match.Length; switch (length) { case 0: return null; case 1: { Type t = match[0] as Type; if (t != null) { if (t.IsInterface && t.IsImport) { t = HandleCoClassAttribute(t); } match = t.GetConstructors(); length = match.Length; } break; } } if (length == 1) { return (match[0] as ConstructorInfo); } return (ConstructorInfo) Select(typeRefs, match, length, ref args, namedParameters, MemberTypes.Constructor); }
internal static MethodInfo SelectMethod(TypeReferences typeRefs, MemberInfo[] match, ref object[] args, string[] namedParameters) { if (match == null) { return null; } int length = match.Length; if (length == 0) { return null; } MemberInfo getMethod = (length == 1) ? match[0] : Select(typeRefs, match, length, ref args, namedParameters, MemberTypes.Method); if ((getMethod != null) && (getMethod.MemberType == MemberTypes.Property)) { getMethod = ((PropertyInfo) getMethod).GetGetMethod(true); } return (getMethod as MethodInfo); }
private static MethodBase SelectMethodBase(TypeReferences typeRefs, MethodBase[] match, ref Object[] args, ParameterModifier[] modifiers, String[] namedParameters){ if (match == null) return null; int n = match.Length; if (n == 0) return null; if (n == 1) return match[0]; MethodBase result = (MethodBase)JSBinder.Select(typeRefs, match, n, ref args, namedParameters, MemberTypes.Method); if (result == null) result = (MethodBase)JSBinder.Select(typeRefs, match, n, ref args, namedParameters, MemberTypes.Constructor); return result; }
private static int SelectBest(TypeReferences typeRefs, MemberInfo[] match, int matches, IReflect[] argIRs, ParameterInfo[][] fparams, object[][] aparams, int candidates, int parameters) { if (candidates == 0) { return -1; } if (candidates == 1) { for (int m = 0; m < matches; m++) { if (fparams[m] != null) { return m; } } } bool[] flagArray = new bool[matches]; int[] numArray = new int[matches]; for (int i = 0; i < matches; i++) { ParameterInfo[] infoArray = fparams[i]; if (infoArray != null) { int length = infoArray.Length; int num4 = (argIRs == null) ? aparams[i].Length : argIRs.Length; if ((num4 > length) && ((length == 0) || !Microsoft.JScript.CustomAttribute.IsDefined(infoArray[length - 1], typeof(ParamArrayAttribute), false))) { fparams[i] = null; candidates--; } else { for (int n = parameters; n < length; n++) { ParameterInfo target = infoArray[n]; if ((n == (length - 1)) && Microsoft.JScript.CustomAttribute.IsDefined(target, typeof(ParamArrayAttribute), false)) { break; } if (TypeReferences.GetDefaultParameterValue(target) is DBNull) { numArray[i] = 50; } } } } } for (int j = 0; candidates > 1; j++) { int num7 = 0; int num8 = 0x7fffffff; bool flag = false; for (int num9 = 0; num9 < matches; num9++) { int num10 = 0; ParameterInfo[] infoArray2 = fparams[num9]; if (infoArray2 != null) { IReflect missing = typeRefs.Missing; if (argIRs == null) { if (aparams[num9].Length > j) { object obj3 = aparams[num9][j]; if (obj3 == null) { obj3 = DBNull.Value; } missing = typeRefs.ToReferenceContext(obj3.GetType()); } } else if (j < parameters) { missing = argIRs[j]; } int num11 = infoArray2.Length; if ((num11 - 1) > j) { num7++; } IReflect formal = typeRefs.Missing; if ((((num11 > 0) && (j >= (num11 - 1))) && (Microsoft.JScript.CustomAttribute.IsDefined(infoArray2[num11 - 1], typeof(ParamArrayAttribute), false) && !(missing is TypedArray))) && ((missing != typeRefs.ArrayObject) && (!(missing is Type) || !((Type) missing).IsArray))) { ParameterInfo info2 = infoArray2[num11 - 1]; if (info2 is ParameterDeclaration) { formal = ((TypedArray) ((ParameterDeclaration) info2).ParameterIReflect).elementType; } else { formal = info2.ParameterType.GetElementType(); } if (j == (num11 - 1)) { numArray[num9]++; } } else if (j < num11) { ParameterInfo parameter = infoArray2[j]; formal = (parameter is ParameterDeclaration) ? ((ParameterDeclaration) parameter).ParameterIReflect : parameter.ParameterType; if ((missing == typeRefs.Missing) && !(TypeReferences.GetDefaultParameterValue(parameter) is DBNull)) { missing = formal; num10 = 1; } } int num12 = (TypeDistance(typeRefs, formal, missing) + numArray[num9]) + num10; if (num12 == num8) { if ((j == (num11 - 1)) && flagArray[num9]) { candidates--; fparams[num9] = null; } flag = flag && flagArray[num9]; } else if (num12 > num8) { if ((flag && (j < num11)) && FormalParamTypeIsObject(fparams[num9][j])) { num8 = num12; } else if (((j <= (num11 - 1)) || (missing != typeRefs.Missing)) || !Microsoft.JScript.CustomAttribute.IsDefined(infoArray2[num11 - 1], typeof(ParamArrayAttribute), false)) { flagArray[num9] = true; } } else { if ((candidates == 1) && !flagArray[num9]) { return num9; } flag = flagArray[num9]; for (int num13 = 0; num13 < num9; num13++) { if ((fparams[num13] != null) && !flagArray[num13]) { bool flag2 = fparams[num13].Length <= j; if ((!flag2 || (parameters > j)) && ((flag2 || !flag) || !FormalParamTypeIsObject(fparams[num13][j]))) { flagArray[num13] = true; } } } num8 = num12; } } } if ((j >= (parameters - 1)) && (num7 < 1)) { break; } } int index = -1; for (int k = 0; (k < matches) && (candidates > 0); k++) { ParameterInfo[] suppars = fparams[k]; if (suppars != null) { if (flagArray[k]) { candidates--; fparams[k] = null; } else if (index == -1) { index = k; } else if (Class.ParametersMatch(suppars, fparams[index])) { MemberInfo info4 = match[index]; JSWrappedMethod method = match[index] as JSWrappedMethod; if (method != null) { info4 = method.method; } if (((info4 is JSFieldMethod) || (info4 is JSConstructor)) || (info4 is JSProperty)) { candidates--; fparams[k] = null; } else { Type declaringType = match[index].DeclaringType; Type c = match[k].DeclaringType; if (declaringType != c) { if (c.IsAssignableFrom(declaringType)) { candidates--; fparams[k] = null; } else if (declaringType.IsAssignableFrom(c)) { fparams[index] = null; index = k; candidates--; } } } } } } if (candidates != 1) { throw new AmbiguousMatchException(); } return index; }
internal static ConstructorInfo SelectConstructor(TypeReferences typeRefs, MemberInfo[] match, IReflect[] argIRs){ if (match == null) return null; int n = match.Length; if (n == 1){ Object val = match[0]; if (val is JSGlobalField) val = ((JSGlobalField)val).GetValue(null); Type t = val as Type; if (t != null){ match = t.GetConstructors(); } n = match.Length; } if (n == 0) return null; if (n == 1) return match[0] as ConstructorInfo; return (ConstructorInfo)JSBinder.Select(typeRefs, match, n, argIRs, MemberTypes.Constructor); }
internal static MethodInfo SelectMethod(TypeReferences typeRefs, MemberInfo[] match, IReflect[] argIRs){ if (match == null) return null; int n = match.Length; if (n == 0) return null; MemberInfo result = n == 1 ? match[0] : JSBinder.Select(typeRefs, match, n, argIRs, MemberTypes.Method); if (result != null && result.MemberType == MemberTypes.Property) return ((PropertyInfo)result).GetGetMethod(true); return result as MethodInfo; }
internal static ConstructorInfo SelectConstructor(TypeReferences typeRefs, MemberInfo[] match, ref Object[] args, String[] namedParameters){ if (match == null) return null; int n = match.Length; if (n == 0) return null; if (n == 1){ Type t = match[0] as Type; if (t != null) { match = t.GetConstructors(); n = match.Length; } } if (n == 1) return match[0] as ConstructorInfo; return (ConstructorInfo)JSBinder.Select(typeRefs, match, n, ref args, namedParameters, MemberTypes.Constructor); }
private static int SelectBest(TypeReferences typeRefs, MemberInfo[] match, int matches, IReflect[] argIRs, ParameterInfo[][] fparams, Object[][] aparams, int candidates, int parameters){ Debug.Assert(matches > 1); if (candidates == 0) return -1; if (candidates == 1) for (int i = 0; i < matches; i++) if (fparams[i] != null) return i; bool[] eliminated = new bool[matches]; //Set up penalties to discourage selection of methods that have more formal parameters than there are actual parameters int[] penalty = new int[matches]; for (int i = 0; i < matches; i++){ ParameterInfo[] fpars = fparams[i]; if (fpars != null){ int m = fpars.Length; int actuals = (argIRs == null ? aparams[i].Length : argIRs.Length); if (actuals > m && (m == 0 || !CustomAttribute.IsDefined(fpars[m-1], typeof(ParamArrayAttribute), false))){ fparams[i] = null; candidates--; Debug.Assert(candidates >= 0); continue; } for (int j = parameters; j < m; j++){ ParameterInfo fpar = fpars[j]; if (j == m-1 && CustomAttribute.IsDefined(fpar, typeof(ParamArrayAttribute), false)) break; Object dv = TypeReferences.GetDefaultParameterValue(fpar); if (dv is System.DBNull){ //No default value, set up a penalty penalty[i] = 50; } } } } for (int p = 0; candidates > 1; p++){ int candidatesWithFormalParametersStillToBeConsidered = 0; //Eliminate any candidate that is worse match than any other candidate for this (possibly missing) actual parameter int minval = Int32.MaxValue; bool objectCanWin = false; for (int i = 0; i < matches; i++){ int penaltyForUsingDefaultValue = 0; ParameterInfo[] fpars = fparams[i]; if (fpars != null){ //match[i] is a candidate IReflect aIR = typeRefs.Missing; if (argIRs == null){ if (aparams[i].Length > p){ Object apar = aparams[i][p]; if (apar == null) apar = DBNull.Value; aIR = typeRefs.ToReferenceContext(apar.GetType()); } }else if (p < parameters) aIR = argIRs[p]; int m = fpars.Length; if (m-1 > p) candidatesWithFormalParametersStillToBeConsidered++; IReflect fIR = typeRefs.Missing; if (m > 0 && p >= m-1 && CustomAttribute.IsDefined(fpars[m-1], typeof(ParamArrayAttribute), false) && !(aIR is TypedArray || aIR == typeRefs.ArrayObject || (aIR is Type && ((Type)aIR).IsArray))){ ParameterInfo fpar = fpars[m-1]; if (fpar is ParameterDeclaration){ fIR = ((ParameterDeclaration)fpar).ParameterIReflect; fIR = ((TypedArray)fIR).elementType; }else fIR = fpar.ParameterType.GetElementType(); if (p == m-1) penalty[i]++; }else if (p < m){ ParameterInfo fpar = fpars[p]; fIR = fpar is ParameterDeclaration ? ((ParameterDeclaration)fpar).ParameterIReflect : fpar.ParameterType; if (aIR == typeRefs.Missing){ //No actual parameter was supplied, if the formal parameter has default value, make the match perfect Object dv = TypeReferences.GetDefaultParameterValue(fpar); if (!(dv is System.DBNull)) { aIR = fIR; penaltyForUsingDefaultValue = 1; } } } int distance = TypeDistance(typeRefs, fIR, aIR) + penalty[i] + penaltyForUsingDefaultValue; if (distance == minval){ if (p == m-1 && eliminated[i]){ candidates--; fparams[i] = null; } objectCanWin = objectCanWin && eliminated[i]; continue; } if (distance > minval){ if (objectCanWin && p < m && JSBinder.FormalParamTypeIsObject(fparams[i][p])){ minval = distance; //Make sure that a future, better match than Object can win. continue; } if (p > m-1 && aIR == typeRefs.Missing && CustomAttribute.IsDefined(fpars[m-1], typeof(ParamArrayAttribute), false)) continue; eliminated[i] = true; continue; } //If we get here, we have a match that is strictly better than all previous matches. //If there are no other remaining candidates, we're done. if (candidates == 1 && !eliminated[i]) return i; //Eliminate those other candidates from consideration. objectCanWin = eliminated[i]; for (int j = 0; j < i; j++) if (fparams[j] != null && !eliminated[j]){ bool noFormalForCurrParam = fparams[j].Length <= p; if (noFormalForCurrParam && parameters <= p) //Do not eliminate an overload if it does not have a formal for the current position //and the call does not have an actual parameter for the current position either. continue; if (noFormalForCurrParam || !objectCanWin || !JSBinder.FormalParamTypeIsObject(fparams[j][p])) eliminated[j] = true; } minval = distance; } } if (p >= parameters-1 && candidatesWithFormalParametersStillToBeConsidered < 1) //Looked at all actual parameters as well as all formal parameters, no further progress can be made break; } int best = -1; for (int j = 0; j < matches && candidates > 0; j++){ ParameterInfo[] fpars = fparams[j]; if (fpars != null){ if (eliminated[j]){ candidates--; fparams[j] = null; continue; } int pc = fpars.Length; if (best == -1){ //Choose the first remaining candidate as "best" best = j; continue; } if (Class.ParametersMatch(fpars, fparams[best])){ MemberInfo bstm = match[best]; JSWrappedMethod jswm = match[best] as JSWrappedMethod; if (jswm != null) bstm = jswm.method; if (bstm is JSFieldMethod || bstm is JSConstructor || bstm is JSProperty){ //The first match is always the most derived, go with it candidates--; fparams[j] = null; continue; } Type bestMemT = match[best].DeclaringType; Type memT = match[j].DeclaringType; if (bestMemT != memT){ if (memT.IsAssignableFrom(bestMemT)){ candidates--; fparams[j] = null; continue; }else if (bestMemT.IsAssignableFrom(memT)){ fparams[best] = null; best = j; candidates--; continue; } } } } } if (candidates != 1) throw new AmbiguousMatchException(); return best; }
internal static MemberInfo Select(TypeReferences typeRefs, MemberInfo[] match, int matches, ref Object[] args, String[] namedParameters, MemberTypes memberType){ Debug.Assert(matches > 1); bool hasNamedParams = false; if (namedParameters != null && namedParameters.Length > 0) if (args.Length >= namedParameters.Length) hasNamedParams = true; else throw new JScriptException(JSError.MoreNamedParametersThanArguments); int candidates = 0; ParameterInfo[][] fparams = new ParameterInfo[matches][]; Object[][] aparams = new Object[matches][]; bool lookForPropertyGetters = memberType == MemberTypes.Method; for (int i = 0; i < matches; i++){ MemberInfo mem = match[i]; if (lookForPropertyGetters && mem.MemberType == MemberTypes.Property) mem = ((PropertyInfo)mem).GetGetMethod(true); if (mem.MemberType == memberType){ if (memberType == MemberTypes.Property) fparams[i] = ((PropertyInfo)mem).GetIndexParameters(); else fparams[i] = ((MethodBase)mem).GetParameters(); if (hasNamedParams) aparams[i] = JSBinder.ArrangeNamedArguments((MethodBase)mem, args, namedParameters); else aparams[i] = args; candidates++; } } int j = JSBinder.SelectBest(typeRefs, match, matches, null, fparams, aparams, candidates, args.Length); if (j < 0) return null; args = aparams[j]; MemberInfo result = match[j]; if (lookForPropertyGetters && result.MemberType == MemberTypes.Property) result = ((PropertyInfo)result).GetGetMethod(true); return result; }
internal static MemberInfo Select(TypeReferences typeRefs, MemberInfo[] match, int matches, IReflect[] argIRs, MemberTypes memberType) { int candidates = 0; ParameterInfo[][] fparams = new ParameterInfo[matches][]; bool flag = memberType == MemberTypes.Method; for (int i = 0; i < matches; i++) { MemberInfo getMethod = match[i]; if ((getMethod is PropertyInfo) && flag) { getMethod = ((PropertyInfo) getMethod).GetGetMethod(true); } if ((getMethod != null) && (getMethod.MemberType == memberType)) { if (getMethod is PropertyInfo) { fparams[i] = ((PropertyInfo) getMethod).GetIndexParameters(); } else { fparams[i] = ((MethodBase) getMethod).GetParameters(); } candidates++; } } int index = SelectBest(typeRefs, match, matches, argIRs, fparams, null, candidates, argIRs.Length); if (index < 0) { return null; } return match[index]; }
internal static PropertyInfo SelectProperty(TypeReferences typeRefs, MemberInfo[] match, Object[] args){ if (match == null) return null; int matches = match.Length; if (matches == 0) return null; if (matches == 1) return match[0] as PropertyInfo; int candidates = 0; PropertyInfo result = null; ParameterInfo[][] fparams = new ParameterInfo[matches][]; Object[][] aparams = new Object[matches][]; for (int i = 0; i < matches; i++){ MemberInfo mem = match[i]; if (mem.MemberType == MemberTypes.Property){ MethodInfo getter = (result = (PropertyInfo)mem).GetGetMethod(true); if (getter == null) fparams[i] = result.GetIndexParameters(); else fparams[i] = getter.GetParameters(); aparams[i] = args; candidates++; } } if (candidates <= 1) return result; int j = JSBinder.SelectBest(typeRefs, match, matches, null, fparams, aparams, candidates, args.Length); if (j < 0) return null; return (PropertyInfo)match[j]; }
internal static MemberInfo Select(TypeReferences typeRefs, MemberInfo[] match, int matches, ref object[] args, string[] namedParameters, MemberTypes memberType) { bool flag = false; if ((namedParameters != null) && (namedParameters.Length > 0)) { if (args.Length < namedParameters.Length) { throw new JScriptException(JSError.MoreNamedParametersThanArguments); } flag = true; } int candidates = 0; ParameterInfo[][] fparams = new ParameterInfo[matches][]; object[][] aparams = new object[matches][]; bool flag2 = memberType == MemberTypes.Method; for (int i = 0; i < matches; i++) { MemberInfo getMethod = match[i]; if (flag2 && (getMethod.MemberType == MemberTypes.Property)) { getMethod = ((PropertyInfo) getMethod).GetGetMethod(true); } if (getMethod.MemberType == memberType) { if (memberType == MemberTypes.Property) { fparams[i] = ((PropertyInfo) getMethod).GetIndexParameters(); } else { fparams[i] = ((MethodBase) getMethod).GetParameters(); } if (flag) { aparams[i] = ArrangeNamedArguments((MethodBase) getMethod, args, namedParameters); } else { aparams[i] = args; } candidates++; } } int index = SelectBest(typeRefs, match, matches, null, fparams, aparams, candidates, args.Length); if (index < 0) { return null; } args = aparams[index]; MemberInfo info2 = match[index]; if (flag2 && (info2.MemberType == MemberTypes.Property)) { info2 = ((PropertyInfo) info2).GetGetMethod(true); } return info2; }
internal static PropertyInfo SelectProperty(TypeReferences typeRefs, MemberInfo[] match, IReflect[] argIRs){ if (match == null) return null; int n = match.Length; if (n == 0) return null; if (n == 1) return match[0] as PropertyInfo; return (PropertyInfo)JSBinder.Select(typeRefs, match, n, argIRs, MemberTypes.Property); }
internal static ConstructorInfo SelectConstructor(TypeReferences typeRefs, MemberInfo[] match, IReflect[] argIRs) { if (match == null) { return null; } int length = match.Length; if (length == 1) { object obj2 = match[0]; if (obj2 is JSGlobalField) { obj2 = ((JSGlobalField) obj2).GetValue(null); } Type t = obj2 as Type; if (t != null) { if (t.IsInterface && t.IsImport) { t = HandleCoClassAttribute(t); } match = t.GetConstructors(); } length = match.Length; } switch (length) { case 0: return null; case 1: return (match[0] as ConstructorInfo); } return (ConstructorInfo) Select(typeRefs, match, length, argIRs, MemberTypes.Constructor); }
//Returns a value that quantifies the cost/badness of converting a value of type actual to type formal. //Used to select the overload that is the closest match to the actual parameter. private static int TypeDistance(TypeReferences typeRefs, IReflect formal, IReflect actual){ if (formal is TypedArray){ if (actual is TypedArray){ TypedArray f = (TypedArray)formal; TypedArray a = (TypedArray)actual; if (f.rank == a.rank) return TypeDistance(typeRefs, f.elementType, a.elementType) == 0 ? 0 : 100; }else if (actual is Type){ TypedArray f = (TypedArray)formal; Type a = (Type)actual; if (a.IsArray && f.rank == a.GetArrayRank()) return TypeDistance(typeRefs, f.elementType, a.GetElementType()) == 0 ? 0 : 100; else if (a == typeRefs.Array || a == typeRefs.ArrayObject) return 30; } return 100; } if (actual is TypedArray){ if (formal is Type){ Type f = (Type)formal; TypedArray a = (TypedArray)actual; if (f.IsArray && f.GetArrayRank() == a.rank) return TypeDistance(typeRefs, f.GetElementType(), a.elementType) == 0 ? 0 : 100; else if (f == typeRefs.Array) return 30; else if (f == typeRefs.Object) return 50; } return 100; } if (formal is ClassScope){ if (actual is ClassScope) return ((ClassScope)actual).IsSameOrDerivedFrom((ClassScope)formal) ? 0 : 100; else return 100; } if (actual is ClassScope){ if (formal is Type) return ((ClassScope)actual).IsPromotableTo((Type)formal) ? 0 : 100; else return 100; } return TypeDistance(typeRefs, Convert.ToType(typeRefs, formal), Convert.ToType(typeRefs, actual)); }
internal static MethodInfo SelectMethod(TypeReferences typeRefs, MemberInfo[] match, IReflect[] argIRs) { if (match == null) { return null; } int length = match.Length; if (length == 0) { return null; } MemberInfo info = (length == 1) ? match[0] : Select(typeRefs, match, length, argIRs, MemberTypes.Method); if ((info != null) && (info.MemberType == MemberTypes.Property)) { return ((PropertyInfo) info).GetGetMethod(true); } return (info as MethodInfo); }
private static int TypeDistance(TypeReferences typeRefs, Type formal, Type actual){ TypeCode atc = Type.GetTypeCode(actual); TypeCode ftc = Type.GetTypeCode(formal); if (actual.IsEnum) atc = TypeCode.Object; if (formal.IsEnum) ftc = TypeCode.Object; switch(atc){ case TypeCode.DBNull: switch(ftc){ default: return formal == typeRefs.Object ? 0 : 1; } case TypeCode.Boolean: switch(ftc){ case TypeCode.Boolean: return 0; case TypeCode.Byte: return 1; case TypeCode.UInt16: return 2; case TypeCode.UInt32: return 3; case TypeCode.UInt64: return 4; case TypeCode.SByte: return 5; case TypeCode.Int16: return 6; case TypeCode.Int32: return 7; case TypeCode.Int64: return 8; case TypeCode.Single: return 9; case TypeCode.Double: return 10; case TypeCode.Decimal: return 11; case TypeCode.Object: return TypeDistance(typeRefs, formal, actual, 12); case TypeCode.String: return 13; default: return 100; } case TypeCode.Char: switch(ftc){ case TypeCode.Char: return 0; case TypeCode.UInt16: return 1; case TypeCode.UInt32: return 2; case TypeCode.Int32: return 3; case TypeCode.UInt64: return 4; case TypeCode.Int64: return 5; case TypeCode.Single: return 6; case TypeCode.Double: return 7; case TypeCode.Decimal: return 8; case TypeCode.Object: return TypeDistance(typeRefs, formal, actual, 9); case TypeCode.String: return 10; case TypeCode.Int16: return 11; case TypeCode.Byte: return 12; case TypeCode.SByte: return 13; case TypeCode.Boolean: return 14; default: return 100; } case TypeCode.SByte: switch(ftc){ case TypeCode.SByte: return 0; case TypeCode.Int16: return 1; case TypeCode.Int32: return 2; case TypeCode.Int64: return 3; case TypeCode.Single: return 4; case TypeCode.Double: return 5; case TypeCode.Decimal: return 6; case TypeCode.Object: return TypeDistance(typeRefs, formal, actual, 7); case TypeCode.String: return 8; case TypeCode.Byte: return 9; case TypeCode.UInt16: return 10; case TypeCode.UInt32: return 12; case TypeCode.UInt64: return 13; case TypeCode.Boolean: return 14; default: return 100; } case TypeCode.Byte: switch(ftc){ case TypeCode.Byte: return 0; case TypeCode.UInt16: return 1; case TypeCode.Int16: return 3; case TypeCode.UInt32: return 4; case TypeCode.Int32: return 5; case TypeCode.UInt64: return 6; case TypeCode.Int64: return 7; case TypeCode.Single: return 8; case TypeCode.Double: return 9; case TypeCode.Decimal: return 10; case TypeCode.Object: return TypeDistance(typeRefs, formal, actual, 11); case TypeCode.String: return 12; case TypeCode.SByte: return 13; case TypeCode.Boolean: return 14; default: return 100; } case TypeCode.Int16: switch(ftc){ case TypeCode.Int16: return 0; case TypeCode.Int32: return 1; case TypeCode.Int64: return 2; case TypeCode.Single: return 3; case TypeCode.Double: return 4; case TypeCode.Decimal: return 5; case TypeCode.Object: return TypeDistance(typeRefs, formal, actual, 6); case TypeCode.String: return 7; case TypeCode.UInt16: return 8; case TypeCode.UInt32: return 10; case TypeCode.UInt64: return 11; case TypeCode.SByte: return 12; case TypeCode.Byte: return 13; case TypeCode.Boolean: return 14; default: return 100; } case TypeCode.UInt16: switch(ftc){ case TypeCode.UInt16: return 0; case TypeCode.UInt32: return 1; case TypeCode.UInt64: return 2; case TypeCode.Int32: return 4; case TypeCode.Int64: return 5; case TypeCode.Single: return 6; case TypeCode.Double: return 7; case TypeCode.Decimal: return 8; case TypeCode.Object: return TypeDistance(typeRefs, formal, actual, 9); case TypeCode.String: return 10; case TypeCode.Int16: return 11; case TypeCode.Byte: return 12; case TypeCode.SByte: return 13; case TypeCode.Boolean: return 14; default: return 100; } case TypeCode.Int32: switch(ftc){ case TypeCode.Int32: return 0; case TypeCode.Int64: return 1; case TypeCode.Double: return 2; case TypeCode.Decimal: return 3; case TypeCode.Object: return TypeDistance(typeRefs, formal, actual, 4); case TypeCode.String: return 5; case TypeCode.UInt64: return 6; case TypeCode.UInt32: return 7; case TypeCode.Single: return 8; case TypeCode.Int16: return 9; case TypeCode.UInt16: return 10; case TypeCode.SByte: return 12; case TypeCode.Byte: return 13; case TypeCode.Boolean: return 14; default: return 100; } case TypeCode.UInt32: switch(ftc){ case TypeCode.UInt32: return 0; case TypeCode.UInt64: return 1; case TypeCode.Int64: return 2; case TypeCode.Double: return 3; case TypeCode.Decimal: return 4; case TypeCode.Object: return TypeDistance(typeRefs, formal, actual, 5); case TypeCode.String: return 6; case TypeCode.Int32: return 7; case TypeCode.Single: return 8; case TypeCode.UInt16: return 9; case TypeCode.Int16: return 11; case TypeCode.Byte: return 12; case TypeCode.SByte: return 13; case TypeCode.Boolean: return 14; default: return 100; } case TypeCode.Int64: switch(ftc){ case TypeCode.Int64: return 0; case TypeCode.Decimal: return 1; case TypeCode.Object: return TypeDistance(typeRefs, formal, actual, 2); case TypeCode.String: return 3; case TypeCode.Double: return 4; case TypeCode.Single: return 5; case TypeCode.Int32: return 6; case TypeCode.Int16: return 7; case TypeCode.SByte: return 8; case TypeCode.UInt64: return 9; case TypeCode.UInt32: return 10; case TypeCode.UInt16: return 11; case TypeCode.Byte: return 13; case TypeCode.Boolean: return 14; default: return 100; } case TypeCode.UInt64: switch(ftc){ case TypeCode.UInt64: return 0; case TypeCode.Decimal: return 1; case TypeCode.Object: return TypeDistance(typeRefs, formal, actual, 2); case TypeCode.String: return 3; case TypeCode.Int64: return 4; case TypeCode.Double: return 5; case TypeCode.Single: return 6; case TypeCode.UInt32: return 7; case TypeCode.UInt16: return 8; case TypeCode.Byte: return 10; case TypeCode.Int32: return 11; case TypeCode.Int16: return 12; case TypeCode.SByte: return 13; case TypeCode.Boolean: return 14; default: return 100; } case TypeCode.Single: switch(ftc){ case TypeCode.Single: return 0; case TypeCode.Double: return 1; case TypeCode.Decimal: return 2; case TypeCode.Int64: return 3; case TypeCode.UInt64: return 4; case TypeCode.Int32: return 5; case TypeCode.UInt32: return 6; case TypeCode.Int16: return 7; case TypeCode.UInt16: return 8; case TypeCode.SByte: return 10; case TypeCode.Byte: return 11; case TypeCode.Object: return TypeDistance(typeRefs, formal, actual, 12); case TypeCode.String: return 13; case TypeCode.Boolean: return 14; default: return 100; } case TypeCode.Double: switch(ftc){ case TypeCode.Double: return 0; case TypeCode.Decimal: return 1; case TypeCode.Single: return 2; case TypeCode.Int64: return 3; case TypeCode.UInt64: return 4; case TypeCode.Int32: return 5; case TypeCode.UInt32: return 6; case TypeCode.Int16: return 7; case TypeCode.UInt16: return 8; case TypeCode.SByte: return 10; case TypeCode.Byte: return 11; case TypeCode.Object: return TypeDistance(typeRefs, formal, actual, 12); case TypeCode.String: return 13; case TypeCode.Boolean: return 14; default: return 100; } case TypeCode.Decimal: switch(ftc){ case TypeCode.Decimal: return 0; case TypeCode.Double: return 1; case TypeCode.Single: return 2; case TypeCode.Int64: return 3; case TypeCode.UInt64: return 4; case TypeCode.Int32: return 5; case TypeCode.UInt32: return 6; case TypeCode.Int16: return 7; case TypeCode.UInt16: return 8; case TypeCode.SByte: return 10; case TypeCode.Byte: return 11; case TypeCode.Object: return formal == typeRefs.Object ? 12 : 100; case TypeCode.String: return 13; case TypeCode.Boolean: return 14; default: return 100; } case TypeCode.DateTime: switch(ftc){ case TypeCode.DateTime: return 0; case TypeCode.Object: return formal == typeRefs.Object ? 1 : 100; case TypeCode.String: return 3; case TypeCode.Double: return 4; case TypeCode.Decimal: return 5; case TypeCode.UInt64: return 6; case TypeCode.Int64: return 7; case TypeCode.UInt32: return 8; case TypeCode.Int32: return 9; default: return 100; } case TypeCode.String: switch(ftc){ case TypeCode.String: return 0; case TypeCode.Object: return formal == typeRefs.Object ? 1 : 100; case TypeCode.Char: return 2; default: return 100; } case TypeCode.Object: if (formal == actual) return 0; if (formal == typeRefs.Missing) return 200; if (!(formal.IsAssignableFrom(actual))){ if (typeRefs.Array.IsAssignableFrom(formal) && (actual == typeRefs.Array || typeRefs.ArrayObject.IsAssignableFrom(actual))) return 10; else if (ftc == TypeCode.String) return 20; else if (actual == typeRefs.ScriptFunction && typeRefs.Delegate.IsAssignableFrom(formal)) return 19; else return 100; } Type[] interfaces = actual.GetInterfaces(); int i; int n = interfaces.Length; for (i = 0; i < n; i++) if (formal == interfaces[i]) return i+1; for (i = 0; actual != typeRefs.Object && actual != null; i++){ if (formal == actual) return i+n+1; actual = actual.BaseType; } return i+n+1; } return 0; //should never get here }
private static MethodBase SelectMethodBase(TypeReferences typeRefs, MethodBase[] match, ref object[] args, ParameterModifier[] modifiers, string[] namedParameters) { if (match == null) { return null; } int length = match.Length; switch (length) { case 0: return null; case 1: return match[0]; } MethodBase base2 = (MethodBase) Select(typeRefs, match, length, ref args, namedParameters, MemberTypes.Method); if (base2 == null) { base2 = (MethodBase) Select(typeRefs, match, length, ref args, namedParameters, MemberTypes.Constructor); } return base2; }
private static int TypeDistance(TypeReferences typeRefs, Type formal, Type actual) { TypeCode typeCode = Type.GetTypeCode(actual); TypeCode code2 = Type.GetTypeCode(formal); if (actual.IsEnum) { typeCode = TypeCode.Object; } if (formal.IsEnum) { code2 = TypeCode.Object; } switch (typeCode) { case TypeCode.Object: if (!(formal == actual)) { int num; if (formal == typeRefs.Missing) { return 200; } if (!formal.IsAssignableFrom(actual)) { if (typeRefs.Array.IsAssignableFrom(formal) && ((actual == typeRefs.Array) || typeRefs.ArrayObject.IsAssignableFrom(actual))) { return 10; } if (code2 == TypeCode.String) { return 20; } if ((actual == typeRefs.ScriptFunction) && typeRefs.Delegate.IsAssignableFrom(formal)) { return 0x13; } return 100; } Type[] interfaces = actual.GetInterfaces(); int length = interfaces.Length; for (num = 0; num < length; num++) { if (formal == interfaces[num]) { return (num + 1); } } num = 0; while ((actual != typeRefs.Object) && (actual != null)) { if (formal == actual) { return ((num + length) + 1); } actual = actual.BaseType; num++; } return ((num + length) + 1); } return 0; case TypeCode.DBNull: if (formal == typeRefs.Object) { return 0; } return 1; case TypeCode.Boolean: switch (code2) { case TypeCode.Object: return TypeDistance(typeRefs, formal, actual, 12); case TypeCode.Boolean: return 0; case TypeCode.SByte: return 5; case TypeCode.Byte: return 1; case TypeCode.Int16: return 6; case TypeCode.UInt16: return 2; case TypeCode.Int32: return 7; case TypeCode.UInt32: return 3; case TypeCode.Int64: return 8; case TypeCode.UInt64: return 4; case TypeCode.Single: return 9; case TypeCode.Double: return 10; case TypeCode.Decimal: return 11; case TypeCode.String: return 13; } break; case TypeCode.Char: switch (code2) { case TypeCode.Object: return TypeDistance(typeRefs, formal, actual, 9); case TypeCode.Boolean: return 14; case TypeCode.Char: return 0; case TypeCode.SByte: return 13; case TypeCode.Byte: return 12; case TypeCode.Int16: return 11; case TypeCode.UInt16: return 1; case TypeCode.Int32: return 3; case TypeCode.UInt32: return 2; case TypeCode.Int64: return 5; case TypeCode.UInt64: return 4; case TypeCode.Single: return 6; case TypeCode.Double: return 7; case TypeCode.Decimal: return 8; case TypeCode.String: return 10; } return 100; case TypeCode.SByte: switch (code2) { case TypeCode.Object: return TypeDistance(typeRefs, formal, actual, 7); case TypeCode.Boolean: return 14; case TypeCode.SByte: return 0; case TypeCode.Byte: return 9; case TypeCode.Int16: return 1; case TypeCode.UInt16: return 10; case TypeCode.Int32: return 2; case TypeCode.UInt32: return 12; case TypeCode.Int64: return 3; case TypeCode.UInt64: return 13; case TypeCode.Single: return 4; case TypeCode.Double: return 5; case TypeCode.Decimal: return 6; case TypeCode.String: return 8; } return 100; case TypeCode.Byte: switch (code2) { case TypeCode.Object: return TypeDistance(typeRefs, formal, actual, 11); case TypeCode.Boolean: return 14; case TypeCode.SByte: return 13; case TypeCode.Byte: return 0; case TypeCode.Int16: return 3; case TypeCode.UInt16: return 1; case TypeCode.Int32: return 5; case TypeCode.UInt32: return 4; case TypeCode.Int64: return 7; case TypeCode.UInt64: return 6; case TypeCode.Single: return 8; case TypeCode.Double: return 9; case TypeCode.Decimal: return 10; case TypeCode.String: return 12; } return 100; case TypeCode.Int16: switch (code2) { case TypeCode.Object: return TypeDistance(typeRefs, formal, actual, 6); case TypeCode.Boolean: return 14; case TypeCode.SByte: return 12; case TypeCode.Byte: return 13; case TypeCode.Int16: return 0; case TypeCode.UInt16: return 8; case TypeCode.Int32: return 1; case TypeCode.UInt32: return 10; case TypeCode.Int64: return 2; case TypeCode.UInt64: return 11; case TypeCode.Single: return 3; case TypeCode.Double: return 4; case TypeCode.Decimal: return 5; case TypeCode.String: return 7; } return 100; case TypeCode.UInt16: switch (code2) { case TypeCode.Object: return TypeDistance(typeRefs, formal, actual, 9); case TypeCode.Boolean: return 14; case TypeCode.SByte: return 13; case TypeCode.Byte: return 12; case TypeCode.Int16: return 11; case TypeCode.UInt16: return 0; case TypeCode.Int32: return 4; case TypeCode.UInt32: return 1; case TypeCode.Int64: return 5; case TypeCode.UInt64: return 2; case TypeCode.Single: return 6; case TypeCode.Double: return 7; case TypeCode.Decimal: return 8; case TypeCode.String: return 10; } return 100; case TypeCode.Int32: switch (code2) { case TypeCode.Object: return TypeDistance(typeRefs, formal, actual, 4); case TypeCode.Boolean: return 14; case TypeCode.SByte: return 12; case TypeCode.Byte: return 13; case TypeCode.Int16: return 9; case TypeCode.UInt16: return 10; case TypeCode.Int32: return 0; case TypeCode.UInt32: return 7; case TypeCode.Int64: return 1; case TypeCode.UInt64: return 6; case TypeCode.Single: return 8; case TypeCode.Double: return 2; case TypeCode.Decimal: return 3; case TypeCode.String: return 5; } return 100; case TypeCode.UInt32: switch (code2) { case TypeCode.Object: return TypeDistance(typeRefs, formal, actual, 5); case TypeCode.Boolean: return 14; case TypeCode.SByte: return 13; case TypeCode.Byte: return 12; case TypeCode.Int16: return 11; case TypeCode.UInt16: return 9; case TypeCode.Int32: return 7; case TypeCode.UInt32: return 0; case TypeCode.Int64: return 2; case TypeCode.UInt64: return 1; case TypeCode.Single: return 8; case TypeCode.Double: return 3; case TypeCode.Decimal: return 4; case TypeCode.String: return 6; } return 100; case TypeCode.Int64: switch (code2) { case TypeCode.Object: return TypeDistance(typeRefs, formal, actual, 2); case TypeCode.Boolean: return 14; case TypeCode.SByte: return 8; case TypeCode.Byte: return 13; case TypeCode.Int16: return 7; case TypeCode.UInt16: return 11; case TypeCode.Int32: return 6; case TypeCode.UInt32: return 10; case TypeCode.Int64: return 0; case TypeCode.UInt64: return 9; case TypeCode.Single: return 5; case TypeCode.Double: return 4; case TypeCode.Decimal: return 1; case TypeCode.String: return 3; } return 100; case TypeCode.UInt64: switch (code2) { case TypeCode.Object: return TypeDistance(typeRefs, formal, actual, 2); case TypeCode.Boolean: return 14; case TypeCode.SByte: return 13; case TypeCode.Byte: return 10; case TypeCode.Int16: return 12; case TypeCode.UInt16: return 8; case TypeCode.Int32: return 11; case TypeCode.UInt32: return 7; case TypeCode.Int64: return 4; case TypeCode.UInt64: return 0; case TypeCode.Single: return 6; case TypeCode.Double: return 5; case TypeCode.Decimal: return 1; case TypeCode.String: return 3; } return 100; case TypeCode.Single: switch (code2) { case TypeCode.Object: return TypeDistance(typeRefs, formal, actual, 12); case TypeCode.Boolean: return 14; case TypeCode.SByte: return 10; case TypeCode.Byte: return 11; case TypeCode.Int16: return 7; case TypeCode.UInt16: return 8; case TypeCode.Int32: return 5; case TypeCode.UInt32: return 6; case TypeCode.Int64: return 3; case TypeCode.UInt64: return 4; case TypeCode.Single: return 0; case TypeCode.Double: return 1; case TypeCode.Decimal: return 2; case TypeCode.String: return 13; } return 100; case TypeCode.Double: switch (code2) { case TypeCode.Object: return TypeDistance(typeRefs, formal, actual, 12); case TypeCode.Boolean: return 14; case TypeCode.SByte: return 10; case TypeCode.Byte: return 11; case TypeCode.Int16: return 7; case TypeCode.UInt16: return 8; case TypeCode.Int32: return 5; case TypeCode.UInt32: return 6; case TypeCode.Int64: return 3; case TypeCode.UInt64: return 4; case TypeCode.Single: return 2; case TypeCode.Double: return 0; case TypeCode.Decimal: return 1; case TypeCode.String: return 13; } return 100; case TypeCode.Decimal: switch (code2) { case TypeCode.Object: if (!(formal == typeRefs.Object)) { return 100; } return 12; case TypeCode.Boolean: return 14; case TypeCode.SByte: return 10; case TypeCode.Byte: return 11; case TypeCode.Int16: return 7; case TypeCode.UInt16: return 8; case TypeCode.Int32: return 5; case TypeCode.UInt32: return 6; case TypeCode.Int64: return 3; case TypeCode.UInt64: return 4; case TypeCode.Single: return 2; case TypeCode.Double: return 1; case TypeCode.Decimal: return 0; case TypeCode.String: return 13; } return 100; case TypeCode.DateTime: switch (code2) { case TypeCode.Int32: return 9; case TypeCode.UInt32: return 8; case TypeCode.Int64: return 7; case TypeCode.UInt64: return 6; case TypeCode.Double: return 4; case TypeCode.Decimal: return 5; case TypeCode.DateTime: return 0; case TypeCode.String: return 3; case TypeCode.Object: if (!(formal == typeRefs.Object)) { return 100; } return 1; } return 100; case TypeCode.String: { TypeCode code18 = code2; switch (code18) { case TypeCode.Object: if (!(formal == typeRefs.Object)) { return 100; } return 1; case TypeCode.Char: return 2; } if (code18 != TypeCode.String) { return 100; } return 0; } default: return 0; } return 100; }
internal static PropertyInfo SelectProperty(TypeReferences typeRefs, MemberInfo[] match, IReflect[] argIRs) { if (match == null) { return null; } int length = match.Length; switch (length) { case 0: return null; case 1: return (match[0] as PropertyInfo); } return (PropertyInfo) Select(typeRefs, match, length, argIRs, MemberTypes.Property); }
internal static MemberInfo[] GetDefaultMembers(TypeReferences typeRefs, IReflect ir) { while (ir is ClassScope) { ClassScope scope = (ClassScope) ir; scope.owner.IsExpando(); if (scope.itemProp != null) { return new MemberInfo[] { scope.itemProp }; } ir = scope.GetParent(); if (ir is WithObject) { ir = (IReflect) ((WithObject) ir).contained_object; } } if (ir is Type) { return GetDefaultMembers((Type) ir); } if (ir is JSObject) { return typeRefs.ScriptObject.GetDefaultMembers(); } return null; }
internal static Type ToType(TypeReferences typeRefs, IReflect ir){ if (ir is Type) return (Type)ir; if (ir is ClassScope) return ((ClassScope)ir).GetTypeBuilderOrEnumBuilder(); if (ir is TypedArray){ return typeRefs.ToReferenceContext(((TypedArray)ir).ToType()); } if (ir is ScriptFunction) return typeRefs.ScriptFunction; return typeRefs.ToReferenceContext(ir.GetType()); }
internal static MemberInfo[] GetDefaultMembers(TypeReferences typeRefs, IReflect ir){ while (ir is ClassScope){ ClassScope csc = (ClassScope)ir; csc.owner.IsExpando(); //Force the class to expose its expando property if it has not already done so if (csc.itemProp != null) return new MemberInfo[]{csc.itemProp}; ir = csc.GetParent(); if (ir is WithObject) ir = (IReflect)((WithObject)ir).contained_object; } if (ir is Type) return JSBinder.GetDefaultMembers((Type)ir); if (ir is JSObject) return typeRefs.ScriptObject.GetDefaultMembers(); return null; }