/// <summary>
        /// Returns a look-up with all Q# examples extracted from doc comments for each namespace.
        /// The key may be null if the extracted example is specified outside a namespace.
        /// </summary>
        public static ILookup <string, string> Extract(QsCompilation compilation)
        {
            var instance = new ExamplesInDocs();

            instance.Apply(compilation);
            return(instance.SharedState.ToLookup(entry => entry.Item1, entry => entry.Item2));
        }
        public bool PreconditionVerification(QsCompilation compilation)
        {
            var controlNs = compilation.Namespaces
                            .FirstOrDefault(ns => ns.Name.Equals(BuiltIn.ClassicallyControlledNamespace));

            if (controlNs == null)
            {
                return(false);
            }

            var providedOperations = new QsNamespace[] { controlNs }.Callables().Select(c => c.FullName.Name);
            var requiredBuiltIns = new List <NonNullable <string> >()
            {
                BuiltIn.ApplyIfZero.Name,
                BuiltIn.ApplyIfZeroA.Name,
                BuiltIn.ApplyIfZeroC.Name,
                BuiltIn.ApplyIfZeroCA.Name,

                BuiltIn.ApplyIfOne.Name,
                BuiltIn.ApplyIfOneA.Name,
                BuiltIn.ApplyIfOneC.Name,
                BuiltIn.ApplyIfOneCA.Name,

                BuiltIn.ApplyIfElseR.Name,
                BuiltIn.ApplyIfElseRA.Name,
                BuiltIn.ApplyIfElseRC.Name,
                BuiltIn.ApplyIfElseRCA.Name
            };

            return(requiredBuiltIns.All(builtIn => providedOperations.Any(provided => provided.Equals(builtIn))));
        }
        /// <inheritdoc/>
        public bool PreconditionVerification(QsCompilation compilation)
        {
            var attributes = compilation.Namespaces.Attributes().Select(att => att.FullName).ToImmutableHashSet();

            return(attributes.Contains(BuiltIn.TargetInstruction.FullName) &&
                   attributes.Contains(BuiltIn.Inline.FullName));
        }
        public bool PreconditionVerification(QsCompilation compilation)
        {
            var classicallyControlledRequired = ImmutableHashSet.Create(
                BuiltIn.ApplyIfZero.FullName,
                BuiltIn.ApplyIfZeroA.FullName,
                BuiltIn.ApplyIfZeroC.FullName,
                BuiltIn.ApplyIfZeroCA.FullName,
                BuiltIn.ApplyIfOne.FullName,
                BuiltIn.ApplyIfOneA.FullName,
                BuiltIn.ApplyIfOneC.FullName,
                BuiltIn.ApplyIfOneCA.FullName,
                BuiltIn.ApplyIfElseR.FullName,
                BuiltIn.ApplyIfElseRA.FullName,
                BuiltIn.ApplyIfElseRC.FullName,
                BuiltIn.ApplyIfElseRCA.FullName);

            if (!this.CheckForRequired(compilation, BuiltIn.ClassicallyControlledNamespace, classicallyControlledRequired))
            {
                return(false);
            }

            var cannonRequired = ImmutableHashSet.Create(
                BuiltIn.NoOp.FullName);

            if (!this.CheckForRequired(compilation, BuiltIn.CanonNamespace, cannonRequired))
            {
                return(false);
            }

            return(true);
        }
        /// <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));
        }
Esempio n. 6
0
        public bool PreconditionVerification(QsCompilation compilation)
        {
            var controlNs = compilation.Namespaces
                            .FirstOrDefault(ns => ns.Name.Equals(BuiltIn.ClassicallyControlledNamespace));

            if (controlNs == null)
            {
                return(false);
            }

            var providedOperations = new QsNamespace[] { controlNs }
            .Callables()
            .Select(c => c.FullName)
            .ToHashSet();
            var requiredBuiltIns = new HashSet <QsQualifiedName>()
            {
                BuiltIn.ApplyIfZero.FullName,
                BuiltIn.ApplyIfZeroA.FullName,
                BuiltIn.ApplyIfZeroC.FullName,
                BuiltIn.ApplyIfZeroCA.FullName,

                BuiltIn.ApplyIfOne.FullName,
                BuiltIn.ApplyIfOneA.FullName,
                BuiltIn.ApplyIfOneC.FullName,
                BuiltIn.ApplyIfOneCA.FullName,

                BuiltIn.ApplyIfElseR.FullName,
                BuiltIn.ApplyIfElseRA.FullName,
                BuiltIn.ApplyIfElseRC.FullName,
                BuiltIn.ApplyIfElseRCA.FullName
            };

            return(requiredBuiltIns.IsSubsetOf(providedOperations));
        }
        public bool Transformation(QsCompilation compilation, out QsCompilation transformed)
        {
            var rewriter = new RewriteAccessModifiers();

            transformed = rewriter.OnCompilation(compilation);
            return(true);
        }
        /// <inheritdoc/>
        public bool Transformation(QsCompilation compilation, out QsCompilation transformed)
        {
            transformed = compilation;
            var generator = new Generator(transformed);

            generator.Apply();

            // write generated QIR to disk
            var assemblyName = this.AssemblyConstants.TryGetValue(ReservedKeywords.AssemblyConstants.AssemblyName, out var asmName) ? asmName : null;
            var targetFile   = Path.GetFullPath(string.IsNullOrWhiteSpace(assemblyName) ? "main.txt" : $"{Path.GetFileName(assemblyName)}.txt");

            PerformanceTracking.TaskStart(PerformanceTracking.Task.BitcodeGeneration);
            var bcOutputFolder = this.AssemblyConstants.TryGetValue(ReservedKeywords.AssemblyConstants.OutputPath, out var path) && !string.IsNullOrWhiteSpace(path) ? path : "qir";
            var bcFile         = CompilationLoader.GeneratedFile(targetFile, Path.GetFullPath(bcOutputFolder), ".bc", "");

            generator.Emit(bcFile, emitBitcode: true);
            PerformanceTracking.TaskEnd(PerformanceTracking.Task.BitcodeGeneration);

            // create the human readable version as well
            var sourceOutputFolder = this.AssemblyConstants.TryGetValue(ReservedKeywords.AssemblyConstants.QirOutputPath, out path) && !string.IsNullOrWhiteSpace(path) ? path : "qir";
            var llvmSourceFile     = CompilationLoader.GeneratedFile(targetFile, Path.GetFullPath(sourceOutputFolder), ".ll", "");

            generator.Emit(llvmSourceFile, emitBitcode: false);
            return(true);
        }
            /// <summary>
            /// Populates the given graph based on the given compilation. Only the compilation's entry points and
            /// those callables that the entry points depend on will be included in the graph. All Generated
            /// Implementations for specializations should be resolved before calling this, except Self-Inverse,
            /// which is handled by creating a dependency to the appropriate specialization of the same callable.
            /// This will throw an error if a Generated Implementation other than a Self-Inverse is encountered.
            /// </summary>
            public static void PopulateConcreteGraph(ConcreteGraphBuilder graph, QsCompilation compilation)
            {
                var walker          = new BuildGraph(graph);
                var entryPointNodes = compilation.EntryPoints.Select(name => new ConcreteCallGraphNode(name, QsSpecializationKind.QsBody, TypeParameterResolutions.Empty));

                foreach (var entryPoint in entryPointNodes)
                {
                    // Make sure all the entry points are added to the graph
                    walker.SharedState.Graph.AddNode(entryPoint);
                    walker.SharedState.RequestStack.Push(entryPoint);
                }

                var globals = compilation.Namespaces.GlobalCallableResolutions();

                while (walker.SharedState.RequestStack.TryPop(out var currentRequest))
                {
                    // If there is a call to an unknown callable, throw exception
                    if (!globals.TryGetValue(currentRequest.CallableName, out QsCallable currentCallable))
                    {
                        throw new ArgumentException($"Couldn't find definition for callable: {currentRequest.CallableName}");
                    }

                    var spec = GetSpecializationFromRequest(currentRequest, currentCallable);

                    // The current request must be added before it is processed to prevent
                    // self-references from duplicating on the stack.
                    walker.SharedState.ResolvedNodeSet.Add(currentRequest);
                    walker.SharedState.CurrentNode            = currentRequest;
                    walker.SharedState.GetSpecializationKinds = (callableName) => GetSpecializationKinds(globals, callableName);
                    walker.Namespaces.OnSpecializationImplementation(spec.Implementation);
                }
            }
            /// <summary>
            /// Populates the given graph based on the given compilation. Only the compilation's entry points and
            /// those callables that the entry points depend on will be included in the graph.
            /// </summary>
            public static void PopulateTrimmedGraph(GraphBuilder graph, QsCompilation compilation)
            {
                var walker          = new BuildGraph(graph);
                var entryPointNodes = compilation.EntryPoints.Select(name => new CallGraphNode(name));

                walker.SharedState.WithTrimming = true;
                foreach (var entryPoint in entryPointNodes)
                {
                    // Make sure all the entry points are added to the graph
                    walker.SharedState.Graph.AddNode(entryPoint);
                    walker.SharedState.RequestStack.Push(entryPoint);
                }

                var globals = compilation.Namespaces.GlobalCallableResolutions();

                while (walker.SharedState.RequestStack.TryPop(out var currentRequest))
                {
                    // If there is a call to an unknown callable, throw exception
                    if (!globals.TryGetValue(currentRequest.CallableName, out QsCallable currentCallable))
                    {
                        throw new ArgumentException($"Couldn't find definition for callable: {currentRequest.CallableName}");
                    }

                    // The current request must be added before it is processed to prevent
                    // self-references from duplicating on the stack.
                    walker.SharedState.ResolvedNodeSet.Add(currentRequest);
                    walker.SharedState.CurrentNode = currentRequest;
                    walker.Namespaces.OnCallableDeclaration(currentCallable);
                }
            }
Esempio n. 11
0
        /// <summary>
        /// Given a reader for the byte stream of a dotnet dll, loads any Q# compilation included as a resource.
        /// Returns true as well as the loaded compilation if the given dll includes a suitable resource, and returns false otherwise.
        /// Throws an ArgumentNullException if any of the given readers is null.
        /// May throw an exception if the given binary file has been compiled with a different compiler version.
        /// </summary>
        private static bool FromResource(PEReader assemblyFile, out QsCompilation compilation)
        {
            if (assemblyFile == null)
            {
                throw new ArgumentNullException(nameof(assemblyFile));
            }
            var metadataReader = assemblyFile.GetMetadataReader();

            compilation = null;

            // The offset of resources is relative to the resources directory.
            // It is possible that there is no offset given because a valid dll allows for extenal resources.
            // In all Q# dlls there will be a resource with the specific name chosen by the compiler.
            var resourceDir = assemblyFile.PEHeaders.CorHeader.ResourcesDirectory;

            if (!assemblyFile.PEHeaders.TryGetDirectoryOffset(resourceDir, out var directoryOffset) ||
                !metadataReader.Resources().TryGetValue(DotnetCoreDll.ResourceName, out var resource) ||
                !resource.Implementation.IsNil)
            {
                return(false);
            }

            // This is going to be very slow, as it loads the entire assembly into a managed array, byte by byte.
            // Due to the finite size of the managed array, that imposes a memory limitation of around 4GB.
            // The other alternative would be to have an unsafe block, or to contribute a fix to PEMemoryBlock to expose a ReadOnlySpan.
            var image             = assemblyFile.GetEntireImage(); // uses int to denote the length and access parameters
            var absResourceOffset = (int)resource.Offset + directoryOffset;

            // the first four bytes of the resource denote how long the resource is, and are followed by the actual resource data
            var resourceLength = BitConverter.ToInt32(image.GetContent(absResourceOffset, sizeof(Int32)).ToArray(), 0);
            var resourceData   = image.GetContent(absResourceOffset + sizeof(Int32), resourceLength).ToArray();

            return(LoadSyntaxTree(new MemoryStream(resourceData), out compilation));
        }
Esempio n. 12
0
            public static QsCompilation Apply(QsCompilation compilation, bool keepAllIntrinsics)
            {
                var globals = compilation.Namespaces.GlobalCallableResolutions();
                var augmentedEntryPoints = BuiltIn.AllBuiltIns
                                           .Where(bi => bi.Kind != BuiltInKind.Attribute && globals.ContainsKey(bi.FullName))
                                           .Select(bi => bi.FullName)
                                           .Concat(compilation.EntryPoints)
                                           .Distinct()
                                           .ToImmutableArray();
                var compilationWithBuiltIns = new QsCompilation(compilation.Namespaces, augmentedEntryPoints);
                var callablesToKeep         = new CallGraph(compilationWithBuiltIns, true).Nodes.Select(node => node.CallableName).ToImmutableHashSet();

                // ToDo: convert to using ternary operator, when target-type
                // conditional expressions are supported in C#
                Func <QsNamespaceElement, bool> filter = elem => Filter(elem, callablesToKeep);

                if (keepAllIntrinsics)
                {
                    filter = elem => FilterWithIntrinsics(elem, callablesToKeep);
                }

                var transformed = new TrimTree(filter).OnCompilation(compilation);

                return(new QsCompilation(transformed.Namespaces.Where(ns => ns.Elements.Any()).ToImmutableArray(), transformed.EntryPoints));
            }
 private ConvertConditions(QsCompilation compilation) : base(new TransformationState(compilation))
 {
     this.Namespaces  = new NamespaceTransformation(this);
     this.Statements  = new StatementTransformation(this);
     this.Expressions = new ExpressionTransformation <TransformationState>(this, TransformationOptions.Disabled);
     this.Types       = new TypeTransformation <TransformationState>(this, TransformationOptions.Disabled);
 }
Esempio n. 14
0
        /// <summary>
        /// Adds a comment to each callable listing all identifiers used within the callable.
        /// </summary>
        public QsCompilation OnCompilation(QsCompilation compilation)
        {
            var namespaces = compilation.Namespaces
                             .Select(this.Namespaces.OnNamespace)
                             .ToImmutableArray();

            return(new QsCompilation(namespaces, compilation.EntryPoints));
        }
        /// <summary>
        /// Eliminates all conjugations from the given compilation by replacing them with the corresponding implementations (i.e. inlining them).
        /// The generation of the adjoint for the outer block is subject to the same limitation as any adjoint auto-generation.
        /// In particular, it is only guaranteed to be valid if operation calls only occur within expression statements, and
        /// throws an InvalidOperationException if the outer block contains while-loops.
        /// Any thrown exception is logged using the given onException action and silently ignored if onException is not specified or null.
        /// Returns true if the transformation succeeded without throwing an exception, and false otherwise.
        /// </summary>
        public static bool InlineConjugations(this QsCompilation compilation, out QsCompilation inlined, Action <Exception>?onException = null)
        {
            var inline     = new InlineConjugations(onException);
            var namespaces = compilation.Namespaces.Select(inline.Namespaces.OnNamespace).ToImmutableArray();

            inlined = new QsCompilation(namespaces, compilation.EntryPoints);
            return(inline.SharedState.Success);
        }
Esempio n. 16
0
            public static QsCompilation Apply(QsCompilation compilation, List <Response> responses)
            {
                var filter = new ResolveGenerics(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.Namespaces.OnNamespace(ns)).ToImmutableArray(), compilation.EntryPoints));
            }
        public static void Apply(QsCompilation compilation)
        {
            var intrinsicCallableSet = compilation.Namespaces.GlobalCallableResolutions()
                                       .Where(kvp => kvp.Value.Specializations.Any(spec => spec.Implementation.IsIntrinsic))
                                       .Select(kvp => kvp.Key)
                                       .ToImmutableHashSet();

            new ValidateMonomorphization(intrinsicCallableSet).OnCompilation(compilation);
        }
Esempio n. 18
0
        public static void Apply(QsCompilation compilation)
        {
            var filter = new ValidateMonomorphization();

            foreach (var ns in compilation.Namespaces)
            {
                filter.Namespaces.OnNamespace(ns);
            }
        }
Esempio n. 19
0
        public bool PreconditionVerification(QsCompilation compilation)
        {
            var targetingNamespace = compilation.Namespaces.FirstOrDefault(ns =>
                                                                           ns.Name.Equals(BuiltIn.TargetingNamespace));
            var hasCapabilityAttribute = targetingNamespace?.Elements.Any(element =>
                                                                          element.GetFullName().Equals(BuiltIn.RequiresCapability.FullName)) ?? false;

            return(hasCapabilityAttribute && !this.AssemblyConstants.ContainsKey(ExecutionTarget));
        }
Esempio n. 20
0
        /// <inheritdoc/>
        public bool Transformation(QsCompilation compilation, out QsCompilation transformed)
        {
            var generator = new Generator(compilation);

            generator.Apply();
            generator.Emit(this.outputFile);
            transformed = compilation;
            return(true);
        }
        public static void Apply(QsCompilation compilation)
        {
            var filter = new MonomorphizationValidationSyntax();

            foreach (var ns in compilation.Namespaces)
            {
                filter.Transform(ns);
            }
        }
Esempio n. 22
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));
        }
Esempio n. 23
0
        private static IList <EntryPointOperation> GenerateEntryPointOperations(QsCompilation compilation)
        {
            var globals = compilation.Namespaces.GlobalCallableResolutions();

            return(compilation.EntryPoints.Select(ep => new EntryPointOperation()
            {
                Name = NameGeneration.InteropFriendlyWrapperName(ep),
                Parameters = GetParams(globals[ep]),
            }).ToList());
        }
Esempio n. 24
0
        /// <summary>
        /// Adds a TargetInstruction attribute to each intrinsic callable that doesn't have one,
        /// unless the automatically determined target instruction name conflicts with another target instruction name.
        /// The automatically determined name of the target instruction is the lower case version of the unqualified callable name.
        /// Type constructors and generic callables are left unchanged.
        /// </summary>
        /// <returns>Returns true if all missing attributes have been successfully added and false if some attributes could not be added.</returns>
        /// <exception cref="InvalidOperationException">All intrinsic callables need to have exactly one body specialization.</exception>
        public static bool TryAddMissingTargetInstructionAttributes(QsCompilation compilation, out QsCompilation transformed)
        {
            var           success          = true;
            List <string> instructionNames = new List <string>();

            // populate the intruction names with all manually specified ones first
            foreach (var callable in compilation.Namespaces.Callables())
            {
                var manuallySpecified = SymbolResolution.TryGetTargetInstructionName(callable.Attributes);
                if (manuallySpecified.IsValue)
                {
                    instructionNames.Add(manuallySpecified.Item);
                }
            }

            QsCallable AddAttribute(QsCallable callable)
            {
                if (callable.Specializations.Length != 1)
                {
                    throw new InvalidOperationException("intrinsic callable needs to have exactly one body specialization");
                }

                var instructionName = callable.FullName.Name.ToLowerInvariant();

                if (instructionNames.Contains(instructionName))
                {
                    success = false;
                    return(callable);
                }
                return(callable.AddAttribute(
                           AttributeUtils.BuildAttribute(
                               BuiltIn.TargetInstruction.FullName,
                               AttributeUtils.StringArgument(instructionName))));
            }

            QsNamespace AddAttributes(QsNamespace ns)
            {
                var elements = ns.Elements.Select(element =>
                                                  element is QsNamespaceElement.QsCallable callable &&
                                                  callable.Item.IsIntrinsic &&
                                                  callable.Item.Signature.TypeParameters.Length == 0 &&
                                                  !NameDecorator.IsAutoGeneratedName(callable.Item.FullName) &&
                                                  !callable.Item.Kind.IsTypeConstructor &&
                                                  !callable.Item.Attributes.Any(BuiltIn.DefinesTargetInstruction)
                    ? QsNamespaceElement.NewQsCallable(AddAttribute(callable.Item))
                    : element);

                return(new QsNamespace(ns.Name, elements.ToImmutableArray(), ns.Documentation));
            }

            var namespaces = compilation.Namespaces.Select(AddAttributes).ToImmutableArray();

            transformed = new QsCompilation(namespaces, compilation.EntryPoints);
            return(success);
        }
Esempio n. 25
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));
            }
Esempio n. 26
0
        public IntrinsicResolution(QsCompilation environment)
        {
            Name                                = "IntrinsicResolution";
            Priority                            = 10; // Not used for built-in transformations like this
            AssemblyConstants                   = new Dictionary <string, string>();
            ImplementsTransformation            = true;
            ImplementsPreconditionVerification  = false;
            ImplementsPostconditionVerification = false;

            Environment = environment;
        }
        public static void Apply(QsCompilation compilation, bool allowTypeParametersForIntrinsics = true)
        {
            var intrinsicCallableSet = allowTypeParametersForIntrinsics
                ? compilation.Namespaces.GlobalCallableResolutions()
                                       .Where(kvp => kvp.Value.Specializations.Any(spec => spec.Implementation.IsIntrinsic))
                                       .Select(kvp => kvp.Key)
                                       .ToImmutableHashSet()
                : ImmutableHashSet <QsQualifiedName> .Empty;

            new ValidateMonomorphization(intrinsicCallableSet).OnCompilation(compilation);
        }
Esempio n. 28
0
        // Constructors

        /// <summary>
        /// Constructs a call graph from a compilation. The optional trim argument may be
        /// used to specify the call graph to be trimmed to only include callables that
        /// entry points are dependent on.
        /// </summary>
        public CallGraph(QsCompilation compilation, bool trim = false)
        {
            if (trim)
            {
                BuildCallGraph.PopulateTrimmedGraph(this.graphBuilder, compilation);
            }
            else
            {
                BuildCallGraph.PopulateGraph(this.graphBuilder, compilation);
            }
        }
            public static QsCompilation Apply(QsCompilation compilation, List <QsCallable> callables, ImmutableHashSet <QsQualifiedName> intrinsicCallableSet, bool keepAllIntrinsics)
            {
                var filter = new ResolveGenerics(
                    callables
                    .Where(call => !keepAllIntrinsics || !intrinsicCallableSet.Contains(call.FullName))
                    .ToLookup(res => res.FullName.Namespace),
                    intrinsicCallableSet,
                    keepAllIntrinsics);

                return(filter.OnCompilation(compilation));
            }
Esempio n. 30
0
        // tools for loading the compiled syntax tree from the dll resource (later setup for shipping Q# libraries)

        /// <summary>
        /// Given a stream containing the binary representation of compiled Q# code, returns the corresponding Q# compilation.
        /// Returns true if the compilation could be deserialized without throwing an exception, and false otherwise.
        /// Throws an ArgumentNullException if the given stream is null, but ignores exceptions thrown during deserialization.
        /// </summary>
        public static bool LoadSyntaxTree(Stream stream, out QsCompilation compilation)
        {
            if (stream == null)
            {
                throw new ArgumentNullException(nameof(stream));
            }
            using var reader = new BsonDataReader(stream);
            (compilation, reader.ReadRootValueAsArray) = (null, false);
            try { compilation = Json.Serializer.Deserialize <QsCompilation>(reader); }
            catch { return(false); }
            return(compilation != null && !compilation.Namespaces.IsDefault && !compilation.EntryPoints.IsDefault);
        }