private static void InitInstance(IReadOnlyList<GenericSymbol> fg, IReadOnlyList<ArgumentSymbol> fa, IReadOnlyList<TypeSymbol> ag, IReadOnlyList<TypeSymbol> aa, List<TypeSymbol> ig, List<TypeSymbol> ia) { if (!ArgumentSymbol.HasVariadic(fg)) { ig.AddRange(fg); if (!ArgumentSymbol.HasVariadic(fa)) { ia.AddRange(fa.GetDataTypes()); } else { ia.AddRange(fa.GetDataTypes()); var t = GetVariadicType(ia); ia.RemoveAt(ia.Count - 1); ia.AddRange(MakeArgument(aa.Count - fa.Count + 1, t)); } } else { ig.AddRange(fg); ig.RemoveAt(ig.Count - 1); var c = (fg.Count > ag.Count) ? (aa.Count - fa.Count + 1) : (ag.Count - fg.Count + 1); var mg = OverLoadTypeMatch.MakeGeneric(c); ig.AddRange(mg); if (!ArgumentSymbol.HasVariadic(fa)) { ia.AddRange(fa.GetDataTypes()); } else { ia.AddRange(fa.GetDataTypes()); ia.RemoveAt(ia.Count - 1); ia.AddRange(mg); } } }
//todo さらに詳しい順位付けをする。 //todo デフォルト引数に対応する。 //todo 型制約に対応する。 internal static OverLoadCallMatch MakeMatch(Root root, RoutineSymbol call, IReadOnlyList<GenericSymbol> fg, IReadOnlyList<ArgumentSymbol> fa, IReadOnlyList<GenericsInstance> inst, IReadOnlyList<TypeSymbol> ag, IReadOnlyList<TypeSymbol> aa) { var ig = new List<TypeSymbol>(); var ia = new List<TypeSymbol>(); var convs = new List<RoutineSymbol>(); var result = new OverLoadCallMatch() { Call = call, FormalGenerics = fg, FormalArguments = fa, ScopeInstance = inst, ActualGenerics = ag, ActualArguments = aa, InstanceGenerics = ig, InstanceArguments = ia, Converters = convs, }; if (TypeSymbol.HasAnyErrorType(fg) || TypeSymbol.HasAnyErrorType(fa.GetDataTypes())) { result.Result = CallMatchResult.Unknown; return result; } if (!OverLoadTypeMatch.ContainGenericCount(fg, ag)) { result.Result = CallMatchResult.UnmatchGenericCount; return result; } if (!ContainArgumentCount(fa, aa) || !ContainTupleCount(fg, fa, ag, aa)) { result.Result = CallMatchResult.UnmatchArgumentCount; return result; } InitInstance(fg, fa, ag, aa, ig, ia); var tgi = InferInstance(root, inst, ag, aa, ig, ia); if (TypeSymbol.HasAnyErrorType(tgi)) { result.Result = CallMatchResult.UnmatchGenericType; return result; } for (int i = 0; i < ia.Count; i++) { var c = root.ConvManager.Find(aa[i], ia[i]); convs.Add(c); } result.Result = CheckConverterResult(convs); if (HasMatch(result.Result)) { result.Call = GenericsInstance.MakeRoutineTemplateInstance(root, tgi, call); } return result; }