public int?CompareTo(ParameterWrapper other, Type actualType) { //+1 if t1, -1 if t2, null if no resolution Type t1 = Type; Type t2 = other.Type; if (t1 == t2) { return(0); } int?ret = null; ret = SelectBestConversionFor(actualType, t1, t2, NarrowingLevel.None); if (ret != null) { return(ret); } ret = SelectBestConversionFor(actualType, t1, t2, NarrowingLevel.Preferred); if (ret != null) { return(ret); } ret = SelectBestConversionFor(actualType, t1, t2, NarrowingLevel.All); if (ret != null) { return(ret); } return(CompareTo(other)); }
private ReturnBuilder MakeKeywordReturnBuilder(ReturnBuilder returnBuilder, ParameterInfo[] methodParams, List <ParameterWrapper> parameters) { if (_binderType == BinderType.Constructor) { List <SymbolId> unusedNames = GetUnusedKeywordParameters(methodParams); List <MemberInfo> bindableMembers = GetBindableMembers(returnBuilder, unusedNames); List <int> kwArgIndexs = new List <int>(); if (unusedNames.Count == bindableMembers.Count) { foreach (MemberInfo mi in bindableMembers) { ParameterWrapper pw = new ParameterWrapper( _binder, mi.MemberType == MemberTypes.Property ? ((PropertyInfo)mi).PropertyType : ((FieldInfo)mi).FieldType, false, SymbolTable.StringToId(mi.Name)); parameters.Add(pw); kwArgIndexs.Add(GetKeywordIndex(mi.Name)); } KeywordConstructorReturnBuilder kwBuilder = new KeywordConstructorReturnBuilder(returnBuilder, _kwArgs.Length, kwArgIndexs.ToArray(), bindableMembers.ToArray()); return(kwBuilder); } } return(returnBuilder); }
public static int?CompareParameters(IList <ParameterWrapper> parameters1, IList <ParameterWrapper> parameters2, Type[] actualTypes) { Debug.Assert(parameters1.Count == parameters2.Count); Debug.Assert(parameters1.Count == actualTypes.Length); int?ret = 0; for (int i = 0; i < parameters1.Count; i++) { ParameterWrapper p1 = parameters1[i]; ParameterWrapper p2 = parameters2[i]; int?cmp = p1.CompareTo(p2, actualTypes[i]); switch (ret) { case 0: ret = cmp; break; case +1: if (cmp == -1) { return(null); } break; case -1: if (cmp == +1) { return(null); } break; case null: if (cmp != 0) { ret = cmp; } break; default: throw new InvalidOperationException(); } } return(ret); }
public int?CompareTo(ParameterWrapper other) { Type t1 = Type; Type t2 = other.Type; if (t1 == t2) { return(0); } if (_binder.CanConvertFrom(t2, t1, NarrowingLevel.None)) { if (_binder.CanConvertFrom(t1, t2, NarrowingLevel.None)) { return(null); } else { return(-1); } } if (_binder.CanConvertFrom(t1, t2, NarrowingLevel.None)) { return(+1); } // Special additional rules to order numeric value types if (_binder.PreferConvert(t1, t2)) { return(-1); } else if (_binder.PreferConvert(t2, t1)) { return(+1); } return(null); }
public int? CompareTo(ParameterWrapper other, Type actualType) { //+1 if t1, -1 if t2, null if no resolution Type t1 = Type; Type t2 = other.Type; if (t1 == t2) return 0; int? ret = null; ret = SelectBestConversionFor(actualType, t1, t2, NarrowingLevel.None); if (ret != null) { return ret; } ret = SelectBestConversionFor(actualType, t1, t2, NarrowingLevel.Preferred); if (ret != null) { return ret; } ret = SelectBestConversionFor(actualType, t1, t2, NarrowingLevel.All); if (ret != null) { return ret; } return CompareTo(other); }
public int? CompareTo(ParameterWrapper other) { Type t1 = Type; Type t2 = other.Type; if (t1 == t2) return 0; if (_binder.CanConvertFrom(t2, t1, NarrowingLevel.None)) { if (_binder.CanConvertFrom(t1, t2, NarrowingLevel.None)) { return null; } else { return -1; } } if (_binder.CanConvertFrom(t1, t2, NarrowingLevel.None)) { return +1; } // Special additional rules to order numeric value types if (_binder.PreferConvert(t1, t2)) return -1; else if (_binder.PreferConvert(t2, t1)) return +1; return null; }
private void AddBasicMethodTargets(MethodBase method) { List <ParameterWrapper> parameters = new List <ParameterWrapper>(); int argIndex = 0; ArgBuilder instanceBuilder; bool hasDefaults = false; if (!CompilerHelpers.IsStatic(method)) { parameters.Add(new ParameterWrapper(_binder, method.DeclaringType, true)); instanceBuilder = new SimpleArgBuilder(argIndex++, parameters[0].Type); } else { instanceBuilder = new NullArgBuilder(); } ParameterInfo[] methodParams = method.GetParameters(); List <ArgBuilder> argBuilders = new List <ArgBuilder>(methodParams.Length); List <ArgBuilder> defaultBuilders = new List <ArgBuilder>(); bool hasByRefOrOut = false; foreach (ParameterInfo pi in methodParams) { if (pi.ParameterType == typeof(CodeContext) && argBuilders.Count == 0) { argBuilders.Add(new ContextArgBuilder()); continue; } int newIndex, kwIndex = GetKeywordIndex(pi); if (kwIndex == -1) { if (!CompilerHelpers.IsMandatoryParameter(pi)) { defaultBuilders.Add(new DefaultArgBuilder(pi.ParameterType, pi.DefaultValue)); hasDefaults = true; } else if (defaultBuilders.Count > 0) { defaultBuilders.Add(null); } newIndex = argIndex++; } else { defaultBuilders.Add(null); newIndex = 0; } ArgBuilder ab; if (pi.ParameterType.IsByRef) { hasByRefOrOut = true; Type refType = typeof(StrongBox <>).MakeGenericType(pi.ParameterType.GetElementType()); ParameterWrapper param = new ParameterWrapper(_binder, refType, true, SymbolTable.StringToId(pi.Name)); parameters.Add(param); ab = new ReferenceArgBuilder(newIndex, param.Type); } else { hasByRefOrOut |= CompilerHelpers.IsOutParameter(pi); ParameterWrapper param = new ParameterWrapper(_binder, pi); parameters.Add(param); ab = new SimpleArgBuilder(newIndex, param.Type, pi); } if (kwIndex == -1) { argBuilders.Add(ab); } else { argBuilders.Add(new KeywordArgBuilder(ab, _kwArgs.Length, kwIndex)); } } ReturnBuilder returnBuilder = MakeKeywordReturnBuilder( new ReturnBuilder(CompilerHelpers.GetReturnType(method)), methodParams, parameters); if (hasDefaults) { for (int defaultsUsed = 1; defaultsUsed < defaultBuilders.Count + 1; defaultsUsed++) { // if the left most default we'll use is not present then don't add a default. This happens in cases such as: // a(a=1, b=2, c=3) and then call with a(a=5, c=3). We'll come through once for c (no default, skip), // once for b (default present, emit) and then a (no default, skip again). W/o skipping we'd generate the same // method multiple times. This also happens w/ non-contigious default values, e.g. foo(a, b=3, c) where we don't want // to generate a default candidate for just c which matches the normal method. if (defaultBuilders[defaultBuilders.Count - defaultsUsed] != null) { AddTarget(MakeDefaultCandidate( method, parameters, instanceBuilder, argBuilders, defaultBuilders, returnBuilder, defaultsUsed)); } } } if (hasByRefOrOut) { AddSimpleTarget(MakeByRefReducedMethodTarget(method)); } AddSimpleTarget(MakeMethodCandidate(method, parameters, instanceBuilder, argBuilders, returnBuilder)); }
private MethodCandidate MakeByRefReducedMethodTarget(MethodBase method) { List <ParameterWrapper> parameters = new List <ParameterWrapper>(); int argIndex = 0; ArgBuilder instanceBuilder; if (!CompilerHelpers.IsStatic(method)) { parameters.Add(new ParameterWrapper(_binder, method.DeclaringType, true)); instanceBuilder = new SimpleArgBuilder(argIndex++, parameters[0].Type); } else { instanceBuilder = new NullArgBuilder(); } List <ArgBuilder> argBuilders = new List <ArgBuilder>(); List <int> returnArgs = new List <int>(); if (CompilerHelpers.GetReturnType(method) != typeof(void)) { returnArgs.Add(-1); } int paramCount = 0; foreach (ParameterInfo pi in method.GetParameters()) { if (pi.ParameterType == typeof(CodeContext) && paramCount == 0) { argBuilders.Add(new ContextArgBuilder()); continue; } paramCount++; int newIndex = 0, kwIndex = -1; if (!CompilerHelpers.IsOutParameter(pi)) { kwIndex = GetKeywordIndex(pi); if (kwIndex == -1) { newIndex = argIndex++; } } ArgBuilder ab; if (CompilerHelpers.IsOutParameter(pi)) { returnArgs.Add(argBuilders.Count); ab = new OutArgBuilder(pi); } else if (pi.ParameterType.IsByRef) { returnArgs.Add(argBuilders.Count); ParameterWrapper param = new ParameterWrapper(_binder, pi.ParameterType.GetElementType(), SymbolTable.StringToId(pi.Name)); parameters.Add(param); ab = new ReturnReferenceArgBuilder(newIndex, pi.ParameterType.GetElementType()); } else { ParameterWrapper param = new ParameterWrapper(_binder, pi); parameters.Add(param); ab = new SimpleArgBuilder(newIndex, param.Type, pi); } if (kwIndex == -1) { argBuilders.Add(ab); } else { argBuilders.Add(new KeywordArgBuilder(ab, _kwArgs.Length, kwIndex)); } } ReturnBuilder returnBuilder = MakeKeywordReturnBuilder( new ByRefReturnBuilder(_binder, returnArgs), method.GetParameters(), parameters); return(MakeMethodCandidate(method, parameters, instanceBuilder, argBuilders, returnBuilder)); }
/// <summary> /// Builds a new MethodCandidate which takes count arguments and the provided list of keyword arguments. /// /// The basic idea here is to figure out which parameters map to params or a dictionary params and /// fill in those spots w/ extra ParameterWrapper's. /// </summary> public MethodCandidate MakeParamsExtended(ActionBinder binder, int count, SymbolId[] names) { List <ParameterWrapper> newParameters = new List <ParameterWrapper>(count); // if we don't have a param array we'll have a param dict which is type object Type elementType = null; int index = -1, kwIndex = -1; // keep track of which kw args map to a real argument, and which ones // map to the params dictionary. List <SymbolId> unusedNames = new List <SymbolId>(names); List <int> unusedNameIndexes = new List <int>(); for (int i = 0; i < unusedNames.Count; i++) { unusedNameIndexes.Add(i); } for (int i = 0; i < _parameters.Count; i++) { ParameterWrapper pw = _parameters[i]; if (_parameters[i].IsParamsArray) { elementType = pw.Type.GetElementType(); index = i; } else { for (int j = 0; j < unusedNames.Count; j++) { if (unusedNames[j] == _parameters[i].Name) { unusedNames.RemoveAt(j); unusedNameIndexes.RemoveAt(j); break; } } newParameters.Add(pw); } } if (index != -1) { while (newParameters.Count < (count - unusedNames.Count)) { ParameterWrapper param = new ParameterWrapper(binder, elementType); newParameters.Insert(System.Math.Min(index, newParameters.Count), param); } } if (kwIndex != -1) { foreach (SymbolId si in unusedNames) { ParameterWrapper pw = new ParameterWrapper(binder, typeof(object), si); newParameters.Add(pw); } } else if (unusedNames.Count != 0) { // unbound kw args and no where to put them, can't call... return(null); } // if we have too many or too few args we also can't call if (count != newParameters.Count) { return(null); } return(new MethodCandidate(_target.MakeParamsExtended(count, unusedNames.ToArray(), unusedNameIndexes.ToArray()), newParameters)); }
public int?CompareParameters(MethodCandidate other, Type[] actualTypes) { return(ParameterWrapper.CompareParameters(this._parameters, other._parameters, actualTypes)); }
private ReturnBuilder MakeKeywordReturnBuilder(ReturnBuilder returnBuilder, ParameterInfo[] methodParams, List<ParameterWrapper> parameters) { if (_binderType == BinderType.Constructor) { List<SymbolId> unusedNames = GetUnusedKeywordParameters(methodParams); List<MemberInfo> bindableMembers = GetBindableMembers(returnBuilder, unusedNames); List<int> kwArgIndexs = new List<int>(); if (unusedNames.Count == bindableMembers.Count) { foreach (MemberInfo mi in bindableMembers) { ParameterWrapper pw = new ParameterWrapper( _binder, mi.MemberType == MemberTypes.Property ? ((PropertyInfo)mi).PropertyType : ((FieldInfo)mi).FieldType, false, SymbolTable.StringToId(mi.Name)); parameters.Add(pw); kwArgIndexs.Add(GetKeywordIndex(mi.Name)); } KeywordConstructorReturnBuilder kwBuilder = new KeywordConstructorReturnBuilder(returnBuilder, _kwArgs.Length, kwArgIndexs.ToArray(), bindableMembers.ToArray()); return kwBuilder; } } return returnBuilder; }
private MethodCandidate MakeByRefReducedMethodTarget(MethodBase method) { List<ParameterWrapper> parameters = new List<ParameterWrapper>(); int argIndex = 0; ArgBuilder instanceBuilder; if (!CompilerHelpers.IsStatic(method)) { parameters.Add(new ParameterWrapper(_binder, method.DeclaringType, true)); instanceBuilder = new SimpleArgBuilder(argIndex++, parameters[0].Type); } else { instanceBuilder = new NullArgBuilder(); } List<ArgBuilder> argBuilders = new List<ArgBuilder>(); List<int> returnArgs = new List<int>(); if (CompilerHelpers.GetReturnType(method) != typeof(void)) { returnArgs.Add(-1); } int paramCount = 0; foreach (ParameterInfo pi in method.GetParameters()) { if (pi.ParameterType == typeof(CodeContext) && paramCount == 0) { argBuilders.Add(new ContextArgBuilder()); continue; } paramCount++; int newIndex = 0, kwIndex = -1; if (!CompilerHelpers.IsOutParameter(pi)) { kwIndex = GetKeywordIndex(pi); if (kwIndex == -1) { newIndex = argIndex++; } } ArgBuilder ab; if (CompilerHelpers.IsOutParameter(pi)) { returnArgs.Add(argBuilders.Count); ab = new OutArgBuilder(pi); } else if (pi.ParameterType.IsByRef) { returnArgs.Add(argBuilders.Count); ParameterWrapper param = new ParameterWrapper(_binder, pi.ParameterType.GetElementType(), SymbolTable.StringToId(pi.Name)); parameters.Add(param); ab = new ReturnReferenceArgBuilder(newIndex, pi.ParameterType.GetElementType()); } else { ParameterWrapper param = new ParameterWrapper(_binder, pi); parameters.Add(param); ab = new SimpleArgBuilder(newIndex, param.Type, pi); } if (kwIndex == -1) { argBuilders.Add(ab); } else { argBuilders.Add(new KeywordArgBuilder(ab, _kwArgs.Length, kwIndex)); } } ReturnBuilder returnBuilder = MakeKeywordReturnBuilder( new ByRefReturnBuilder(_binder, returnArgs), method.GetParameters(), parameters); return MakeMethodCandidate(method, parameters, instanceBuilder, argBuilders, returnBuilder); }
private void AddBasicMethodTargets(MethodBase method) { List<ParameterWrapper> parameters = new List<ParameterWrapper>(); int argIndex = 0; ArgBuilder instanceBuilder; bool hasDefaults = false; if (!CompilerHelpers.IsStatic(method)) { parameters.Add(new ParameterWrapper(_binder, method.DeclaringType, true)); instanceBuilder = new SimpleArgBuilder(argIndex++, parameters[0].Type); } else { instanceBuilder = new NullArgBuilder(); } ParameterInfo[] methodParams = method.GetParameters(); List<ArgBuilder> argBuilders = new List<ArgBuilder>(methodParams.Length); List<ArgBuilder> defaultBuilders = new List<ArgBuilder>(); bool hasByRefOrOut = false; foreach (ParameterInfo pi in methodParams) { if (pi.ParameterType == typeof(CodeContext) && argBuilders.Count == 0) { argBuilders.Add(new ContextArgBuilder()); continue; } int newIndex, kwIndex = GetKeywordIndex(pi); if (kwIndex == -1) { if (!CompilerHelpers.IsMandatoryParameter(pi)) { defaultBuilders.Add(new DefaultArgBuilder(pi.ParameterType, pi.DefaultValue)); hasDefaults = true; } else if (defaultBuilders.Count > 0) { defaultBuilders.Add(null); } newIndex = argIndex++; } else { defaultBuilders.Add(null); newIndex = 0; } ArgBuilder ab; if (pi.ParameterType.IsByRef) { hasByRefOrOut = true; Type refType = typeof(StrongBox<>).MakeGenericType(pi.ParameterType.GetElementType()); ParameterWrapper param = new ParameterWrapper(_binder, refType, true, SymbolTable.StringToId(pi.Name)); parameters.Add(param); ab = new ReferenceArgBuilder(newIndex, param.Type); } else { hasByRefOrOut |= CompilerHelpers.IsOutParameter(pi); ParameterWrapper param = new ParameterWrapper(_binder, pi); parameters.Add(param); ab = new SimpleArgBuilder(newIndex, param.Type, pi); } if (kwIndex == -1) { argBuilders.Add(ab); } else { argBuilders.Add(new KeywordArgBuilder(ab, _kwArgs.Length, kwIndex)); } } ReturnBuilder returnBuilder = MakeKeywordReturnBuilder( new ReturnBuilder(CompilerHelpers.GetReturnType(method)), methodParams, parameters); if (hasDefaults) { for (int defaultsUsed = 1; defaultsUsed < defaultBuilders.Count + 1; defaultsUsed++) { // if the left most default we'll use is not present then don't add a default. This happens in cases such as: // a(a=1, b=2, c=3) and then call with a(a=5, c=3). We'll come through once for c (no default, skip), // once for b (default present, emit) and then a (no default, skip again). W/o skipping we'd generate the same // method multiple times. This also happens w/ non-contigious default values, e.g. foo(a, b=3, c) where we don't want // to generate a default candidate for just c which matches the normal method. if (defaultBuilders[defaultBuilders.Count - defaultsUsed] != null) { AddTarget(MakeDefaultCandidate( method, parameters, instanceBuilder, argBuilders, defaultBuilders, returnBuilder, defaultsUsed)); } } } if (hasByRefOrOut) AddSimpleTarget(MakeByRefReducedMethodTarget(method)); AddSimpleTarget(MakeMethodCandidate(method, parameters, instanceBuilder, argBuilders, returnBuilder)); }