/// <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 ReplaceTypeParamCallsExpressionKind(ReplaceTypeParamCallsExpression expr, Concretion currentParamTypes, GetConcreteIdentifierFunc getConcreteIdentifier) : base(expr) { GetConcreteIdentifier = getConcreteIdentifier; CurrentParamTypes = currentParamTypes; }
private ReplaceTypeParamCalls(GetConcreteIdentifierFunc getConcreteIdentifier, ImmutableHashSet <QsQualifiedName> intrinsicCallableSet) : base(new TransformationState(getConcreteIdentifier, intrinsicCallableSet)) { this.Expressions = new ExpressionTransformation(this); this.ExpressionKinds = new ExpressionKindTransformation(this); this.Types = new TypeTransformation(this); }
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)); }
private ReplaceTypeParamCalls(GetConcreteIdentifierFunc getConcreteIdentifier, ImmutableHashSet <QsQualifiedName> intrinsicsToKeep) : base(new TransformationState(getConcreteIdentifier, intrinsicsToKeep)) { this.Namespaces = new NamespaceTransformation <TransformationState>(this); this.Statements = new StatementTransformation(this); this.StatementKinds = new StatementKindTransformation <TransformationState>(this); this.Expressions = new ExpressionTransformation(this); this.ExpressionKinds = new ExpressionKindTransformation(this); this.Types = new TypeTransformation(this); }
public static QsCompilation Apply(QsCompilation compilation) { if (compilation == null || compilation.Namespaces.Contains(null)) { throw new ArgumentNullException(nameof(compilation)); } var globals = compilation.Namespaces.GlobalCallableResolutions(); 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.Namespace.Value + "." + currentRequest.originalName.Name.Value}"); } 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 = ReplaceTypeParamImplementationsSyntax.Apply(currentResponse); // Rewrite calls currentResponse = ReplaceTypeParamCallsSyntax.Apply(currentResponse, getConcreteIdentifier); responses.Add(currentResponse); } var filter = new ResolveGenericsSyntax(responses .GroupBy(res => res.concreteCallable.FullName.Namespace) .ToImmutableDictionary(group => group.Key, group => group.Select(res => res.concreteCallable))); return(new QsCompilation(compilation.Namespaces.Select(ns => filter.Transform(ns)).ToImmutableArray(), compilation.EntryPoints)); }
public static Response Apply(Response current, GetConcreteIdentifierFunc getConcreteIdentifier, ImmutableHashSet <QsQualifiedName> intrinsicCallableSet) { var filter = new ReplaceTypeParamCalls(getConcreteIdentifier, intrinsicCallableSet); // Create a new response with the transformed callable return(new Response { OriginalName = current.OriginalName, TypeResolutions = current.TypeResolutions, ConcreteCallable = filter.Namespaces.OnCallableDeclaration(current.ConcreteCallable) }); }
public static Response Apply(Response current, GetConcreteIdentifierFunc getConcreteIdentifier) { var filter = new ReplaceTypeParamCalls(getConcreteIdentifier); // Create a new response with the transformed callable return(new Response { originalName = current.originalName, typeResolutions = current.typeResolutions, concreteCallable = filter.Namespaces.OnCallableDeclaration(current.concreteCallable) }); }
public static Response Apply(Response current, GetConcreteIdentifierFunc getConcreteIdentifier) { var filter = new ReplaceTypeParamCallsSyntax(new ScopeTransformation <ReplaceTypeParamCallsExpression>( new ReplaceTypeParamCallsExpression(new Concretion(), getConcreteIdentifier))); // Create a new response with the transformed callable return(new Response { originalName = current.originalName, typeResolutions = current.typeResolutions, concreteCallable = filter.onCallableImplementation(current.concreteCallable) }); }
public TransformationState(GetConcreteIdentifierFunc getConcreteIdentifier, ImmutableHashSet <QsQualifiedName> intrinsicCallableSet) { this.GetConcreteIdentifier = getConcreteIdentifier; this.IntrinsicCallableSet = intrinsicCallableSet; }
private ReplaceTypeParamCalls(GetConcreteIdentifierFunc getConcreteIdentifier) : base(new TransformationState(getConcreteIdentifier)) { this.Expressions = new ExpressionTransformation(this); this.ExpressionKinds = new ExpressionKindTransformation(this); this.Types = new TypeTransformation(this); }
public TransformationState(GetConcreteIdentifierFunc getConcreteIdentifier) { this.GetConcreteIdentifier = getConcreteIdentifier; }
public TransformationState(GetConcreteIdentifierFunc getConcreteIdentifier, ImmutableHashSet <QsQualifiedName> exemptCallableSet) { this.GetConcreteIdentifier = getConcreteIdentifier; this.ExemptCallableSet = exemptCallableSet; }
public ReplaceTypeParamCallsExpression(Concretion currentParamTypes, GetConcreteIdentifierFunc getConcreteIdentifier) : base(ex => new ReplaceTypeParamCallsExpressionKind(ex as ReplaceTypeParamCallsExpression, currentParamTypes, getConcreteIdentifier), ex => new ReplaceTypeParamCallsExpressionType(ex as ReplaceTypeParamCallsExpression, currentParamTypes)) { CurrentParamTypes = currentParamTypes; }
/// <summary> /// Performs Monomorphization on the given compilation. If the monomorphizeIntrinsics parameter /// is set to false, then intrinsics will not be monomorphized. /// </summary> public static QsCompilation Apply(QsCompilation compilation, bool monomorphizeIntrinsics = false) { var globals = compilation.Namespaces.GlobalCallableResolutions(); var concretizations = new List <QsCallable>(); var concreteNamesMap = new Dictionary <ConcreteCallGraphNode, QsQualifiedName>(); var nodesWithResolutions = new ConcreteCallGraph(compilation).Nodes // Remove specialization information so that we only deal with the full callables. // Note: this only works fine if for all nodes in the call graph, // all existing functor specializations and their dependencies are also in the call graph. .Select(n => new ConcreteCallGraphNode(n.CallableName, QsSpecializationKind.QsBody, n.ParamResolutions)) .Where(n => n.ParamResolutions.Any()) .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 nodesWithResolutions) { // If there is a call to an unknown callable, throw exception if (!globals.TryGetValue(node.CallableName, out var originalGlobal)) { throw new ArgumentException($"Couldn't find definition for callable: {node.CallableName}"); } if (monomorphizeIntrinsics || !originalGlobal.IsIntrinsic) { // Get concrete name var concreteName = NameDecorator.PrependGuid(node.CallableName); // Add to concrete name mapping concreteNamesMap[node] = concreteName; // Generate the concrete version of the callable var concrete = ReplaceTypeParamImplementations.Apply(originalGlobal, node.ParamResolutions, getAccessModifiers) .WithFullName(oldName => concreteName) .WithSpecializations(specs => specs.Select(spec => spec.WithParent(_ => concreteName)).ToImmutableArray()); concretizations.Add(concrete); } } var callablesByNamespace = concretizations.ToLookup(x => x.FullName.Namespace); var namespacesWithImpls = compilation.Namespaces.Select(ns => { var elemsToAdd = callablesByNamespace[ns.Name].Select(call => QsNamespaceElement.NewQsCallable(call)); return(ns.WithElements(elems => elems .Where(elem => !(elem is QsNamespaceElement.QsCallable call) || !IsGeneric(call.Item) || (call.Item.IsIntrinsic && !monomorphizeIntrinsics) || BuiltIn.RewriteStepDependencies.Contains(call.Item.FullName)) .Concat(elemsToAdd) .ToImmutableArray())); }).ToImmutableArray(); var compWithImpls = new QsCompilation(namespacesWithImpls, compilation.EntryPoints); GetConcreteIdentifierFunc getConcreteIdentifier = (globalCallable, types) => GetConcreteIdentifier(concreteNamesMap, globalCallable, types); var intrinsicsToKeep = monomorphizeIntrinsics ? ImmutableHashSet <QsQualifiedName> .Empty : globals .Where(kvp => kvp.Value.Specializations.Any(spec => spec.Implementation.IsIntrinsic)) .Select(kvp => kvp.Key) .ToImmutableHashSet(); return(ReplaceTypeParamCalls.Apply(compWithImpls, getConcreteIdentifier, intrinsicsToKeep)); }
public static QsCallable Apply(QsCallable current, GetConcreteIdentifierFunc getConcreteIdentifier, ImmutableHashSet <QsQualifiedName> intrinsicCallableSet) { var filter = new ReplaceTypeParamCalls(getConcreteIdentifier, intrinsicCallableSet); return(filter.Namespaces.OnCallableDeclaration(current)); }
public static QsCompilation Apply(QsCompilation compilation, GetConcreteIdentifierFunc getConcreteIdentifier, ImmutableHashSet <QsQualifiedName> intrinsicsToKeep) { var filter = new ReplaceTypeParamCalls(getConcreteIdentifier, intrinsicsToKeep); return(filter.OnCompilation(compilation)); }