/// <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));
        }
예제 #2
0
 public ReplaceTypeParamCallsExpressionKind(ReplaceTypeParamCallsExpression expr,
                                            Concretion currentParamTypes,
                                            GetConcreteIdentifierFunc getConcreteIdentifier) : base(expr)
 {
     GetConcreteIdentifier = getConcreteIdentifier;
     CurrentParamTypes     = currentParamTypes;
 }
예제 #3
0
 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);
 }
예제 #4
0
        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));
        }
예제 #5
0
 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);
 }
예제 #6
0
            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));
            }
예제 #7
0
            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)
                });
            }
예제 #8
0
            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)
                });
            }
예제 #9
0
            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)
                });
            }
예제 #10
0
 public TransformationState(GetConcreteIdentifierFunc getConcreteIdentifier, ImmutableHashSet <QsQualifiedName> intrinsicCallableSet)
 {
     this.GetConcreteIdentifier = getConcreteIdentifier;
     this.IntrinsicCallableSet  = intrinsicCallableSet;
 }
예제 #11
0
 private ReplaceTypeParamCalls(GetConcreteIdentifierFunc getConcreteIdentifier) : base(new TransformationState(getConcreteIdentifier))
 {
     this.Expressions     = new ExpressionTransformation(this);
     this.ExpressionKinds = new ExpressionKindTransformation(this);
     this.Types           = new TypeTransformation(this);
 }
예제 #12
0
 public TransformationState(GetConcreteIdentifierFunc getConcreteIdentifier)
 {
     this.GetConcreteIdentifier = getConcreteIdentifier;
 }
예제 #13
0
 public TransformationState(GetConcreteIdentifierFunc getConcreteIdentifier, ImmutableHashSet <QsQualifiedName> exemptCallableSet)
 {
     this.GetConcreteIdentifier = getConcreteIdentifier;
     this.ExemptCallableSet     = exemptCallableSet;
 }
예제 #14
0
 public ReplaceTypeParamCallsExpression(Concretion currentParamTypes, GetConcreteIdentifierFunc getConcreteIdentifier) :
     base(ex => new ReplaceTypeParamCallsExpressionKind(ex as ReplaceTypeParamCallsExpression, currentParamTypes, getConcreteIdentifier),
          ex => new ReplaceTypeParamCallsExpressionType(ex as ReplaceTypeParamCallsExpression, currentParamTypes))
 {
     CurrentParamTypes = currentParamTypes;
 }
예제 #15
0
        /// <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));
            }
예제 #17
0
            public static QsCompilation Apply(QsCompilation compilation, GetConcreteIdentifierFunc getConcreteIdentifier, ImmutableHashSet <QsQualifiedName> intrinsicsToKeep)
            {
                var filter = new ReplaceTypeParamCalls(getConcreteIdentifier, intrinsicsToKeep);

                return(filter.OnCompilation(compilation));
            }