// Rewrite Calls private static Identifier GetConcreteIdentifier( Dictionary <ConcreteCallGraphNode, QsQualifiedName> concreteNames, Identifier.GlobalCallable globalCallable, TypeParameterResolutions types) { if (types.IsEmpty) { return(globalCallable); } var node = new ConcreteCallGraphNode(globalCallable.Item, QsSpecializationKind.QsBody, types); if (concreteNames.TryGetValue(node, out var name)) { return(Identifier.NewGlobalCallable(name)); } else { return(globalCallable); } }
/// <summary> /// Returns the specialization that the request is referring to. /// </summary> private static QsSpecialization GetSpecializationFromRequest(ConcreteCallGraphNode request, QsCallable callable) { var relevantSpecs = callable.Specializations.Where(s => s.Kind == request.Kind); var typeArgs = QsNullable <ImmutableArray <ResolvedType> > .Null; if (callable.Signature.TypeParameters.Any()) { // Convert ParamResolutions from a dictionary to a type argument list typeArgs = QsNullable <ImmutableArray <ResolvedType> > .NewValue(callable.Signature.TypeParameters.Select(typeParam => { if (typeParam is QsLocalSymbol.ValidName name) { if (request.ParamResolutions.TryGetValue(Tuple.Create(callable.FullName, name.Item), out var res)) { return(res); } else { throw new ArgumentException($"Couldn't resolve all type parameters for {callable.FullName}"); } } else { throw new ArgumentException("Encountered invalid type parameter name during call graph construction"); } }).ToImmutableArray()); typeArgs = SpecializationBundleProperties.BundleId(typeArgs); } else if (relevantSpecs.Count() != 1) { throw new ArgumentException($"Missing specialization {request.Kind} for {request.CallableName}"); } if (!typeArgs.IsNull) { // Finds the correct type specialization for the type arguments of the currentRequest. // The assumption is that upon resolution, these type arguments have been cast to // the type of any explicitly defined ones in the closest matching specialization. var specArgMatches = relevantSpecs.Select(spec => { if (spec.TypeArguments.IsNull) { return(0, spec); } if (spec.TypeArguments.Item.Count() != typeArgs.Item.Count()) { throw new ArgumentException($"Incorrect number of type arguments in request for {request.CallableName}"); } var specTypeArgs = spec.TypeArguments.Item.Select(StripPositionInfo.Apply).ToImmutableArray(); var mismatch = specTypeArgs.Where((tArg, idx) => !tArg.Resolution.IsMissingType && !tArg.Resolution.Equals(typeArgs.Item[idx])).Any(); if (mismatch) { return(-1, spec); } var matches = specTypeArgs.Where((tArg, idx) => !tArg.Resolution.IsMissingType && tArg.Resolution.Equals(typeArgs.Item[idx])).Count(); return(matches, spec); }); if (!specArgMatches.Any(m => m.Item1 >= 0)) { throw new ArgumentException($"Could not find a suitable {request.Kind} specialization for {request.CallableName}"); } relevantSpecs = specArgMatches .OrderByDescending(match => match.Item1) .Select(match => match.spec); } return(relevantSpecs.First()); }