/// <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 override QsCallable OnCallableDeclaration(QsCallable c) { var relaventAccessModifiers = this.SharedState.GetAccessModifiers.Apply(this.SharedState.TypeParams.Values) .Append(c.Modifiers.Access); c = new QsCallable( c.Kind, c.FullName, c.Attributes, new Modifiers(GetAccessModifiers.GetLeastAccess(relaventAccessModifiers)), c.SourceFile, c.Location, c.Signature, c.ArgumentTuple, c.Specializations, c.Documentation, c.Comments); return(base.OnCallableDeclaration(c)); }
private ReplaceTypeParamImplementations(TypeParameterResolutions typeParams, GetAccessModifiers getAccessModifiers) : base(new TransformationState(typeParams, getAccessModifiers)) { this.Namespaces = new NamespaceTransformation(this); this.Statements = new StatementTransformation <TransformationState>(this); this.StatementKinds = new StatementKindTransformation <TransformationState>(this); this.Expressions = new ExpressionTransformation(this); this.ExpressionKinds = new ExpressionKindTransformation <TransformationState>(this); this.Types = new TypeTransformation(this); }
public TransformationState(TypeParameterResolutions typeParams, GetAccessModifiers getAccessModifiers) { this.TypeParams = typeParams; this.GetAccessModifiers = getAccessModifiers; }
public static QsCallable Apply(QsCallable callable, TypeParameterResolutions typeParams, GetAccessModifiers getAccessModifiers) { var filter = new ReplaceTypeParamImplementations(typeParams, getAccessModifiers); return(filter.Namespaces.OnCallableDeclaration(callable)); }
/// <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)); }