/// <summary> /// Performs Monomorphization on the given compilation. If the keepAllIntrinsics parameter /// is set to true, then unused intrinsics will not be removed from the resulting compilation. /// </summary> public static QsCompilation Apply(QsCompilation compilation, bool keepAllIntrinsics = true) { var globals = compilation.Namespaces.GlobalCallableResolutions(); var concretizations = new List <QsCallable>(); var concreteNames = new Dictionary <ConcreteCallGraphNode, QsQualifiedName>(); var nodes = new ConcreteCallGraph(compilation).Nodes // Remove specialization information so that we only deal with the full callables. .Select(n => new ConcreteCallGraphNode(n.CallableName, QsSpecializationKind.QsBody, n.ParamResolutions)) .ToImmutableHashSet(); var getAccessModifiers = new GetAccessModifiers((typeName) => GetAccessModifier(compilation.Namespaces.GlobalTypeResolutions(), typeName)); // Loop through the nodes, getting a list of concrete callables foreach (var node in nodes) { // If there is a call to an unknown callable, throw exception if (!globals.TryGetValue(node.CallableName, out QsCallable originalGlobal)) { throw new ArgumentException($"Couldn't find definition for callable: {node.CallableName}"); } if (node.ParamResolutions.Any()) { // Get concrete name var concreteName = UniqueVariableNames.PrependGuid(node.CallableName); // Add to concrete name mapping concreteNames[node] = concreteName; // Generate the concrete version of the callable var concrete = ReplaceTypeParamImplementations.Apply(originalGlobal, node.ParamResolutions, getAccessModifiers); concretizations.Add( concrete.WithFullName(oldName => concreteName) .WithSpecializations(specs => specs.Select(spec => spec.WithParent(_ => concreteName)).ToImmutableArray())); } else { concretizations.Add(originalGlobal); } } GetConcreteIdentifierFunc getConcreteIdentifier = (globalCallable, types) => GetConcreteIdentifier(concreteNames, globalCallable, types); var intrinsicCallableSet = globals .Where(kvp => kvp.Value.Specializations.Any(spec => spec.Implementation.IsIntrinsic)) .Select(kvp => kvp.Key) .ToImmutableHashSet(); var final = new List <QsCallable>(); // Loop through concretizations, replacing all references to generics with their concrete counterparts foreach (var callable in concretizations) { final.Add(ReplaceTypeParamCalls.Apply(callable, getConcreteIdentifier, intrinsicCallableSet)); } return(ResolveGenerics.Apply(compilation, final, intrinsicCallableSet, keepAllIntrinsics)); }
public static QsCompilation Apply(QsCompilation compilation) { if (compilation == null || compilation.Namespaces.Contains(null)) { throw new ArgumentNullException(nameof(compilation)); } var globals = compilation.Namespaces.GlobalCallableResolutions(); var intrinsicCallableSet = globals .Where(kvp => kvp.Value.Specializations.Any(spec => spec.Implementation.IsIntrinsic)) .Select(kvp => kvp.Key) .ToImmutableHashSet(); var entryPoints = compilation.EntryPoints .Select(call => new Request { OriginalName = call, TypeResolutions = ImmutableConcretion.Empty, ConcreteName = call }); var requests = new Stack <Request>(entryPoints); var responses = new List <Response>(); while (requests.Any()) { Request currentRequest = requests.Pop(); // If there is a call to an unknown callable, throw exception if (!globals.TryGetValue(currentRequest.OriginalName, out QsCallable originalGlobal)) { throw new ArgumentException($"Couldn't find definition for callable: {currentRequest.OriginalName}"); } var currentResponse = new Response { OriginalName = currentRequest.OriginalName, TypeResolutions = currentRequest.TypeResolutions, ConcreteCallable = originalGlobal.WithFullName(name => currentRequest.ConcreteName) }; GetConcreteIdentifierFunc getConcreteIdentifier = (globalCallable, types) => GetConcreteIdentifier(currentResponse, requests, responses, globalCallable, types); // Rewrite implementation currentResponse = ReplaceTypeParamImplementations.Apply(currentResponse); // Rewrite calls currentResponse = ReplaceTypeParamCalls.Apply(currentResponse, getConcreteIdentifier, intrinsicCallableSet); responses.Add(currentResponse); } return(ResolveGenerics.Apply(compilation, responses, intrinsicCallableSet)); }