diff --git a/.github/workflows/automerge.yml b/.github/workflows/automerge.yml deleted file mode 100644 index 0e735d7fae..0000000000 --- a/.github/workflows/automerge.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: automerge -on: - pull_request: - types: - - labeled - - unlabeled - - synchronize - - opened - - edited - - ready_for_review - - reopened - - unlocked - pull_request_review: - types: - - submitted - check_suite: - types: - - completed - status: {} -jobs: - automerge: - runs-on: ubuntu-latest - steps: - - name: automerge - uses: "pascalgn/automerge-action@c9bd1823770819dc8fb8a5db2d11a3a95fbe9b07" # v0.12.0 - env: - GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" - MERGE_LABELS: "" - MERGE_METHOD_LABEL_REQUIRED: true - MERGE_METHOD_LABELS: automerge=merge,autosquash=squash - MERGE_REMOVE_LABELS: automerge,autosquash diff --git a/.gitignore b/.gitignore index 0b9aca0ca1..50d8104ac5 100644 --- a/.gitignore +++ b/.gitignore @@ -363,3 +363,4 @@ src/ProjectTemplates/Quantum.Test1/.template.config/template.json /src/VisualStudioExtension/QsharpHoneywellAppTemplate/HoneywellAppProjectTemplate.xml /src/VisualStudioExtension/QsharpIonQAppTemplate/IonQAppProjectTemplate.xml /examples/QIR/Emission/qir/* +src/QsCompiler/QirGeneration/QirGeneration.nuspec diff --git a/bootstrap.ps1 b/bootstrap.ps1 index 6a269ed091..3dc2ff3e45 100644 --- a/bootstrap.ps1 +++ b/bootstrap.ps1 @@ -73,3 +73,6 @@ Write-Host "##[info]Finding NuSpec references..." Push-Location (Join-Path $PSScriptRoot 'src/QsCompiler/Compiler') .\FindNuspecReferences.ps1; Pop-Location +Push-Location (Join-Path $PSScriptRoot 'src/QsCompiler/QirGeneration') +.\FindNuspecReferences.ps1; +Pop-Location diff --git a/build/manifest.ps1 b/build/manifest.ps1 index 1255885ae9..116396cbc2 100644 --- a/build/manifest.ps1 +++ b/build/manifest.ps1 @@ -32,7 +32,8 @@ else { $artifacts = @{ Packages = @( "Microsoft.Quantum.Compiler", - "Microsoft.Quantum.DocumentationGenerator" + "Microsoft.Quantum.QirGeneration", + "Microsoft.Quantum.DocumentationGenerator", "Microsoft.Quantum.ProjectTemplates", "Microsoft.Quantum.Sdk" ) | ForEach-Object { Join-Path $Env:NUGET_OUTDIR "$_.$Env:NUGET_VERSION.nupkg" }; @@ -48,6 +49,8 @@ $artifacts = @{ ".\src\QsCompiler\Optimizations\bin\$Env:BUILD_CONFIGURATION\netstandard2.1\Microsoft.Quantum.QsOptimizations.dll", ".\src\QsCompiler\SyntaxProcessor\bin\$Env:BUILD_CONFIGURATION\netstandard2.1\Microsoft.Quantum.QsSyntaxProcessor.dll", ".\src\QsCompiler\TextProcessor\bin\$Env:BUILD_CONFIGURATION\netstandard2.1\Microsoft.Quantum.QsTextProcessor.dll", + ".\src\QsCompiler\QirGeneration\bin\$Env:BUILD_CONFIGURATION\netstandard2.1\Microsoft.Quantum.QirGeneration.dll", + ".\src\QsCompiler\LlvmBindings\bin\$Env:BUILD_CONFIGURATION\netstandard2.1\Microsoft.Quantum.LlvmBindings.dll", ".\src\QsCompiler\Transformations\bin\$Env:BUILD_CONFIGURATION\netstandard2.1\Microsoft.Quantum.QsTransformations.dll", ".\src\QsCompiler\CommandLineTool\bin\$Env:BUILD_CONFIGURATION\netcoreapp3.1\qsc.dll", ".\src\QuantumSdk\Tools\BuildConfiguration\bin\$Env:BUILD_CONFIGURATION\netcoreapp3.1\Microsoft.Quantum.Sdk.BuildConfiguration.dll", diff --git a/build/pack.ps1 b/build/pack.ps1 index 9ec07039e2..83a2d33fde 100644 --- a/build/pack.ps1 +++ b/build/pack.ps1 @@ -86,10 +86,12 @@ function Pack-Dotnet() { $all_ok = $True Publish-One '../src/QsCompiler/CommandLineTool/CommandLineTool.csproj' +Publish-One '../src/QsCompiler/LlvmBindings/LlvmBindings.csproj' Publish-One '../src/QuantumSdk/Tools/BuildConfiguration/BuildConfiguration.csproj' Publish-One '../src/QuantumSdk/Tools/DefaultEntryPoint/DefaultEntryPoint.csproj' Pack-One '../src/QsCompiler/Compiler/Compiler.csproj' '-IncludeReferencedProjects' +Pack-One '../src/QsCompiler/QirGeneration/QirGeneration.csproj' Pack-Dotnet '../src/Documentation/DocumentationGenerator/DocumentationGenerator.csproj' Pack-One '../src/ProjectTemplates/Microsoft.Quantum.ProjectTemplates.nuspec' Pack-One '../src/QuantumSdk/QuantumSdk.nuspec' diff --git a/examples/CompilerExtensions/CustomExtension/CustomExtension.csproj b/examples/CompilerExtensions/CustomExtension/CustomExtension.csproj index edb8b20220..f815359e4c 100644 --- a/examples/CompilerExtensions/CustomExtension/CustomExtension.csproj +++ b/examples/CompilerExtensions/CustomExtension/CustomExtension.csproj @@ -5,7 +5,7 @@ - + diff --git a/examples/CompilerExtensions/CustomExtension/ListIdentifiers.cs b/examples/CompilerExtensions/CustomExtension/ListIdentifiers.cs index f706e0343b..4a893dc81b 100644 --- a/examples/CompilerExtensions/CustomExtension/ListIdentifiers.cs +++ b/examples/CompilerExtensions/CustomExtension/ListIdentifiers.cs @@ -90,8 +90,8 @@ internal NamespaceTransformation(ListIdentifiers parent) private static QsCallable AddComments(QsCallable c, params string[] comments) => new QsCallable( - c.Kind, c.FullName, c.Attributes, c.Modifiers, - c.SourceFile, c.Location, + c.Kind, c.FullName, c.Attributes, c.Access, + c.Source, c.Location, c.Signature, c.ArgumentTuple, c.Specializations, c.Documentation, new QsComments(c.Comments.OpeningComments.AddRange(comments), c.Comments.ClosingComments)); diff --git a/examples/CompilerExtensions/Demo/Demo.csproj b/examples/CompilerExtensions/Demo/Demo.csproj index d08761c0e7..226448a965 100644 --- a/examples/CompilerExtensions/Demo/Demo.csproj +++ b/examples/CompilerExtensions/Demo/Demo.csproj @@ -1,4 +1,4 @@ - + Detailed diff --git a/examples/QIR/Emission/Emission.csproj b/examples/QIR/Emission/Emission.csproj index 98556cdfc4..84bd0e119f 100644 --- a/examples/QIR/Emission/Emission.csproj +++ b/examples/QIR/Emission/Emission.csproj @@ -1,4 +1,4 @@ - + Detailed diff --git a/src/Documentation/DocumentationGenerator/Extensions.cs b/src/Documentation/DocumentationGenerator/Extensions.cs index 8ee0360de4..4175cd3a84 100644 --- a/src/Documentation/DocumentationGenerator/Extensions.cs +++ b/src/Documentation/DocumentationGenerator/Extensions.cs @@ -297,15 +297,16 @@ internal static Dictionary ToDictionaryOfDeclarations(this $"'{typeParam.Item.TypeName}", _ => type.Resolution.Tag switch { - ResolvedTypeKind.Tags.BigInt => "[BigInt](xref:microsoft.quantum.lang-ref.bigint)", - ResolvedTypeKind.Tags.Bool => "[Bool](xref:microsoft.quantum.lang-ref.bool)", - ResolvedTypeKind.Tags.Double => "[Double](xref:microsoft.quantum.lang-ref.double)", - ResolvedTypeKind.Tags.Int => "[Int](xref:microsoft.quantum.lang-ref.int)", - ResolvedTypeKind.Tags.Pauli => "[Pauli](xref:microsoft.quantum.lang-ref.pauli)", - ResolvedTypeKind.Tags.Qubit => "[Qubit](xref:microsoft.quantum.lang-ref.qubit)", - ResolvedTypeKind.Tags.Range => "[Range](xref:microsoft.quantum.lang-ref.range)", - ResolvedTypeKind.Tags.String => "[String](xref:microsoft.quantum.lang-ref.string)", - ResolvedTypeKind.Tags.UnitType => "[Unit](xref:microsoft.quantum.lang-ref.unit)", + ResolvedTypeKind.Tags.BigInt => "[BigInt](xref:microsoft.quantum.qsharp.valueliterals#bigint-literals)", + ResolvedTypeKind.Tags.Bool => "[Bool](xref:microsoft.quantum.qsharp.valueliterals#bool-literals)", + ResolvedTypeKind.Tags.Double => "[Double](xref:microsoft.quantum.qsharp.valueliterals#double-literals)", + ResolvedTypeKind.Tags.Int => "[Int](xref:microsoft.quantum.qsharp.valueliterals#int-literals)", + ResolvedTypeKind.Tags.Pauli => "[Pauli](xref:microsoft.quantum.qsharp.valueliterals#pauli-literals)", + ResolvedTypeKind.Tags.Qubit => "[Qubit](xref:microsoft.quantum.qsharp.valueliterals#qubit-literals)", + ResolvedTypeKind.Tags.Range => "[Range](xref:microsoft.quantum.qsharp.valueliterals#range-literals)", + ResolvedTypeKind.Tags.String => "[String](xref:microsoft.quantum.qsharp.valueliterals#string-literals)", + ResolvedTypeKind.Tags.UnitType => "[Unit](xref:microsoft.quantum.qsharp.valueliterals#unit-literal)", + ResolvedTypeKind.Tags.Result => "[Result](xref:microsoft.quantum.qsharp.valueliterals#result-literal)", ResolvedTypeKind.Tags.InvalidType => "__invalid__", _ => $"__invalid<{type.Resolution.ToString()}>__", }, diff --git a/src/ProjectTemplates/Microsoft.Quantum.ProjectTemplates.nuspec b/src/ProjectTemplates/Microsoft.Quantum.ProjectTemplates.nuspec index 5819ecb996..9c2a4ce032 100644 --- a/src/ProjectTemplates/Microsoft.Quantum.ProjectTemplates.nuspec +++ b/src/ProjectTemplates/Microsoft.Quantum.ProjectTemplates.nuspec @@ -9,7 +9,7 @@ MIT https://docs.microsoft.com/azure/quantum - images\qdk-nuget-icon.png + https://secure.gravatar.com/avatar/bd1f02955b2853ba0a3b1cdc2434e8ec.png false .NET Core templates pack for Q#, part of the Microsoft Quantum Development Kit. @@ -26,7 +26,6 @@ - diff --git a/src/QsCompiler/CommandLineTool/CommandLineTool.csproj b/src/QsCompiler/CommandLineTool/CommandLineTool.csproj index eb63c71888..92b8619a15 100644 --- a/src/QsCompiler/CommandLineTool/CommandLineTool.csproj +++ b/src/QsCompiler/CommandLineTool/CommandLineTool.csproj @@ -27,6 +27,10 @@ + + + + diff --git a/src/QsCompiler/CommandLineTool/Commands/Build.cs b/src/QsCompiler/CommandLineTool/Commands/Build.cs index 963402f818..8899e89476 100644 --- a/src/QsCompiler/CommandLineTool/Commands/Build.cs +++ b/src/QsCompiler/CommandLineTool/Commands/Build.cs @@ -72,13 +72,6 @@ public static IEnumerable UsageExamples HelpText = "Specifies whether the compiler should emit a .NET Core dll containing the compiled Q# code.")] public bool EmitDll { get; set; } - [Option( - "qir", - Required = false, - SetName = CodeMode, - HelpText = "Destination folder for the emitted QIR; only executable projects can be compiled into QIR.")] - public string QirOutputFolder { get; set; } - [Option( "perf", Required = false, @@ -225,11 +218,13 @@ public static int Run(BuildOptions options, ConsoleLogger logger) { ProjectName = options.ProjectName, AssemblyConstants = assemblyConstants, + ForceRewriteStepExecution = options.ForceRewriteStepExecution, TargetPackageAssemblies = options.TargetSpecificDecompositions ?? Enumerable.Empty(), RuntimeCapability = options.RuntimeCapability, - SkipMonomorphization = options.RuntimeCapability == RuntimeCapability.FullComputation && options.QirOutputFolder == null, + SkipMonomorphization = options.SkipMonomorphization, GenerateFunctorSupport = true, SkipSyntaxTreeTrimming = options.TrimLevel == 0, + SkipConjugationInlining = options.TrimLevel == 0, AttemptFullPreEvaluation = options.TrimLevel > 2, BuildOutputFolder = options.OutputFolder ?? (usesPlugins ? "." : null), DllOutputPath = options.EmitDll ? " " : null, // set to e.g. an empty space to generate the dll in the same location as the .bson file @@ -237,7 +232,6 @@ public static int Run(BuildOptions options, ConsoleLogger logger) RewriteStepAssemblies = options.Plugins?.Select(step => (step, (string?)null)) ?? ImmutableArray<(string, string)>.Empty, EnableAdditionalChecks = false, // todo: enable debug mode? ExposeReferencesViaTestNames = options.ExposeReferencesViaTestNames, - QirOutputFolder = options.QirOutputFolder }; if (options.PerfOutputFolder != null) diff --git a/src/QsCompiler/CommandLineTool/Commands/Diagnose.cs b/src/QsCompiler/CommandLineTool/Commands/Diagnose.cs index a39ec54c66..80b21ff9fc 100644 --- a/src/QsCompiler/CommandLineTool/Commands/Diagnose.cs +++ b/src/QsCompiler/CommandLineTool/Commands/Diagnose.cs @@ -237,11 +237,13 @@ public static int Run(DiagnoseOptions options, ConsoleLogger logger) var loadOptions = new CompilationLoader.Configuration { AssemblyConstants = assemblyConstants, + ForceRewriteStepExecution = options.ForceRewriteStepExecution, TargetPackageAssemblies = options.TargetSpecificDecompositions ?? Enumerable.Empty(), RuntimeCapability = options.RuntimeCapability, - SkipMonomorphization = options.RuntimeCapability == RuntimeCapability.FullComputation, + SkipMonomorphization = options.SkipMonomorphization, GenerateFunctorSupport = true, SkipSyntaxTreeTrimming = options.TrimLevel == 0, + SkipConjugationInlining = options.TrimLevel == 0, AttemptFullPreEvaluation = options.TrimLevel > 2, IsExecutable = options.MakeExecutable, RewriteStepAssemblies = options.Plugins?.Select(step => (step, (string?)null)) ?? ImmutableArray<(string, string)>.Empty, diff --git a/src/QsCompiler/CommandLineTool/LoadContext.cs b/src/QsCompiler/CommandLineTool/LoadContext.cs index 484188d1e8..745fe47eaf 100644 --- a/src/QsCompiler/CommandLineTool/LoadContext.cs +++ b/src/QsCompiler/CommandLineTool/LoadContext.cs @@ -10,6 +10,7 @@ using System.IO; using System.Linq; using System.Reflection; +using System.Runtime.InteropServices; using System.Runtime.Loader; namespace Microsoft.Quantum.QsCompiler @@ -46,22 +47,66 @@ private LoadContext(string parentAssembly) } /// - protected override Assembly? Load(AssemblyName name) + protected override IntPtr LoadUnmanagedDll(string name) { - var path = this.resolver.ResolveAssemblyToPath(name); - return path == null ? null : this.LoadFromAssemblyPath(path); + var path = this.resolver.ResolveUnmanagedDllToPath(name); + path ??= this.ResolveFromFallbackPaths(name); + return path == null ? IntPtr.Zero : this.LoadUnmanagedDllFromPath(path); + } + + /// + /// Search all fallback paths for a suitable .dll, .dylib, or .so file, ignoring all exceptions. + /// Returns the full path to the file if such a file was found. + /// + private string? ResolveFromFallbackPaths(string name) + { + bool MatchByName(string file) => + Path.GetFileNameWithoutExtension(file) + .Equals(name, StringComparison.InvariantCultureIgnoreCase); + + var found = new List(); + foreach (var dir in this.fallbackPaths) + { + try + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + found.AddRange(Directory.GetFiles(dir, "*.dylib", SearchOption.AllDirectories).Where(MatchByName)); + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + found.AddRange(Directory.GetFiles(dir, "*.so", SearchOption.AllDirectories).Where(MatchByName)); + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + found.AddRange(Directory.GetFiles(dir, "*.dll", SearchOption.AllDirectories).Where(MatchByName)); + } + else + { + found.AddRange(Directory.GetFiles(dir, "*.dll", SearchOption.AllDirectories).Where(MatchByName)); + found.AddRange(Directory.GetFiles(dir, "*.dylib", SearchOption.AllDirectories).Where(MatchByName)); + found.AddRange(Directory.GetFiles(dir, "*.so", SearchOption.AllDirectories).Where(MatchByName)); + } + } + catch + { + continue; + } + } + + return found.FirstOrDefault(); } /// - protected override IntPtr LoadUnmanagedDll(string name) + protected override Assembly? Load(AssemblyName name) { - var path = this.resolver.ResolveUnmanagedDllToPath(name); - return path == null ? IntPtr.Zero : this.LoadUnmanagedDllFromPath(path); + var path = this.resolver.ResolveAssemblyToPath(name); + return path == null ? null : this.LoadFromAssemblyPath(path); } /// /// Search all fallback paths for a suitable .dll ignoring all exceptions. - /// Returns the full path to the dll if a suitable assembly could was found. + /// Returns the full path to the dll if a suitable assembly was found. /// private string? ResolveFromFallbackPaths(AssemblyName name) { @@ -81,6 +126,7 @@ bool MatchByName(string file) => continue; } } + if (found.Count <= 1 || name.Version == null) { return found.FirstOrDefault(); diff --git a/src/QsCompiler/CommandLineTool/Options.cs b/src/QsCompiler/CommandLineTool/Options.cs index 125306fb51..5d6582ec8b 100644 --- a/src/QsCompiler/CommandLineTool/Options.cs +++ b/src/QsCompiler/CommandLineTool/Options.cs @@ -64,6 +64,20 @@ public class CompilationOptions : Options HelpText = "Additional properties to populate the AssemblyConstants dictionary with. Each item is expected to be of the form \"key:value\".")] public IEnumerable? AdditionalAssemblyProperties { get; set; } + [Option( + "skip-monomorphization", + Required = false, + Default = false, + HelpText = "Specifies whether to omit monomorphizing the AST for executables.")] + public bool SkipMonomorphization { get; set; } + + [Option( + "force-rewrite-step-execution", + Required = false, + Default = false, + HelpText = "Specifies whether to execute rewrite steps even if their precondition is not satisfied. If the parameter is set to true and the precondition is not satisfied, the transformation will be executed, its output will be ignored and the compilation fails.")] + public bool ForceRewriteStepExecution { get; set; } + [Option( "runtime", Required = false, diff --git a/src/QsCompiler/CommandLineTool/Program.cs b/src/QsCompiler/CommandLineTool/Program.cs index 531e836a72..681134d15b 100644 --- a/src/QsCompiler/CommandLineTool/Program.cs +++ b/src/QsCompiler/CommandLineTool/Program.cs @@ -2,7 +2,9 @@ // Licensed under the MIT License. using System; +using System.IO; using System.Linq; +using System.Reflection; using CommandLine; using Microsoft.Quantum.QsCompiler.Diagnostics; using Microsoft.VisualStudio.LanguageServer.Protocol; @@ -76,11 +78,6 @@ public static class ReturnCode /// public const int MonomorphizationErrors = -12; - /// - /// Return code indicating that generating QIR for the built compilation failed. - /// - public const int QirGenerationErrors = -13; - /// /// Return code indicating that an unexpected exception was thrown when executing the invoked command to the Q# command line compiler. /// @@ -96,8 +93,6 @@ public static int Status(CompilationLoader loaded) => loaded.Monomorphization == CompilationLoader.Status.Failed ? MonomorphizationErrors : loaded.TargetSpecificReplacements == CompilationLoader.Status.Failed ? TargetingErrors : loaded.TargetSpecificCompilation == CompilationLoader.Status.Failed ? TargetingErrors : - loaded.TargetInstructionInference == CompilationLoader.Status.Failed ? TargetingErrors : - loaded.QirGeneration == CompilationLoader.Status.Failed ? QirGenerationErrors : loaded.Documentation == CompilationLoader.Status.Failed ? DocGenerationErrors : loaded.BinaryFormat == CompilationLoader.Status.Failed ? BinaryGenerationErrors : loaded.DllGeneration == CompilationLoader.Status.Failed ? DllGenerationErrors : @@ -112,8 +107,10 @@ private static int Run(Func compile, T options) var logger = options.GetLogger(); try { + var current = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!; + var fallbackFolders = options.PackageLoadFallbackFolders.Prepend(current); CompilationLoader.LoadAssembly = path => - LoadContext.LoadAssembly(path, options.PackageLoadFallbackFolders?.ToArray()); + LoadContext.LoadAssembly(path, fallbackFolders.ToArray()); var result = compile(options, logger); logger.ReportSummary(result); @@ -121,7 +118,6 @@ private static int Run(Func compile, T options) } catch (Exception ex) { - logger.Verbosity = DiagnosticSeverity.Hint; logger.Log(ErrorCode.UnexpectedCommandLineCompilerException, Enumerable.Empty()); logger.Log(ex); return ReturnCode.UnexpectedError; diff --git a/src/QsCompiler/CompilationManager/PerformanceTracking.cs b/src/QsCompiler/CompilationManager/PerformanceTracking.cs index 38ae613969..42278cf67e 100644 --- a/src/QsCompiler/CompilationManager/PerformanceTracking.cs +++ b/src/QsCompiler/CompilationManager/PerformanceTracking.cs @@ -48,6 +48,7 @@ public static class PerformanceTracking { Task.SourcesLoading, Task.OverallCompilation }, { Task.ReplaceTargetSpecificImplementations, Task.Build }, { Task.BinaryGeneration, Task.OutputGeneration }, + { Task.BitcodeGeneration, Task.OutputGeneration }, { Task.DllGeneration, Task.OutputGeneration }, { Task.QirGeneration, Task.OutputGeneration }, { Task.DocumentationGeneration, Task.OutputGeneration }, @@ -109,6 +110,11 @@ public enum Task /// BinaryGeneration, + /// + /// Task that generates LLVM bitcode as part of the 'OutputGeneration' task. + /// + BitcodeGeneration, + /// /// Task that generates a DLL as part of the 'OutputGeneration' task. /// diff --git a/src/QsCompiler/Compiler/CompilationLoader.cs b/src/QsCompiler/Compiler/CompilationLoader.cs index 6cb28323a4..8c82c12b88 100644 --- a/src/QsCompiler/Compiler/CompilationLoader.cs +++ b/src/QsCompiler/Compiler/CompilationLoader.cs @@ -61,6 +61,13 @@ public struct Configuration /// public string? ProjectName; + /// + /// If set to true, forces all rewrite steps to execute, regardless of whether their precondition was satisfied. + /// If the precondition of a step is not satisfied, the transformation is executed but the output will be ignored, + /// and an error is generated, indicating a compilation failure. + /// + public bool ForceRewriteStepExecution; + /// /// If set to true, the syntax tree rewrite step that replaces all generation directives /// for all functor specializations is executed during compilation. @@ -68,8 +75,12 @@ public struct Configuration public bool GenerateFunctorSupport; /// - /// Unless this is set to true, the syntax tree rewrite step that eliminates selective abstractions is executed during compilation. - /// In particular, all conjugations are inlined. + /// Unless this is set to true, the syntax tree rewrite step that inlines conjugations is executed during compilation. + /// + public bool SkipConjugationInlining; + + /// + /// Unless this is set to true, all unused callables are removed from the syntax tree. /// public bool SkipSyntaxTreeTrimming; @@ -111,12 +122,6 @@ public struct Configuration /// public string? BuildOutputFolder; - /// - /// Directory where QIR will be generated. - /// No QIR will be generated unless this path is specified and valid. - /// - public string? QirOutputFolder; - /// /// Output path for the dll containing the compiled binaries. /// No dll will be generated unless this path is specified and valid. @@ -251,6 +256,7 @@ private class ExecutionStatus internal Status TargetSpecificReplacements = Status.NotRun; internal Status FunctorSupport = Status.NotRun; internal Status PreEvaluation = Status.NotRun; + internal Status ConjugationInlining = Status.NotRun; internal Status TreeTrimming = Status.NotRun; internal Status ConvertClassicalControl = Status.NotRun; internal Status Monomorphization = Status.NotRun; @@ -259,8 +265,6 @@ private class ExecutionStatus internal Status BinaryFormat = Status.NotRun; internal Status DllGeneration = Status.NotRun; internal Status CapabilityInference = Status.NotRun; - internal Status TargetInstructionInference = Status.NotRun; - internal Status QirGeneration = Status.NotRun; internal Status[] LoadedRewriteSteps; internal ExecutionStatus(IEnumerable externalRewriteSteps) => @@ -274,18 +278,17 @@ internal bool Success(Configuration options) => this.ReferenceLoading <= 0 && this.WasSuccessful(true, this.Validation) && this.WasSuccessful(true, this.PluginLoading) && + this.WasSuccessful(options.IsExecutable && !options.SkipSyntaxTreeTrimming, this.TreeTrimming) && this.WasSuccessful(options.GenerateFunctorSupport, this.FunctorSupport) && - this.WasSuccessful(!options.SkipSyntaxTreeTrimming, this.TreeTrimming) && + this.WasSuccessful(!options.SkipConjugationInlining, this.ConjugationInlining) && this.WasSuccessful(options.AttemptFullPreEvaluation, this.PreEvaluation) && this.WasSuccessful(options.LoadTargetSpecificDecompositions, this.TargetSpecificReplacements) && this.WasSuccessful(options.ConvertClassicalControl, this.ConvertClassicalControl) && this.WasSuccessful(options.IsExecutable && !options.SkipMonomorphization, this.Monomorphization) && this.WasSuccessful(!options.IsExecutable, this.CapabilityInference) && - this.WasSuccessful(options.QirOutputFolder != null, this.TargetInstructionInference) && this.WasSuccessful(options.SerializeSyntaxTree, this.Serialization) && this.WasSuccessful(options.BuildOutputFolder != null, this.BinaryFormat) && this.WasSuccessful(options.DllOutputPath != null, this.DllGeneration) && - this.WasSuccessful(options.QirOutputFolder != null, this.QirGeneration) && this.LoadedRewriteSteps.All(status => this.WasSuccessful(true, status)); } @@ -351,13 +354,6 @@ internal bool Success(Configuration options) => /// public Status CapabilityInference => this.compilationStatus.CapabilityInference; - /// - /// Indicates whether a separate callable that corresponds to an instruction - /// implemented by the execution target has been generated for each intrinsic specialization. - /// This rewrite step is only executed when generating QIR. - /// - public Status TargetInstructionInference => this.compilationStatus.TargetInstructionInference; - /// /// Indicates whether documentation for the compilation was generated successfully. /// This step is only executed if the corresponding configuration is specified. @@ -376,12 +372,6 @@ internal bool Success(Configuration options) => /// public Status BinaryFormat => this.compilationStatus.BinaryFormat; - /// - /// Indicates whether QIR has been emitted successfully. - /// This step is only executed if the corresponding configuration is specified. - /// - public Status QirGeneration => this.compilationStatus.QirGeneration; - /// /// Indicates whether a dll containing the compiled binary has been generated successfully. /// This step is only executed if the corresponding configuration is specified. @@ -547,11 +537,11 @@ public CompilationLoader(SourceLoader loadSources, ReferenceLoader loadReference { if (this.config.RuntimeCapability == null || this.config.RuntimeCapability == RuntimeCapability.FullComputation) { - this.logger?.Log(WarningCode.MissingEntryPoint, Array.Empty()); + this.LogAndUpdate(ref this.compilationStatus.Validation, WarningCode.MissingEntryPoint); } else { - this.LogAndUpdate(ref this.compilationStatus.Validation, ErrorCode.MissingEntryPoint, Array.Empty()); + this.LogAndUpdate(ref this.compilationStatus.Validation, ErrorCode.MissingEntryPoint); } } @@ -576,6 +566,16 @@ public CompilationLoader(SourceLoader loadSources, ReferenceLoader loadReference PerformanceTracking.TaskStart(PerformanceTracking.Task.RewriteSteps); var steps = new List<(int, string, Func)>(); + var qirEmissionEnabled = this.externalRewriteSteps.Any(step => step.Name == "QIR Generation"); + + if (this.config.IsExecutable && !this.config.SkipSyntaxTreeTrimming) + { + // TODO: It would be nicer to trim unused intrinsics. Currently, this is not possible due to how the old setup of the C# runtime works. + // With the new setup (interface-based approach for target packages), it is possible to trim ununsed intrinsics. + var rewriteStep = new LoadedStep(new SyntaxTreeTrimming(keepAllIntrinsics: !qirEmissionEnabled), typeof(IRewriteStep), thisDllUri); + steps.Add((rewriteStep.Priority, rewriteStep.Name, () => this.ExecuteAsAtomicTransformation(rewriteStep, ref this.compilationStatus.TreeTrimming))); + } + if (this.config.ConvertClassicalControl) { var rewriteStep = new LoadedStep(new ClassicallyControlled(), typeof(IRewriteStep), thisDllUri); @@ -588,10 +588,10 @@ public CompilationLoader(SourceLoader loadSources, ReferenceLoader loadReference steps.Add((rewriteStep.Priority, rewriteStep.Name, () => this.ExecuteAsAtomicTransformation(rewriteStep, ref this.compilationStatus.FunctorSupport))); } - if (!this.config.SkipSyntaxTreeTrimming) + if (!this.config.SkipConjugationInlining) { var rewriteStep = new LoadedStep(new ConjugationInlining(), typeof(IRewriteStep), thisDllUri); - steps.Add((rewriteStep.Priority, rewriteStep.Name, () => this.ExecuteAsAtomicTransformation(rewriteStep, ref this.compilationStatus.TreeTrimming))); + steps.Add((rewriteStep.Priority, rewriteStep.Name, () => this.ExecuteAsAtomicTransformation(rewriteStep, ref this.compilationStatus.ConjugationInlining))); } if (this.config.AttemptFullPreEvaluation) @@ -602,7 +602,7 @@ public CompilationLoader(SourceLoader loadSources, ReferenceLoader loadReference if (this.config.IsExecutable && !this.config.SkipMonomorphization) { - var rewriteStep = new LoadedStep(new Monomorphization(this.config.QirOutputFolder == null), typeof(IRewriteStep), thisDllUri); + var rewriteStep = new LoadedStep(new Monomorphization(monomorphizeIntrinsics: qirEmissionEnabled), typeof(IRewriteStep), thisDllUri); steps.Add((rewriteStep.Priority, rewriteStep.Name, () => this.ExecuteAsAtomicTransformation(rewriteStep, ref this.compilationStatus.Monomorphization))); } @@ -612,12 +612,6 @@ public CompilationLoader(SourceLoader loadSources, ReferenceLoader loadReference steps.Add((capabilityInference.Priority, capabilityInference.Name, () => this.ExecuteAsAtomicTransformation(capabilityInference, ref this.compilationStatus.CapabilityInference))); } - if (this.config.QirOutputFolder != null) - { - var separateTargetInstructions = new LoadedStep(new TargetInstructionInference(), typeof(IRewriteStep), thisDllUri); - steps.Add((separateTargetInstructions.Priority, separateTargetInstructions.Name, () => this.ExecuteAsAtomicTransformation(separateTargetInstructions, ref this.compilationStatus.TargetInstructionInference))); - } - for (int j = 0; j < this.externalRewriteSteps.Length; j++) { var rewriteStep = this.externalRewriteSteps[j]; @@ -658,18 +652,6 @@ public CompilationLoader(SourceLoader loadSources, ReferenceLoader loadReference } } - if (this.config.QirOutputFolder != null && this.compilationStatus.TargetInstructionInference == Status.Succeeded) - { - var projId = Path.GetFullPath(this.config.ProjectNameWithExtension ?? "main"); - var outFolder = Path.GetFullPath(string.IsNullOrWhiteSpace(this.config.QirOutputFolder) ? "." : this.config.QirOutputFolder); - var target = GeneratedFile(projId, outFolder, ".ll", ""); - - PerformanceTracking.TaskStart(PerformanceTracking.Task.QirGeneration); - var qirGeneration = new LoadedStep(new QirGeneration(target), typeof(IRewriteStep), thisDllUri); - this.ExecuteAsAtomicTransformation(qirGeneration, ref this.compilationStatus.QirGeneration); - PerformanceTracking.TaskEnd(PerformanceTracking.Task.QirGeneration); - } - PerformanceTracking.TaskEnd(PerformanceTracking.Task.OutputGeneration); PerformanceTracking.TaskEnd(PerformanceTracking.Task.OverallCompilation); } @@ -730,12 +712,20 @@ private void LogAndUpdate(ref Status current, Exception ex) /// /// Logs an error with the given error code and message parameters, and updates the status passed as reference accordingly. /// - private void LogAndUpdate(ref Status current, ErrorCode code, IEnumerable args) + private void LogAndUpdate(ref Status current, ErrorCode code, params string[] args) { this.logger?.Log(code, args); current = Status.Failed; } + /// + /// Logs an error with the given warning code and message parameters, and updates the status passed as reference accordingly. + /// + private void LogAndUpdate(ref Status current, WarningCode code, params string[] args) + { + this.logger?.Log(code, args); + } + /// /// Logs the given diagnostic and updates the status passed as reference accordingly. /// Adds the given diagnostic to the tracked load diagnostics. @@ -751,7 +741,7 @@ private void LogAndUpdateLoadDiagnostics(ref Status current, Diagnostic d) /// private void OnCompilerException(Exception ex) { - this.LogAndUpdate(ref this.compilationStatus.Validation, ErrorCode.UnexpectedCompilerException, Enumerable.Empty()); + this.LogAndUpdate(ref this.compilationStatus.Validation, ErrorCode.UnexpectedCompilerException); this.LogAndUpdate(ref this.compilationStatus.Validation, ex); } @@ -830,7 +820,7 @@ private void PrintLoadedRewriteSteps(IEnumerable rewriteSteps) /// private QsCompilation? ReplaceTargetSpecificImplementations(IEnumerable paths, Uri rewriteStepOrigin, int nrReferences) { - void LogError(ErrorCode errCode, string[] args) => this.LogAndUpdate(ref this.compilationStatus.TargetSpecificReplacements, errCode, args); + void LogError(ErrorCode errCode, params string[] args) => this.LogAndUpdate(ref this.compilationStatus.TargetSpecificReplacements, errCode, args); void LogException(Exception ex) => this.LogAndUpdate(ref this.compilationStatus.TargetSpecificReplacements, ex); (string, ImmutableArray)? LoadReferences(string path) @@ -842,12 +832,12 @@ private void PrintLoadedRewriteSteps(IEnumerable rewriteSteps) { return (path, loaded.Namespaces); } - LogError(ErrorCode.FailedToLoadTargetSpecificDecompositions, new[] { targetDll }); + LogError(ErrorCode.FailedToLoadTargetSpecificDecompositions, targetDll); return null; } catch (Exception ex) { - LogError(ErrorCode.InvalidPathToTargetSpecificDecompositions, new[] { path }); + LogError(ErrorCode.InvalidPathToTargetSpecificDecompositions, path); LogException(ex); return null; } @@ -857,7 +847,7 @@ private void PrintLoadedRewriteSteps(IEnumerable rewriteSteps) var combinedSuccessfully = References.CombineSyntaxTrees(out var replacements, additionalAssemblies: nrReferences, onError: LogError, natives); if (!combinedSuccessfully) { - LogError(ErrorCode.ConflictsInTargetSpecificDecompositions, Array.Empty()); + LogError(ErrorCode.ConflictsInTargetSpecificDecompositions); } var targetSpecificDecompositions = new QsCompilation(replacements, ImmutableArray.Empty); @@ -880,6 +870,7 @@ private Status ExecuteRewriteStep(LoadedStep rewriteStep, QsCompilation compilat rewriteStep.Name == "QIR Generation" && severity == DiagnosticSeverity.Information ? Informations.Code(InformationCode.QirEmissionGeneratedInfo) : null; + var messageSource = ProjectManager.MessageSource(rewriteStep.Origin); void LogDiagnostics(ref Status status) { try @@ -892,13 +883,11 @@ void LogDiagnostics(ref Status status) } catch { - this.LogAndUpdate(ref status, Warning(WarningCode.RewriteStepDiagnosticsGenerationFailed, rewriteStep.Name)); + this.LogAndUpdate(ref status, WarningCode.RewriteStepDiagnosticsGenerationFailed, rewriteStep.Name, messageSource); } } var status = Status.Succeeded; - var messageSource = ProjectManager.MessageSource(rewriteStep.Origin); - Diagnostic Warning(WarningCode code, params string[] args) => Warnings.LoadWarning(code, args, messageSource); try { transformed = compilation; @@ -906,8 +895,15 @@ void LogDiagnostics(ref Status status) if (preconditionFailed) { LogDiagnostics(ref status); - this.LogAndUpdate(ref status, Warning(WarningCode.PreconditionVerificationFailed, rewriteStep.Name, messageSource)); - return status; + if (this.config.ForceRewriteStepExecution) + { + this.LogAndUpdate(ref status, ErrorCode.PreconditionVerificationFailed, rewriteStep.Name, messageSource); + } + else + { + this.LogAndUpdate(ref status, WarningCode.PreconditionVerificationFailed, rewriteStep.Name, messageSource); + return status; + } } var transformationFailed = rewriteStep.ImplementsTransformation && (!rewriteStep.Transformation(compilation, out transformed) || transformed == null); @@ -953,7 +949,7 @@ private ImmutableDictionary LoadSourceFiles(IEnumerable sou this.compilationStatus.SourceFileLoading = 0; if (sources == null) { - this.LogAndUpdate(ref this.compilationStatus.SourceFileLoading, ErrorCode.SourceFilesMissing, Enumerable.Empty()); + this.LogAndUpdate(ref this.compilationStatus.SourceFileLoading, ErrorCode.SourceFilesMissing); } void OnException(Exception ex) => this.LogAndUpdate(ref this.compilationStatus.SourceFileLoading, ex); void OnDiagnostic(Diagnostic d) => this.LogAndUpdateLoadDiagnostics(ref this.compilationStatus.SourceFileLoading, d); @@ -975,7 +971,7 @@ private References LoadAssemblies(IEnumerable refs, bool loadTestNames, this.compilationStatus.ReferenceLoading = 0; if (refs == null) { - this.logger?.Log(WarningCode.ReferencesSetToNull, Enumerable.Empty()); + this.LogAndUpdate(ref this.compilationStatus.ReferenceLoading, WarningCode.ReferencesSetToNull); } void OnException(Exception ex) => this.LogAndUpdate(ref this.compilationStatus.ReferenceLoading, ex); void OnDiagnostic(Diagnostic d) => this.LogAndUpdateLoadDiagnostics(ref this.compilationStatus.ReferenceLoading, d); @@ -995,7 +991,7 @@ private References LoadAssemblies(IEnumerable refs, bool loadTestNames, private bool WriteSyntaxTreeSerialization(MemoryStream ms) { void LogError() => this.LogAndUpdate( - ref this.compilationStatus.Serialization, ErrorCode.SerializationFailed, Enumerable.Empty()); + ref this.compilationStatus.Serialization, ErrorCode.SerializationFailed); void LogExceptionAndError(Exception ex) { @@ -1045,7 +1041,7 @@ void LogExceptionAndError(Exception ex) catch (Exception ex) { this.LogAndUpdate(ref this.compilationStatus.BinaryFormat, ex); - this.LogAndUpdate(ref this.compilationStatus.BinaryFormat, ErrorCode.GeneratingBinaryFailed, Enumerable.Empty()); + this.LogAndUpdate(ref this.compilationStatus.BinaryFormat, ErrorCode.GeneratingBinaryFailed); return null; } } @@ -1101,8 +1097,7 @@ bool CanBeIncluded(string dll) var csharpTree = MetadataGeneration.GenerateAssemblyMetadata(references.Where(r => r.Item3).Select(r => r.Item2)); foreach (var (dropped, _, _) in references.Where(r => !r.Item3)) { - var warning = Warnings.LoadWarning(WarningCode.ReferenceCannotBeIncludedInDll, new[] { dropped }, null); - this.LogAndUpdate(ref this.compilationStatus.DllGeneration, warning); + this.LogAndUpdate(ref this.compilationStatus.DllGeneration, WarningCode.ReferencesSetToNull, dropped); } var compilation = CodeAnalysis.CSharp.CSharpCompilation.Create( @@ -1129,7 +1124,7 @@ bool CanBeIncluded(string dll) catch (Exception ex) { this.LogAndUpdate(ref this.compilationStatus.DllGeneration, ex); - this.LogAndUpdate(ref this.compilationStatus.DllGeneration, ErrorCode.GeneratingDllFailed, Enumerable.Empty()); + this.LogAndUpdate(ref this.compilationStatus.DllGeneration, ErrorCode.GeneratingDllFailed); return null; } } @@ -1189,6 +1184,7 @@ public static string GeneratedFile(string fileId, string outputFolder, string fi string FullDirectoryName(string dir) => Path.GetFullPath(dir.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar) + Path.DirectorySeparatorChar); + fileEnding = fileEnding.Trim().TrimStart('.'); outputFolder = string.IsNullOrWhiteSpace(outputFolder) ? "." : outputFolder; var outputUri = new Uri(FullDirectoryName(outputFolder)); var currentDir = new Uri(FullDirectoryName(".")); @@ -1197,7 +1193,7 @@ string FullDirectoryName(string dir) => var fileDir = filePath.StartsWith(outputUri.LocalPath) ? Path.GetDirectoryName(filePath) : Path.GetDirectoryName(outputUri.LocalPath); - var targetFile = Path.GetFullPath(Path.Combine(fileDir, Path.GetFileNameWithoutExtension(filePath) + fileEnding)); + var targetFile = Path.GetFullPath(Path.Combine(fileDir, $"{Path.GetFileNameWithoutExtension(filePath)}.{fileEnding}")); if (content == null) { diff --git a/src/QsCompiler/Compiler/Compiler.csproj b/src/QsCompiler/Compiler/Compiler.csproj index eb398a5e28..13b1eae63e 100644 --- a/src/QsCompiler/Compiler/Compiler.csproj +++ b/src/QsCompiler/Compiler/Compiler.csproj @@ -14,7 +14,6 @@ - diff --git a/src/QsCompiler/Compiler/Compiler.nuspec.template b/src/QsCompiler/Compiler/Compiler.nuspec.template index 23c7798194..857dd2dc7c 100644 --- a/src/QsCompiler/Compiler/Compiler.nuspec.template +++ b/src/QsCompiler/Compiler/Compiler.nuspec.template @@ -13,12 +13,9 @@ See: https://docs.microsoft.com/azure/quantum/qdk-relnotes/ https://github.com/microsoft/qsharp-compiler - images\qdk-nuget-icon.png + https://secure.gravatar.com/avatar/bd1f02955b2853ba0a3b1cdc2434e8ec.png $copyright$ Quantum Q# QSharp - - - diff --git a/src/QsCompiler/Compiler/Logging.cs b/src/QsCompiler/Compiler/Logging.cs index 7ad998ede2..18d74c52fa 100644 --- a/src/QsCompiler/Compiler/Logging.cs +++ b/src/QsCompiler/Compiler/Logging.cs @@ -62,12 +62,17 @@ public LogTracker( /// Called whenever an exception is logged after the exception has been properly tracked. /// Prints the given exception as Hint if the logger verbosity is sufficiently high. /// - protected internal virtual void OnException(Exception ex) => + protected internal virtual void OnException(Exception ex) + { + var verbosity = this.Verbosity; + this.Verbosity = DiagnosticSeverity.Hint; this.Output(ex == null ? null : new Diagnostic { Severity = DiagnosticSeverity.Hint, Message = $"{Environment.NewLine}{ex}{Environment.NewLine}" }); + this.Verbosity = verbosity; + } // NB: Calling the LSP.Range constructor results in an object with // non-nullable fields set to null values, confusing other places diff --git a/src/QsCompiler/Compiler/PluginInterface.cs b/src/QsCompiler/Compiler/PluginInterface.cs index 538c10a81e..bb6f7c44d1 100644 --- a/src/QsCompiler/Compiler/PluginInterface.cs +++ b/src/QsCompiler/Compiler/PluginInterface.cs @@ -17,6 +17,12 @@ namespace Microsoft.Quantum.QsCompiler /// public static class RewriteStepPriorities { + /// + /// Priority of the built-in transformation that removes all + /// unused callables from the syntax tree. + /// + public const int SyntaxTreeTrimming = 1200; + /// /// Priority of the built-in transformation that replaces /// if-statements with the corresponding calls to built-in quantum operations if possible. @@ -52,12 +58,6 @@ public static class RewriteStepPriorities /// required by each callable. /// public const int CapabilityInference = 60; - - /// - /// Priority of the built-in transformation that creates a separate callable for each intrinsic - /// specialization and adds a TargetInstruction attribute if needed. - /// - public const int TargetInstructionSeparation = 25; } public interface IRewriteStep diff --git a/src/QsCompiler/Compiler/RewriteSteps/ExternalRewriteStepsManager.cs b/src/QsCompiler/Compiler/RewriteSteps/ExternalRewriteStepsManager.cs index 14b0fe8a03..cfede78406 100644 --- a/src/QsCompiler/Compiler/RewriteSteps/ExternalRewriteStepsManager.cs +++ b/src/QsCompiler/Compiler/RewriteSteps/ExternalRewriteStepsManager.cs @@ -52,7 +52,7 @@ internal static ImmutableArray Load(CompilationLoader.Configuration // We don't overwrite assembly properties specified by configuration. var defaultOutput = assemblyConstants.TryGetValue(AssemblyConstants.OutputPath, out var path) ? path : null; - assemblyConstants.TryAdd(AssemblyConstants.OutputPath, loaded.OutputFolder ?? defaultOutput ?? config.BuildOutputFolder); + assemblyConstants[AssemblyConstants.OutputPath] = loaded.OutputFolder ?? defaultOutput ?? config.BuildOutputFolder; assemblyConstants.TryAdd(AssemblyConstants.AssemblyName, config.ProjectNameWithoutPathOrExtension); } diff --git a/src/QsCompiler/Compiler/RewriteSteps/Monomorphization.cs b/src/QsCompiler/Compiler/RewriteSteps/Monomorphization.cs index cfe1aef6e9..534f65c505 100644 --- a/src/QsCompiler/Compiler/RewriteSteps/Monomorphization.cs +++ b/src/QsCompiler/Compiler/RewriteSteps/Monomorphization.cs @@ -14,7 +14,7 @@ namespace Microsoft.Quantum.QsCompiler.BuiltInRewriteSteps /// internal class Monomorphization : IRewriteStep { - private readonly bool keepAllIntrinsics; + private readonly bool monomorphizeIntrinsics; public string Name => "Monomorphization"; @@ -33,10 +33,10 @@ internal class Monomorphization : IRewriteStep /// /// Constructor for the Monomorphization Rewrite Step. /// - /// When true, intrinsics will not be removed as part of the rewrite step. - public Monomorphization(bool keepAllIntrinsics = true) + /// When true, intrinsics will be monomorphized as part of the rewrite step. + public Monomorphization(bool monomorphizeIntrinsics = false) { - this.keepAllIntrinsics = keepAllIntrinsics; + this.monomorphizeIntrinsics = monomorphizeIntrinsics; this.AssemblyConstants = new Dictionary(); } @@ -44,7 +44,7 @@ public Monomorphization(bool keepAllIntrinsics = true) public bool Transformation(QsCompilation compilation, out QsCompilation transformed) { - transformed = Monomorphize.Apply(compilation, this.keepAllIntrinsics); + transformed = Monomorphize.Apply(compilation, this.monomorphizeIntrinsics); return true; } @@ -52,7 +52,7 @@ public bool PostconditionVerification(QsCompilation compilation) { try { - ValidateMonomorphization.Apply(compilation); + ValidateMonomorphization.Apply(compilation, allowTypeParametersForIntrinsics: !this.monomorphizeIntrinsics); } catch { diff --git a/src/QsCompiler/Compiler/RewriteSteps/QirGeneration.cs b/src/QsCompiler/Compiler/RewriteSteps/QirGeneration.cs deleted file mode 100644 index 7c7e5b89b7..0000000000 --- a/src/QsCompiler/Compiler/RewriteSteps/QirGeneration.cs +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Collections.Generic; -using System.Reflection; -using Microsoft.CodeAnalysis; -using Microsoft.Quantum.QsCompiler.Diagnostics; -using Microsoft.Quantum.QsCompiler.QIR; -using Microsoft.Quantum.QsCompiler.SyntaxTree; -using Microsoft.Quantum.QsCompiler.Transformations.Monomorphization.Validation; - -namespace Microsoft.Quantum.QsCompiler.BuiltInRewriteSteps -{ - internal class QirGeneration : IRewriteStep - { - private readonly string outputFile; - - private readonly List diagnostics; - - public QirGeneration(string outputFileName) - { - this.outputFile = outputFileName; - this.diagnostics = new List(); - this.AssemblyConstants = new Dictionary(); - } - - /// - public string Name => "QIR Generation"; - - /// - public int Priority => -10; // currently not used - - /// - public IDictionary AssemblyConstants { get; } - - /// - public IEnumerable GeneratedDiagnostics => this.diagnostics; - - /// - public bool ImplementsPreconditionVerification => true; - - /// - public bool ImplementsTransformation => true; - - /// - public bool ImplementsPostconditionVerification => false; - - /// - public bool PreconditionVerification(QsCompilation compilation) - { - try - { - ValidateMonomorphization.Apply(compilation); - return true; - } - catch - { - this.diagnostics.Add(new IRewriteStep.Diagnostic - { - Severity = DiagnosticSeverity.Error, - Stage = IRewriteStep.Stage.PreconditionVerification, - Message = DiagnosticItem.Message(ErrorCode.SyntaxTreeNotMonomorphized, Array.Empty()), - Source = Assembly.GetExecutingAssembly().Location - }); - return false; - } - } - - /// - public bool Transformation(QsCompilation compilation, out QsCompilation transformed) - { - var generator = new Generator(compilation); - generator.Apply(); - generator.Emit(this.outputFile); - transformed = compilation; - return true; - } - - /// - public bool PostconditionVerification(QsCompilation compilation) => - throw new NotImplementedException(); - } -} diff --git a/src/QsCompiler/Compiler/RewriteSteps/SyntaxTreeTrimming.cs b/src/QsCompiler/Compiler/RewriteSteps/SyntaxTreeTrimming.cs new file mode 100644 index 0000000000..b0ea7a1cc4 --- /dev/null +++ b/src/QsCompiler/Compiler/RewriteSteps/SyntaxTreeTrimming.cs @@ -0,0 +1,54 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.Collections.Generic; +using System.Linq; +using Microsoft.Quantum.QsCompiler.SyntaxTree; +using Microsoft.Quantum.QsCompiler.Transformations.SyntaxTreeTrimming; + +namespace Microsoft.Quantum.QsCompiler.BuiltInRewriteSteps +{ + /// + /// Removes unused callables from the syntax tree. + /// + internal class SyntaxTreeTrimming : IRewriteStep + { + private readonly bool keepAllIntrinsics; + + public string Name => "Syntax Tree Trimming"; + + public int Priority => RewriteStepPriorities.SyntaxTreeTrimming; + + public IDictionary AssemblyConstants { get; } = new Dictionary(); + + public IEnumerable GeneratedDiagnostics => Enumerable.Empty(); + + public bool ImplementsPreconditionVerification => true; + + public bool ImplementsTransformation => true; + + public bool ImplementsPostconditionVerification => false; + + /// + /// Constructor for the SyntaxTreeTrimming Rewrite Step. + /// + /// When true, intrinsics will not be removed as part of the rewrite step. + public SyntaxTreeTrimming(bool keepAllIntrinsics = true) + { + this.keepAllIntrinsics = keepAllIntrinsics; + } + + public bool PreconditionVerification(QsCompilation compilation) => compilation.EntryPoints.Any(); + + public bool Transformation(QsCompilation compilation, out QsCompilation transformed) + { + transformed = TrimSyntaxTree.Apply(compilation, this.keepAllIntrinsics); + return true; + } + + public bool PostconditionVerification(QsCompilation compilation) + { + throw new System.NotImplementedException(); + } + } +} diff --git a/src/QsCompiler/Compiler/RewriteSteps/TargetInstructionInference.cs b/src/QsCompiler/Compiler/RewriteSteps/TargetInstructionInference.cs deleted file mode 100644 index 43c1d418af..0000000000 --- a/src/QsCompiler/Compiler/RewriteSteps/TargetInstructionInference.cs +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Linq; -using Microsoft.CodeAnalysis; -using Microsoft.Quantum.QsCompiler.Diagnostics; -using Microsoft.Quantum.QsCompiler.SyntaxTree; -using Microsoft.Quantum.QsCompiler.Transformations.Targeting; - -namespace Microsoft.Quantum.QsCompiler.BuiltInRewriteSteps -{ - /// - /// Creates a separate callable for each intrinsic specialization. - /// 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. - /// Generates a warning without failing the transformation if some attributes could not be added. - /// Leaves any type parameterized callables and type constructors unmodified. - /// - /// - /// An intrinsic callable contains non-intrinsic specializations - /// or a non-intrinsic callable contains intrinsic specializations, - /// or the a callable doesn't have a body specialization. - /// - internal class TargetInstructionInference : IRewriteStep - { - private readonly List diagnostics = new List(); - - public TargetInstructionInference() - { - this.diagnostics = new List(); - this.AssemblyConstants = new Dictionary(); - } - - /// - public string Name => "Target Instruction Separation"; - - /// - public int Priority => RewriteStepPriorities.TargetInstructionSeparation; - - /// - public IDictionary AssemblyConstants { get; } - - /// - public IEnumerable GeneratedDiagnostics => this.diagnostics; - - /// - public bool ImplementsPreconditionVerification => true; - - /// - public bool ImplementsTransformation => true; - - /// - public bool ImplementsPostconditionVerification => false; - - /// - 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 Transformation(QsCompilation compilation, out QsCompilation transformed) - { - transformed = InferTargetInstructions.ReplaceSelfAdjointSpecializations(compilation); - transformed = InferTargetInstructions.LiftIntrinsicSpecializations(transformed); - var allAttributesAdded = InferTargetInstructions.TryAddMissingTargetInstructionAttributes(transformed, out transformed); - if (!allAttributesAdded) - { - this.diagnostics.Add(new IRewriteStep.Diagnostic - { - Severity = DiagnosticSeverity.Warning, - Message = DiagnosticItem.Message(WarningCode.MissingTargetInstructionName, Array.Empty()), - Stage = IRewriteStep.Stage.Transformation, - }); - } - return true; - } - - /// - public bool PostconditionVerification(QsCompilation compilation) => - throw new NotImplementedException(); - } -} diff --git a/src/QsCompiler/Core/Dependencies.fs b/src/QsCompiler/Core/Dependencies.fs index 0203b96384..4f79929214 100644 --- a/src/QsCompiler/Core/Dependencies.fs +++ b/src/QsCompiler/Core/Dependencies.fs @@ -41,6 +41,57 @@ type BuiltIn = static member RewriteStepDependencies = ImmutableHashSet.Create(BuiltIn.RangeReverse.FullName, BuiltIn.Length.FullName) + /// The set of all built in callables and attributes + static member AllBuiltIns = + [| + // dependencies in Microsoft.Quantum.Core + BuiltIn.Length + BuiltIn.RangeStart + BuiltIn.RangeStep + BuiltIn.RangeEnd + BuiltIn.RangeReverse + BuiltIn.Attribute + BuiltIn.EntryPoint + BuiltIn.Deprecated + BuiltIn.Inline + // dependencies in Microsoft.Quantum.Targeting + BuiltIn.TargetInstruction + BuiltIn.RequiresCapability + // dependencies in Microsoft.Quantum.Diagnostics + BuiltIn.Test + BuiltIn.EnableTestingViaName + BuiltIn.DumpMachine + BuiltIn.DumpRegister + // dependencies in Microsoft.Quantum.Canon + BuiltIn.NoOp + // dependencies in Microsoft.Quantum.Convert + BuiltIn.IntAsDouble + BuiltIn.DoubleAsInt + // ToDo: Uncomment once BigInts are supported in QIR + //BuiltIn.IntAsBigInt + // dependencies in Microsoft.Quantum.Math + BuiltIn.Truncate + BuiltIn.ApplyConditionally + BuiltIn.ApplyConditionallyA + BuiltIn.ApplyConditionallyC + BuiltIn.ApplyConditionallyCA + BuiltIn.ApplyIfZero + BuiltIn.ApplyIfZeroA + BuiltIn.ApplyIfZeroC + BuiltIn.ApplyIfZeroCA + BuiltIn.ApplyIfOne + BuiltIn.ApplyIfOneA + BuiltIn.ApplyIfOneC + BuiltIn.ApplyIfOneCA + BuiltIn.ApplyIfElseR + BuiltIn.ApplyIfElseRA + BuiltIn.ApplyIfElseRC + BuiltIn.ApplyIfElseRCA + // dependencies in other namespaces (e.g. things used for code actions) + BuiltIn.IndexRange + |] + |> ImmutableHashSet.Create + /// Returns true if the given attribute marks the corresponding declaration as entry point. static member MarksEntryPoint(att: QsDeclarationAttribute) = match att.TypeId with @@ -162,6 +213,18 @@ type BuiltIn = static member EnableTestingViaName = { FullName = { Name = "EnableTestingViaName"; Namespace = BuiltIn.DiagnosticsNamespace }; Kind = Attribute } + static member DumpMachine = + { + FullName = { Name = "DumpMachine"; Namespace = BuiltIn.DiagnosticsNamespace } + Kind = Function(TypeParameters = ImmutableArray.Create "T") + } + + static member DumpRegister = + { + FullName = { Name = "DumpRegister"; Namespace = BuiltIn.DiagnosticsNamespace } + Kind = Function(TypeParameters = ImmutableArray.Create "T") + } + // dependencies in Microsoft.Quantum.Canon static member NoOp = diff --git a/src/QsCompiler/DataStructures/Diagnostics.fs b/src/QsCompiler/DataStructures/Diagnostics.fs index 0e1e89c242..bbbe924090 100644 --- a/src/QsCompiler/DataStructures/Diagnostics.fs +++ b/src/QsCompiler/DataStructures/Diagnostics.fs @@ -318,6 +318,8 @@ type ErrorCode = | PreEvaluationFailed = 7111 | RewriteStepExecutionFailed = 7112 | PostconditionVerificationFailed = 7113 + // the corresponding warning code exists + | PreconditionVerificationFailed = 7202 | CsharpGenerationGeneratedError = 8001 | QirEmissionGeneratedError = 8002 @@ -378,6 +380,7 @@ type WarningCode = | UnresolvedItemsInGeneratedQs = 7101 | RewriteStepDiagnosticsGenerationFailed = 7201 + // the corresponding error code exists | PreconditionVerificationFailed = 7202 | RewriteStepLoadedViaReflection = 7203 | FailedToLoadRewriteStepViaReflection = 7204 @@ -881,6 +884,8 @@ type DiagnosticItem = "Executing the transformation for the compilation step \"{0}\" loaded from \"{1}\" failed." | ErrorCode.PostconditionVerificationFailed -> "The postcondition for the compilation step \"{0}\" loaded from \"{1}\" was not satisfied. The transformation has produced incorrect output and should be excluded from the compilation process." + | ErrorCode.PreconditionVerificationFailed -> + "The precondition for the compilation step \"{0}\" loaded from \"{1}\" was not met." | ErrorCode.CsharpGenerationGeneratedError -> "" | ErrorCode.QirEmissionGeneratedError -> "" diff --git a/src/QsCompiler/DataStructures/ReservedKeywords.fs b/src/QsCompiler/DataStructures/ReservedKeywords.fs index ce84373328..ad69423953 100644 --- a/src/QsCompiler/DataStructures/ReservedKeywords.fs +++ b/src/QsCompiler/DataStructures/ReservedKeywords.fs @@ -298,8 +298,11 @@ module DotnetCoreDll = let ResourceName = "__qsharp_data__.bson" let ResourceNameQsDataBondV1 = "__qsharp_data_bond_v1__.bson" + let ResourceNameQsDataQirV1 = "__qsharp_data_qir_v1__.bc" // Should always provide the name of the resource currently used by the compiler to attach the syntax tree to a DLL. let SyntaxTreeResourceName = ResourceNameQsDataBondV1 + // Should always provide the name of the resource currently used by the compiler to attach the qir bitcode to a DLL. + let QirResourceName = ResourceNameQsDataQirV1 let MetadataNamespace = "__qsharp__" let ReferenceAlias = "__qsharp_reference__" let MetadataType = "Metadata" diff --git a/src/QsCompiler/LlvmBindings/LlvmBindings.csproj b/src/QsCompiler/LlvmBindings/LlvmBindings.csproj index 9381c68aed..612f63cfe6 100644 --- a/src/QsCompiler/LlvmBindings/LlvmBindings.csproj +++ b/src/QsCompiler/LlvmBindings/LlvmBindings.csproj @@ -4,6 +4,7 @@ netstandard2.1 true + Microsoft.Quantum.LlvmBindings $(NoWarn);SA1636 $(NoWarn);CS1574 diff --git a/src/QsCompiler/QirGeneration/Context.cs b/src/QsCompiler/QirGeneration/Context.cs index 211bd22199..24d7d1e422 100644 --- a/src/QsCompiler/QirGeneration/Context.cs +++ b/src/QsCompiler/QirGeneration/Context.cs @@ -5,12 +5,12 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics.CodeAnalysis; -using System.IO; using System.Linq; using Microsoft.Quantum.QIR; using Microsoft.Quantum.QIR.Emission; using Microsoft.Quantum.QsCompiler.SyntaxTokens; using Microsoft.Quantum.QsCompiler.SyntaxTree; +using Microsoft.Quantum.QsCompiler.Transformations.QsCodeOutput; using Microsoft.Quantum.QsCompiler.Transformations.Targeting; using Ubiquity.NET.Llvm; using Ubiquity.NET.Llvm.Instructions; @@ -112,7 +112,9 @@ static GenerationContext() private readonly List<(IrFunction, Action>)> liftedPartialApplications = new List<(IrFunction, Action>)>(); private readonly Dictionary callableTables = new Dictionary(); + private readonly List pendingCallableTables = new List(); private readonly Dictionary memoryManagementTables = new Dictionary(); + private readonly List pendingMemoryManagementTables = new List(); #endregion @@ -380,6 +382,9 @@ public void InitializeRuntimeLibrary() /// public void RegisterQuantumInstructionSet() { + this.quantumInstructionSet.AddFunction(QuantumInstructionSet.DumpMachine, this.Context.VoidType, this.Context.Int8Type.CreatePointerType()); + this.quantumInstructionSet.AddFunction(QuantumInstructionSet.DumpRegister, this.Context.VoidType, this.Context.Int8Type.CreatePointerType(), this.Types.Array); + foreach (var c in this.globalCallables.Values) { if (TryGetTargetInstructionName(c, out var name)) @@ -458,29 +463,6 @@ IrFunction EntryPoint(QsCallable callable, IrFunction implementation) => this.CreateBridgeFunction(qualifiedName, QsSpecializationKind.QsBody, EntryPoint, AttributeNames.EntryPoint); } - /// - /// Writes the current content to the output file. - /// - public void Emit(string fileName, bool overwrite = true) - { - if (!overwrite && File.Exists(fileName)) - { - throw new ArgumentException($"The file \"{fileName}\" already exist(s)."); - } - - this.GenerateRequiredFunctions(); - - if (!this.Module.Verify(out string validationErrors)) - { - File.WriteAllText(fileName, $"LLVM errors:{Environment.NewLine}{validationErrors}"); - } - - if (!this.Module.WriteToTextFile(fileName, out string errorMessage)) - { - throw new IOException(errorMessage); - } - } - #endregion #region Look-up @@ -549,7 +531,7 @@ internal void StartFunction() /// /// true if the function has been properly ended /// The current function or the current block is set to null. - internal bool EndFunction() + internal bool EndFunction(bool generatePending = false) { if (this.CurrentFunction == null || this.CurrentBlock == null) { @@ -563,6 +545,10 @@ internal bool EndFunction() this.CurrentBuilder.Return(); } + if (generatePending) + { + this.GenerateRequiredFunctions(); + } return this.ScopeMgr.IsEmpty && !this.inlineLevels.Any(); } @@ -868,6 +854,7 @@ internal GlobalVariable GetOrCreateCallableTable(QsCallable callable) : null; var table = this.CreateCallableTable(key, BuildSpec); this.callableTables.Add(key, (callable, table)); + this.pendingCallableTables.Add(key); return table; } } @@ -906,6 +893,7 @@ internal Constant GetOrCreateCallableMemoryManagementTable(TupleValue? capture) var array = ConstantArray.From(this.Types.CaptureCountFunction.CreatePointerType(), funcs); table = this.Module.AddGlobal(array.NativeType, true, Linkage.DllExport, array, name); this.memoryManagementTables.Add(type, table); + this.pendingMemoryManagementTables.Add(type); return table; } @@ -913,6 +901,8 @@ internal Constant GetOrCreateCallableMemoryManagementTable(TupleValue? capture) /// Sets the current function to the given one and sets the parameter names to the given names. /// Populates the body of the given function by invoking the given action with the function parameters. /// If the current block after the invokation is not terminated, adds a void return. + /// Does *not* generate any required functions that have been added by ; + /// it is up to the caller to ensure that the necessary functions are created. /// internal void GenerateFunction(IrFunction func, string?[] argNames, Action> executeBody) { @@ -936,7 +926,7 @@ internal void GenerateFunction(IrFunction func, string?[] argNames, Action @@ -963,7 +953,7 @@ internal void GenerateFunction(IrFunction func, string?[] argNames, Action - private void GenerateRequiredFunctions() + internal void GenerateRequiredFunctions() { TupleValue GetArgumentTuple(ResolvedType type, Value argTuple) { @@ -1018,14 +1008,14 @@ Value GenerateBaseMethodCall(QsCallable callable, QsSpecializationKind specKind, } else { - return this.TryGetFunction(callable.FullName, specKind, out IrFunction? func) - ? this.CurrentBuilder.Call(func, args) - : throw new InvalidOperationException($"No function defined for {callable.FullName} {specKind}"); + var func = this.GetFunctionByName(callable.FullName, specKind); + return this.CurrentBuilder.Call(func, args); } } - foreach (var (callable, _) in this.callableTables.Values) + foreach (var key in this.pendingCallableTables) { + var (callable, _) = this.callableTables[key]; foreach (var spec in callable.Specializations) { var fullName = FunctionWrapperName(callable.FullName, spec.Kind); @@ -1048,14 +1038,17 @@ Value GenerateBaseMethodCall(QsCallable callable, QsSpecializationKind specKind, } } } + this.pendingCallableTables.Clear(); foreach (var (func, body) in this.liftedPartialApplications) { this.GenerateFunction(func, new[] { "capture-tuple", "arg-tuple", "result-tuple" }, body); } + this.liftedPartialApplications.Clear(); - foreach (var (type, table) in this.memoryManagementTables) + foreach (var type in this.pendingMemoryManagementTables) { + var table = this.memoryManagementTables[type]; var functions = new List<(string, Action)> { ($"{table.Name}__RefCount", (change, capture) => this.ScopeMgr.UpdateReferenceCount(change, capture)), @@ -1078,6 +1071,7 @@ Value GenerateBaseMethodCall(QsCallable callable, QsSpecializationKind specKind, } } } + this.pendingMemoryManagementTables.Clear(); } #endregion @@ -1289,6 +1283,15 @@ void ExecuteBody(Value loopVariable) => #region Type helpers + /// + /// Bitcasts the given value to the expected type if needed. + /// Does nothing if the native type of the value already matches the expected type. + /// + internal Value CastToType(Value value, ITypeRef expectedType) => + value.NativeType.Equals(expectedType) + ? value + : this.CurrentBuilder.BitCast(value, expectedType); + /// The kind of the Q# type on top of the expression type stack internal ResolvedType CurrentExpressionType() => this.ExpressionTypeStack.Peek(); @@ -1307,7 +1310,8 @@ internal ITypeRef LlvmTypeFromQsharpType(ResolvedType resolvedType) { this.BuiltType = null; this.Transformation.Types.OnType(resolvedType); - return this.BuiltType ?? throw new NotImplementedException("Llvm type could not be constructed"); + return this.BuiltType ?? throw new NotImplementedException( + $"Llvm type for {SyntaxTreeToQsharp.Default.ToCode(resolvedType)} could not be constructed."); } /// diff --git a/src/QsCompiler/QirGeneration/FindNuspecReferences.ps1 b/src/QsCompiler/QirGeneration/FindNuspecReferences.ps1 new file mode 100644 index 0000000000..d7856b4fcd --- /dev/null +++ b/src/QsCompiler/QirGeneration/FindNuspecReferences.ps1 @@ -0,0 +1,61 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +######################################## +# When creating a package with dotnet pack, nuget changes every ProjectReference to be itself +# a PackageReference without checking if that project has a corresponding package. +# This is problematic because we don't want to create a separate package the dlls in the QIR emission. +# On the other hand, when creating a package using nuget pack, nuget does not +# identifies PackageReferences defined in the project file, so all the dependencies need to be +# explicitly listed for the package to work. +# +# We don't want to hardcode the list of dependencies on the .nuspec, as they can quickly become out-of-sync. +# This script will find the PackageReferences recursively on the Compiler project and add them +# to its nuspec, so we can then create the package using nuget pack with the corresponding dependencies listed. +# +# nuget is tracking this problem at: https://github.com/NuGet/Home/issues/4491 +######################################## + +# Start with the nuspec template +$nuspec = [xml](Get-Content "QirGeneration.nuspec.template") +$dep = $nuspec.CreateElement('dependencies', $nuspec.package.metadata.NamespaceURI) + + +# Recursively find PackageReferences on all ProjectReferences: +function Add-NuGetDependencyFromCsprojToNuspec($PathToCsproj) +{ + $csproj = [xml](Get-Content $PathToCsproj) + + # Find all PackageReferences nodes: + $packageDependency = $csproj.Project.ItemGroup.PackageReference | Where-Object { $null -ne $_ } + $packageDependency | ForEach-Object { + # Identify package's id either from "Include" or "Update" attribute: + $id = $_.Include + if ($id -eq $null -or $id -eq "") { + $id = $_.Update + } + + # Check if package already added as dependency, only add if new: + $added = $dep.dependency | Where { $_.id -eq $id } + if (!$added -and $_.PrivateAssets -ne "All") { + Write-Host "Adding $id" + $onedependency = $dep.AppendChild($nuspec.CreateElement('dependency', $nuspec.package.metadata.NamespaceURI)) + $onedependency.SetAttribute('id', $id) + $onedependency.SetAttribute('version', $_.Version) + } + } +} + +# Find all package dependencies on QirGeneration.csproj, +# and add the compiler as a package dependency instead. +# The llvm bindings need to be published before including them in the package, +# and are hence already included by the template. +Add-NuGetDependencyFromCsprojToNuspec "QirGeneration.csproj" $dep +$dependency = $dep.AppendChild($nuspec.CreateElement('dependency', $nuspec.package.metadata.NamespaceURI)) +$dependency.SetAttribute('id', 'Microsoft.Quantum.Compiler') +$dependency.SetAttribute('version', '$version$') + + +# Save into .nuspec file: +$nuspec.package.metadata.AppendChild($dep) +$nuspec.Save("$PSScriptRoot\QirGeneration.nuspec") diff --git a/src/QsCompiler/QirGeneration/FunctionLibrary.cs b/src/QsCompiler/QirGeneration/FunctionLibrary.cs index 7f3bf088da..b80332097c 100644 --- a/src/QsCompiler/QirGeneration/FunctionLibrary.cs +++ b/src/QsCompiler/QirGeneration/FunctionLibrary.cs @@ -23,10 +23,11 @@ public class FunctionLibrary : IEnumerable> private readonly Func nameMapper; /// + /// Initializes a new instance of the class. /// Constructs a new function library. /// - /// The LLVM module in which the functions will be declared and/or defined - /// A function that maps the short name of the function into a mangled name + /// The LLVM module in which the functions will be declared and/or defined. + /// A function that maps the short name of the function into a mangled name. public FunctionLibrary(BitcodeModule mod, Func mapper) { this.module = mod; @@ -38,12 +39,12 @@ public FunctionLibrary(BitcodeModule mod, Func mapper) /// This doesn't actually create a declaration for the function; instead, it records all of the /// required information so that the declaration can be created on demand. /// - /// The simple, unmangled name of the function - /// The return type of the function - /// The types of the function's arguments, as an array + /// The simple, unmangled name of the function. + /// The return type of the function. + /// The types of the function's arguments, as an array. public void AddFunction(string name, ITypeRef returnType, params ITypeRef[] argTypes) { - this.runtimeFunctions[name] = this.module.Context.GetFunctionType(returnType, argTypes); + this.runtimeFunctions.Add(name, this.module.Context.GetFunctionType(returnType, argTypes)); } /// @@ -51,20 +52,20 @@ public void AddFunction(string name, ITypeRef returnType, params ITypeRef[] argT /// This doesn't actually create a declaration for the function; instead, it records all of the /// required information so that the declaration can be created on demand. /// - /// The simple, unmangled name of the function - /// The return type of the function - /// The types of the function's fixed arguments, as an array + /// The simple, unmangled name of the function. + /// The return type of the function. + /// The types of the function's fixed arguments, as an array. public void AddVarArgsFunction(string name, ITypeRef returnType, params ITypeRef[] argTypes) { - this.runtimeFunctions[name] = this.module.Context.GetFunctionType(returnType, argTypes, true); + this.runtimeFunctions.Add(name, this.module.Context.GetFunctionType(returnType, argTypes, true)); } /// /// Gets a reference to a function. /// If the function has not already been declared, a new declaration is generated for it. /// - /// The simple, unmangled name of the function - /// The object that represents the function + /// The simple, unmangled name of the function. + /// The object that represents the function. public IrFunction GetOrCreateFunction(string name) { var mappedName = this.nameMapper(name); @@ -119,7 +120,7 @@ public void Dispose() /// The enumerator returns KeyValuePairs with the base name of the function as /// key and the actual LLVM function object as the value. /// - /// The enumerator + /// The enumerator. public IEnumerator> GetEnumerator() => new LibEnumerator(this.usedRuntimeFunctions); @@ -129,7 +130,7 @@ public IEnumerator> GetEnumerator() => /// The enumerator returns KeyValuePairs with the base name of the function as /// key and the actual LLVM function object as the value. /// - /// The enumerator + /// The enumerator. IEnumerator IEnumerable.GetEnumerator() => new LibEnumerator(this.usedRuntimeFunctions); } } diff --git a/src/QsCompiler/QirGeneration/Generator.cs b/src/QsCompiler/QirGeneration/Generator.cs index 552ac51c02..881b533649 100644 --- a/src/QsCompiler/QirGeneration/Generator.cs +++ b/src/QsCompiler/QirGeneration/Generator.cs @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +using System; +using System.IO; using Microsoft.Quantum.QIR; using Microsoft.Quantum.QsCompiler.SyntaxTree; using Microsoft.Quantum.QsCompiler.Transformations.Core; @@ -68,16 +70,36 @@ public void Apply() this.SharedState.CreateInteropFriendlyWrapper(epName); this.SharedState.CreateEntryPoint(epName); } + + this.SharedState.GenerateRequiredFunctions(); } /// /// Writes the current content to the output file. /// - /// - /// The file to which the output is written. The file extension is replaced with a .ll extension. - /// + /// The file to which the output is written. + /// False if the file should be human readable, true if the file should contain bitcode. /// Whether or not to overwrite a file if it already exists. - public void Emit(string fileName, bool overwrite = true) => - this.SharedState.Emit(fileName, overwrite: overwrite); + public void Emit(string fileName, bool emitBitcode = false, bool overwrite = true) + { + if (!overwrite && File.Exists(fileName)) + { + throw new ArgumentException($"The file \"{fileName}\" already exist(s)."); + } + + if (!this.SharedState.Module.Verify(out string validationErrors)) + { + File.WriteAllText(fileName, $"LLVM errors:{Environment.NewLine}{validationErrors}"); + } + + if (emitBitcode) + { + this.SharedState.Module.WriteToFile(fileName); + } + else if (!this.SharedState.Module.WriteToTextFile(fileName, out string errorMessage)) + { + throw new IOException(errorMessage); + } + } } } diff --git a/src/QsCompiler/QirGeneration/Interop.cs b/src/QsCompiler/QirGeneration/Interop.cs index 662a30b373..deac963396 100644 --- a/src/QsCompiler/QirGeneration/Interop.cs +++ b/src/QsCompiler/QirGeneration/Interop.cs @@ -61,15 +61,6 @@ private static TOut[] WithoutNullValues(Func map, IEnumer where TOut : class => items.Select(map).Where(i => i != null).Select(i => i!).ToArray(); - /// - /// Bitcasts the given value to the expected type if needed. - /// Does nothing if the native type of the value already matches the expected type. - /// - private Value CastToType(Value value, ITypeRef expectedType) => - value.NativeType.Equals(expectedType) - ? value - : this.sharedState.CurrentBuilder.BitCast(value, expectedType); - /// private ITypeRef? MapToInteropType(ResolvedType type) => this.MapToInteropType(this.sharedState.LlvmTypeFromQsharpType(type)); @@ -263,7 +254,7 @@ void PopulateItem(Value index) { // bitcast to the correct type and return var expectedArgType = this.sharedState.LlvmTypeFromQsharpType(type); - var argValue = this.CastToType(givenValue, expectedArgType); + var argValue = this.sharedState.CastToType(givenValue, expectedArgType); return this.sharedState.Values.From(argValue, type); } } @@ -328,7 +319,7 @@ Value PopulateStruct(IPointerType mappedType, Value[] tupleItems) for (var itemIdx = 0; itemIdx < mappedStructType.Members.Count; ++itemIdx) { var itemPtr = this.sharedState.CurrentBuilder.GetElementPtr(mappedStructType, mappedTuple, this.PointerIndex(itemIdx)); - var tupleItem = this.CastToType(tupleItems[itemIdx], mappedStructType.Members[itemIdx]); + var tupleItem = this.sharedState.CastToType(tupleItems[itemIdx], mappedStructType.Members[itemIdx]); this.sharedState.CurrentBuilder.Store(tupleItem, itemPtr); } return mappedTuple; @@ -433,7 +424,7 @@ void PopulateItem(Value index) // callables and qubits var expectedType = this.MapToInteropType(res.LlvmType)!; this.sharedState.ScopeMgr.IncreaseReferenceCount(res); - return this.CastToType(res.Value, expectedType); + return this.sharedState.CastToType(res.Value, expectedType); } } diff --git a/src/QsCompiler/QirGeneration/QIR/Functions.cs b/src/QsCompiler/QirGeneration/QIR/Functions.cs index b9934ca80b..a6d48d6182 100644 --- a/src/QsCompiler/QirGeneration/QIR/Functions.cs +++ b/src/QsCompiler/QirGeneration/QIR/Functions.cs @@ -8,6 +8,7 @@ using Microsoft.Quantum.QsCompiler.QIR; using Microsoft.Quantum.QsCompiler.SyntaxTokens; using Microsoft.Quantum.QsCompiler.SyntaxTree; +using Microsoft.Quantum.QsCompiler.Transformations.SearchAndReplace; using Ubiquity.NET.Llvm.Values; namespace Microsoft.Quantum.QIR @@ -37,10 +38,9 @@ internal class Functions private static readonly ResolvedType Int = ResolvedType.New(ResolvedTypeKind.Int); private static readonly ResolvedType BigInt = ResolvedType.New(ResolvedTypeKind.BigInt); private static readonly ResolvedType Double = ResolvedType.New(ResolvedTypeKind.Double); - private static readonly ResolvedType Range = ResolvedType.New(ResolvedTypeKind.Range); private readonly GenerationContext sharedState; - internal readonly ImmutableDictionary> BuiltIn; + private readonly ImmutableDictionary> builtIn; public Functions(GenerationContext sharedState) { @@ -55,9 +55,11 @@ public Functions(GenerationContext sharedState) dict.Add(QsCompiler.BuiltIn.RangeReverse.FullName, this.RangeReverse); dict.Add(QsCompiler.BuiltIn.Message.FullName, this.Message); dict.Add(QsCompiler.BuiltIn.Truncate.FullName, this.DoubleAsInt); // This redundancy needs to be eliminated in the Q# libraries. + dict.Add(QsCompiler.BuiltIn.DumpMachine.FullName, this.DumpMachine); + dict.Add(QsCompiler.BuiltIn.DumpRegister.FullName, this.DumpRegister); this.sharedState = sharedState; - this.BuiltIn = dict.ToImmutable(); + this.builtIn = dict.ToImmutable(); } // static methods @@ -81,6 +83,32 @@ public Functions(GenerationContext sharedState) // public and internal methods + /// + /// True, if the callable with the given name is handled by QIR emission + /// and does not need to be declared within QIR or implemented by the runtime. + /// + public bool IsBuiltIn(QsQualifiedName name) => + this.builtIn.ContainsKey(NameDecorator.OriginalNameFromMonomorphized(name)); + + /// + /// The result of the evaluation if the given name matches one of the recognized runtime functions, + /// and null otherwise. + /// + internal bool TryEvaluate(QsQualifiedName name, TypedExpression arg, [MaybeNullWhen(false)] out IValue evaluated) + { + var unmangledName = NameDecorator.OriginalNameFromMonomorphized(name); + if (this.builtIn.TryGetValue(unmangledName, out var function)) + { + evaluated = function(arg); + return true; + } + else + { + evaluated = null; + return false; + } + } + /// The range expression for which to create the access functions /// /// Three functions to access the start, step, and end of a range. @@ -119,24 +147,6 @@ public Functions(GenerationContext sharedState) return (startValue, stepValue, endValue); } - /// - /// The result of the evaluation if the given name matches one of the recognized runtime functions, - /// and null otherwise. - /// - internal bool TryEvaluate(QsQualifiedName name, TypedExpression arg, [MaybeNullWhen(false)] out IValue evaluated) - { - if (this.BuiltIn.TryGetValue(name, out var function)) - { - evaluated = function(arg); - return true; - } - else - { - evaluated = null; - return false; - } - } - // private methods private IValue Length(TypedExpression arg) @@ -212,5 +222,50 @@ private IValue Message(TypedExpression arg) this.sharedState.CurrentBuilder.Call(message, value.Value); return this.sharedState.Values.Unit; } + + private IValue DumpMachine(TypedExpression arg) + { + var value = this.sharedState.EvaluateSubexpression(arg).Value; + if (!value.NativeType.IsPointer) + { + var pointer = this.sharedState.CurrentBuilder.Alloca(value.NativeType); + this.sharedState.CurrentBuilder.Store(value, pointer); + value = pointer; + } + + var dump = this.sharedState.GetOrCreateTargetInstruction(QuantumInstructionSet.DumpMachine); + value = this.sharedState.CastToType(value, this.sharedState.Context.Int8Type.CreatePointerType()); + this.sharedState.CurrentBuilder.Call(dump, value); + return this.sharedState.Values.Unit; + } + + private IValue DumpRegister(TypedExpression arg) + { + Value arg1; + Value arg2; + if (arg.Expression is ResolvedExpressionKind.ValueTuple vs) + { + arg1 = this.sharedState.EvaluateSubexpression(vs.Item[0]).Value; + arg2 = this.sharedState.EvaluateSubexpression(vs.Item[1]).Value; + } + else + { + var argTuple = (TupleValue)this.sharedState.EvaluateSubexpression(arg); + arg1 = argTuple.GetTupleElement(1).Value; + arg2 = argTuple.GetTupleElement(2).Value; + } + + if (!arg1.NativeType.IsPointer) + { + var pointer = this.sharedState.CurrentBuilder.Alloca(arg1.NativeType); + this.sharedState.CurrentBuilder.Store(arg1, pointer); + arg1 = pointer; + } + + var dump = this.sharedState.GetOrCreateTargetInstruction(QuantumInstructionSet.DumpRegister); + arg1 = this.sharedState.CastToType(arg1, this.sharedState.Context.Int8Type.CreatePointerType()); + this.sharedState.CurrentBuilder.Call(dump, arg1, arg2); + return this.sharedState.Values.Unit; + } } } diff --git a/src/QsCompiler/QirGeneration/QIR/RuntimeLibrary.cs b/src/QsCompiler/QirGeneration/QIR/RuntimeLibrary.cs index 2da2b46b2c..183fa43997 100644 --- a/src/QsCompiler/QirGeneration/QIR/RuntimeLibrary.cs +++ b/src/QsCompiler/QirGeneration/QIR/RuntimeLibrary.cs @@ -8,7 +8,7 @@ namespace Microsoft.Quantum.QIR /// public static class RuntimeLibrary { - // Q# specific helpers + // Q# specific helpers (not part of QIR spec and hence to be kept internal) internal const string HeapAllocate = "memory_allocate"; // result functions @@ -95,4 +95,15 @@ public static class RuntimeLibrary public const string Fail = "fail"; public const string Message = "message"; } + + /// + /// Static class that contains the names of runtime function that implement + /// callables that are part of the quantum instruction set (not part of the QIR specs) + /// and require special handling. + /// + internal static class QuantumInstructionSet + { + internal const string DumpMachine = "dumpmachine__body"; + internal const string DumpRegister = "dumpregister__body"; + } } diff --git a/src/QsCompiler/QirGeneration/QirGeneration.csproj b/src/QsCompiler/QirGeneration/QirGeneration.csproj index e48a59e5f5..8ac18dbec8 100644 --- a/src/QsCompiler/QirGeneration/QirGeneration.csproj +++ b/src/QsCompiler/QirGeneration/QirGeneration.csproj @@ -8,15 +8,10 @@ - + - - - - - diff --git a/src/QsCompiler/QirGeneration/QirGeneration.nuspec.template b/src/QsCompiler/QirGeneration/QirGeneration.nuspec.template new file mode 100644 index 0000000000..7e7adb5384 --- /dev/null +++ b/src/QsCompiler/QirGeneration/QirGeneration.nuspec.template @@ -0,0 +1,25 @@ + + + + Microsoft.Quantum.QirGeneration + $version$ + $title$ + Microsoft + QuantumEngineering, Microsoft + + MIT + false + Q# compiler extension for QIR emission. + + See: https://docs.microsoft.com/en-us/quantum/relnotes/ + https://github.com/microsoft/qsharp-compiler + https://secure.gravatar.com/avatar/bd1f02955b2853ba0a3b1cdc2434e8ec.png + + $copyright$ + Quantum Q# QSharp QIR + + + + + + diff --git a/src/QsCompiler/QirGeneration/QirGeneration.props b/src/QsCompiler/QirGeneration/QirGeneration.props new file mode 100644 index 0000000000..f17a50836c --- /dev/null +++ b/src/QsCompiler/QirGeneration/QirGeneration.props @@ -0,0 +1,10 @@ + + + + + + $(MSBuildThisFileDirectory)/../lib/netstandard2.1/Microsoft.Quantum.QirGeneration.dll + + + + diff --git a/src/QsCompiler/QirGeneration/RewriteSteps.cs b/src/QsCompiler/QirGeneration/RewriteSteps.cs new file mode 100644 index 0000000000..4c26e9c0c4 --- /dev/null +++ b/src/QsCompiler/QirGeneration/RewriteSteps.cs @@ -0,0 +1,175 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.IO; +using System.Linq; +using System.Reflection; +using Microsoft.CodeAnalysis; +using Microsoft.Quantum.QsCompiler.Diagnostics; +using Microsoft.Quantum.QsCompiler.QIR; +using Microsoft.Quantum.QsCompiler.SyntaxTree; +using Microsoft.Quantum.QsCompiler.Transformations.Monomorphization.Validation; +using Microsoft.Quantum.QsCompiler.Transformations.Targeting; + +namespace Microsoft.Quantum.QsCompiler +{ + internal class QirGeneration : IRewriteStep + { + internal static int EmissionPriority = -10; + private readonly List diagnostics; + + public QirGeneration() + { + this.diagnostics = new List(); + this.AssemblyConstants = new Dictionary(); + } + + /// + public string Name => "QIR Generation"; + + /// + public int Priority => EmissionPriority; + + /// + public IDictionary AssemblyConstants { get; } + + /// + public IEnumerable GeneratedDiagnostics => this.diagnostics; + + /// + public bool ImplementsPreconditionVerification => true; + + /// + public bool ImplementsTransformation => true; + + /// + public bool ImplementsPostconditionVerification => false; + + /// + public bool PreconditionVerification(QsCompilation compilation) + { + try + { + ValidateMonomorphization.Apply(compilation); + return true; + } + catch + { + this.diagnostics.Add(new IRewriteStep.Diagnostic + { + Severity = DiagnosticSeverity.Error, + Stage = IRewriteStep.Stage.PreconditionVerification, + Message = DiagnosticItem.Message(ErrorCode.SyntaxTreeNotMonomorphized, Array.Empty()), + Source = Assembly.GetExecutingAssembly().Location + }); + return false; + } + } + + /// + 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; + } + + /// + public bool PostconditionVerification(QsCompilation compilation) => + throw new NotImplementedException(); + } + + /// + /// Creates a separate callable for each intrinsic specialization. + /// 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. + /// Generates a warning without failing the transformation if some attributes could not be added. + /// Leaves any type parameterized callables and type constructors unmodified. + /// + /// + /// An intrinsic callable contains non-intrinsic specializations + /// or a non-intrinsic callable contains intrinsic specializations, + /// or the a callable doesn't have a body specialization. + /// + internal class TargetInstructionInference : IRewriteStep + { + private readonly List diagnostics = new List(); + + public TargetInstructionInference() + { + this.diagnostics = new List(); + this.AssemblyConstants = new Dictionary(); + } + + /// + public string Name => "Target Instruction Separation"; + + /// + public int Priority => QirGeneration.EmissionPriority + 1; + + /// + public IDictionary AssemblyConstants { get; } + + /// + public IEnumerable GeneratedDiagnostics => this.diagnostics; + + /// + public bool ImplementsPreconditionVerification => true; + + /// + public bool ImplementsTransformation => true; + + /// + public bool ImplementsPostconditionVerification => false; + + /// + 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 Transformation(QsCompilation compilation, out QsCompilation transformed) + { + transformed = InferTargetInstructions.ReplaceSelfAdjointSpecializations(compilation); + transformed = InferTargetInstructions.LiftIntrinsicSpecializations(transformed); + var allAttributesAdded = InferTargetInstructions.TryAddMissingTargetInstructionAttributes(transformed, out transformed); + if (!allAttributesAdded) + { + this.diagnostics.Add(new IRewriteStep.Diagnostic + { + Severity = DiagnosticSeverity.Warning, + Message = DiagnosticItem.Message(WarningCode.MissingTargetInstructionName, Array.Empty()), + Stage = IRewriteStep.Stage.Transformation, + }); + } + return true; + } + + /// + public bool PostconditionVerification(QsCompilation compilation) => + throw new NotImplementedException(); + } +} diff --git a/src/QsCompiler/QirGeneration/ScopeManager.cs b/src/QsCompiler/QirGeneration/ScopeManager.cs index 9dbe0851b6..b55520a7fe 100644 --- a/src/QsCompiler/QirGeneration/ScopeManager.cs +++ b/src/QsCompiler/QirGeneration/ScopeManager.cs @@ -7,15 +7,11 @@ using System.Linq; using Microsoft.Quantum.QIR; using Microsoft.Quantum.QIR.Emission; -using Microsoft.Quantum.QsCompiler.SyntaxTokens; -using Microsoft.Quantum.QsCompiler.SyntaxTree; using Ubiquity.NET.Llvm.Types; using Ubiquity.NET.Llvm.Values; namespace Microsoft.Quantum.QsCompiler.QIR { - using ResolvedTypeKind = QsTypeKind; - /// /// This class is used to track the validity of variables and values, to track alias and reference counts, /// and to release and unreference values when they go out of scope. diff --git a/src/QsCompiler/QirGeneration/Subtransformations/NamespaceTransformation.cs b/src/QsCompiler/QirGeneration/Subtransformations/NamespaceTransformation.cs index a3ac97dce2..320c394230 100644 --- a/src/QsCompiler/QirGeneration/Subtransformations/NamespaceTransformation.cs +++ b/src/QsCompiler/QirGeneration/Subtransformations/NamespaceTransformation.cs @@ -63,7 +63,7 @@ public override void OnIntrinsicImplementation() { this.SharedState.StartFunction(); this.SharedState.GenerateConstructor(currentSpec, currentCallable.ArgumentTuple); - this.SharedState.EndFunction(); + this.SharedState.EndFunction(generatePending: true); } } @@ -72,7 +72,7 @@ public override Tuple OnProvidedImplementation(QsArgum this.SharedState.StartFunction(); this.SharedState.GenerateFunctionHeader(this.context.GetCurrentSpecialization(), argTuple); this.Transformation.Statements.OnScope(body); - this.SharedState.EndFunction(); + this.SharedState.EndFunction(generatePending: true); return Tuple.Create(argTuple, body); } @@ -86,8 +86,7 @@ public override QsSpecialization OnSpecializationDeclaration(QsSpecialization sp public override QsCallable OnCallableDeclaration(QsCallable c) { - var unmangledName = NameDecorator.OriginalNameFromMonomorphized(c.FullName); - if (this.SharedState.Functions.BuiltIn.ContainsKey(unmangledName)) + if (this.SharedState.Functions.IsBuiltIn(c.FullName)) { return c; } diff --git a/src/QsCompiler/QirGeneration/Subtransformations/TypeTransformation.cs b/src/QsCompiler/QirGeneration/Subtransformations/TypeTransformation.cs index 5a0beb28e7..1280e460c4 100644 --- a/src/QsCompiler/QirGeneration/Subtransformations/TypeTransformation.cs +++ b/src/QsCompiler/QirGeneration/Subtransformations/TypeTransformation.cs @@ -122,5 +122,11 @@ public override QsResolvedTypeKind OnUserDefinedType(UserDefinedType udt) } return QsResolvedTypeKind.InvalidType; } + + public override QsResolvedTypeKind OnTypeParameter(QsTypeParameter tp) + { + this.SharedState.BuiltType = this.SharedState.Context.Int8Type.CreatePointerType(); + return base.OnTypeParameter(tp); + } } } diff --git a/src/QsCompiler/Tests.Compiler/CallGraphTests.fs b/src/QsCompiler/Tests.Compiler/CallGraphTests.fs index 9555e36865..7241583aa6 100644 --- a/src/QsCompiler/Tests.Compiler/CallGraphTests.fs +++ b/src/QsCompiler/Tests.Compiler/CallGraphTests.fs @@ -298,10 +298,46 @@ type CallGraphTests(output: ITestOutputHelper) = AssertNotInGraph graph "Bar" + [] + [] + member this.``Multiple Entry Points``() = + let graph = PopulateCallGraphWithExe 9 |> BuildTrimmedGraph + + [ "Main1", [ "Foo" ]; "Main2", [ "Bar" ]; "Foo", []; "Bar", [] ] + |> List.map (fun x -> AssertExpectedDirectDependencies (fst x) (snd x) graph) + |> ignore + + [] + [] + member this.``Unit Test as Starting Point``() = + let graph = PopulateCallGraphWithExe 10 |> BuildTrimmedGraph + + [ "Test", [ "Foo" ]; "Foo", [] ] + |> List.map (fun x -> AssertExpectedDirectDependencies (fst x) (snd x) graph) + |> ignore + + AssertNotInGraph graph "Bar" + + [] + [] + member this.``Entry Points and Unit Tests``() = + let graph = PopulateCallGraphWithExe 11 |> BuildTrimmedGraph + + [ + "Main1", [ "Foo" ] + "Main2", [ "Bar" ] + "Test1", [ "Zip" ] + "Test2", [ "Zap" ] + ] + |> List.map (fun x -> AssertExpectedDirectDependencies (fst x) (snd x) graph) + |> ignore + + AssertNotInGraph graph "Unused" + [] [] member this.``Concrete Graph has Concretizations``() = - let graph = PopulateCallGraphWithExe 9 |> ConcreteCallGraph + let graph = PopulateCallGraphWithExe 12 |> ConcreteCallGraph let makeNode name resType = MakeNode name QsSpecializationKind.QsBody [ ("A", resType) ] @@ -325,7 +361,7 @@ type CallGraphTests(output: ITestOutputHelper) = [] [] member this.``Concrete Graph Contains All Specializations``() = - let graph = PopulateCallGraphWithExe 10 |> ConcreteCallGraph + let graph = PopulateCallGraphWithExe 13 |> ConcreteCallGraph let makeNode name spec = MakeNode name spec [] @@ -348,7 +384,7 @@ type CallGraphTests(output: ITestOutputHelper) = [] [] member this.``Concrete Graph Double Reference Resolution``() = - let graph = PopulateCallGraphWithExe 11 |> ConcreteCallGraph + let graph = PopulateCallGraphWithExe 14 |> ConcreteCallGraph let makeNode resType = MakeNode "Foo" QsSpecializationKind.QsBody [ ("A", resType) ] @@ -362,7 +398,7 @@ type CallGraphTests(output: ITestOutputHelper) = [] [] member this.``Concrete Graph Non-Call Reference Only Body``() = - let graph = PopulateCallGraphWithExe 12 |> ConcreteCallGraph + let graph = PopulateCallGraphWithExe 15 |> ConcreteCallGraph let makeNode spec = MakeNode "Foo" spec [] @@ -380,7 +416,7 @@ type CallGraphTests(output: ITestOutputHelper) = [] [] member this.``Concrete Graph Non-Call Reference With Adjoint``() = - let graph = PopulateCallGraphWithExe 13 |> ConcreteCallGraph + let graph = PopulateCallGraphWithExe 16 |> ConcreteCallGraph let makeNode spec = MakeNode "Foo" spec [] @@ -398,7 +434,7 @@ type CallGraphTests(output: ITestOutputHelper) = [] [] member this.``Concrete Graph Non-Call Reference With All``() = - let graph = PopulateCallGraphWithExe 14 |> ConcreteCallGraph + let graph = PopulateCallGraphWithExe 17 |> ConcreteCallGraph let makeNode spec = MakeNode "Foo" spec [] @@ -415,7 +451,7 @@ type CallGraphTests(output: ITestOutputHelper) = [] [] member this.``Concrete Graph Call Self-Adjoint Reference``() = - let compilation = PopulateCallGraphWithExe 15 + let compilation = PopulateCallGraphWithExe 18 let mutable transformed = { Namespaces = ImmutableArray.Empty; EntryPoints = ImmutableArray.Empty } Assert.True(CodeGeneration.GenerateFunctorSpecializations(compilation, &transformed)) let graph = transformed |> ConcreteCallGraph @@ -446,7 +482,7 @@ type CallGraphTests(output: ITestOutputHelper) = [] [] member this.``Concrete Graph Clears Type Param Resolutions After Statements``() = - let compilation = PopulateCallGraphWithExe 16 + let compilation = PopulateCallGraphWithExe 19 let mutable transformed = { Namespaces = ImmutableArray.Empty; EntryPoints = ImmutableArray.Empty } Assert.True(CodeGeneration.GenerateFunctorSpecializations(compilation, &transformed)) let graph = transformed |> ConcreteCallGraph @@ -461,6 +497,90 @@ type CallGraphTests(output: ITestOutputHelper) = Assert.Empty unresolvedTypeParameters + [] + [] + member this.``Concrete Graph Multiple Entry Points``() = + let graph = PopulateCallGraphWithExe 20 |> ConcreteCallGraph + + let makeNode name resType = + MakeNode name QsSpecializationKind.QsBody [ ("A", resType) ] + + let makeNodeNoRes name = + MakeNode name QsSpecializationKind.QsBody [] + + let Main1 = makeNodeNoRes "Main1" + let Main2 = makeNodeNoRes "Main2" + let FooDouble = makeNode "Foo" Double + let FooString = makeNode "Foo" String + let FooEmpty = makeNodeNoRes "Foo" + + AssertInConcreteGraph graph Main1 + AssertInConcreteGraph graph Main2 + AssertInConcreteGraph graph FooDouble + AssertInConcreteGraph graph FooString + + AssertNotInConcreteGraph graph FooEmpty + + [] + [] + member this.``Concrete Graph Unit Tests``() = + let graph = PopulateCallGraphWithExe 21 |> ConcreteCallGraph + + let makeNode name resType = + MakeNode name QsSpecializationKind.QsBody [ ("A", resType) ] + + let makeNodeNoRes name = + MakeNode name QsSpecializationKind.QsBody [] + + let Test1 = makeNodeNoRes "Test1" + let Test2 = makeNodeNoRes "Test2" + let FooDouble = makeNode "Foo" Double + let FooString = makeNode "Foo" String + let FooEmpty = makeNodeNoRes "Foo" + + AssertInConcreteGraph graph Test1 + AssertInConcreteGraph graph Test2 + AssertInConcreteGraph graph FooDouble + AssertInConcreteGraph graph FooString + + AssertNotInConcreteGraph graph FooEmpty + + [] + [] + member this.``Concrete Graph Entry Points and Unit Tests``() = + let graph = PopulateCallGraphWithExe 22 |> ConcreteCallGraph + + let makeNode name resType = + MakeNode name QsSpecializationKind.QsBody [ ("A", resType) ] + + let makeNodeNoRes name = + MakeNode name QsSpecializationKind.QsBody [] + + let Main1 = makeNodeNoRes "Main1" + let Main2 = makeNodeNoRes "Main2" + let Test1 = makeNodeNoRes "Test1" + let Test2 = makeNodeNoRes "Test2" + let FooDouble = makeNode "Foo" Double + let FooString = makeNode "Foo" String + let FooEmpty = makeNodeNoRes "Foo" + let BarDouble = makeNode "Bar" Double + let BarString = makeNode "Bar" String + let BarEmpty = makeNodeNoRes "Bar" + let Unused = makeNodeNoRes "Unused" + + AssertInConcreteGraph graph Main1 + AssertInConcreteGraph graph Main2 + AssertInConcreteGraph graph Test1 + AssertInConcreteGraph graph Test2 + AssertInConcreteGraph graph FooDouble + AssertInConcreteGraph graph FooString + AssertInConcreteGraph graph BarDouble + AssertInConcreteGraph graph BarString + + AssertNotInConcreteGraph graph FooEmpty + AssertNotInConcreteGraph graph BarEmpty + AssertNotInConcreteGraph graph Unused + [] [] member this.``No Cycles``() = diff --git a/src/QsCompiler/Tests.Compiler/ClassicalControlTests.fs b/src/QsCompiler/Tests.Compiler/ClassicalControlTests.fs index 19e1ada7cb..087c4e7857 100644 --- a/src/QsCompiler/Tests.Compiler/ClassicalControlTests.fs +++ b/src/QsCompiler/Tests.Compiler/ClassicalControlTests.fs @@ -54,7 +54,7 @@ type ClassicalControlTests() = Assert.NotNull processedCompilation Signatures.SignatureCheck - [ Signatures.ClassicalControlNs ] + [ Signatures.ClassicalControlNS ] Signatures.ClassicalControlSignatures.[testNumber - 1] processedCompilation @@ -187,7 +187,7 @@ type ClassicalControlTests() = |> (fun x -> x.Value) let ApplyIfElseTest compilation = - let original = GetCallableWithName compilation Signatures.ClassicalControlNs "Foo" |> GetBodyFromCallable + let original = GetCallableWithName compilation Signatures.ClassicalControlNS "Foo" |> GetBodyFromCallable let lines = original |> GetLinesFromSpecialization Assert.True @@ -253,7 +253,7 @@ type ClassicalControlTests() = let result = CompileClassicalControlTest 1 let generated = - GetCallablesWithSuffix result Signatures.ClassicalControlNs "_Foo" + GetCallablesWithSuffix result Signatures.ClassicalControlNS "_Foo" |> (fun x -> Assert.True(1 = Seq.length x) Seq.item 0 x |> GetBodyFromCallable) @@ -289,7 +289,7 @@ type ClassicalControlTests() = [] member this.``ApplyIfZero And ApplyIfOne``() = let result = CompileClassicalControlTest 7 - let originalOp = GetCallableWithName result Signatures.ClassicalControlNs "Foo" |> GetBodyFromCallable + let originalOp = GetCallableWithName result Signatures.ClassicalControlNS "Foo" |> GetBodyFromCallable [ (1, BuiltIn.ApplyIfZero); (3, BuiltIn.ApplyIfOne) ] |> Seq.map ExpandBuiltInQualifiedSymbol @@ -300,7 +300,7 @@ type ClassicalControlTests() = member this.``Apply If Zero Else One``() = let (targs, args) = CompileClassicalControlTest 8 |> ApplyIfElseTest - let Bar = { Namespace = Signatures.ClassicalControlNs; Name = "Bar" } + let Bar = { Namespace = Signatures.ClassicalControlNS; Name = "Bar" } let SubOp1 = { Namespace = "SubOps"; Name = "SubOp1" } IsApplyIfElseArgsMatch args "r" Bar SubOp1 @@ -313,7 +313,7 @@ type ClassicalControlTests() = member this.``Apply If One Else Zero``() = let (targs, args) = CompileClassicalControlTest 9 |> ApplyIfElseTest - let Bar = { Namespace = Signatures.ClassicalControlNs; Name = "Bar" } + let Bar = { Namespace = Signatures.ClassicalControlNS; Name = "Bar" } let SubOp1 = { Namespace = "SubOps"; Name = "SubOp1" } // The operation arguments should be swapped from the previous test @@ -329,10 +329,10 @@ type ClassicalControlTests() = let ifOp = { Namespace = "SubOps"; Name = "SubOp1" } let elifOp = { Namespace = "SubOps"; Name = "SubOp2" } let elseOp = { Namespace = "SubOps"; Name = "SubOp3" } - let original = GetCallableWithName result Signatures.ClassicalControlNs "Foo" |> GetBodyFromCallable + let original = GetCallableWithName result Signatures.ClassicalControlNS "Foo" |> GetBodyFromCallable let generated = - GetCallablesWithSuffix result Signatures.ClassicalControlNs "_Foo" + GetCallablesWithSuffix result Signatures.ClassicalControlNS "_Foo" |> (fun x -> Assert.True(1 = Seq.length x) Seq.item 0 x |> GetBodyFromCallable) @@ -373,10 +373,10 @@ type ClassicalControlTests() = let result = CompileClassicalControlTest 11 let ifOp = { Namespace = "SubOps"; Name = "SubOp1" } let elseOp = { Namespace = "SubOps"; Name = "SubOp2" } - let original = GetCallableWithName result Signatures.ClassicalControlNs "Foo" |> GetBodyFromCallable + let original = GetCallableWithName result Signatures.ClassicalControlNS "Foo" |> GetBodyFromCallable let generated = - GetCallablesWithSuffix result Signatures.ClassicalControlNs "_Foo" + GetCallablesWithSuffix result Signatures.ClassicalControlNS "_Foo" |> (fun x -> Assert.True(1 = Seq.length x) Seq.item 0 x |> GetBodyFromCallable) @@ -417,10 +417,10 @@ type ClassicalControlTests() = let result = CompileClassicalControlTest 12 let ifOp = { Namespace = "SubOps"; Name = "SubOp1" } let elseOp = { Namespace = "SubOps"; Name = "SubOp2" } - let original = GetCallableWithName result Signatures.ClassicalControlNs "Foo" |> GetBodyFromCallable + let original = GetCallableWithName result Signatures.ClassicalControlNS "Foo" |> GetBodyFromCallable let generated = - GetCallablesWithSuffix result Signatures.ClassicalControlNs "_Foo" + GetCallablesWithSuffix result Signatures.ClassicalControlNS "_Foo" |> (fun x -> Assert.True(1 = Seq.length x) Seq.item 0 x |> GetBodyFromCallable) @@ -474,7 +474,7 @@ type ClassicalControlTests() = let callables = result.Namespaces - |> Seq.filter (fun x -> x.Name = Signatures.ClassicalControlNs) + |> Seq.filter (fun x -> x.Name = Signatures.ClassicalControlNS) |> GlobalCallableResolutions let original = callables |> Seq.find (fun x -> x.Key.Name = "Foo") |> fun x -> x.Value @@ -520,7 +520,7 @@ type ClassicalControlTests() = let callables = result.Namespaces - |> Seq.filter (fun x -> x.Name = Signatures.ClassicalControlNs) + |> Seq.filter (fun x -> x.Name = Signatures.ClassicalControlNS) |> GlobalCallableResolutions let selfOp = callables |> Seq.find (fun x -> x.Key.Name = "Self") |> fun x -> x.Value @@ -563,7 +563,7 @@ type ClassicalControlTests() = let callables = result.Namespaces - |> Seq.filter (fun x -> x.Name = Signatures.ClassicalControlNs) + |> Seq.filter (fun x -> x.Name = Signatures.ClassicalControlNS) |> GlobalCallableResolutions let distributeOp = callables |> Seq.find (fun x -> x.Key.Name = "Distribute") |> fun x -> x.Value @@ -599,7 +599,7 @@ type ClassicalControlTests() = let callables = result.Namespaces - |> Seq.filter (fun x -> x.Name = Signatures.ClassicalControlNs) + |> Seq.filter (fun x -> x.Name = Signatures.ClassicalControlNS) |> GlobalCallableResolutions (*-----------------------------------------*) @@ -758,7 +758,7 @@ type ClassicalControlTests() = let callables = result.Namespaces - |> Seq.filter (fun x -> x.Name = Signatures.ClassicalControlNs) + |> Seq.filter (fun x -> x.Name = Signatures.ClassicalControlNS) |> GlobalCallableResolutions (*-----------------------------------------*) @@ -888,7 +888,7 @@ type ClassicalControlTests() = let callables = result.Namespaces - |> Seq.filter (fun x -> x.Name = Signatures.ClassicalControlNs) + |> Seq.filter (fun x -> x.Name = Signatures.ClassicalControlNS) |> GlobalCallableResolutions (*-----------------------------------------*) @@ -1014,7 +1014,7 @@ type ClassicalControlTests() = let callables = result.Namespaces - |> Seq.filter (fun x -> x.Name = Signatures.ClassicalControlNs) + |> Seq.filter (fun x -> x.Name = Signatures.ClassicalControlNS) |> GlobalCallableResolutions (*-----------------------------------------*) @@ -1073,8 +1073,8 @@ type ClassicalControlTests() = [] member this.``Within Block Support``() = let result = CompileClassicalControlTest 23 - let original = GetCallableWithName result Signatures.ClassicalControlNs "Foo" |> GetBodyFromCallable - let generated = GetCallablesWithSuffix result Signatures.ClassicalControlNs "_Foo" + let original = GetCallableWithName result Signatures.ClassicalControlNS "Foo" |> GetBodyFromCallable + let generated = GetCallablesWithSuffix result Signatures.ClassicalControlNS "_Foo" Assert.True(2 = Seq.length generated) // Should already be asserted by the signature check @@ -1107,7 +1107,7 @@ type ClassicalControlTests() = [] member this.``Arguments Partially Resolve Type Parameters``() = let result = CompileClassicalControlTest 24 - let original = GetCallableWithName result Signatures.ClassicalControlNs "Foo" |> GetBodyFromCallable + let original = GetCallableWithName result Signatures.ClassicalControlNS "Foo" |> GetBodyFromCallable let lines = GetLinesFromSpecialization original let (success, _, args) = @@ -1118,7 +1118,7 @@ type ClassicalControlTests() = sprintf "Callable %O(%A) did not have expected content" original.Parent QsSpecializationKind.QsBody) let (success, typeArgs, _) = - IsApplyIfArgMatch args "r" { Namespace = Signatures.ClassicalControlNs; Name = "Bar" } + IsApplyIfArgMatch args "r" { Namespace = Signatures.ClassicalControlNS; Name = "Bar" } Assert.True(success, "ApplyIfZero did not have the correct arguments") @@ -1149,7 +1149,7 @@ type ClassicalControlTests() = [] member this.``Apply Conditionally``() = let result = CompileClassicalControlTest 29 - let original = GetCallableWithName result Signatures.ClassicalControlNs "Foo" |> GetBodyFromCallable + let original = GetCallableWithName result Signatures.ClassicalControlNS "Foo" |> GetBodyFromCallable let lines = original |> GetLinesFromSpecialization Assert.True @@ -1164,7 +1164,7 @@ type ClassicalControlTests() = Assert.True(success, sprintf "Callable %O(%A) did not have expected content" original.Parent original.Kind) - let Bar = { Namespace = Signatures.ClassicalControlNs; Name = "Bar" } + let Bar = { Namespace = Signatures.ClassicalControlNS; Name = "Bar" } let SubOp1 = { Namespace = "SubOps"; Name = "SubOp1" } IsApplyIfElseArgsMatch args "[r1], [r2]" Bar SubOp1 @@ -1176,7 +1176,7 @@ type ClassicalControlTests() = [] member this.``Apply Conditionally With NoOp``() = let result = CompileClassicalControlTest 30 - let original = GetCallableWithName result Signatures.ClassicalControlNs "Foo" |> GetBodyFromCallable + let original = GetCallableWithName result Signatures.ClassicalControlNS "Foo" |> GetBodyFromCallable let lines = original |> GetLinesFromSpecialization Assert.True @@ -1191,7 +1191,7 @@ type ClassicalControlTests() = Assert.True(success, sprintf "Callable %O(%A) did not have expected content" original.Parent original.Kind) - let Bar = { Namespace = Signatures.ClassicalControlNs; Name = "Bar" } + let Bar = { Namespace = Signatures.ClassicalControlNS; Name = "Bar" } let NoOp = { Namespace = "Microsoft.Quantum.Canon"; Name = "NoOp" } IsApplyIfElseArgsMatch args "[r1], [r2]" Bar NoOp @@ -1203,7 +1203,7 @@ type ClassicalControlTests() = [] member this.``Inequality with ApplyConditionally``() = let result = CompileClassicalControlTest 31 - let original = GetCallableWithName result Signatures.ClassicalControlNs "Foo" |> GetBodyFromCallable + let original = GetCallableWithName result Signatures.ClassicalControlNS "Foo" |> GetBodyFromCallable let lines = original |> GetLinesFromSpecialization Assert.True @@ -1218,7 +1218,7 @@ type ClassicalControlTests() = Assert.True(success, sprintf "Callable %O(%A) did not have expected content" original.Parent original.Kind) - let Bar = { Namespace = Signatures.ClassicalControlNs; Name = "Bar" } + let Bar = { Namespace = Signatures.ClassicalControlNS; Name = "Bar" } let SubOp1 = { Namespace = "SubOps"; Name = "SubOp1" } IsApplyIfElseArgsMatch args "[r1], [r2]" SubOp1 Bar @@ -1231,7 +1231,7 @@ type ClassicalControlTests() = member this.``Inequality with Apply If One Else Zero``() = let (targs, args) = CompileClassicalControlTest 32 |> ApplyIfElseTest - let Bar = { Namespace = Signatures.ClassicalControlNs; Name = "Bar" } + let Bar = { Namespace = Signatures.ClassicalControlNS; Name = "Bar" } let SubOp1 = { Namespace = "SubOps"; Name = "SubOp1" } IsApplyIfElseArgsMatch args "r" SubOp1 Bar @@ -1244,7 +1244,7 @@ type ClassicalControlTests() = member this.``Inequality with Apply If Zero Else One``() = let (targs, args) = CompileClassicalControlTest 33 |> ApplyIfElseTest - let Bar = { Namespace = Signatures.ClassicalControlNs; Name = "Bar" } + let Bar = { Namespace = Signatures.ClassicalControlNS; Name = "Bar" } let SubOp1 = { Namespace = "SubOps"; Name = "SubOp1" } IsApplyIfElseArgsMatch args "r" Bar SubOp1 @@ -1256,7 +1256,7 @@ type ClassicalControlTests() = [] member this.``Inequality with ApplyIfOne``() = let result = CompileClassicalControlTest 34 - let originalOp = GetCallableWithName result Signatures.ClassicalControlNs "Foo" |> GetBodyFromCallable + let originalOp = GetCallableWithName result Signatures.ClassicalControlNS "Foo" |> GetBodyFromCallable [ (1, BuiltIn.ApplyIfOne) ] |> Seq.map ExpandBuiltInQualifiedSymbol @@ -1266,7 +1266,7 @@ type ClassicalControlTests() = [] member this.``Inequality with ApplyIfZero``() = let result = CompileClassicalControlTest 35 - let originalOp = GetCallableWithName result Signatures.ClassicalControlNs "Foo" |> GetBodyFromCallable + let originalOp = GetCallableWithName result Signatures.ClassicalControlNS "Foo" |> GetBodyFromCallable [ (1, BuiltIn.ApplyIfZero) ] |> Seq.map ExpandBuiltInQualifiedSymbol @@ -1276,7 +1276,7 @@ type ClassicalControlTests() = [] member this.``Literal on the Left``() = let result = CompileClassicalControlTest 36 - let originalOp = GetCallableWithName result Signatures.ClassicalControlNs "Foo" |> GetBodyFromCallable + let originalOp = GetCallableWithName result Signatures.ClassicalControlNS "Foo" |> GetBodyFromCallable [ (1, BuiltIn.ApplyIfZero) ] |> Seq.map ExpandBuiltInQualifiedSymbol @@ -1299,10 +1299,10 @@ type ClassicalControlTests() = let result = CompileClassicalControlTest 38 let ifOp = { Namespace = "SubOps"; Name = "SubOp1" } let elseOp = { Namespace = "SubOps"; Name = "SubOp2" } - let original = GetCallableWithName result Signatures.ClassicalControlNs "Foo" |> GetBodyFromCallable + let original = GetCallableWithName result Signatures.ClassicalControlNS "Foo" |> GetBodyFromCallable let generated = - GetCallablesWithSuffix result Signatures.ClassicalControlNs "_Foo" + GetCallablesWithSuffix result Signatures.ClassicalControlNS "_Foo" |> (fun x -> Assert.True(1 = Seq.length x) Seq.item 0 x |> GetBodyFromCallable) @@ -1342,10 +1342,10 @@ type ClassicalControlTests() = let result = CompileClassicalControlTest 39 let ifOp = { Namespace = "SubOps"; Name = "SubOp1" } let elseOp = { Namespace = "SubOps"; Name = "SubOp2" } - let original = GetCallableWithName result Signatures.ClassicalControlNs "Foo" |> GetBodyFromCallable + let original = GetCallableWithName result Signatures.ClassicalControlNS "Foo" |> GetBodyFromCallable let generated = - GetCallablesWithSuffix result Signatures.ClassicalControlNs "_Foo" + GetCallablesWithSuffix result Signatures.ClassicalControlNS "_Foo" |> (fun x -> Assert.True(1 = Seq.length x) Seq.item 0 x |> GetBodyFromCallable) diff --git a/src/QsCompiler/Tests.Compiler/LinkingTests.fs b/src/QsCompiler/Tests.Compiler/LinkingTests.fs index 9e98541929..1490b5e349 100644 --- a/src/QsCompiler/Tests.Compiler/LinkingTests.fs +++ b/src/QsCompiler/Tests.Compiler/LinkingTests.fs @@ -11,6 +11,7 @@ open Microsoft.Quantum.QsCompiler open Microsoft.Quantum.QsCompiler.CompilationBuilder open Microsoft.Quantum.QsCompiler.DataTypes open Microsoft.Quantum.QsCompiler.Diagnostics +open Microsoft.Quantum.QsCompiler.ReservedKeywords.AssemblyConstants open Microsoft.Quantum.QsCompiler.SyntaxExtensions open Microsoft.Quantum.QsCompiler.SyntaxTree open Microsoft.Quantum.QsCompiler.SyntaxTokens @@ -18,6 +19,7 @@ open Microsoft.Quantum.QsCompiler.Transformations.BasicTransformations open Microsoft.Quantum.QsCompiler.Transformations.Monomorphization open Microsoft.Quantum.QsCompiler.Transformations.Monomorphization.Validation open Microsoft.Quantum.QsCompiler.Transformations.SearchAndReplace +open Microsoft.Quantum.QsCompiler.Transformations.SyntaxTreeTrimming open Microsoft.Quantum.QsCompiler.Transformations.Targeting open Microsoft.VisualStudio.LanguageServer.Protocol open Xunit @@ -123,10 +125,8 @@ type LinkingTests(output: ITestOutputHelper) = member private this.CompileMonomorphization input = let compilationDataStructures = this.BuildContent(compilationManager, input) let monomorphicCompilation = Monomorphize.Apply compilationDataStructures.BuiltCompilation - Assert.NotNull monomorphicCompilation ValidateMonomorphization.Apply monomorphicCompilation - monomorphicCompilation member private this.CompileIntrinsicResolution source environment = @@ -141,16 +141,16 @@ type LinkingTests(output: ITestOutputHelper) = let result = this.CompileIntrinsicResolution srcChunks.[chunckNumber] srcChunks.[chunckNumber + 1] Signatures.SignatureCheck - [ Signatures.IntrinsicResolutionNs ] + [ Signatures.IntrinsicResolutionNS ] Signatures.IntrinsicResolutionSignatures.[testNumber - 1] result (*Find the overridden operation in the appropriate namespace*) - let targetCallName = QsQualifiedName.New(Signatures.IntrinsicResolutionNs, "Override") + let targetCallName = QsQualifiedName.New(Signatures.IntrinsicResolutionNS, "Override") let targetCallable = result.Namespaces - |> Seq.find (fun ns -> ns.Name = Signatures.IntrinsicResolutionNs) + |> Seq.find (fun ns -> ns.Name = Signatures.IntrinsicResolutionNS) |> (fun x -> [ x ]) |> SyntaxTreeExtensions.Callables |> Seq.find (fun call -> call.FullName = targetCallName) @@ -182,7 +182,7 @@ type LinkingTests(output: ITestOutputHelper) = let namespaces = sourceCompilation.BuiltCompilation.Namespaces - |> Seq.filter (fun ns -> ns.Name.StartsWith Signatures.InternalRenamingNs) + |> Seq.filter (fun ns -> ns.Name.StartsWith Signatures.InternalRenamingNS) let references = createReferences [ "InternalRenaming.dll", namespaces ] let referenceCompilation = this.BuildContent(manager, "", references) @@ -205,7 +205,7 @@ type LinkingTests(output: ITestOutputHelper) = let compilation = this.CompileMonomorphization source let generated = - getCallablesWithSuffix compilation Signatures.MonomorphizationNs "_IsInternalUsesInternal" + getCallablesWithSuffix compilation Signatures.MonomorphizationNS "_IsInternalUsesInternal" |> (fun x -> Assert.True(1 = Seq.length x) Seq.item 0 x) @@ -213,7 +213,7 @@ type LinkingTests(output: ITestOutputHelper) = Assert.True(generated.Access = Internal, "Callables originally internal should remain internal.") let generated = - getCallablesWithSuffix compilation Signatures.MonomorphizationNs "_IsInternalUsesPublic" + getCallablesWithSuffix compilation Signatures.MonomorphizationNS "_IsInternalUsesPublic" |> (fun x -> Assert.True(1 = Seq.length x) Seq.item 0 x) @@ -221,7 +221,7 @@ type LinkingTests(output: ITestOutputHelper) = Assert.True(generated.Access = Internal, "Callables originally internal should remain internal.") let generated = - getCallablesWithSuffix compilation Signatures.MonomorphizationNs "_IsPublicUsesInternal" + getCallablesWithSuffix compilation Signatures.MonomorphizationNS "_IsPublicUsesInternal" |> (fun x -> Assert.True(1 = Seq.length x) Seq.item 0 x) @@ -229,7 +229,7 @@ type LinkingTests(output: ITestOutputHelper) = Assert.True(generated.Access = Internal, "Callables with internal arguments should be internal.") let generated = - getCallablesWithSuffix compilation Signatures.MonomorphizationNs "_IsPublicUsesPublic" + getCallablesWithSuffix compilation Signatures.MonomorphizationNS "_IsPublicUsesPublic" |> (fun x -> Assert.True(1 = Seq.length x) Seq.item 0 x) @@ -237,6 +237,14 @@ type LinkingTests(output: ITestOutputHelper) = Assert.True (generated.Access = Public, "Callables originally public should remain public if all arguments are public.") + member private this.RunSyntaxTreeTrimTest testNumber keepIntrinsics = + let source = (LinkingTests.ReadAndChunkSourceFile "SyntaxTreeTrim.qs").[testNumber - 1] + let compilationDataStructures = this.BuildContent(compilationManager, source) + + TrimSyntaxTree.Apply(compilationDataStructures.BuiltCompilation, keepIntrinsics) + |> Signatures.SignatureCheck + [ Signatures.SyntaxTreeTrimmingNS ] + Signatures.SyntaxTreeTrimmingSignatures.[testNumber - 1] [] [] @@ -252,7 +260,7 @@ type LinkingTests(output: ITestOutputHelper) = for testCase in LinkingTests.ReadAndChunkSourceFile "Monomorphization.qs" |> Seq.zip Signatures.MonomorphizationSignatures do this.CompileMonomorphization(snd testCase) - |> Signatures.SignatureCheck [ Signatures.GenericsNs; Signatures.MonomorphizationNs ] (fst testCase) + |> Signatures.SignatureCheck [ Signatures.GenericsNS; Signatures.MonomorphizationNS ] (fst testCase) compilationManager.TryRemoveSourceFileAsync(fileId, false) |> ignore @@ -343,6 +351,7 @@ type LinkingTests(output: ITestOutputHelper) = elif lhs.Expression |> isGlobalCallable (isConcretizationOf BuiltIn.IndexRange.FullName) then gotIndexRange <- true Assert.Equal(0, ex.TypeParameterResolutions.Count) + | _ -> () let walker = TypedExpressionWalker(Action<_> onExpr, ()) @@ -530,16 +539,16 @@ type LinkingTests(output: ITestOutputHelper) = member this.``Rename internal operation call references``() = this.RunInternalRenamingTest 1 - [ qualifiedName Signatures.InternalRenamingNs "Foo" ] - [ qualifiedName Signatures.InternalRenamingNs "Bar" ] + [ qualifiedName Signatures.InternalRenamingNS "Foo" ] + [ qualifiedName Signatures.InternalRenamingNS "Bar" ] [] member this.``Rename internal function call references``() = this.RunInternalRenamingTest 2 - [ qualifiedName Signatures.InternalRenamingNs "Foo" ] - [ qualifiedName Signatures.InternalRenamingNs "Bar" ] + [ qualifiedName Signatures.InternalRenamingNS "Foo" ] + [ qualifiedName Signatures.InternalRenamingNS "Bar" ] [] @@ -547,9 +556,9 @@ type LinkingTests(output: ITestOutputHelper) = this.RunInternalRenamingTest 3 [ - qualifiedName Signatures.InternalRenamingNs "Foo" - qualifiedName Signatures.InternalRenamingNs "Bar" - qualifiedName Signatures.InternalRenamingNs "Baz" + qualifiedName Signatures.InternalRenamingNS "Foo" + qualifiedName Signatures.InternalRenamingNS "Bar" + qualifiedName Signatures.InternalRenamingNS "Baz" ] [] @@ -559,11 +568,11 @@ type LinkingTests(output: ITestOutputHelper) = this.RunInternalRenamingTest 4 [ - qualifiedName Signatures.InternalRenamingNs "Foo" - qualifiedName Signatures.InternalRenamingNs "Bar" - qualifiedName (Signatures.InternalRenamingNs + ".Extra") "Qux" + qualifiedName Signatures.InternalRenamingNS "Foo" + qualifiedName Signatures.InternalRenamingNS "Bar" + qualifiedName (Signatures.InternalRenamingNS + ".Extra") "Qux" ] - [ qualifiedName (Signatures.InternalRenamingNs + ".Extra") "Baz" ] + [ qualifiedName (Signatures.InternalRenamingNS + ".Extra") "Baz" ] [] @@ -571,27 +580,27 @@ type LinkingTests(output: ITestOutputHelper) = this.RunInternalRenamingTest 5 [ - qualifiedName Signatures.InternalRenamingNs "Foo" - qualifiedName Signatures.InternalRenamingNs "Bar" - qualifiedName (Signatures.InternalRenamingNs + ".Extra") "Qux" + qualifiedName Signatures.InternalRenamingNS "Foo" + qualifiedName Signatures.InternalRenamingNS "Bar" + qualifiedName (Signatures.InternalRenamingNS + ".Extra") "Qux" ] - [ qualifiedName (Signatures.InternalRenamingNs + ".Extra") "Baz" ] + [ qualifiedName (Signatures.InternalRenamingNS + ".Extra") "Baz" ] [] member this.``Rename internal attribute references``() = this.RunInternalRenamingTest 6 - [ qualifiedName Signatures.InternalRenamingNs "Foo" ] - [ qualifiedName Signatures.InternalRenamingNs "Bar" ] + [ qualifiedName Signatures.InternalRenamingNS "Foo" ] + [ qualifiedName Signatures.InternalRenamingNS "Bar" ] [] member this.``Rename specializations for internal operations``() = this.RunInternalRenamingTest 7 - [ qualifiedName Signatures.InternalRenamingNs "Foo" ] - [ qualifiedName Signatures.InternalRenamingNs "Bar" ] + [ qualifiedName Signatures.InternalRenamingNS "Foo" ] + [ qualifiedName Signatures.InternalRenamingNS "Bar" ] [] @@ -603,7 +612,7 @@ type LinkingTests(output: ITestOutputHelper) = let namespaces = sourceCompilation.BuiltCompilation.Namespaces - |> Seq.filter (fun ns -> ns.Name.StartsWith Signatures.InternalRenamingNs) + |> Seq.filter (fun ns -> ns.Name.StartsWith Signatures.InternalRenamingNS) let references = createReferences [ "InternalRenaming1.dll", namespaces @@ -613,9 +622,8 @@ type LinkingTests(output: ITestOutputHelper) = let callables = GlobalCallableResolutions referenceCompilation.BuiltCompilation.Namespaces let decorator = new NameDecorator("QsRef") - for idx = 0 to references.Declarations.Count - 1 do - let name = decorator.Decorate(qualifiedName Signatures.InternalRenamingNs "Foo", idx) + let name = decorator.Decorate(qualifiedName Signatures.InternalRenamingNS "Foo", idx) let specializations = callables.[name].Specializations Assert.Equal(4, specializations.Length) Assert.True(specializations |> Seq.forall (fun s -> s.Source = callables.[name].Source)) @@ -750,3 +758,15 @@ type LinkingTests(output: ITestOutputHelper) = checkValidCombination (buildDict [ (source 1, (chunks.[0], declInSource1)) (source 2, (chunks.[6], declInSource2)) ]) + + [] + member this.``Trimmer Removes Unused Callables``() = this.RunSyntaxTreeTrimTest 1 false + + [] + member this.``Trimmer Keeps UDTs``() = this.RunSyntaxTreeTrimTest 2 false + + [] + member this.``Trimmer Keeps Intrinsics When Told``() = this.RunSyntaxTreeTrimTest 3 true + + [] + member this.``Trimmer Removes Intrinsics When Told``() = this.RunSyntaxTreeTrimTest 4 false diff --git a/src/QsCompiler/Tests.Compiler/QirTests.fs b/src/QsCompiler/Tests.Compiler/QirTests.fs index 87adb38abd..7c6d2c6e13 100644 --- a/src/QsCompiler/Tests.Compiler/QirTests.fs +++ b/src/QsCompiler/Tests.Compiler/QirTests.fs @@ -39,17 +39,24 @@ let private compilerArgs target (name: string) = then ("TestCases", "QirTests", "QirTarget.qs") |> Path.Combine else "") - "--qir" - Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "--load" + + Path.Combine + (Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Microsoft.Quantum.QirGeneration.dll") + "--verbosity" "Diagnostic" } let private customTest name compilerArgs snippets = - clearOutput (name + ".ll") + if not <| Directory.Exists "qir" + then Directory.CreateDirectory "qir" |> ignore + + let fileName = Path.Combine("qir", name + ".ll") + clearOutput fileName compilerArgs |> testOne ReturnCode.Success - let fullText = (name + ".ll") |> File.ReadAllText + let fullText = fileName |> File.ReadAllText snippets |> List.map (fun s -> checkAltOutput (s + ".ll") fullText) let private qirMultiTest target name snippets = @@ -174,6 +181,11 @@ let ``QIR declarations`` () = [] let ``QIR functors`` () = qirTest true "TestFunctors" +[] +let ``QIR built-in generics`` () = + qirMultiTest false "TestGenerics" [ "TestGenerics1"; "TestGenerics2"; "TestGenerics3"; "TestGenerics4" ] + + [] let ``QIR paulis`` () = qirTest false "TestPaulis" @@ -202,7 +214,11 @@ let ``QIR expressions`` () = qirTest false "TestExpressions" [] let ``QIR targeting`` () = let compilerArgs = - [ "--runtime"; "BasicMeasurementFeedback" ] + [ + "--runtime" + "BasicMeasurementFeedback" + "--force-rewrite-step-execution" // to make sure the target specific transformation actually runs + ] |> Seq.append (compilerArgs true "TestTargeting") |> Seq.toArray diff --git a/src/QsCompiler/Tests.Compiler/TestCases/CompilationLoader.qs b/src/QsCompiler/Tests.Compiler/TestCases/CompilationLoader.qs index d2a9b5ad8b..62b22b2472 100644 --- a/src/QsCompiler/Tests.Compiler/TestCases/CompilationLoader.qs +++ b/src/QsCompiler/Tests.Compiler/TestCases/CompilationLoader.qs @@ -25,7 +25,7 @@ namespace Microsoft.Quantum.Testing.CompilationLoader { return (isDivisibleByThree, isDivisibleByFive, isDivisibleByEleven); } - @ EntryPoint() + @EntryPoint() operation Main() : Unit { let (isDivisibleByThree, _, _) = IsDivisibleByThreeOrFiveOrSeven(3); let (_, isDivisibleByFive, _) = IsDivisibleByThreeOrFiveOrSeven(5); @@ -36,7 +36,7 @@ namespace Microsoft.Quantum.Testing.CompilationLoader { // --- Declarations namespace Microsoft.Quantum.Testing.CompilationLoader { - @ EntryPoint() + @EntryPoint() operation Main() : Unit { let zeros = new Int[10]; let emptyRegister = new Qubit[0]; @@ -50,7 +50,7 @@ namespace Microsoft.Quantum.Testing.CompilationLoader { // --- Functions namespace Microsoft.Quantum.Testing.CompilationLoader { - @ EntryPoint() + @EntryPoint() operation Main() : Unit { Foo(); Bar(); @@ -84,7 +84,7 @@ namespace Microsoft.Quantum.Testing.CompilationLoader { } } - @ EntryPoint() + @EntryPoint() operation Main() : Unit { ForLoop(); WhileLoop(); @@ -94,7 +94,7 @@ namespace Microsoft.Quantum.Testing.CompilationLoader { // --- Mutable namespace Microsoft.Quantum.Testing.CompilationLoader { - @ EntryPoint() + @EntryPoint() operation Main() : Unit { mutable aMutableBoolean = false; set aMutableBoolean = true; @@ -104,7 +104,7 @@ namespace Microsoft.Quantum.Testing.CompilationLoader { // --- Operations namespace Microsoft.Quantum.Testing.CompilationLoader { - @ EntryPoint() + @EntryPoint() operation Main() : Unit { Foo(); Bar(); @@ -122,7 +122,7 @@ namespace Microsoft.Quantum.Testing.CompilationLoader { // --- Qubit Usage namespace Microsoft.Quantum.Testing.CompilationLoader { - @ EntryPoint() + @EntryPoint() operation Main() : Unit { using (qubit = Qubit()) {} } @@ -131,7 +131,7 @@ namespace Microsoft.Quantum.Testing.CompilationLoader { // --- Tuple Deconstruction namespace Microsoft.Quantum.Testing.CompilationLoader { - @ EntryPoint() + @EntryPoint() operation Main() : Unit { let (i, f) = (5, 0.1); // i is bound to 5 and f to 0.1 mutable (a, (_, b)) = (1, (2, 3)); // a is bound to 1, b is bound to 3 @@ -157,7 +157,7 @@ namespace Microsoft.Quantum.Testing.CompilationLoader { return res; } - @ EntryPoint() + @EntryPoint() operation Main() : Unit { let reals = [10.0, 0.0, 11.0]; let imaginaries = [0.0, 10.0, 11.0]; @@ -174,7 +174,7 @@ namespace Microsoft.Quantum.Testing.CompilationLoader { return Complex(c1::Re + c2::Re, c1::Im + c2::Im); } - @ EntryPoint() + @EntryPoint() operation Main() : Unit { let realUnit = Complex(1.0, 0.0); let imaginaryUnit = Complex(0.0, 1.0); diff --git a/src/QsCompiler/Tests.Compiler/TestCases/GlobalVerification.qs b/src/QsCompiler/Tests.Compiler/TestCases/GlobalVerification.qs index 51e4f9c9e4..96a178c381 100644 --- a/src/QsCompiler/Tests.Compiler/TestCases/GlobalVerification.qs +++ b/src/QsCompiler/Tests.Compiler/TestCases/GlobalVerification.qs @@ -1514,129 +1514,129 @@ namespace Microsoft.Quantum.Testing.GlobalVerification { // valid declaration attributes - @ Attribute() + @Attribute() newtype CustomAttribute = Double; - @ Attribute() + @Attribute() newtype AttAsUserDefType = CustomAttribute; - @ Attribute() + @Attribute() newtype AttArrayAsUserDefType = CustomAttribute[]; - @ Attribute() - @ AttType1() + @Attribute() + @AttType1() newtype AttType1 = Unit; - @ Attribute() - @ AttType2() + @Attribute() + @AttType2() newtype AttType2 = Unit; - @ IntAttribute(0b111) - @ StringAttribute("") - @ BigIntArrayAttribute([0xF0a00101L]) - @ PauliResultAttribute (PauliX, Zero) + @IntAttribute(0b111) + @StringAttribute("") + @BigIntArrayAttribute([0xF0a00101L]) + @PauliResultAttribute (PauliX, Zero) operation ValidAttributes1 () : Unit {} - @ IntAttribute(0b111) - @ StringAttribute("") - @ BigIntArrayAttribute([0xF0a00101L]) - @ PauliResultAttribute (PauliX, Zero) + @IntAttribute(0b111) + @StringAttribute("") + @BigIntArrayAttribute([0xF0a00101L]) + @PauliResultAttribute (PauliX, Zero) function ValidAttributes2 () : Unit {} - @ IntAttribute(0b111) - @ StringAttribute("") - @ BigIntArrayAttribute([0xF0a00101L]) - @ PauliResultAttribute (PauliX, Zero) + @IntAttribute(0b111) + @StringAttribute("") + @BigIntArrayAttribute([0xF0a00101L]) + @PauliResultAttribute (PauliX, Zero) newtype ValidAttributes3 = Unit; - @ BigIntArrayAttribute(new BigInt[3]) + @BigIntArrayAttribute(new BigInt[3]) function ValidAttributes4 () : Unit {} - @ StringAttribute($"some text") + @StringAttribute($"some text") function ValidAttributes5 () : Unit {} - @ CustomAttribute(1.) + @CustomAttribute(1.) function ValidAttributes6 () : Unit {} - @ Microsoft.Quantum.Testing.Attributes.CustomAttribute() + @Microsoft.Quantum.Testing.Attributes.CustomAttribute() function ValidAttributes7 () : Unit {} - @ Microsoft.Quantum.Core.IntTupleAttribute(1,1) + @Microsoft.Quantum.Core.IntTupleAttribute(1,1) function ValidAttributes8 () : Unit {} - @ Microsoft.Quantum.Testing.Attributes.IntTupleAttribute(1,1) + @Microsoft.Quantum.Testing.Attributes.IntTupleAttribute(1,1) function ValidAttributes9 () : Unit {} - @ AttType1() - @ AttType2() + @AttType1() + @AttType2() function ValidAttributes10 () : Unit {} - @ AttType2() - @ AttType1() - @ AttType1() + @AttType2() + @AttType1() + @AttType1() function AttributeDuplication1 () : Unit {} - @ StringAttribute("") - @ StringAttribute("") - @ AttType1() - @ AttType2() + @StringAttribute("") + @StringAttribute("") + @AttType1() + @AttType2() operation AttributeDuplication2 () : Unit {} - @ AttType1() - @ AttType1() + @AttType1() + @AttType1() newtype AttributeDuplication3 = Unit; // invalid declaration attributes - @ StringAttribute($"{1}") + @StringAttribute($"{1}") function InvalidAttributes1 () : Unit {} - @ IntTupleAttribute(1,1) + @IntTupleAttribute(1,1) function InvalidAttributes2 () : Unit {} - @ NonExistent() + @NonExistent() function InvalidAttributes3 () : Unit {} - @ Undefined.NonExistent() + @Undefined.NonExistent() function InvalidAttributes4 () : Unit {} - @ Microsoft.Quantum.Core.NonExistent() + @Microsoft.Quantum.Core.NonExistent() function InvalidAttributes5 () : Unit {} - @ Microsoft.Quantum.Testing.Attributes.CustomAttribute(1.) + @Microsoft.Quantum.Testing.Attributes.CustomAttribute(1.) function InvalidAttributes6 () : Unit {} - @ AttAsUserDefType(CustomAttribute(1.)) + @AttAsUserDefType(CustomAttribute(1.)) function InvalidAttributes7 () : Unit {} - @ AttArrayAsUserDefType(new CustomAttribute[0]) + @AttArrayAsUserDefType(new CustomAttribute[0]) function InvalidAttributes8 () : Unit {} operation InvalidAttributes9 () : Unit { - @ IntAttribute(1) + @IntAttribute(1) body(...) {} } operation InvalidAttributes10 () : Unit { body(...) {} - @ IntAttribute(1) + @IntAttribute(1) adjoint(...) {} } operation InvalidAttributes11 () : Unit { body(...) {} - @ IntAttribute(1) + @IntAttribute(1) controlled (cs, ...) {} } operation InvalidAttributes12 () : Unit { - @ IntAttribute(1) + @IntAttribute(1) controlled adjoint (cs, ...) {} body(...) {} } - @ Attribute() + @Attribute() operation InvalidAttributes13 () : Unit {} - @ Attribute() + @Attribute() function InvalidAttributes14 () : Unit {} } diff --git a/src/QsCompiler/Tests.Compiler/TestCases/LinkingTests/Core.qs b/src/QsCompiler/Tests.Compiler/TestCases/LinkingTests/Core.qs index a1c779b303..899ff69b22 100644 --- a/src/QsCompiler/Tests.Compiler/TestCases/LinkingTests/Core.qs +++ b/src/QsCompiler/Tests.Compiler/TestCases/LinkingTests/Core.qs @@ -4,25 +4,39 @@ // needs to be available for testing namespace Microsoft.Quantum.Core { - @ Attribute() + @Attribute() newtype Attribute = Unit; - @ Attribute() + @Attribute() newtype EntryPoint = Unit; - @ Attribute() - newtype Deprecated = String; + @Attribute() + newtype Inline = Unit; + @Attribute() + newtype Deprecated = (NewName : String); - function Default<'T>() : 'T { + function Default<'T> () : 'T { return (new 'T[1])[0]; } - function Length<'T>(arr : 'T[]) : Int { + function Length<'T> (a : 'T[]) : Int { + body intrinsic; + } + + function RangeStart (range : Range) : Int { + body intrinsic; + } + + function RangeEnd (range : Range) : Int { + body intrinsic; + } + + function RangeStep (range : Range) : Int { body intrinsic; } - function RangeReverse(r : Range) : Range { + function RangeReverse(range : Range) : Range { body intrinsic; } } @@ -30,7 +44,7 @@ namespace Microsoft.Quantum.Core { namespace Microsoft.Quantum.Diagnostics { // needs to be available for testing - @ Attribute() + @Attribute() newtype Test = String; } diff --git a/src/QsCompiler/Tests.Compiler/TestCases/LinkingTests/EntryPointDiagnostics.qs b/src/QsCompiler/Tests.Compiler/TestCases/LinkingTests/EntryPointDiagnostics.qs index 57f7b28c6e..719fcdb5c4 100644 --- a/src/QsCompiler/Tests.Compiler/TestCases/LinkingTests/EntryPointDiagnostics.qs +++ b/src/QsCompiler/Tests.Compiler/TestCases/LinkingTests/EntryPointDiagnostics.qs @@ -6,7 +6,7 @@ namespace Microsoft.Quantum.Testing.EntryPoints { - @ EntryPoint() + @EntryPoint() operation InvalidEntryPoint42(argName : Int, arg_name : Int) : Unit {} } @@ -14,7 +14,7 @@ namespace Microsoft.Quantum.Testing.EntryPoints { namespace Microsoft.Quantum.Testing.EntryPoints { - @ EntryPoint() + @EntryPoint() operation InvalidEntryPoint43(argName : Int, ArgName : Int) : Unit {} } @@ -22,7 +22,7 @@ namespace Microsoft.Quantum.Testing.EntryPoints { namespace Microsoft.Quantum.Testing.EntryPoints { - @ EntryPoint() + @EntryPoint() operation InvalidEntryPoint43(argName : Int, Arg_Name : Int) : Unit {} } @@ -30,7 +30,7 @@ namespace Microsoft.Quantum.Testing.EntryPoints { namespace Microsoft.Quantum.Testing.EntryPoints { - @ EntryPoint() + @EntryPoint() operation InvalidEntryPoint44(simulator : Int) : Unit {} } @@ -38,7 +38,7 @@ namespace Microsoft.Quantum.Testing.EntryPoints { namespace Microsoft.Quantum.Testing.EntryPoints { - @ EntryPoint() + @EntryPoint() operation InvalidEntryPoint45(s : Int) : Unit {} } @@ -46,7 +46,7 @@ namespace Microsoft.Quantum.Testing.EntryPoints { namespace Microsoft.Quantum.Testing.EntryPoints { - @ EntryPoint() + @EntryPoint() operation EntryPoint1() : Result { return Zero; } @@ -56,7 +56,7 @@ namespace Microsoft.Quantum.Testing.EntryPoints { namespace Microsoft.Quantum.Testing.EntryPoints { - @ EntryPoint() + @EntryPoint() operation EntryPoint2() : Result[] { return [Zero]; } @@ -66,7 +66,7 @@ namespace Microsoft.Quantum.Testing.EntryPoints { namespace Microsoft.Quantum.Testing.EntryPoints { - @ EntryPoint() + @EntryPoint() operation EntryPoint3() : (Result, Result[]) { return (Zero, [Zero]); } @@ -76,7 +76,7 @@ namespace Microsoft.Quantum.Testing.EntryPoints { namespace Microsoft.Quantum.Testing.EntryPoints { - @ EntryPoint() + @EntryPoint() operation EntryPoint4() : ((Result, Result), Result[]) { return ((Zero, Zero), [Zero]); } @@ -86,7 +86,7 @@ namespace Microsoft.Quantum.Testing.EntryPoints { namespace Microsoft.Quantum.Testing.EntryPoints { - @ EntryPoint() + @EntryPoint() operation EntryPoint5() : Unit {} } @@ -94,7 +94,7 @@ namespace Microsoft.Quantum.Testing.EntryPoints { namespace Microsoft.Quantum.Testing.EntryPoints { - @ EntryPoint() + @EntryPoint() operation EntryPoint6() : (Int, Result) { return (0, Zero); } @@ -104,7 +104,7 @@ namespace Microsoft.Quantum.Testing.EntryPoints { namespace Microsoft.Quantum.Testing.EntryPoints { - @ EntryPoint() + @EntryPoint() operation EntryPoint7() : String[] { return [""]; } @@ -114,7 +114,7 @@ namespace Microsoft.Quantum.Testing.EntryPoints { namespace Microsoft.Quantum.Testing.EntryPoints { - @ EntryPoint() + @EntryPoint() operation EntryPoint8() : ((Result[], (Result, Int)[]), Result) { return (([Zero], [(Zero, 0)]), Zero); } diff --git a/src/QsCompiler/Tests.Compiler/TestCases/LinkingTests/EntryPointSpecializations.qs b/src/QsCompiler/Tests.Compiler/TestCases/LinkingTests/EntryPointSpecializations.qs index b4bfc17d13..bda0df7f63 100644 --- a/src/QsCompiler/Tests.Compiler/TestCases/LinkingTests/EntryPointSpecializations.qs +++ b/src/QsCompiler/Tests.Compiler/TestCases/LinkingTests/EntryPointSpecializations.qs @@ -6,7 +6,7 @@ namespace Microsoft.Quantum.Testing.EntryPoints { - @ EntryPoint() + @EntryPoint() operation InvalidEntryPointSpec1() : Unit is Adj { } @@ -16,7 +16,7 @@ namespace Microsoft.Quantum.Testing.EntryPoints { namespace Microsoft.Quantum.Testing.EntryPoints { - @ EntryPoint() + @EntryPoint() operation InvalidEntryPointSpec2() : Unit is Ctl { } } @@ -25,7 +25,7 @@ namespace Microsoft.Quantum.Testing.EntryPoints { namespace Microsoft.Quantum.Testing.EntryPoints { - @ EntryPoint() + @EntryPoint() operation InvalidEntryPointSpec3() : Unit is Ctl + Adj { } @@ -35,7 +35,7 @@ namespace Microsoft.Quantum.Testing.EntryPoints { namespace Microsoft.Quantum.Testing.EntryPoints { - @ EntryPoint() + @EntryPoint() operation InvalidEntryPointSpec4() : Unit { body (...) {} adjoint self; @@ -47,7 +47,7 @@ namespace Microsoft.Quantum.Testing.EntryPoints { namespace Microsoft.Quantum.Testing.EntryPoints { - @ EntryPoint() + @EntryPoint() operation InvalidEntryPointSpec5() : Unit { body (...) {} controlled auto; @@ -58,7 +58,7 @@ namespace Microsoft.Quantum.Testing.EntryPoints { namespace Microsoft.Quantum.Testing.EntryPoints { - @ EntryPoint() + @EntryPoint() operation InvalidEntryPointSpec6() : Unit { body (...) {} controlled adjoint (cs, ...) {} diff --git a/src/QsCompiler/Tests.Compiler/TestCases/LinkingTests/Generics.qs b/src/QsCompiler/Tests.Compiler/TestCases/LinkingTests/Generics.qs index ffdca4fce9..53720c60cb 100644 --- a/src/QsCompiler/Tests.Compiler/TestCases/LinkingTests/Generics.qs +++ b/src/QsCompiler/Tests.Compiler/TestCases/LinkingTests/Generics.qs @@ -22,6 +22,27 @@ namespace Microsoft.Quantum.Testing.Generics { let bar = (ReturnGeneric("Yes", (ReturnGeneric(12.0, "No", _))(4), _))("Maybe"); } + operation Test2Main () : Unit { + using (q = Qubit()) { + GenericCallsGeneric(q, 12); + let temp = ArrayGeneric(q, ArrayGeneric(q, "twelve")); + let temp2 = ArrayGeneric(q, 12); + } + } + + operation Test3Main () : Unit { + GenericCallsSpecializations("First", 12, ()); + Adjoint GenericCallsSpecializations(12.0, "Second", 4.0); + using (q = Qubit[4]) { + Controlled GenericCallsSpecializations(q[0..1], (12.0, "Third", q[2..3])); + } + } + + operation Test4Main () : Unit { + GenericCallsSelf(); + GenericCallsSelf2(0.0); + } + // Tests that unused generics are removed operation NotUsed<'A, 'B>(a: 'A, b: 'B) : Int { using (q = Qubit()) { @@ -52,14 +73,6 @@ namespace Microsoft.Quantum.Testing.Generics { return temp; } - operation Test2Main () : Unit { - using (q = Qubit()) { - GenericCallsGeneric(q, 12); - let temp = ArrayGeneric(q, ArrayGeneric(q, "twelve")); - let temp2 = ArrayGeneric(q, 12); - } - } - operation ArrayGeneric<'Q>(q : Qubit, bar : 'Q) : Int { mutable temp = new 'Q[3]; set temp w/= 0 <- bar; @@ -74,14 +87,6 @@ namespace Microsoft.Quantum.Testing.Generics { let thing = ArrayGeneric(q, bar); } - operation Test3Main () : Unit { - GenericCallsSpecializations("First", 12, ()); - Adjoint GenericCallsSpecializations(12.0, "Second", 4.0); - using (q = Qubit[4]) { - Controlled GenericCallsSpecializations(q[0..1], (12.0, "Third", q[2..3])); - } - } - operation GenericCallsSpecializations<'A,'B,'C>(a : 'A, b : 'B, c : 'C) : Unit is Adj+Ctl { body (...) { BasicGeneric(a, b); @@ -109,9 +114,4 @@ namespace Microsoft.Quantum.Testing.Generics { operation GenericCallsSelf2<'A>(x : 'A) : Unit { GenericCallsSelf2(x); } - - operation Test4Main () : Unit { - GenericCallsSelf(); - GenericCallsSelf2(0.0); - } } diff --git a/src/QsCompiler/Tests.Compiler/TestCases/LinkingTests/InvalidEntryPoints.qs b/src/QsCompiler/Tests.Compiler/TestCases/LinkingTests/InvalidEntryPoints.qs index dc53e487d8..4403b20672 100644 --- a/src/QsCompiler/Tests.Compiler/TestCases/LinkingTests/InvalidEntryPoints.qs +++ b/src/QsCompiler/Tests.Compiler/TestCases/LinkingTests/InvalidEntryPoints.qs @@ -8,160 +8,160 @@ namespace Microsoft.Quantum.Testing.EntryPoints { // tests related to entry point placement verification - @ EntryPoint() + @EntryPoint() operation EntryPointInLibrary() : Unit { } - @ EntryPoint() + @EntryPoint() newtype InvalidEntryPointPlacement1 = Int; - @ EntryPoint() + @EntryPoint() function InvalidEntryPointPlacement2<'T> (a : 'T) : Unit {} - @ EntryPoint() + @EntryPoint() operation InvalidEntryPointPlacement3<'T> (a : 'T) : Unit {} operation InvalidEntryPointPlacement4 () : Unit { - @ EntryPoint() + @EntryPoint() body(...) {} } operation InvalidEntryPointPlacement5 () : Unit { body (...) {} - @ EntryPoint() + @EntryPoint() adjoint (...) {} } operation InvalidEntryPointPlacement6 () : Unit { body (...) {} - @ EntryPoint() + @EntryPoint() controlled (cs, ...) {} } operation InvalidEntryPointPlacement7 () : Unit { body (...) {} - @ EntryPoint() + @EntryPoint() controlled adjoint (cs, ...) {} } // testing argument and return type restrictions for entry points - @ EntryPoint() + @EntryPoint() function InvalidEntryPoint1 (arg : Qubit) : Unit {} - @ EntryPoint() + @EntryPoint() operation InvalidEntryPoint2 (arg : (Int, Qubit)) : Unit {} - @ EntryPoint() + @EntryPoint() function InvalidEntryPoint3 (arg : Qubit[]) : Unit {} - @ EntryPoint() + @EntryPoint() operation InvalidEntryPoint4 () : Qubit { return Default(); } - @ EntryPoint() + @EntryPoint() operation InvalidEntryPoint5 () : ((Int, Qubit), Int) { return Default<((Int, Qubit), Int)>(); } - @ EntryPoint() + @EntryPoint() operation InvalidEntryPoint6 () : (Int, Qubit)[] { return Default<(Int, Qubit)[]>(); } - @ EntryPoint() + @EntryPoint() operation InvalidEntryPoint7 (arg : (Unit -> Unit)) : Unit {} - @ EntryPoint() + @EntryPoint() operation InvalidEntryPoint8 (arg : ((Unit -> Unit), Int)) : Unit {} - @ EntryPoint() + @EntryPoint() function InvalidEntryPoint9 (arg : ((Unit -> Unit)[], Int)) : Unit {} - @ EntryPoint() + @EntryPoint() function InvalidEntryPoint10 () : (Unit -> Unit) { return Default<(Unit -> Unit)>(); } - @ EntryPoint() + @EntryPoint() function InvalidEntryPoint11 () : (Unit -> Unit)[] { return Default<(Unit -> Unit)[]>(); } - @ EntryPoint() + @EntryPoint() operation InvalidEntryPoint12 () : (BigInt, (Unit -> Unit)) { return Default<(BigInt, (Unit -> Unit))>(); } - @ EntryPoint() + @EntryPoint() operation InvalidEntryPoint13 () : (Qubit -> Unit) { return Default<(Qubit -> Unit)>(); } - @ EntryPoint() + @EntryPoint() function InvalidEntryPoint14 () : (Unit -> Qubit) { return Default<(Unit -> Qubit)>(); } - @ EntryPoint() + @EntryPoint() function InvalidEntryPoint15 () : (Qubit[] -> Unit) { return Default<(Qubit[] -> Unit)>(); } - @ EntryPoint() + @EntryPoint() function InvalidEntryPoint16 () : (Unit -> (Int, Qubit)) { return Default<(Unit -> (Int, Qubit))>(); } - @ EntryPoint() + @EntryPoint() function InvalidEntryPoint17 (arg : (Unit => Unit is Adj)) : Unit {} - @ EntryPoint() + @EntryPoint() operation InvalidEntryPoint18 (arg : ((Unit => Unit), Int)) : Unit {} - @ EntryPoint() + @EntryPoint() operation InvalidEntryPoint19 (arg : ((Unit => Unit is Ctl)[], Int)) : Unit {} - @ EntryPoint() + @EntryPoint() function InvalidEntryPoint20 () : (Unit => Unit is Ctl + Adj) { return Default<(Unit => Unit is Ctl + Adj)>(); } - @ EntryPoint() + @EntryPoint() function InvalidEntryPoint21 () : (Unit => Unit)[] { return Default<(Unit => Unit)[]>(); } - @ EntryPoint() + @EntryPoint() function InvalidEntryPoint22 () : (BigInt, (Unit => Unit)) { return Default<(BigInt, (Unit => Unit))>(); } - @ EntryPoint() + @EntryPoint() operation InvalidEntryPoint23 () : (Qubit => Unit is Adj) { return Default<(Qubit => Unit is Adj)>(); } - @ EntryPoint() + @EntryPoint() function InvalidEntryPoint24 () : (Unit => Qubit is Ctl) { return Default<(Unit => Qubit is Ctl)>(); } - @ EntryPoint() + @EntryPoint() function InvalidEntryPoint25 () : (Qubit[] => Unit) { return Default<(Qubit[] => Unit)>(); } - @ EntryPoint() + @EntryPoint() operation InvalidEntryPoint26 () : (Unit => (Int, Qubit) is Ctl + Adj) { return Default<(Unit => (Int, Qubit) is Ctl + Adj)>(); } @@ -171,47 +171,47 @@ namespace Microsoft.Quantum.Testing.EntryPoints { newtype Complex = (Re : Double, Im : Double); - @ EntryPoint() + @EntryPoint() operation InvalidEntryPoint27 (arg : Complex) : Unit {} - @ EntryPoint() + @EntryPoint() function InvalidEntryPoint28 (arg : (Int, Complex)) : Unit {} - @ EntryPoint() + @EntryPoint() function InvalidEntryPoint29 (arg : Complex[]) : Unit {} - @ EntryPoint() + @EntryPoint() function InvalidEntryPoint30 () : Complex { return Default(); } - @ EntryPoint() + @EntryPoint() operation InvalidEntryPoint31 () : ((Int, Complex), Int) { return Default<((Int, Complex), Int)>(); } - @ EntryPoint() + @EntryPoint() function InvalidEntryPoint32 () : (Int, Complex)[] { return Default<(Int, Complex)[]>(); } - @ EntryPoint() + @EntryPoint() operation InvalidEntryPoint33 () : (Complex => Unit is Adj) { return Default<(Complex => Unit is Adj)>(); } - @ EntryPoint() + @EntryPoint() function InvalidEntryPoint34 () : (Unit => Complex is Ctl) { return Default<(Unit => Complex is Ctl)>(); } - @ EntryPoint() + @EntryPoint() function InvalidEntryPoint35 () : (Complex[] => Unit) { return Default<(Complex[] => Unit)>(); } - @ EntryPoint() + @EntryPoint() operation InvalidEntryPoint36 () : (Unit => (Int, Complex) is Ctl + Adj) { return Default<(Unit => (Int, Complex) is Ctl + Adj)>(); } @@ -219,21 +219,21 @@ namespace Microsoft.Quantum.Testing.EntryPoints { // no inner tuples in entry point arguments - @ EntryPoint() + @EntryPoint() operation InvalidEntryPoint37(arg : (Int, BigInt[])) : Unit {} - @ EntryPoint() + @EntryPoint() operation InvalidEntryPoint38(arg1 : (Pauli, Result)[], arg2 : Double) : Unit {} // array item type validation in entry point arguments - @ EntryPoint() + @EntryPoint() operation InvalidEntryPoint39(arg : Int[][]) : Unit {} - @ EntryPoint() + @EntryPoint() operation InvalidEntryPoint40(arg : (Int[])[]) : Unit {} - @ EntryPoint() + @EntryPoint() operation InvalidEntryPoint41(a : Int[], (b : Int[][], c : Double)) : Unit {} } diff --git a/src/QsCompiler/Tests.Compiler/TestCases/LinkingTests/Monomorphization.qs b/src/QsCompiler/Tests.Compiler/TestCases/LinkingTests/Monomorphization.qs index 3a2640fbb3..9e7614309b 100644 --- a/src/QsCompiler/Tests.Compiler/TestCases/LinkingTests/Monomorphization.qs +++ b/src/QsCompiler/Tests.Compiler/TestCases/LinkingTests/Monomorphization.qs @@ -4,7 +4,7 @@ namespace Microsoft.Quantum.Testing.Monomorphization { open Microsoft.Quantum.Testing.Generics; - @ EntryPoint() + @EntryPoint() operation Test1() : Unit { Test1Main(); } @@ -15,7 +15,7 @@ namespace Microsoft.Quantum.Testing.Monomorphization { namespace Microsoft.Quantum.Testing.Monomorphization { open Microsoft.Quantum.Testing.Generics; - @ EntryPoint() + @EntryPoint() operation Test2() : Unit { Test2Main(); } @@ -26,7 +26,7 @@ namespace Microsoft.Quantum.Testing.Monomorphization { namespace Microsoft.Quantum.Testing.Monomorphization { open Microsoft.Quantum.Testing.Generics; - @ EntryPoint() + @EntryPoint() operation Test3() : Unit { Test3Main(); } @@ -37,7 +37,7 @@ namespace Microsoft.Quantum.Testing.Monomorphization { namespace Microsoft.Quantum.Testing.Monomorphization { open Microsoft.Quantum.Testing.Generics; - @ EntryPoint() + @EntryPoint() operation Test4() : Unit { Test4Main(); } @@ -55,7 +55,7 @@ namespace Microsoft.Quantum.Testing.Monomorphization { operation IsPublicUsesInternal<'A>(x : 'A) : Unit { } operation IsPublicUsesPublic<'A>(x : 'A) : Unit { } - @ EntryPoint() + @EntryPoint() operation TestAccessModifiers() : Unit { IsInternalUsesInternal(MyInternalUDT(12)); IsInternalUsesPublic(MyPublicUDT("Yes")); @@ -76,7 +76,7 @@ namespace Microsoft.Quantum.Testing.Monomorphization { operation IsPublicUsesInternal<'A>() : 'A { return Default<'A>(); } operation IsPublicUsesPublic<'A>() : 'A { return Default<'A>(); } - @ EntryPoint() + @EntryPoint() operation TestAccessModifiers() : Unit { let temp1 = IsInternalUsesInternal(); let temp2 = IsInternalUsesPublic(); @@ -97,7 +97,7 @@ namespace Microsoft.Quantum.Testing.Monomorphization { operation IsPublicUsesInternal<'A>(x : 'A) : Unit { } operation IsPublicUsesPublic<'A>(x : 'A) : Unit { } - @ EntryPoint() + @EntryPoint() operation TestAccessModifiers() : Unit { IsInternalUsesInternal(new MyInternalUDT[1]); IsInternalUsesPublic(new MyPublicUDT[1]); @@ -118,7 +118,7 @@ namespace Microsoft.Quantum.Testing.Monomorphization { operation IsPublicUsesInternal<'A>() : 'A { return Default<'A>(); } operation IsPublicUsesPublic<'A>() : 'A { return Default<'A>(); } - @ EntryPoint() + @EntryPoint() operation TestAccessModifiers() : Unit { let temp1 = IsInternalUsesInternal(); let temp2 = IsInternalUsesPublic(); @@ -139,7 +139,7 @@ namespace Microsoft.Quantum.Testing.Monomorphization { operation IsPublicUsesInternal<'A>(x : 'A) : Unit { } operation IsPublicUsesPublic<'A>(x : 'A) : Unit { } - @ EntryPoint() + @EntryPoint() operation TestAccessModifiers() : Unit { IsInternalUsesInternal((MyInternalUDT(12), 0)); IsInternalUsesPublic((MyPublicUDT("Yes"), 0)); @@ -160,7 +160,7 @@ namespace Microsoft.Quantum.Testing.Monomorphization { operation IsPublicUsesInternal<'A>() : 'A { return Default<'A>(); } operation IsPublicUsesPublic<'A>() : 'A { return Default<'A>(); } - @ EntryPoint() + @EntryPoint() operation TestAccessModifiers() : Unit { let temp1 = IsInternalUsesInternal<(MyInternalUDT, Int)>(); let temp2 = IsInternalUsesPublic<(MyPublicUDT, Int)>(); @@ -184,7 +184,7 @@ namespace Microsoft.Quantum.Testing.Monomorphization { internal operation InternalFoo(x : MyInternalUDT) : Unit { } operation PublicFoo(x : MyPublicUDT) : Unit { } - @ EntryPoint() + @EntryPoint() operation TestAccessModifiers() : Unit { IsInternalUsesInternal(InternalFoo); IsInternalUsesPublic(PublicFoo); @@ -208,7 +208,7 @@ namespace Microsoft.Quantum.Testing.Monomorphization { internal operation InternalFoo(x : MyInternalUDT) : Unit { } operation PublicFoo(x : MyPublicUDT) : Unit { } - @ EntryPoint() + @EntryPoint() operation TestAccessModifiers() : Unit { let temp1 = IsInternalUsesInternal<(MyInternalUDT => Unit)>(); let temp2 = IsInternalUsesPublic<(MyPublicUDT => Unit)>(); @@ -222,7 +222,7 @@ namespace Microsoft.Quantum.Testing.Monomorphization { namespace Microsoft.Quantum.Testing.Monomorphization { open Microsoft.Quantum.Arrays; - @ EntryPoint() + @EntryPoint() operation TestTypeParameterResolutions(qs : Int[]) : Unit { let res = new Result[Length(qs)]; let idx = IndexRange(qs); @@ -238,8 +238,8 @@ namespace Microsoft.Quantum.Testing.Monomorphization { body intrinsic; } - @ EntryPoint() + @EntryPoint() operation TestDuplicateIntrinsic() : Unit { CustomIntrinsic(); } -} \ No newline at end of file +} diff --git a/src/QsCompiler/Tests.Compiler/TestCases/LinkingTests/SyntaxTreeTrim.qs b/src/QsCompiler/Tests.Compiler/TestCases/LinkingTests/SyntaxTreeTrim.qs new file mode 100644 index 0000000000..22a1f020f6 --- /dev/null +++ b/src/QsCompiler/Tests.Compiler/TestCases/LinkingTests/SyntaxTreeTrim.qs @@ -0,0 +1,59 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +// Trimmer Removes Unused Callables +namespace Microsoft.Quantum.Testing.SyntaxTreeTrimming { + + @EntryPoint() + operation Main() : Unit { + UsedOp(); + } + + operation UsedOp() : Unit { UsedFunc(); } + operation UnusedOp() : Unit { UnusedFunc(); } + + function UsedFunc() : Unit { } + function UnusedFunc() : Unit { } +} + +// ================================= + +// Trimmer Keeps UDTs +namespace Microsoft.Quantum.Testing.SyntaxTreeTrimming { + + newtype UsedUDT = Int; + newtype UnusedUDT = String; + + @EntryPoint() + operation Main() : Unit { + let x = UsedUDT(3); + } +} + +// ================================= + +// Trimmer Keeps Intrinsics When Told +namespace Microsoft.Quantum.Testing.SyntaxTreeTrimming { + + @EntryPoint() + operation Main() : Unit { + UsedIntrinsic(); + } + + operation UsedIntrinsic() : Unit { body intrinsic; } + operation UnusedIntrinsic() : Unit { body intrinsic; } +} + +// ================================= + +// Trimmer Removes Intrinsics When Told +namespace Microsoft.Quantum.Testing.SyntaxTreeTrimming { + + @EntryPoint() + operation Main() : Unit { + UsedIntrinsic(); + } + + operation UsedIntrinsic() : Unit { body intrinsic; } + operation UnusedIntrinsic() : Unit { body intrinsic; } +} diff --git a/src/QsCompiler/Tests.Compiler/TestCases/LinkingTests/ValidEntryPoints.qs b/src/QsCompiler/Tests.Compiler/TestCases/LinkingTests/ValidEntryPoints.qs index 5ab96f47a9..3d7919ed79 100644 --- a/src/QsCompiler/Tests.Compiler/TestCases/LinkingTests/ValidEntryPoints.qs +++ b/src/QsCompiler/Tests.Compiler/TestCases/LinkingTests/ValidEntryPoints.qs @@ -6,7 +6,7 @@ namespace Microsoft.Quantum.Testing.EntryPoints { - @ EntryPoint() + @EntryPoint() function ValidEntryPoint1() : Unit { } } @@ -14,7 +14,7 @@ namespace Microsoft.Quantum.Testing.EntryPoints { namespace Microsoft.Quantum.Testing.EntryPoints { - @ EntryPoint() + @EntryPoint() operation ValidEntryPoint2() : Unit { } } @@ -22,7 +22,7 @@ namespace Microsoft.Quantum.Testing.EntryPoints { namespace Microsoft.Quantum.Testing.EntryPoints { - @ EntryPoint() + @EntryPoint() operation ValidEntryPoint3() : Unit { body (...) {} } @@ -32,7 +32,7 @@ namespace Microsoft.Quantum.Testing.EntryPoints { namespace Microsoft.Quantum.Testing.EntryPoints { - @ EntryPoint() + @EntryPoint() operation ValidEntryPoint4(arg : String) : Unit {} } @@ -40,7 +40,7 @@ namespace Microsoft.Quantum.Testing.EntryPoints { namespace Microsoft.Quantum.Testing.EntryPoints { - @ EntryPoint() + @EntryPoint() operation ValidEntryPoint5(arg : String[]) : Unit {} } @@ -48,7 +48,7 @@ namespace Microsoft.Quantum.Testing.EntryPoints { namespace Microsoft.Quantum.Testing.EntryPoints { - @ EntryPoint() + @EntryPoint() operation ValidEntryPoint6(a : Int, b: Double[]) : Unit {} } @@ -56,7 +56,7 @@ namespace Microsoft.Quantum.Testing.EntryPoints { namespace Microsoft.Quantum.Testing.EntryPoints { - @ EntryPoint() + @EntryPoint() operation ValidEntryPoint7(arg1 : (Int)[], arg2 : Double) : Unit {} } @@ -64,7 +64,7 @@ namespace Microsoft.Quantum.Testing.EntryPoints { namespace Microsoft.Quantum.Testing.EntryPoints { - @ EntryPoint() + @EntryPoint() operation ValidEntryPoint8((b1 : Bool, b2 : Bool), r : Range) : Unit {} } @@ -72,7 +72,7 @@ namespace Microsoft.Quantum.Testing.EntryPoints { namespace Microsoft.Quantum.Testing.EntryPoints { - @ EntryPoint() + @EntryPoint() operation ValidEntryPoint9() : Result { return Default(); } @@ -82,7 +82,7 @@ namespace Microsoft.Quantum.Testing.EntryPoints { namespace Microsoft.Quantum.Testing.EntryPoints { - @ EntryPoint() + @EntryPoint() operation ValidEntryPoint10() : Result[] { return Default(); } @@ -92,7 +92,7 @@ namespace Microsoft.Quantum.Testing.EntryPoints { namespace Microsoft.Quantum.Testing.EntryPoints { - @ EntryPoint() + @EntryPoint() operation ValidEntryPoint11() : (Result, Result[]) { return Default<(Result, Result[])>(); } @@ -102,7 +102,7 @@ namespace Microsoft.Quantum.Testing.EntryPoints { namespace Microsoft.Quantum.Testing.EntryPoints { - @ EntryPoint() + @EntryPoint() operation ValidEntryPoint12() : (Int, BigInt[]) { return Default<(Int, BigInt[])>(); } @@ -112,7 +112,7 @@ namespace Microsoft.Quantum.Testing.EntryPoints { namespace Microsoft.Quantum.Testing.EntryPoints { - @ EntryPoint() + @EntryPoint() operation ValidEntryPoint13() : (Double, (Pauli, Int)[]) { return Default<(Double, (Pauli, Int)[])>(); } @@ -122,7 +122,7 @@ namespace Microsoft.Quantum.Testing.EntryPoints { namespace Microsoft.Quantum.Testing.EntryPoints { - @ EntryPoint() + @EntryPoint() operation ValidEntryPoint14() : ((Bool, String)[][], (Unit, Range)) { return Default<((Bool, String)[][], (Unit, Range))>(); } @@ -132,7 +132,7 @@ namespace Microsoft.Quantum.Testing.EntryPoints { namespace Microsoft.Quantum.Testing.EntryPoints { - @ EntryPoint() + @EntryPoint() operation ValidEntryPoint15(a : Int[], (b : Double[], c : String[])) : Unit { } } @@ -140,7 +140,7 @@ namespace Microsoft.Quantum.Testing.EntryPoints { namespace Microsoft.Quantum.Testing.EntryPoints { - @ EntryPoint() + @EntryPoint() operation ValidEntryPoint16(a : BigInt[]) : Unit {} } @@ -148,7 +148,7 @@ namespace Microsoft.Quantum.Testing.EntryPoints { namespace Microsoft.Quantum.Testing.EntryPoints { - @ EntryPoint() + @EntryPoint() operation ValidEntryPoint17(a : Range[]) : Unit {} } @@ -156,7 +156,7 @@ namespace Microsoft.Quantum.Testing.EntryPoints { namespace Microsoft.Quantum.Testing.EntryPoints { - @ EntryPoint() + @EntryPoint() operation ValidEntryPoint18(a : Result[]) : Unit {} } @@ -164,7 +164,7 @@ namespace Microsoft.Quantum.Testing.EntryPoints { namespace Microsoft.Quantum.Testing.EntryPoints { - @ EntryPoint() + @EntryPoint() operation ValidEntryPoint19(a : Pauli[]) : Unit {} } diff --git a/src/QsCompiler/Tests.Compiler/TestCases/LocalVerification.qs b/src/QsCompiler/Tests.Compiler/TestCases/LocalVerification.qs index 73fde82c4a..d68f5381a6 100644 --- a/src/QsCompiler/Tests.Compiler/TestCases/LocalVerification.qs +++ b/src/QsCompiler/Tests.Compiler/TestCases/LocalVerification.qs @@ -1169,43 +1169,43 @@ namespace Microsoft.Quantum.Testing.LocalVerification { // deprecation warnings - @ Attribute() - @ Deprecated("") + @Attribute() + @Deprecated("") newtype DeprecatedAttribute = Unit; - @ Attribute() - @ Deprecated("OldAttribute") + @Attribute() + @Deprecated("OldAttribute") newtype RenamedAttribute = Unit; - @ Deprecated("") + @Deprecated("") newtype DeprecatedType = Unit; - @ Deprecated("NewTypeName") + @Deprecated("NewTypeName") newtype RenamedType = Unit; - @ Deprecated("") + @Deprecated("") function DeprecatedCallable() : Unit {} - @ Deprecated("NewCallableName") + @Deprecated("NewCallableName") function RenamedCallable() : Unit {} - @ Deprecated("") - @ Deprecated("") + @Deprecated("") + @Deprecated("") function DuplicateDeprecateAttribute1() : Unit {} - @ Deprecated("") - @ Deprecated("NewName") // will be ignored + @Deprecated("") + @Deprecated("NewName") // will be ignored function DuplicateDeprecateAttribute2() : Unit {} newtype DeprecatedItemType1 = (Unit -> DeprecatedType)[]; - @ Attribute() + @Attribute() newtype DeprecatedItemType2 = DeprecatedType; newtype RenamedItemType1 = (Int, RenamedType); - @ Attribute() + @Attribute() newtype RenamedItemType2 = RenamedType; @@ -1221,7 +1221,7 @@ namespace Microsoft.Quantum.Testing.LocalVerification { DeprecatedCallable(); } - @ Deprecated("nested") + @Deprecated("nested") function NestedDeprecatedCallable() : Unit { DeprecatedCallable(); } @@ -1235,16 +1235,16 @@ namespace Microsoft.Quantum.Testing.LocalVerification { } - @ DeprecatedAttribute() + @DeprecatedAttribute() function UsingDeprecatedAttribute1 () : Unit {} - @ DeprecatedAttribute() + @DeprecatedAttribute() operation UsingDeprecatedAttribute2 () : Unit {} - @ DeprecatedAttribute() + @DeprecatedAttribute() newtype UsingDeprecatedAttribute3 = Unit; - @ Deprecated("") + @Deprecated("") function DeprecatedAttributeInDeprecatedCallable() : Unit { UsingDeprecatedAttribute1(); } @@ -1253,7 +1253,7 @@ namespace Microsoft.Quantum.Testing.LocalVerification { DeprecatedAttributeInDeprecatedCallable(); } - @ Deprecated("") + @Deprecated("") function DeprecatedTypeInDeprecatedCallable() : Unit { let _ = DeprecatedType(); } @@ -1262,13 +1262,13 @@ namespace Microsoft.Quantum.Testing.LocalVerification { DeprecatedTypeInDeprecatedCallable(); } - @ RenamedAttribute() + @RenamedAttribute() function UsingRenamedAttribute1 () : Unit {} - @ RenamedAttribute() + @RenamedAttribute() operation UsingRenamedAttribute2 () : Unit {} - @ RenamedAttribute() + @RenamedAttribute() newtype UsingRenamedAttribute3 = Unit; @@ -1311,152 +1311,152 @@ namespace Microsoft.Quantum.Testing.LocalVerification { @Test("QuantumSimulator") function ValidTestAttribute1 () : Unit {} - @ Test("ResourcesEstimator") + @Test("ResourcesEstimator") function ValidTestAttribute2 () : Unit {} - @ Test("ToffoliSimulator") + @Test("ToffoliSimulator") function ValidTestAttribute3 () : Unit {} - @ Test("QuantumSimulator") + @Test("QuantumSimulator") operation ValidTestAttribute4 () : Unit {} - @ Test("ResourcesEstimator") + @Test("ResourcesEstimator") operation ValidTestAttribute5 () : Unit {} - @ Test("ToffoliSimulator") + @Test("ToffoliSimulator") operation ValidTestAttribute6 () : Unit {} - @ Test("QuantumSimulator") + @Test("QuantumSimulator") operation ValidTestAttribute7 () : Unit is Adj + Ctl{} - @ Test("ResourcesEstimator") + @Test("ResourcesEstimator") operation ValidTestAttribute8 () : Unit is Adj {} - @ Test("ToffoliSimulator") + @Test("ToffoliSimulator") operation ValidTestAttribute9 () : Unit is Ctl {} - @ Test("QuantumSimulator") + @Test("QuantumSimulator") function ValidTestAttribute10 () : ((Unit)) {} - @ Test("ResourcesEstimator") + @Test("ResourcesEstimator") function ValidTestAttribute11 (arg : Unit) : Unit { } - @ Test("ToffoliSimulator") + @Test("ToffoliSimulator") operation ValidTestAttribute12 (arg : (Unit)) : Unit { } - @ Test("QuantumSimulator") - @ Test("ToffoliSimulator") - @ Test("ResourcesEstimator") + @Test("QuantumSimulator") + @Test("ToffoliSimulator") + @Test("ResourcesEstimator") function ValidTestAttribute13 () : Unit { } - @ Test("QuantumSimulator") - @ Test("ToffoliSimulator") - @ Test("ResourcesEstimator") + @Test("QuantumSimulator") + @Test("ToffoliSimulator") + @Test("ResourcesEstimator") operation ValidTestAttribute14 () : Unit { } - @ Test("QuantumSimulator") - @ Test("QuantumSimulator") + @Test("QuantumSimulator") + @Test("QuantumSimulator") operation ValidTestAttribute15 () : Unit { } - @ Test("QuantumSimulator") + @Test("QuantumSimulator") operation ValidTestAttribute16 () : { } - @ Test("SomeNamespace.Target") + @Test("SomeNamespace.Target") operation ValidTestAttribute17 () : Unit { } - @ Test("SomeNamespace.Target1") - @ Test("_Some3_Namespace_._My45.Target2") + @Test("SomeNamespace.Target1") + @Test("_Some3_Namespace_._My45.Target2") function ValidTestAttribute18 () : Unit { } - @ Test("SomeNamespace.Target") - @ Test("SomeNamespace.Target") + @Test("SomeNamespace.Target") + @Test("SomeNamespace.Target") function ValidTestAttribute19 () : Unit { } - @ Test("SomeNamespace.Target") - @ Test("QuantumSimulator") + @Test("SomeNamespace.Target") + @Test("QuantumSimulator") operation ValidTestAttribute20 () : Unit { } - @ Test("QuantumSimulator") + @Test("QuantumSimulator") newtype InvalidTestAttribute1 = Unit; function InvalidTestAttribute2 () : Unit { - @ Test("ToffoliSimulator") + @Test("ToffoliSimulator") body (...) {} } operation InvalidTestAttribute3 () : Unit { - @ Test("ResourcesEstimator") + @Test("ResourcesEstimator") body (...) {} } operation InvalidTestAttribute4 () : Unit { body (...) { } - @ Test("ResourcesEstimator") + @Test("ResourcesEstimator") adjoint (...) { } } - @ Test("ResourcesEstimator") + @Test("ResourcesEstimator") function InvalidTestAttribute5<'T> () : Unit { } - @ Test("QuantumSimulator") + @Test("QuantumSimulator") operation InvalidTestAttribute6<'T> () : Unit { } - @ Test("ResourcesEstimator") + @Test("ResourcesEstimator") operation InvalidTestAttribute7 () : Int { return 1; } - @ Test("ToffoliSimulator") + @Test("ToffoliSimulator") function InvalidTestAttribute8 () : String { return ""; } - @ Test("QuantumSimulator") + @Test("QuantumSimulator") function InvalidTestAttribute9 (a : Unit, b : Unit) : Unit { } - @ Test("ResourcesEstimator") + @Test("ResourcesEstimator") operation InvalidTestAttribute10 (a : Bool) : Unit { } - @ Test("ToffoliSimulator") + @Test("ToffoliSimulator") operation InvalidTestAttribute11 ((a : Double)) : Unit { } - @ Test("") + @Test("") operation InvalidTestAttribute12 () : Unit { } - @ Test(" ") + @Test(" ") function InvalidTestAttribute13 () : Unit { } - @ Test("Target") + @Test("Target") function InvalidTestAttribute14 () : Unit { } - @ Test("Target") - @ Test("ToffoliSimulator") - @ Test("ToffoliSimulator") + @Test("Target") + @Test("ToffoliSimulator") + @Test("ToffoliSimulator") operation InvalidTestAttribute15 () : Unit { } - @ Test("QuantumSimulator") + @Test("QuantumSimulator") operation InvalidTestAttribute16 () : NonExistent { } - @ Test () + @Test () operation InvalidTestAttribute17 () : Unit { } - @ Test + @Test operation InvalidTestAttribute18 () : Unit { } - @ Test("SomeNamespace.") + @Test("SomeNamespace.") operation InvalidTestAttribute19 () : Unit { } - @ Test("NS.3Qubit") + @Test("NS.3Qubit") operation InvalidTestAttribute20 () : Unit { } - @ Test("SomeNamespace .Target") + @Test("SomeNamespace .Target") function InvalidTestAttribute21 () : Unit { } - @ Test("Some Namespace.Target") + @Test("Some Namespace.Target") function InvalidTestAttribute22 () : Unit { } diff --git a/src/QsCompiler/Tests.Compiler/TestCases/OptimizerTests/FunctionEval_output.txt b/src/QsCompiler/Tests.Compiler/TestCases/OptimizerTests/FunctionEval_output.txt index 596558d91d..0c4c92235d 100644 --- a/src/QsCompiler/Tests.Compiler/TestCases/OptimizerTests/FunctionEval_output.txt +++ b/src/QsCompiler/Tests.Compiler/TestCases/OptimizerTests/FunctionEval_output.txt @@ -11,14 +11,14 @@ namespace Microsoft.Quantum.Testing.Optimization.FunctionEval { mutable z = [0, 0, 0, 0, 0]; set z = z w/ 0 <- x; - while (z[0] > 0) { + while z[0] > 0 { set y = y + w; set z = z w/ 0 <- z[0] / 2; } mutable b = 0; - for (a in z) { + for a in z { set b = b + a; } @@ -28,11 +28,11 @@ namespace Microsoft.Quantum.Testing.Optimization.FunctionEval { function g1 (x : Int) : Int { - if (x == 0) { + if x == 0 { return 0; } - if (x == 1) { + if x == 1 { return 1; } @@ -50,7 +50,7 @@ namespace Microsoft.Quantum.Testing.Optimization.FunctionEval { let y = ArcSinh(x); - if (y == 0.0) { + if y == 0.0 { return 2.0; } diff --git a/src/QsCompiler/Tests.Compiler/TestCases/OptimizerTests/Inlining_output.txt b/src/QsCompiler/Tests.Compiler/TestCases/OptimizerTests/Inlining_output.txt index 369e9be9aa..a2640f21c4 100644 --- a/src/QsCompiler/Tests.Compiler/TestCases/OptimizerTests/Inlining_output.txt +++ b/src/QsCompiler/Tests.Compiler/TestCases/OptimizerTests/Inlining_output.txt @@ -2,10 +2,10 @@ namespace Microsoft.Quantum.Testing.Optimization.Inlining { operation f (q : Qubit, n : Int) : Unit { - if (n == 0) { + if n == 0 { // Do nothing } - elif (n == 1) { + elif n == 1 { T(q); } else { diff --git a/src/QsCompiler/Tests.Compiler/TestCases/OptimizerTests/LoopUnrolling_output.txt b/src/QsCompiler/Tests.Compiler/TestCases/OptimizerTests/LoopUnrolling_output.txt index 67fb7b529b..9dc713241f 100644 --- a/src/QsCompiler/Tests.Compiler/TestCases/OptimizerTests/LoopUnrolling_output.txt +++ b/src/QsCompiler/Tests.Compiler/TestCases/OptimizerTests/LoopUnrolling_output.txt @@ -4,7 +4,7 @@ namespace Microsoft.Quantum.Testing.Optimization.LoopUnrolling { mutable r = 0; - using ((__qsItem0__qs__, __qsItem1__qs__, __qsItem2__qs__, __qsItem3__qs__, __qsItem4__qs__, __qsItem5__qs__, __qsItem6__qs__, __qsItem7__qs__, __qsItem8__qs__, __qsItem9__qs__) = (Qubit(), Qubit(), Qubit(), Qubit(), Qubit(), Qubit(), Qubit(), Qubit(), Qubit(), Qubit())) { + use (__qsItem0__qs__, __qsItem1__qs__, __qsItem2__qs__, __qsItem3__qs__, __qsItem4__qs__, __qsItem5__qs__, __qsItem6__qs__, __qsItem7__qs__, __qsItem8__qs__, __qsItem9__qs__) = (Qubit(), Qubit(), Qubit(), Qubit(), Qubit(), Qubit(), Qubit(), Qubit(), Qubit(), Qubit()) { X(__qsItem0__qs__); X(__qsItem1__qs__); X(__qsItem2__qs__); diff --git a/src/QsCompiler/Tests.Compiler/TestCases/OptimizerTests/Miscellaneous_output.txt b/src/QsCompiler/Tests.Compiler/TestCases/OptimizerTests/Miscellaneous_output.txt index 262bdb264f..4875cd685a 100644 --- a/src/QsCompiler/Tests.Compiler/TestCases/OptimizerTests/Miscellaneous_output.txt +++ b/src/QsCompiler/Tests.Compiler/TestCases/OptimizerTests/Miscellaneous_output.txt @@ -34,7 +34,7 @@ namespace Microsoft.Quantum.Testing { body (...) { Adjoint CNOT(q1, (r1!)[0]); - for (item in r1!) { + for item in r1! { CNOT(q1, item); CNOT(q1, item); CNOT(q1, item); @@ -47,7 +47,7 @@ namespace Microsoft.Quantum.Testing { controlled (__controlQubits__, ...) { Controlled (Adjoint CNOT)(__controlQubits__, (q1, (r1!)[0])); - for (item in r1!) { + for item in r1! { Controlled CNOT(__controlQubits__, (q1, item)); Controlled CNOT(__controlQubits__, (q1, item)); Controlled CNOT(__controlQubits__, (q1, item)); @@ -62,7 +62,7 @@ namespace Microsoft.Quantum.Testing { body (...) { Adjoint CNOT(q2, (b2!)[0]); - for (item in b2!) { + for item in b2! { CNOT(q2, item); CNOT(q2, item); CNOT(q2, item); @@ -70,10 +70,10 @@ namespace Microsoft.Quantum.Testing { let r = M(q2); - if (r == One) { + if r == One { Adjoint CNOT(q!, (b2!)[0]); - for (__qsVar1__item__ in b2!) { + for __qsVar1__item__ in b2! { CNOT(q!, __qsVar1__item__); CNOT(q!, __qsVar1__item__); CNOT(q!, __qsVar1__item__); @@ -81,7 +81,7 @@ namespace Microsoft.Quantum.Testing { Adjoint CNOT(q!, (b2!)[0]); - for (__qsVar2__item__ in b2!) { + for __qsVar2__item__ in b2! { CNOT(q!, __qsVar2__item__); CNOT(q!, __qsVar2__item__); CNOT(q!, __qsVar2__item__); @@ -89,7 +89,7 @@ namespace Microsoft.Quantum.Testing { Adjoint CNOT(q!, (b2!)[0]); - for (__qsVar3__item__ in b2!) { + for __qsVar3__item__ in b2! { CNOT(q!, __qsVar3__item__); CNOT(q!, __qsVar3__item__); CNOT(q!, __qsVar3__item__); @@ -103,7 +103,7 @@ namespace Microsoft.Quantum.Testing { adjoint (...) { Adjoint CNOT(q!, (b2!)[0]); - for (item in b2!) { + for item in b2! { CNOT(q!, item); CNOT(q!, item); CNOT(q!, item); @@ -111,7 +111,7 @@ namespace Microsoft.Quantum.Testing { Adjoint CNOT(q!, (b2!)[0]); - for (__qsVar1__item__ in b2!) { + for __qsVar1__item__ in b2! { CNOT(q!, __qsVar1__item__); CNOT(q!, __qsVar1__item__); CNOT(q!, __qsVar1__item__); @@ -119,7 +119,7 @@ namespace Microsoft.Quantum.Testing { Adjoint CNOT(q!, (b2!)[0]); - for (__qsVar2__item__ in b2!) { + for __qsVar2__item__ in b2! { CNOT(q!, __qsVar2__item__); CNOT(q!, __qsVar2__item__); CNOT(q!, __qsVar2__item__); @@ -127,7 +127,7 @@ namespace Microsoft.Quantum.Testing { Adjoint CNOT(q!, (b2!)[0]); - for (__qsVar3__item__ in b2!) { + for __qsVar3__item__ in b2! { CNOT(q!, __qsVar3__item__); CNOT(q!, __qsVar3__item__); CNOT(q!, __qsVar3__item__); @@ -135,7 +135,7 @@ namespace Microsoft.Quantum.Testing { Adjoint CNOT(q!, (b2!)[0]); - for (__qsVar4__item__ in b2!) { + for __qsVar4__item__ in b2! { CNOT(q!, __qsVar4__item__); CNOT(q!, __qsVar4__item__); CNOT(q!, __qsVar4__item__); @@ -143,7 +143,7 @@ namespace Microsoft.Quantum.Testing { Adjoint CNOT(q!, (b2!)[0]); - for (__qsVar5__item__ in b2!) { + for __qsVar5__item__ in b2! { CNOT(q!, __qsVar5__item__); CNOT(q!, __qsVar5__item__); CNOT(q!, __qsVar5__item__); @@ -151,7 +151,7 @@ namespace Microsoft.Quantum.Testing { Adjoint CNOT(q2, (b2!)[0]); - for (__qsVar6__item__ in b2!) { + for __qsVar6__item__ in b2! { CNOT(q2, __qsVar6__item__); CNOT(q2, __qsVar6__item__); CNOT(q2, __qsVar6__item__); @@ -161,7 +161,7 @@ namespace Microsoft.Quantum.Testing { controlled (ctrls, ...) { Controlled (Adjoint CNOT)(ctrls, (q2, (b2!)[0])); - for (item in b2!) { + for item in b2! { Controlled CNOT(ctrls, (q2, item)); Controlled CNOT(ctrls, (q2, item)); Controlled CNOT(ctrls, (q2, item)); @@ -169,10 +169,10 @@ namespace Microsoft.Quantum.Testing { let r = M(q2); - if (r == One) { + if r == One { Controlled (Adjoint CNOT)(ctrls, (q!, (b2!)[0])); - for (__qsVar1__item__ in b2!) { + for __qsVar1__item__ in b2! { Controlled CNOT(ctrls, (q!, __qsVar1__item__)); Controlled CNOT(ctrls, (q!, __qsVar1__item__)); Controlled CNOT(ctrls, (q!, __qsVar1__item__)); @@ -180,7 +180,7 @@ namespace Microsoft.Quantum.Testing { Controlled (Adjoint CNOT)(ctrls, (q!, (b2!)[0])); - for (__qsVar2__item__ in b2!) { + for __qsVar2__item__ in b2! { Controlled CNOT(ctrls, (q!, __qsVar2__item__)); Controlled CNOT(ctrls, (q!, __qsVar2__item__)); Controlled CNOT(ctrls, (q!, __qsVar2__item__)); @@ -188,7 +188,7 @@ namespace Microsoft.Quantum.Testing { Controlled (Adjoint CNOT)(ctrls, (q!, (b2!)[0])); - for (__qsVar3__item__ in b2!) { + for __qsVar3__item__ in b2! { Controlled CNOT(ctrls, (q!, __qsVar3__item__)); Controlled CNOT(ctrls, (q!, __qsVar3__item__)); Controlled CNOT(ctrls, (q!, __qsVar3__item__)); @@ -196,7 +196,7 @@ namespace Microsoft.Quantum.Testing { Controlled (Adjoint CNOT)(ctrls, (q!, (b2!)[0])); - for (__qsVar4__item__ in b2!) { + for __qsVar4__item__ in b2! { Controlled CNOT(ctrls, (q!, __qsVar4__item__)); Controlled CNOT(ctrls, (q!, __qsVar4__item__)); Controlled CNOT(ctrls, (q!, __qsVar4__item__)); @@ -204,7 +204,7 @@ namespace Microsoft.Quantum.Testing { Controlled (Adjoint CNOT)(ctrls, (q!, (b2!)[0])); - for (__qsVar5__item__ in b2!) { + for __qsVar5__item__ in b2! { Controlled CNOT(ctrls, (q!, __qsVar5__item__)); Controlled CNOT(ctrls, (q!, __qsVar5__item__)); Controlled CNOT(ctrls, (q!, __qsVar5__item__)); @@ -212,7 +212,7 @@ namespace Microsoft.Quantum.Testing { Controlled (Adjoint CNOT)(ctrls, (q!, (b2!)[0])); - for (__qsVar6__item__ in b2!) { + for __qsVar6__item__ in b2! { Controlled CNOT(ctrls, (q!, __qsVar6__item__)); Controlled CNOT(ctrls, (q!, __qsVar6__item__)); Controlled CNOT(ctrls, (q!, __qsVar6__item__)); @@ -223,7 +223,7 @@ namespace Microsoft.Quantum.Testing { controlled adjoint (ctrls, ...) { Controlled (Adjoint CNOT)(ctrls, (q2, (b2!)[0])); - for (item in b2!) { + for item in b2! { Controlled CNOT(ctrls, (q2, item)); Controlled CNOT(ctrls, (q2, item)); Controlled CNOT(ctrls, (q2, item)); @@ -236,9 +236,9 @@ namespace Microsoft.Quantum.Testing { let twice = d * 2.0; - if (twice > 1.0) { + if twice > 1.0 { - if (p == PauliZ) { + if p == PauliZ { return op0; } } @@ -249,14 +249,14 @@ namespace Microsoft.Quantum.Testing { operation Test () : Unit { - using ((q1, q2, __qsItem1__qs__, __qsItem2__qs__, __qsItem3__qs__, __qsItem4__qs__) = (Qubit(), Qubit(), Qubit(), Qubit(), Qubit(), Qubit())) { + use (q1, q2, __qsItem1__qs__, __qsItem2__qs__, __qsItem3__qs__, __qsItem4__qs__) = (Qubit(), Qubit(), Qubit(), Qubit(), Qubit(), Qubit()) { CNOT(q1, __qsItem1__qs__); CNOT(q1, __qsItem2__qs__); CNOT(q1, __qsItem3__qs__); CNOT(q1, __qsItem4__qs__); let r = M(q1); - if (r == One) { + if r == One { CNOT(q2, __qsItem1__qs__); CNOT(q2, __qsItem2__qs__); CNOT(q2, __qsItem3__qs__); diff --git a/src/QsCompiler/Tests.Compiler/TestCases/OptimizerTests/NoOp_output.txt b/src/QsCompiler/Tests.Compiler/TestCases/OptimizerTests/NoOp_output.txt index 4c264466aa..f8a91d926b 100644 --- a/src/QsCompiler/Tests.Compiler/TestCases/OptimizerTests/NoOp_output.txt +++ b/src/QsCompiler/Tests.Compiler/TestCases/OptimizerTests/NoOp_output.txt @@ -9,7 +9,7 @@ namespace Microsoft.Quantum.Testing.Optimization.NoOp { mutable y = 0; - for (i in 0 .. x) { + for i in 0 .. x { f(y + i); set y = y + 1; } diff --git a/src/QsCompiler/Tests.Compiler/TestCases/PopulateCallGraph.qs b/src/QsCompiler/Tests.Compiler/TestCases/PopulateCallGraph.qs index d5bd43dd54..bd7a0c9529 100644 --- a/src/QsCompiler/Tests.Compiler/TestCases/PopulateCallGraph.qs +++ b/src/QsCompiler/Tests.Compiler/TestCases/PopulateCallGraph.qs @@ -4,7 +4,7 @@ // Basic Entry Point namespace Microsoft.Quantum.Testing.PopulateCallGraph { - @ EntryPoint() + @EntryPoint() operation Main() : Unit { Foo(); Bar(); @@ -24,7 +24,7 @@ namespace Microsoft.Quantum.Testing.PopulateCallGraph { // Unrelated To Entry Point namespace Microsoft.Quantum.Testing.PopulateCallGraph { - @ EntryPoint() + @EntryPoint() operation Main() : Unit { Foo(); } @@ -43,7 +43,7 @@ namespace Microsoft.Quantum.Testing.PopulateCallGraph { // Not Called With Entry Point namespace Microsoft.Quantum.Testing.PopulateCallGraph { - @ EntryPoint() + @EntryPoint() operation Main() : Unit { Foo(); } @@ -90,7 +90,7 @@ namespace Microsoft.Quantum.Testing.PopulateCallGraph { // Entry Point No Descendants namespace Microsoft.Quantum.Testing.PopulateCallGraph { - @ EntryPoint() + @EntryPoint() operation Main() : Unit { } operation Foo() : Unit { @@ -105,7 +105,7 @@ namespace Microsoft.Quantum.Testing.PopulateCallGraph { // Calls Entry Point From Entry Point namespace Microsoft.Quantum.Testing.PopulateCallGraph { - @ EntryPoint() + @EntryPoint() operation Main() : Unit { Foo(); } @@ -120,7 +120,7 @@ namespace Microsoft.Quantum.Testing.PopulateCallGraph { // Entry Point Ancestor And Descendant namespace Microsoft.Quantum.Testing.PopulateCallGraph { - @ EntryPoint() + @EntryPoint() operation Main() : Unit { Foo(); } @@ -134,10 +134,85 @@ namespace Microsoft.Quantum.Testing.PopulateCallGraph { // ================================= +// Multiple Entry Points +namespace Microsoft.Quantum.Testing.PopulateCallGraph { + + @EntryPoint() + operation Main1() : Unit { + Foo(); + } + + @EntryPoint() + operation Main2() : Unit { + Bar(); + } + + operation Foo() : Unit { } + + operation Bar() : Unit { } +} + +// ================================= + +// Unit Test as Starting Point +namespace Microsoft.Quantum.Testing.PopulateCallGraph { + + open Microsoft.Quantum.Diagnostics; + + @Test("QuantumSimulator") + operation Test() : Unit { + Foo(); + } + + operation Foo() : Unit { } + + operation Bar() : Unit { } +} + +// ================================= + +// Entry Points and Unit Tests +namespace Microsoft.Quantum.Testing.PopulateCallGraph { + + open Microsoft.Quantum.Diagnostics; + + @EntryPoint() + operation Main1() : Unit { + Foo(); + } + + @EntryPoint() + operation Main2() : Unit { + Bar(); + } + + @Test("QuantumSimulator") + operation Test1() : Unit { + Zip(); + } + + @Test("QuantumSimulator") + operation Test2() : Unit { + Zap(); + } + + operation Foo() : Unit { } + + operation Bar() : Unit { } + + operation Zip() : Unit { } + + operation Zap() : Unit { } + + operation Unused() : Unit { } +} + +// ================================= + // Concrete Graph has Concretizations namespace Microsoft.Quantum.Testing.PopulateCallGraph { - @ EntryPoint() + @EntryPoint() operation Main() : Unit { Foo(); Bar(); @@ -155,7 +230,7 @@ namespace Microsoft.Quantum.Testing.PopulateCallGraph { // Concrete Graph Contains All Specializations namespace Microsoft.Quantum.Testing.PopulateCallGraph { - @ EntryPoint() + @EntryPoint() operation Main() : Unit { Adjoint FooAdj(); using (q = Qubit()) { @@ -212,6 +287,7 @@ namespace Microsoft.Quantum.Testing.PopulateCallGraph { // Concrete Graph Double Reference Resolution namespace Microsoft.Quantum.Testing.PopulateCallGraph { + function Foo<'A>(x : 'A) : 'A { return x; } @@ -226,6 +302,7 @@ namespace Microsoft.Quantum.Testing.PopulateCallGraph { // Concrete Graph Non-Call Reference Only Body namespace Microsoft.Quantum.Testing.PopulateCallGraph { + operation Foo() : Unit { } @EntryPoint() @@ -238,6 +315,7 @@ namespace Microsoft.Quantum.Testing.PopulateCallGraph { // Concrete Graph Non-Call Reference With Adjoint namespace Microsoft.Quantum.Testing.PopulateCallGraph { + operation Foo() : Unit is Adj { body(...) { } adjoint(...) { } @@ -253,6 +331,7 @@ namespace Microsoft.Quantum.Testing.PopulateCallGraph { // Concrete Graph Non-Call Reference With All namespace Microsoft.Quantum.Testing.PopulateCallGraph { + operation Foo() : Unit is Ctl+Adj { body(...) { } controlled(ctl, ...) { } @@ -270,6 +349,7 @@ namespace Microsoft.Quantum.Testing.PopulateCallGraph { // Concrete Graph Call Self-Adjoint Reference namespace Microsoft.Quantum.Testing.PopulateCallGraph { + operation Foo() : Unit is Ctl+Adj { body(...) { } controlled distribute; @@ -290,6 +370,7 @@ namespace Microsoft.Quantum.Testing.PopulateCallGraph { // Concrete Graph Clears Type Param Resolutions After Statements namespace Microsoft.Quantum.Testing.PopulateCallGraph { + @EntryPoint() operation Main () : Unit { using (qs = Qubit[1]) { @@ -307,3 +388,75 @@ namespace Microsoft.Quantum.Testing.PopulateCallGraph { Bar(Foo, x); } } + +// ================================= + +// Concrete Graph Multiple Entry Points +namespace Microsoft.Quantum.Testing.PopulateCallGraph { + + @EntryPoint() + operation Main1() : Unit { + Foo(); + } + + @EntryPoint() + operation Main2() : Unit { + Foo(); + } + + operation Foo<'A>() : Unit { } +} + +// ================================= + +// Concrete Graph Unit Tests +namespace Microsoft.Quantum.Testing.PopulateCallGraph { + + open Microsoft.Quantum.Diagnostics; + + @Test("QuantumSimulator") + operation Test1() : Unit { + Foo(); + } + + @Test("QuantumSimulator") + operation Test2() : Unit { + Foo(); + } + + operation Foo<'A>() : Unit { } +} + +// ================================= + +// Concrete Graph Entry Points and Unit Tests +namespace Microsoft.Quantum.Testing.PopulateCallGraph { + + open Microsoft.Quantum.Diagnostics; + + @EntryPoint() + operation Main1() : Unit { + Foo(); + } + + @EntryPoint() + operation Main2() : Unit { + Foo(); + } + + @Test("QuantumSimulator") + operation Test1() : Unit { + Bar(); + } + + @Test("QuantumSimulator") + operation Test2() : Unit { + Bar(); + } + + operation Foo<'A>() : Unit { } + + operation Bar<'A>() : Unit { } + + operation Unused() : Unit { } +} diff --git a/src/QsCompiler/Tests.Compiler/TestCases/QirTests/TestGenerics.qs b/src/QsCompiler/Tests.Compiler/TestCases/QirTests/TestGenerics.qs new file mode 100644 index 0000000000..882068c8c0 --- /dev/null +++ b/src/QsCompiler/Tests.Compiler/TestCases/QirTests/TestGenerics.qs @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Testing.QIR { + open Microsoft.Quantum.Diagnostics; + + @EntryPoint() + function DumpMachineToFileTest(filePath : String) : Unit { + DumpMachine(filePath); + } + + @EntryPoint() + function DumpMachineTest() : Unit { + DumpMachine(); + } + + @EntryPoint() + operation DumpRegisterTest() : Unit { + use q2 = Qubit[2]; + DumpRegister((), q2); + } + + @EntryPoint() + operation DumpRegisterToFileTest(filePath : String) : Unit { + use q2 = Qubit[2]; + DumpRegister(filePath, q2); + } +} + +namespace Microsoft.Quantum.Diagnostics { + + function DumpMachine<'T>(arg : 'T) : Unit { + body intrinsic; + } + + function DumpRegister<'T>(arg : 'T, qs : Qubit[]) : Unit { + body intrinsic; + } +} diff --git a/src/QsCompiler/Tests.Compiler/TestCases/QirTests/TestGenerics1.ll b/src/QsCompiler/Tests.Compiler/TestCases/QirTests/TestGenerics1.ll new file mode 100644 index 0000000000..62e5021fc6 --- /dev/null +++ b/src/QsCompiler/Tests.Compiler/TestCases/QirTests/TestGenerics1.ll @@ -0,0 +1,5 @@ +define void @Microsoft__Quantum__Testing__QIR__DumpMachineTest__body() #0 { +entry: + call void @__quantum__qis__dumpmachine__body(i8* null) + ret void +} diff --git a/src/QsCompiler/Tests.Compiler/TestCases/QirTests/TestGenerics2.ll b/src/QsCompiler/Tests.Compiler/TestCases/QirTests/TestGenerics2.ll new file mode 100644 index 0000000000..74793a48fc --- /dev/null +++ b/src/QsCompiler/Tests.Compiler/TestCases/QirTests/TestGenerics2.ll @@ -0,0 +1,6 @@ +define void @Microsoft__Quantum__Testing__QIR__DumpMachineToFileTest__body(%String* %filePath) { +entry: + %0 = bitcast %String* %filePath to i8* + call void @__quantum__qis__dumpmachine__body(i8* %0) + ret void +} diff --git a/src/QsCompiler/Tests.Compiler/TestCases/QirTests/TestGenerics3.ll b/src/QsCompiler/Tests.Compiler/TestCases/QirTests/TestGenerics3.ll new file mode 100644 index 0000000000..c1dc41ad92 --- /dev/null +++ b/src/QsCompiler/Tests.Compiler/TestCases/QirTests/TestGenerics3.ll @@ -0,0 +1,9 @@ +define void @Microsoft__Quantum__Testing__QIR__DumpRegisterTest__body() #0 { +entry: + %q2 = call %Array* @__quantum__rt__qubit_allocate_array(i64 2) + call void @__quantum__rt__array_update_alias_count(%Array* %q2, i32 1) + call void @__quantum__qis__dumpregister__body(i8* null, %Array* %q2) + call void @__quantum__rt__array_update_alias_count(%Array* %q2, i32 -1) + call void @__quantum__rt__qubit_release_array(%Array* %q2) + ret void +} diff --git a/src/QsCompiler/Tests.Compiler/TestCases/QirTests/TestGenerics4.ll b/src/QsCompiler/Tests.Compiler/TestCases/QirTests/TestGenerics4.ll new file mode 100644 index 0000000000..7439522e93 --- /dev/null +++ b/src/QsCompiler/Tests.Compiler/TestCases/QirTests/TestGenerics4.ll @@ -0,0 +1,10 @@ +define void @Microsoft__Quantum__Testing__QIR__DumpRegisterToFileTest__body(%String* %filePath) { +entry: + %q2 = call %Array* @__quantum__rt__qubit_allocate_array(i64 2) + call void @__quantum__rt__array_update_alias_count(%Array* %q2, i32 1) + %0 = bitcast %String* %filePath to i8* + call void @__quantum__qis__dumpregister__body(i8* %0, %Array* %q2) + call void @__quantum__rt__array_update_alias_count(%Array* %q2, i32 -1) + call void @__quantum__rt__qubit_release_array(%Array* %q2) + ret void +} diff --git a/src/QsCompiler/Tests.Compiler/TestCases/Types.qs b/src/QsCompiler/Tests.Compiler/TestCases/Types.qs index 69050a3eff..32112ff241 100644 --- a/src/QsCompiler/Tests.Compiler/TestCases/Types.qs +++ b/src/QsCompiler/Tests.Compiler/TestCases/Types.qs @@ -8,28 +8,28 @@ // needs to be available to test attributes namespace Microsoft.Quantum.Core { - @ Attribute() + @Attribute() newtype IntTupleAttribute = (Int, Int); } namespace Microsoft.Quantum.Testing.Attributes { - @ Attribute() + @Attribute() newtype IntAttribute = Int; - @ Attribute() + @Attribute() newtype IntTupleAttribute = (Int, Int); - @ Attribute() + @Attribute() newtype StringAttribute = String; - @ Attribute() + @Attribute() newtype BigIntArrayAttribute = BigInt[]; - @ Attribute() + @Attribute() newtype PauliResultAttribute = (Pauli, Result); - @ Attribute() + @Attribute() newtype CustomAttribute = Unit; } diff --git a/src/QsCompiler/Tests.Compiler/TestUtils/Signatures.fs b/src/QsCompiler/Tests.Compiler/TestUtils/Signatures.fs index 1b943deb28..084e1c3f94 100644 --- a/src/QsCompiler/Tests.Compiler/TestUtils/Signatures.fs +++ b/src/QsCompiler/Tests.Compiler/TestUtils/Signatures.fs @@ -122,71 +122,85 @@ let public SignatureCheck checkedNamespaces targetSignatures compilation = sig_rtrnType.Resolution) /// Names of several testing namespaces -let public MonomorphizationNs = "Microsoft.Quantum.Testing.Monomorphization" -let public GenericsNs = "Microsoft.Quantum.Testing.Generics" -let public IntrinsicResolutionNs = "Microsoft.Quantum.Testing.IntrinsicResolution" -let public ClassicalControlNs = "Microsoft.Quantum.Testing.ClassicalControl" -let public InternalRenamingNs = "Microsoft.Quantum.Testing.InternalRenaming" +let public MonomorphizationNS = "Microsoft.Quantum.Testing.Monomorphization" +let public GenericsNS = "Microsoft.Quantum.Testing.Generics" +let public IntrinsicResolutionNS = "Microsoft.Quantum.Testing.IntrinsicResolution" +let public ClassicalControlNS = "Microsoft.Quantum.Testing.ClassicalControl" +let public InternalRenamingNS = "Microsoft.Quantum.Testing.InternalRenaming" let public CycleDetectionNS = "Microsoft.Quantum.Testing.CycleDetection" let public PopulateCallGraphNS = "Microsoft.Quantum.Testing.PopulateCallGraph" +let public SyntaxTreeTrimmingNS = "Microsoft.Quantum.Testing.SyntaxTreeTrimming" /// Expected callable signatures to be found when running Monomorphization tests let public MonomorphizationSignatures = [| // Test Case 1 (_DefaultTypes, [| - MonomorphizationNs, "Test1", [||], "Unit" - GenericsNs, "Test1Main", [||], "Unit" + MonomorphizationNS, "Test1", [||], "Unit" + GenericsNS, "Test1Main", [||], "Unit" + GenericsNS, "Test2Main", [||], "Unit" + GenericsNS, "Test3Main", [||], "Unit" + GenericsNS, "Test4Main", [||], "Unit" - GenericsNs, "BasicGeneric", [| "Double"; "Int" |], "Unit" - GenericsNs, "BasicGeneric", [| "String"; "String" |], "Unit" - GenericsNs, "BasicGeneric", [| "Unit"; "Unit" |], "Unit" - GenericsNs, "BasicGeneric", [| "String"; "Double" |], "Unit" - GenericsNs, "BasicGeneric", [| "Int"; "Double" |], "Unit" - GenericsNs, "NoArgsGeneric", [||], "Double" - GenericsNs, "ReturnGeneric", [| "Double"; "String"; "Int" |], "Int" - GenericsNs, "ReturnGeneric", [| "String"; "Int"; "String" |], "String" + GenericsNS, "BasicGeneric", [| "Double"; "Int" |], "Unit" + GenericsNS, "BasicGeneric", [| "String"; "String" |], "Unit" + GenericsNS, "BasicGeneric", [| "Unit"; "Unit" |], "Unit" + GenericsNS, "BasicGeneric", [| "String"; "Double" |], "Unit" + GenericsNS, "BasicGeneric", [| "Int"; "Double" |], "Unit" + GenericsNS, "NoArgsGeneric", [||], "Double" + GenericsNS, "ReturnGeneric", [| "Double"; "String"; "Int" |], "Int" + GenericsNS, "ReturnGeneric", [| "String"; "Int"; "String" |], "String" |]) // Test Case 2 (_DefaultTypes, [| - MonomorphizationNs, "Test2", [||], "Unit" - GenericsNs, "Test2Main", [||], "Unit" + MonomorphizationNS, "Test2", [||], "Unit" + GenericsNS, "Test1Main", [||], "Unit" + GenericsNS, "Test2Main", [||], "Unit" + GenericsNS, "Test3Main", [||], "Unit" + GenericsNS, "Test4Main", [||], "Unit" - GenericsNs, "ArrayGeneric", [| "Qubit"; "String" |], "Int" - GenericsNs, "ArrayGeneric", [| "Qubit"; "Int" |], "Int" - GenericsNs, "GenericCallsGeneric", [| "Qubit"; "Int" |], "Unit" + GenericsNS, "ArrayGeneric", [| "Qubit"; "String" |], "Int" + GenericsNS, "ArrayGeneric", [| "Qubit"; "Int" |], "Int" + GenericsNS, "GenericCallsGeneric", [| "Qubit"; "Int" |], "Unit" |]) // Test Case 3 (_DefaultTypes, [| - MonomorphizationNs, "Test3", [||], "Unit" - GenericsNs, "Test3Main", [||], "Unit" + MonomorphizationNS, "Test3", [||], "Unit" + GenericsNS, "Test1Main", [||], "Unit" + GenericsNS, "Test2Main", [||], "Unit" + GenericsNS, "Test3Main", [||], "Unit" + GenericsNS, "Test4Main", [||], "Unit" - GenericsNs, "GenericCallsSpecializations", [| "Double"; "String"; "Qubit[]" |], "Unit" - GenericsNs, "GenericCallsSpecializations", [| "Double"; "String"; "Double" |], "Unit" - GenericsNs, "GenericCallsSpecializations", [| "String"; "Int"; "Unit" |], "Unit" + GenericsNS, "GenericCallsSpecializations", [| "Double"; "String"; "Qubit[]" |], "Unit" + GenericsNS, "GenericCallsSpecializations", [| "Double"; "String"; "Double" |], "Unit" + GenericsNS, "GenericCallsSpecializations", [| "String"; "Int"; "Unit" |], "Unit" - GenericsNs, "BasicGeneric", [| "Double"; "String" |], "Unit" - GenericsNs, "BasicGeneric", [| "String"; "Qubit[]" |], "Unit" - GenericsNs, "BasicGeneric", [| "String"; "Int" |], "Unit" - GenericsNs, "BasicGeneric", [| "Qubit[]"; "Qubit[]" |], "Unit" - GenericsNs, "BasicGeneric", [| "Qubit[]"; "Double" |], "Unit" - GenericsNs, "BasicGeneric", [| "Qubit[]"; "Unit" |], "Unit" - GenericsNs, "BasicGeneric", [| "String"; "Double" |], "Unit" - GenericsNs, "BasicGeneric", [| "Int"; "Unit" |], "Unit" + GenericsNS, "BasicGeneric", [| "Double"; "String" |], "Unit" + GenericsNS, "BasicGeneric", [| "String"; "Qubit[]" |], "Unit" + GenericsNS, "BasicGeneric", [| "String"; "Int" |], "Unit" + GenericsNS, "BasicGeneric", [| "Qubit[]"; "Qubit[]" |], "Unit" + GenericsNS, "BasicGeneric", [| "Qubit[]"; "Double" |], "Unit" + GenericsNS, "BasicGeneric", [| "Qubit[]"; "Unit" |], "Unit" + GenericsNS, "BasicGeneric", [| "String"; "Double" |], "Unit" + GenericsNS, "BasicGeneric", [| "Int"; "Unit" |], "Unit" - GenericsNs, "ArrayGeneric", [| "Qubit"; "Double" |], "Int" - GenericsNs, "ArrayGeneric", [| "Qubit"; "Qubit[]" |], "Int" - GenericsNs, "ArrayGeneric", [| "Qubit"; "Unit" |], "Int" + GenericsNS, "ArrayGeneric", [| "Qubit"; "Double" |], "Int" + GenericsNS, "ArrayGeneric", [| "Qubit"; "Qubit[]" |], "Int" + GenericsNS, "ArrayGeneric", [| "Qubit"; "Unit" |], "Int" |]) // Test Case 4 (_DefaultTypes, [| - MonomorphizationNs, "Test4", [||], "Unit" - GenericsNs, "Test4Main", [||], "Unit" - GenericsNs, "_GenericCallsSelf", [||], "Unit" - GenericsNs, "_GenericCallsSelf2", [| "Double" |], "Unit" + MonomorphizationNS, "Test4", [||], "Unit" + GenericsNS, "Test1Main", [||], "Unit" + GenericsNS, "Test2Main", [||], "Unit" + GenericsNS, "Test3Main", [||], "Unit" + GenericsNS, "Test4Main", [||], "Unit" + + GenericsNS, "_GenericCallsSelf", [||], "Unit" + GenericsNS, "_GenericCallsSelf2", [| "Double" |], "Unit" |]) |] |> _MakeSignatures @@ -194,7 +208,7 @@ let public MonomorphizationSignatures = let private _IntrinsicResolutionTypes = _MakeTypeMap [| "TestType", { - Namespace = "Microsoft.Quantum.Testing.IntrinsicResolution" + Namespace = IntrinsicResolutionNS Name = "TestType" Range = Null } @@ -205,45 +219,45 @@ let public IntrinsicResolutionSignatures = [| (_DefaultTypes, [| - IntrinsicResolutionNs, "IntrinsicResolutionTest1", [||], "Unit" - IntrinsicResolutionNs, "LocalIntrinsic", [||], "Unit" - IntrinsicResolutionNs, "Override", [||], "Unit" - IntrinsicResolutionNs, "EnvironmentIntrinsic", [||], "Unit" + IntrinsicResolutionNS, "IntrinsicResolutionTest1", [||], "Unit" + IntrinsicResolutionNS, "LocalIntrinsic", [||], "Unit" + IntrinsicResolutionNS, "Override", [||], "Unit" + IntrinsicResolutionNS, "EnvironmentIntrinsic", [||], "Unit" |]) (_IntrinsicResolutionTypes, [| - IntrinsicResolutionNs, "IntrinsicResolutionTest2", [||], "Unit" - IntrinsicResolutionNs, "Override", [||], "TestType" - IntrinsicResolutionNs, "TestType", [||], "TestType" + IntrinsicResolutionNS, "IntrinsicResolutionTest2", [||], "Unit" + IntrinsicResolutionNS, "Override", [||], "TestType" + IntrinsicResolutionNS, "TestType", [||], "TestType" |]) (_IntrinsicResolutionTypes, [| - IntrinsicResolutionNs, "IntrinsicResolutionTest3", [||], "Unit" - IntrinsicResolutionNs, "Override", [||], "TestType" - IntrinsicResolutionNs, "TestType", [||], "TestType" + IntrinsicResolutionNS, "IntrinsicResolutionTest3", [||], "Unit" + IntrinsicResolutionNS, "Override", [||], "TestType" + IntrinsicResolutionNS, "TestType", [||], "TestType" |]) (_IntrinsicResolutionTypes, [| - IntrinsicResolutionNs, "IntrinsicResolutionTest4", [||], "Unit" - IntrinsicResolutionNs, "Override", [| "TestType" |], "Unit" - IntrinsicResolutionNs, "TestType", [||], "TestType" + IntrinsicResolutionNS, "IntrinsicResolutionTest4", [||], "Unit" + IntrinsicResolutionNS, "Override", [| "TestType" |], "Unit" + IntrinsicResolutionNS, "TestType", [||], "TestType" |]) (_DefaultTypes, [| - IntrinsicResolutionNs, "IntrinsicResolutionTest5", [||], "Unit" - IntrinsicResolutionNs, "Override", [||], "Unit" + IntrinsicResolutionNS, "IntrinsicResolutionTest5", [||], "Unit" + IntrinsicResolutionNS, "Override", [||], "Unit" |]) (_DefaultTypes, [| - IntrinsicResolutionNs, "IntrinsicResolutionTest6", [||], "Unit" - IntrinsicResolutionNs, "Override", [||], "Unit" + IntrinsicResolutionNS, "IntrinsicResolutionTest6", [||], "Unit" + IntrinsicResolutionNS, "Override", [||], "Unit" |]) |] |> _MakeSignatures let private _TypeParameterTypes = - _MakeTypeMap [| _MakeTypeParam ClassicalControlNs "Bar" "Q" - _MakeTypeParam ClassicalControlNs "Bar" "W" |] + _MakeTypeMap [| _MakeTypeParam ClassicalControlNS "Bar" "Q" + _MakeTypeParam ClassicalControlNS "Bar" "W" |] let private _DefaultWithOperation = _MakeTypeMap [| "SubOp1Type[]", @@ -261,270 +275,319 @@ let public ClassicalControlSignatures = [| // Basic Lift (_DefaultTypes, [| - ClassicalControlNs, "Foo", [||], "Unit" // The original operation - ClassicalControlNs, "_Foo", [| "Result" |], "Unit" // The generated operation + ClassicalControlNS, "Foo", [||], "Unit" // The original operation + ClassicalControlNS, "_Foo", [| "Result" |], "Unit" // The generated operation |]) // Lift Loops (_DefaultTypes, [| - ClassicalControlNs, "Foo", [||], "Unit" - ClassicalControlNs, "_Foo", [| "Result" |], "Unit" + ClassicalControlNS, "Foo", [||], "Unit" + ClassicalControlNS, "_Foo", [| "Result" |], "Unit" |]) // Don't Lift Single Call - (_DefaultTypes, [| ClassicalControlNs, "Foo", [||], "Unit" |]) + (_DefaultTypes, [| ClassicalControlNS, "Foo", [||], "Unit" |]) // Lift Single Non-Call (_DefaultTypes, [| - ClassicalControlNs, "Foo", [||], "Unit" - ClassicalControlNs, "_Foo", [| "Result" |], "Unit" + ClassicalControlNS, "Foo", [||], "Unit" + ClassicalControlNS, "_Foo", [| "Result" |], "Unit" |]) // Don't Lift Return Statements - (_DefaultTypes, [| ClassicalControlNs, "Foo", [||], "Unit" |]) + (_DefaultTypes, [| ClassicalControlNS, "Foo", [||], "Unit" |]) // All-Or-None Lifting (_DefaultTypes, [| - ClassicalControlNs, "IfInvalid", [||], "Unit" - ClassicalControlNs, "ElseInvalid", [||], "Unit" - ClassicalControlNs, "BothInvalid", [||], "Unit" + ClassicalControlNS, "IfInvalid", [||], "Unit" + ClassicalControlNS, "ElseInvalid", [||], "Unit" + ClassicalControlNS, "BothInvalid", [||], "Unit" |]) // ApplyIfZero And ApplyIfOne - (_DefaultTypes, [| ClassicalControlNs, "Foo", [||], "Unit" |]) + (_DefaultTypes, [| ClassicalControlNS, "Foo", [||], "Unit" |]) // Apply If Zero Else One (_DefaultTypes, [| - ClassicalControlNs, "Bar", [| "Result" |], "Unit" - ClassicalControlNs, "Foo", [||], "Unit" + ClassicalControlNS, "Bar", [| "Result" |], "Unit" + ClassicalControlNS, "Foo", [||], "Unit" |]) // Apply If One Else Zero (_DefaultTypes, [| - ClassicalControlNs, "Bar", [| "Result" |], "Unit" - ClassicalControlNs, "Foo", [||], "Unit" + ClassicalControlNS, "Bar", [| "Result" |], "Unit" + ClassicalControlNS, "Foo", [||], "Unit" |]) // If Elif (_DefaultTypes, [| - ClassicalControlNs, "Foo", [||], "Unit" - ClassicalControlNs, "_Foo", [| "Result" |], "Unit" + ClassicalControlNS, "Foo", [||], "Unit" + ClassicalControlNS, "_Foo", [| "Result" |], "Unit" |]) // And Condition (_DefaultTypes, [| - ClassicalControlNs, "Foo", [||], "Unit" - ClassicalControlNs, "_Foo", [| "Result" |], "Unit" + ClassicalControlNS, "Foo", [||], "Unit" + ClassicalControlNS, "_Foo", [| "Result" |], "Unit" |]) // Or Condition (_DefaultTypes, [| - ClassicalControlNs, "Foo", [||], "Unit" - ClassicalControlNs, "_Foo", [| "Result" |], "Unit" + ClassicalControlNS, "Foo", [||], "Unit" + ClassicalControlNS, "_Foo", [| "Result" |], "Unit" |]) // Don't Lift Functions (_DefaultTypes, [| - ClassicalControlNs, "Foo", [||], "Unit" - ClassicalControlNs, "SubFunc1", [||], "Unit" - ClassicalControlNs, "SubFunc2", [||], "Unit" - ClassicalControlNs, "SubFunc3", [||], "Unit" + ClassicalControlNS, "Foo", [||], "Unit" + ClassicalControlNS, "SubFunc1", [||], "Unit" + ClassicalControlNS, "SubFunc2", [||], "Unit" + ClassicalControlNS, "SubFunc3", [||], "Unit" |]) // Lift Self-Contained Mutable (_DefaultTypes, [| - ClassicalControlNs, "Foo", [||], "Unit" - ClassicalControlNs, "_Foo", [| "Result" |], "Unit" + ClassicalControlNS, "Foo", [||], "Unit" + ClassicalControlNS, "_Foo", [| "Result" |], "Unit" |]) // Don't Lift General Mutable - (_DefaultTypes, [| ClassicalControlNs, "Foo", [||], "Unit" |]) + (_DefaultTypes, [| ClassicalControlNS, "Foo", [||], "Unit" |]) // Generics Support (_DefaultTypes, [| - ClassicalControlNs, "Foo", [||], "Unit" - ClassicalControlNs, "_Foo", [| "Result" |], "Unit" + ClassicalControlNS, "Foo", [||], "Unit" + ClassicalControlNS, "_Foo", [| "Result" |], "Unit" |]) // Adjoint Support (_DefaultTypes, [| - ClassicalControlNs, "Provided", [||], "Unit" - ClassicalControlNs, "Self", [||], "Unit" - ClassicalControlNs, "Invert", [||], "Unit" - ClassicalControlNs, "_Provided", [| "Result" |], "Unit" - ClassicalControlNs, "_Provided", [| "Result" |], "Unit" - ClassicalControlNs, "_Self", [| "Result" |], "Unit" - ClassicalControlNs, "_Invert", [| "Result" |], "Unit" + ClassicalControlNS, "Provided", [||], "Unit" + ClassicalControlNS, "Self", [||], "Unit" + ClassicalControlNS, "Invert", [||], "Unit" + ClassicalControlNS, "_Provided", [| "Result" |], "Unit" + ClassicalControlNS, "_Provided", [| "Result" |], "Unit" + ClassicalControlNS, "_Self", [| "Result" |], "Unit" + ClassicalControlNS, "_Invert", [| "Result" |], "Unit" |]) // Controlled Support (_DefaultTypes, [| - ClassicalControlNs, "Provided", [||], "Unit" - ClassicalControlNs, "Distribute", [||], "Unit" - ClassicalControlNs, "_Provided", [| "Result" |], "Unit" - ClassicalControlNs, "_Provided", [| "Result"; "Qubit[]"; "Unit" |], "Unit" - ClassicalControlNs, "_Distribute", [| "Result" |], "Unit" + ClassicalControlNS, "Provided", [||], "Unit" + ClassicalControlNS, "Distribute", [||], "Unit" + ClassicalControlNS, "_Provided", [| "Result" |], "Unit" + ClassicalControlNS, "_Provided", [| "Result"; "Qubit[]"; "Unit" |], "Unit" + ClassicalControlNS, "_Distribute", [| "Result" |], "Unit" |]) // Controlled Adjoint Support - Provided (_DefaultTypes, [| - ClassicalControlNs, "ProvidedBody", [||], "Unit" - ClassicalControlNs, "ProvidedAdjoint", [||], "Unit" - ClassicalControlNs, "ProvidedControlled", [||], "Unit" - ClassicalControlNs, "ProvidedAll", [||], "Unit" + ClassicalControlNS, "ProvidedBody", [||], "Unit" + ClassicalControlNS, "ProvidedAdjoint", [||], "Unit" + ClassicalControlNS, "ProvidedControlled", [||], "Unit" + ClassicalControlNS, "ProvidedAll", [||], "Unit" - ClassicalControlNs, "_ProvidedBody", [| "Result" |], "Unit" - ClassicalControlNs, "_ProvidedBody", [| "Result"; "Qubit[]"; "Unit" |], "Unit" + ClassicalControlNS, "_ProvidedBody", [| "Result" |], "Unit" + ClassicalControlNS, "_ProvidedBody", [| "Result"; "Qubit[]"; "Unit" |], "Unit" - ClassicalControlNs, "_ProvidedAdjoint", [| "Result" |], "Unit" - ClassicalControlNs, "_ProvidedAdjoint", [| "Result" |], "Unit" - ClassicalControlNs, "_ProvidedAdjoint", [| "Result"; "Qubit[]"; "Unit" |], "Unit" + ClassicalControlNS, "_ProvidedAdjoint", [| "Result" |], "Unit" + ClassicalControlNS, "_ProvidedAdjoint", [| "Result" |], "Unit" + ClassicalControlNS, "_ProvidedAdjoint", [| "Result"; "Qubit[]"; "Unit" |], "Unit" - ClassicalControlNs, "_ProvidedControlled", [| "Result" |], "Unit" - ClassicalControlNs, "_ProvidedControlled", [| "Result"; "Qubit[]"; "Unit" |], "Unit" - ClassicalControlNs, "_ProvidedControlled", [| "Result"; "Qubit[]"; "Unit" |], "Unit" + ClassicalControlNS, "_ProvidedControlled", [| "Result" |], "Unit" + ClassicalControlNS, "_ProvidedControlled", [| "Result"; "Qubit[]"; "Unit" |], "Unit" + ClassicalControlNS, "_ProvidedControlled", [| "Result"; "Qubit[]"; "Unit" |], "Unit" - ClassicalControlNs, "_ProvidedAll", [| "Result" |], "Unit" - ClassicalControlNs, "_ProvidedAll", [| "Result" |], "Unit" - ClassicalControlNs, "_ProvidedAll", [| "Result"; "Qubit[]"; "Unit" |], "Unit" - ClassicalControlNs, "_ProvidedAll", [| "Result"; "Qubit[]"; "Unit" |], "Unit" + ClassicalControlNS, "_ProvidedAll", [| "Result" |], "Unit" + ClassicalControlNS, "_ProvidedAll", [| "Result" |], "Unit" + ClassicalControlNS, "_ProvidedAll", [| "Result"; "Qubit[]"; "Unit" |], "Unit" + ClassicalControlNS, "_ProvidedAll", [| "Result"; "Qubit[]"; "Unit" |], "Unit" |]) // Controlled Adjoint Support - Distribute (_DefaultTypes, [| - ClassicalControlNs, "DistributeBody", [||], "Unit" - ClassicalControlNs, "DistributeAdjoint", [||], "Unit" - ClassicalControlNs, "DistributeControlled", [||], "Unit" - ClassicalControlNs, "DistributeAll", [||], "Unit" + ClassicalControlNS, "DistributeBody", [||], "Unit" + ClassicalControlNS, "DistributeAdjoint", [||], "Unit" + ClassicalControlNS, "DistributeControlled", [||], "Unit" + ClassicalControlNS, "DistributeAll", [||], "Unit" - ClassicalControlNs, "_DistributeBody", [| "Result" |], "Unit" + ClassicalControlNS, "_DistributeBody", [| "Result" |], "Unit" - ClassicalControlNs, "_DistributeAdjoint", [| "Result" |], "Unit" - ClassicalControlNs, "_DistributeAdjoint", [| "Result" |], "Unit" + ClassicalControlNS, "_DistributeAdjoint", [| "Result" |], "Unit" + ClassicalControlNS, "_DistributeAdjoint", [| "Result" |], "Unit" - ClassicalControlNs, "_DistributeControlled", [| "Result" |], "Unit" - ClassicalControlNs, "_DistributeControlled", [| "Result"; "Qubit[]"; "Unit" |], "Unit" + ClassicalControlNS, "_DistributeControlled", [| "Result" |], "Unit" + ClassicalControlNS, "_DistributeControlled", [| "Result"; "Qubit[]"; "Unit" |], "Unit" - ClassicalControlNs, "_DistributeAll", [| "Result" |], "Unit" - ClassicalControlNs, "_DistributeAll", [| "Result" |], "Unit" - ClassicalControlNs, "_DistributeAll", [| "Result"; "Qubit[]"; "Unit" |], "Unit" + ClassicalControlNS, "_DistributeAll", [| "Result" |], "Unit" + ClassicalControlNS, "_DistributeAll", [| "Result" |], "Unit" + ClassicalControlNS, "_DistributeAll", [| "Result"; "Qubit[]"; "Unit" |], "Unit" |]) // Controlled Adjoint Support - Invert (_DefaultTypes, [| - ClassicalControlNs, "InvertBody", [||], "Unit" - ClassicalControlNs, "InvertAdjoint", [||], "Unit" - ClassicalControlNs, "InvertControlled", [||], "Unit" - ClassicalControlNs, "InvertAll", [||], "Unit" + ClassicalControlNS, "InvertBody", [||], "Unit" + ClassicalControlNS, "InvertAdjoint", [||], "Unit" + ClassicalControlNS, "InvertControlled", [||], "Unit" + ClassicalControlNS, "InvertAll", [||], "Unit" - ClassicalControlNs, "_InvertBody", [| "Result" |], "Unit" + ClassicalControlNS, "_InvertBody", [| "Result" |], "Unit" - ClassicalControlNs, "_InvertAdjoint", [| "Result" |], "Unit" - ClassicalControlNs, "_InvertAdjoint", [| "Result" |], "Unit" + ClassicalControlNS, "_InvertAdjoint", [| "Result" |], "Unit" + ClassicalControlNS, "_InvertAdjoint", [| "Result" |], "Unit" - ClassicalControlNs, "_InvertControlled", [| "Result" |], "Unit" - ClassicalControlNs, "_InvertControlled", [| "Result"; "Qubit[]"; "Unit" |], "Unit" + ClassicalControlNS, "_InvertControlled", [| "Result" |], "Unit" + ClassicalControlNS, "_InvertControlled", [| "Result"; "Qubit[]"; "Unit" |], "Unit" - ClassicalControlNs, "_InvertAll", [| "Result" |], "Unit" - ClassicalControlNs, "_InvertAll", [| "Result" |], "Unit" - ClassicalControlNs, "_InvertAll", [| "Result"; "Qubit[]"; "Unit" |], "Unit" + ClassicalControlNS, "_InvertAll", [| "Result" |], "Unit" + ClassicalControlNS, "_InvertAll", [| "Result" |], "Unit" + ClassicalControlNS, "_InvertAll", [| "Result"; "Qubit[]"; "Unit" |], "Unit" |]) // Controlled Adjoint Support - Self (_DefaultTypes, [| - ClassicalControlNs, "SelfBody", [||], "Unit" - ClassicalControlNs, "SelfControlled", [||], "Unit" + ClassicalControlNS, "SelfBody", [||], "Unit" + ClassicalControlNS, "SelfControlled", [||], "Unit" - ClassicalControlNs, "_SelfBody", [| "Result" |], "Unit" + ClassicalControlNS, "_SelfBody", [| "Result" |], "Unit" - ClassicalControlNs, "_SelfControlled", [| "Result" |], "Unit" - ClassicalControlNs, "_SelfControlled", [| "Result"; "Qubit[]"; "Unit" |], "Unit" + ClassicalControlNS, "_SelfControlled", [| "Result" |], "Unit" + ClassicalControlNS, "_SelfControlled", [| "Result"; "Qubit[]"; "Unit" |], "Unit" |]) // Within Block Support (_DefaultTypes, [| - ClassicalControlNs, "Foo", [||], "Unit" - ClassicalControlNs, "_Foo", [| "Result" |], "Unit" - ClassicalControlNs, "_Foo", [| "Result" |], "Unit" + ClassicalControlNS, "Foo", [||], "Unit" + ClassicalControlNS, "_Foo", [| "Result" |], "Unit" + ClassicalControlNS, "_Foo", [| "Result" |], "Unit" |]) // Arguments Partially Resolve Type Parameters (_TypeParameterTypes, [| - ClassicalControlNs, "Bar", [| "Bar.Q"; "Bar.W" |], "Unit" - ClassicalControlNs, "Foo", [||], "Unit" + ClassicalControlNS, "Bar", [| "Bar.Q"; "Bar.W" |], "Unit" + ClassicalControlNS, "Foo", [||], "Unit" |]) // Lift Functor Application (_DefaultTypes, [| - ClassicalControlNs, "Foo", [||], "Unit" - ClassicalControlNs, "_Foo", [| "Result" |], "Unit" + ClassicalControlNS, "Foo", [||], "Unit" + ClassicalControlNS, "_Foo", [| "Result" |], "Unit" |]) // Lift Partial Application (_DefaultTypes, [| - ClassicalControlNs, "Bar", [| "Int"; "Double" |], "Unit" - ClassicalControlNs, "Foo", [||], "Unit" - ClassicalControlNs, "_Foo", [| "Result" |], "Unit" + ClassicalControlNS, "Bar", [| "Int"; "Double" |], "Unit" + ClassicalControlNS, "Foo", [||], "Unit" + ClassicalControlNS, "_Foo", [| "Result" |], "Unit" |]) // Lift Array Item Call (_DefaultWithOperation, [| - ClassicalControlNs, "Foo", [||], "Unit" - ClassicalControlNs, "_Foo", [| "SubOp1Type[]"; "Result" |], "Unit" + ClassicalControlNS, "Foo", [||], "Unit" + ClassicalControlNS, "_Foo", [| "SubOp1Type[]"; "Result" |], "Unit" |]) // Lift One Not Both (_DefaultTypes, [| - ClassicalControlNs, "Foo", [||], "Unit" - ClassicalControlNs, "_Foo", [| "Result" |], "Unit" + ClassicalControlNS, "Foo", [||], "Unit" + ClassicalControlNS, "_Foo", [| "Result" |], "Unit" |]) // Apply Conditionally (_DefaultTypes, [| - ClassicalControlNs, "Bar", [| "Result" |], "Unit" - ClassicalControlNs, "Foo", [||], "Unit" + ClassicalControlNS, "Bar", [| "Result" |], "Unit" + ClassicalControlNS, "Foo", [||], "Unit" |]) // Apply Conditionally With NoOp (_DefaultTypes, [| - ClassicalControlNs, "Bar", [| "Result" |], "Unit" - ClassicalControlNs, "Foo", [||], "Unit" + ClassicalControlNS, "Bar", [| "Result" |], "Unit" + ClassicalControlNS, "Foo", [||], "Unit" |]) // Inequality with ApplyConditionally (_DefaultTypes, [| - ClassicalControlNs, "Bar", [| "Result" |], "Unit" - ClassicalControlNs, "Foo", [||], "Unit" + ClassicalControlNS, "Bar", [| "Result" |], "Unit" + ClassicalControlNS, "Foo", [||], "Unit" |]) // Inequality with Apply If One Else Zero (_DefaultTypes, [| - ClassicalControlNs, "Bar", [| "Result" |], "Unit" - ClassicalControlNs, "Foo", [||], "Unit" + ClassicalControlNS, "Bar", [| "Result" |], "Unit" + ClassicalControlNS, "Foo", [||], "Unit" |]) // Inequality with Apply If Zero Else One (_DefaultTypes, [| - ClassicalControlNs, "Bar", [| "Result" |], "Unit" - ClassicalControlNs, "Foo", [||], "Unit" + ClassicalControlNS, "Bar", [| "Result" |], "Unit" + ClassicalControlNS, "Foo", [||], "Unit" |]) // Inequality with ApplyIfOne - (_DefaultTypes, [| ClassicalControlNs, "Foo", [||], "Unit" |]) + (_DefaultTypes, [| ClassicalControlNS, "Foo", [||], "Unit" |]) // Inequality with ApplyIfZero - (_DefaultTypes, [| ClassicalControlNs, "Foo", [||], "Unit" |]) + (_DefaultTypes, [| ClassicalControlNS, "Foo", [||], "Unit" |]) // Literal on the Left - (_DefaultTypes, [| ClassicalControlNs, "Foo", [||], "Unit" |]) + (_DefaultTypes, [| ClassicalControlNS, "Foo", [||], "Unit" |]) // Simple NOT condition - (_DefaultTypes, [| ClassicalControlNs, "Foo", [||], "Unit" |]) + (_DefaultTypes, [| ClassicalControlNS, "Foo", [||], "Unit" |]) // Outer NOT condition (_DefaultTypes, [| - ClassicalControlNs, "Foo", [||], "Unit" - ClassicalControlNs, "_Foo", [| "Result" |], "Unit" + ClassicalControlNS, "Foo", [||], "Unit" + ClassicalControlNS, "_Foo", [| "Result" |], "Unit" |]) // Nested NOT condition (_DefaultTypes, [| - ClassicalControlNs, "Foo", [||], "Unit" - ClassicalControlNs, "_Foo", [| "Result" |], "Unit" + ClassicalControlNS, "Foo", [||], "Unit" + ClassicalControlNS, "_Foo", [| "Result" |], "Unit" |]) // One-sided NOT condition - (_DefaultTypes, [| ClassicalControlNs, "Foo", [||], "Unit" |]) + (_DefaultTypes, [| ClassicalControlNS, "Foo", [||], "Unit" |]) + |] + |> _MakeSignatures + +let private _SyntaxTreeTrimmingTypes = + let UsedUDT = + "UsedUDT", + { + Namespace = SyntaxTreeTrimmingNS + Name = "UsedUDT" + Range = Null + } + |> UserDefinedType + let UnusedUDT = + "UnusedUDT", + { + Namespace = SyntaxTreeTrimmingNS + Name = "UnusedUDT" + Range = Null + } + |> UserDefinedType + _MakeTypeMap [| UsedUDT; UnusedUDT |] + +let public SyntaxTreeTrimmingSignatures = + [| // Trimmer Removes Unused Callables + (_DefaultTypes, + [| + SyntaxTreeTrimmingNS, "Main", [||], "Unit" + SyntaxTreeTrimmingNS, "UsedOp", [||], "Unit" + SyntaxTreeTrimmingNS, "UsedFunc", [||], "Unit" + |]) + // Trimmer Keeps UDTs + (_SyntaxTreeTrimmingTypes, + [| + SyntaxTreeTrimmingNS, "Main", [||], "Unit" + SyntaxTreeTrimmingNS, "UsedUDT", [| "Int" |], "UsedUDT" + |]) + // Trimmer Keeps Intrinsics When Told + (_DefaultTypes, + [| + SyntaxTreeTrimmingNS, "Main", [||], "Unit" + SyntaxTreeTrimmingNS, "UsedIntrinsic", [||], "Unit" + SyntaxTreeTrimmingNS, "UnusedIntrinsic", [||], "Unit" + |]) + // Trimmer Removes Intrinsics When Told + (_DefaultTypes, + [| + SyntaxTreeTrimmingNS, "Main", [||], "Unit" + SyntaxTreeTrimmingNS, "UsedIntrinsic", [||], "Unit" + |]) |] |> _MakeSignatures diff --git a/src/QsCompiler/Tests.Compiler/Tests.Compiler.fsproj b/src/QsCompiler/Tests.Compiler/Tests.Compiler.fsproj index 18f11436d2..6d6d1f42dd 100644 --- a/src/QsCompiler/Tests.Compiler/Tests.Compiler.fsproj +++ b/src/QsCompiler/Tests.Compiler/Tests.Compiler.fsproj @@ -171,6 +171,21 @@ Always + + Always + + + Always + + + Always + + + Always + + + Always + Always @@ -339,6 +354,9 @@ Always + + Always + Always @@ -513,6 +531,7 @@ + false diff --git a/src/QsCompiler/Transformations/CallGraph/CallGraphWalker.cs b/src/QsCompiler/Transformations/CallGraph/CallGraphWalker.cs index ca59f0efd1..fcb8ad2112 100644 --- a/src/QsCompiler/Transformations/CallGraph/CallGraphWalker.cs +++ b/src/QsCompiler/Transformations/CallGraph/CallGraphWalker.cs @@ -66,9 +66,11 @@ public static void PopulateGraph(GraphBuilder graph, QsCompilation compilation) /// public static void PopulateTrimmedGraph(GraphBuilder graph, QsCompilation compilation) { + var globals = compilation.Namespaces.GlobalCallableResolutions(); var walker = new BuildGraph(graph); - var entryPointNodes = compilation.EntryPoints.Select(name => new CallGraphNode(name)); walker.SharedState.WithTrimming = true; + + var entryPointNodes = compilation.EntryPoints.Select(name => new CallGraphNode(name)); foreach (var entryPoint in entryPointNodes) { // Make sure all the entry points are added to the graph @@ -76,7 +78,16 @@ public static void PopulateTrimmedGraph(GraphBuilder graph, QsCompilation compil walker.SharedState.RequestStack.Push(entryPoint); } - var globals = compilation.Namespaces.GlobalCallableResolutions(); + var unitTests = globals + .Where(kvp => kvp.Value.Attributes.Any(BuiltIn.MarksTestOperation)) + .Select(kvp => new CallGraphNode(kvp.Key)); + foreach (var unitTest in unitTests) + { + // Make sure all the unit tests are added to the graph + walker.SharedState.Graph.AddNode(unitTest); + walker.SharedState.RequestStack.Push(unitTest); + } + while (walker.SharedState.RequestStack.TryPop(out var currentRequest)) { // If there is a call to an unknown callable, throw exception diff --git a/src/QsCompiler/Transformations/CallGraph/ConcreteCallGraphWalker.cs b/src/QsCompiler/Transformations/CallGraph/ConcreteCallGraphWalker.cs index eba02247ab..7b7d854d05 100644 --- a/src/QsCompiler/Transformations/CallGraph/ConcreteCallGraphWalker.cs +++ b/src/QsCompiler/Transformations/CallGraph/ConcreteCallGraphWalker.cs @@ -41,6 +41,7 @@ public static void PopulateConcreteGraph(ConcreteGraphBuilder graph, QsCompilati { var globals = compilation.Namespaces.GlobalCallableResolutions(); var walker = new BuildGraph(graph); + var entryPointNodes = compilation.EntryPoints.SelectMany(name => GetSpecializationKinds(globals, name).Select(kind => new ConcreteCallGraphNode(name, kind, TypeParameterResolutions.Empty))); @@ -51,6 +52,16 @@ public static void PopulateConcreteGraph(ConcreteGraphBuilder graph, QsCompilati walker.SharedState.RequestStack.Push(entryPoint); } + var unitTests = globals + .Where(kvp => kvp.Value.Attributes.Any(BuiltIn.MarksTestOperation)) + .SelectMany(kvp => kvp.Value.Specializations.Select(spec => new ConcreteCallGraphNode(kvp.Key, spec.Kind, TypeParameterResolutions.Empty))); + foreach (var unitTest in unitTests) + { + // Make sure all the unit tests are added to the graph + walker.SharedState.Graph.AddNode(unitTest); + walker.SharedState.RequestStack.Push(unitTest); + } + while (walker.SharedState.RequestStack.TryPop(out var currentRequest)) { // If there is a call to an unknown callable, throw exception diff --git a/src/QsCompiler/Transformations/Monomorphization.cs b/src/QsCompiler/Transformations/Monomorphization.cs index 877e553c17..144ccc47e4 100644 --- a/src/QsCompiler/Transformations/Monomorphization.cs +++ b/src/QsCompiler/Transformations/Monomorphization.cs @@ -24,152 +24,91 @@ namespace Microsoft.Quantum.QsCompiler.Transformations.Monomorphization /// are found from uses of the callables. /// This transformation also removes all callables that are not used directly or /// indirectly from any of the marked entry point. - /// Intrinsic callables are, by default, not monomorphized or removed from the compilation, but - /// may optionally be removed if unused if the keepAllIntrinsics parameter is set to false. + /// Monomorphizing intrinsic callables is optional and intrinsics can be prevented + /// from being monomorphized if the monomorphizeIntrinsics parameter is set to false. /// There are also some built-in callables that are also exempt from /// being removed from non-use, as they are needed for later rewrite steps. /// public static class Monomorphize { + private static bool IsGeneric(QsCallable callable) => + callable.Signature.TypeParameters.Any() || callable.Specializations.Any(spec => spec.Signature.TypeParameters.Any()); + /// - /// 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. + /// Performs Monomorphization on the given compilation. If the monomorphizeIntrinsics parameter + /// is set to false, then intrinsics will not be monomorphized. /// - public static QsCompilation Apply(QsCompilation compilation, bool keepAllIntrinsics = true) + public static QsCompilation Apply(QsCompilation compilation, bool monomorphizeIntrinsics = false) { var globals = compilation.Namespaces.GlobalCallableResolutions(); var concretizations = new List(); - var concreteNames = new Dictionary(); + var concreteNamesMap = new Dictionary(); - var nodes = new ConcreteCallGraph(compilation).Nodes + 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 nodes) + foreach (var node in nodesWithResolutions) { // If there is a call to an unknown callable, throw exception - if (!globals.TryGetValue(node.CallableName, out QsCallable originalGlobal)) + if (!globals.TryGetValue(node.CallableName, out var originalGlobal)) { throw new ArgumentException($"Couldn't find definition for callable: {node.CallableName}"); } - if (node.ParamResolutions.Any()) + if (monomorphizeIntrinsics || !originalGlobal.IsIntrinsic) { // Get concrete name var concreteName = NameDecorator.PrependGuid(node.CallableName); // Add to concrete name mapping - concreteNames[node] = concreteName; + concreteNamesMap[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); + var concrete = + ReplaceTypeParamImplementations.Apply(originalGlobal, node.ParamResolutions, getAccessModifiers) + .WithFullName(oldName => concreteName) + .WithSpecializations(specs => specs.Select(spec => spec.WithParent(_ => concreteName)).ToImmutableArray()); + concretizations.Add(concrete); } } - 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(); - // 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); - } - - // Resolve Generics - - private class ResolveGenerics : SyntaxTreeTransformation - { - public static QsCompilation Apply(QsCompilation compilation, List callables, ImmutableHashSet intrinsicCallableSet, bool keepAllIntrinsics) + var callablesByNamespace = concretizations.ToLookup(x => x.FullName.Namespace); + var namespacesWithImpls = compilation.Namespaces.Select(ns => { - var filter = new ResolveGenerics( - callables - .Where(call => !keepAllIntrinsics || !intrinsicCallableSet.Contains(call.FullName)) - .ToLookup(res => res.FullName.Namespace), - intrinsicCallableSet, - keepAllIntrinsics); - - return filter.OnCompilation(compilation); - } + var elemsToAdd = callablesByNamespace[ns.Name].Select(call => QsNamespaceElement.NewQsCallable(call)); - public class TransformationState - { - public readonly ILookup NamespaceCallables; - public readonly ImmutableHashSet IntrinsicCallableSet; - public readonly bool KeepAllIntrinsics; + 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(); - public TransformationState(ILookup namespaceCallables, ImmutableHashSet intrinsicCallableSet, bool keepAllIntrinsics) - { - this.NamespaceCallables = namespaceCallables; - this.IntrinsicCallableSet = intrinsicCallableSet; - this.KeepAllIntrinsics = keepAllIntrinsics; - } - } + var compWithImpls = new QsCompilation(namespacesWithImpls, compilation.EntryPoints); - /// - /// Constructor for the ResolveGenericsSyntax class. Its transform function replaces global callables in the namespace. - /// - /// Maps namespace names to an enumerable of all global callables in that namespace. - private ResolveGenerics(ILookup namespaceCallables, ImmutableHashSet intrinsicCallableSet, bool keepAllIntrinsics) - : base(new TransformationState(namespaceCallables, intrinsicCallableSet, keepAllIntrinsics)) - { - this.Namespaces = new NamespaceTransformation(this); - this.Statements = new StatementTransformation(this, TransformationOptions.Disabled); - this.Expressions = new ExpressionTransformation(this, TransformationOptions.Disabled); - this.Types = new TypeTransformation(this, TransformationOptions.Disabled); - } + GetConcreteIdentifierFunc getConcreteIdentifier = (globalCallable, types) => + GetConcreteIdentifier(concreteNamesMap, globalCallable, types); - private class NamespaceTransformation : NamespaceTransformation - { - public NamespaceTransformation(SyntaxTreeTransformation parent) - : base(parent) - { - } + var intrinsicsToKeep = monomorphizeIntrinsics + ? ImmutableHashSet.Empty + : globals + .Where(kvp => kvp.Value.Specializations.Any(spec => spec.Implementation.IsIntrinsic)) + .Select(kvp => kvp.Key) + .ToImmutableHashSet(); - private bool NamespaceElementFilter(QsNamespaceElement elem) - { - if (elem is QsNamespaceElement.QsCallable call) - { - return BuiltIn.RewriteStepDependencies.Contains(call.Item.FullName) || - (this.SharedState.KeepAllIntrinsics && this.SharedState.IntrinsicCallableSet.Contains(call.Item.FullName)); - } - else - { - return true; - } - } - - public override QsNamespace OnNamespace(QsNamespace ns) - { - // Removes unused or generic callables from the namespace - // Adds in the used concrete callables - return ns.WithElements(elems => elems - .Where(this.NamespaceElementFilter) - .Concat(this.SharedState.NamespaceCallables[ns.Name].Select(QsNamespaceElement.NewQsCallable)) - .ToImmutableArray()); - } - } + return ReplaceTypeParamCalls.Apply(compWithImpls, getConcreteIdentifier, intrinsicsToKeep); } // Rewrite Implementations @@ -350,30 +289,36 @@ private static Identifier GetConcreteIdentifier( private class ReplaceTypeParamCalls : SyntaxTreeTransformation { - public static QsCallable Apply(QsCallable current, GetConcreteIdentifierFunc getConcreteIdentifier, ImmutableHashSet intrinsicCallableSet) + public static QsCallable Apply(QsCallable current, GetConcreteIdentifierFunc getConcreteIdentifier, ImmutableHashSet intrinsicsToKeep) { - var filter = new ReplaceTypeParamCalls(getConcreteIdentifier, intrinsicCallableSet); + var filter = new ReplaceTypeParamCalls(getConcreteIdentifier, intrinsicsToKeep); return filter.Namespaces.OnCallableDeclaration(current); } + public static QsCompilation Apply(QsCompilation compilation, GetConcreteIdentifierFunc getConcreteIdentifier, ImmutableHashSet intrinsicsToKeep) + { + var filter = new ReplaceTypeParamCalls(getConcreteIdentifier, intrinsicsToKeep); + return filter.OnCompilation(compilation); + } + public class TransformationState { public readonly Stack CurrentTypeParamResolutions = new Stack(); public readonly GetConcreteIdentifierFunc GetConcreteIdentifier; - public readonly ImmutableHashSet IntrinsicCallableSet; + public readonly ImmutableHashSet IntrinsicsToKeep; public TypeParameterResolutions? LastCalculatedTypeResolutions = null; - public TransformationState(GetConcreteIdentifierFunc getConcreteIdentifier, ImmutableHashSet intrinsicCallableSet) + public TransformationState(GetConcreteIdentifierFunc getConcreteIdentifier, ImmutableHashSet intrinsicsToKeep) { this.GetConcreteIdentifier = getConcreteIdentifier; - this.IntrinsicCallableSet = intrinsicCallableSet; + this.IntrinsicsToKeep = intrinsicsToKeep; } } - private ReplaceTypeParamCalls(GetConcreteIdentifierFunc getConcreteIdentifier, ImmutableHashSet intrinsicCallableSet) - : base(new TransformationState(getConcreteIdentifier, intrinsicCallableSet)) + private ReplaceTypeParamCalls(GetConcreteIdentifierFunc getConcreteIdentifier, ImmutableHashSet intrinsicsToKeep) + : base(new TransformationState(getConcreteIdentifier, intrinsicsToKeep)) { - this.Namespaces = new NamespaceTransformation(this, TransformationOptions.Disabled); + this.Namespaces = new NamespaceTransformation(this); this.Statements = new StatementTransformation(this); this.StatementKinds = new StatementKindTransformation(this); this.Expressions = new ExpressionTransformation(this); @@ -407,8 +352,8 @@ public override TypeParameterResolutions OnTypeParamResolutions(TypeParameterRes { if (typeParams.Any()) { - var noIntrinsicRes = typeParams.Where(kvp => !this.SharedState.IntrinsicCallableSet.Contains(kvp.Key.Item1)).ToImmutableDictionary(); - var intrinsicRes = typeParams.Where(kvp => this.SharedState.IntrinsicCallableSet.Contains(kvp.Key.Item1)).ToImmutableDictionary(); + var noIntrinsicRes = typeParams.Where(kvp => !this.SharedState.IntrinsicsToKeep.Contains(kvp.Key.Item1)).ToImmutableDictionary(); + var intrinsicRes = typeParams.Where(kvp => this.SharedState.IntrinsicsToKeep.Contains(kvp.Key.Item1)).ToImmutableDictionary(); this.SharedState.CurrentTypeParamResolutions.Push(noIntrinsicRes); @@ -432,8 +377,8 @@ public override QsExpressionKind OnId { if (sym is Identifier.GlobalCallable global) { - // We want to skip over intrinsic callables. They will not be monomorphized. - if (!this.SharedState.IntrinsicCallableSet.Contains(global.Item)) + // We want to skip over callables listed in IntrinsicsToKeep; they will not be monomorphized. + if (!this.SharedState.IntrinsicsToKeep.Contains(global.Item)) { var combination = new TypeResolutionCombination(this.SharedState.CurrentTypeParamResolutions); this.SharedState.LastCalculatedTypeResolutions = combination.CombinedResolutionDictionary; diff --git a/src/QsCompiler/Transformations/MonomorphizationValidation.cs b/src/QsCompiler/Transformations/MonomorphizationValidation.cs index 275ca5bf42..d71c4f2bfa 100644 --- a/src/QsCompiler/Transformations/MonomorphizationValidation.cs +++ b/src/QsCompiler/Transformations/MonomorphizationValidation.cs @@ -12,12 +12,14 @@ namespace Microsoft.Quantum.QsCompiler.Transformations.Monomorphization.Validati { public class ValidateMonomorphization : SyntaxTreeTransformation { - public static void Apply(QsCompilation compilation) + public static void Apply(QsCompilation compilation, bool allowTypeParametersForIntrinsics = true) { - var intrinsicCallableSet = compilation.Namespaces.GlobalCallableResolutions() - .Where(kvp => kvp.Value.Specializations.Any(spec => spec.Implementation.IsIntrinsic)) - .Select(kvp => kvp.Key) - .ToImmutableHashSet(); + var intrinsicCallableSet = allowTypeParametersForIntrinsics + ? compilation.Namespaces.GlobalCallableResolutions() + .Where(kvp => kvp.Value.Specializations.Any(spec => spec.Implementation.IsIntrinsic)) + .Select(kvp => kvp.Key) + .ToImmutableHashSet() + : ImmutableHashSet.Empty; new ValidateMonomorphization(intrinsicCallableSet).OnCompilation(compilation); } diff --git a/src/QsCompiler/Transformations/QsharpCodeOutput.cs b/src/QsCompiler/Transformations/QsharpCodeOutput.cs index aeaf7bd22c..8bc45d208b 100644 --- a/src/QsCompiler/Transformations/QsharpCodeOutput.cs +++ b/src/QsCompiler/Transformations/QsharpCodeOutput.cs @@ -1102,13 +1102,11 @@ public override QsStatementKind OnQubitScope(QsQubitScope stm) var symbols = this.SymbolTuple(stm.Binding.Lhs); var initializers = this.InitializerTuple(stm.Binding.Rhs); var header = -#pragma warning disable 618 // qsBorrowing and qsUsing are obsolete. - stm.Kind.IsBorrow ? Keywords.qsBorrowing.id - : stm.Kind.IsAllocate ? Keywords.qsUsing.id -#pragma warning restore 618 + stm.Kind.IsBorrow ? Keywords.qsBorrow.id + : stm.Kind.IsAllocate ? Keywords.qsUse.id : throw new NotImplementedException("unknown qubit scope"); - var intro = $"{header} ({symbols} = {initializers})"; + var intro = $"{header} {symbols} = {initializers}"; this.AddBlockStatement(intro, stm.Body); return QsStatementKind.NewQsQubitScope(stm); } @@ -1117,7 +1115,7 @@ public override QsStatementKind OnQubitScope(QsQubitScope stm) public override QsStatementKind OnForStatement(QsForStatement stm) { var symbols = this.SymbolTuple(stm.LoopItem.Item1); - var intro = $"{Keywords.qsFor.id} ({symbols} {Keywords.qsRangeIter.id} {this.expressionToQs(stm.IterationValues)})"; + var intro = $"{Keywords.qsFor.id} {symbols} {Keywords.qsRangeIter.id} {this.expressionToQs(stm.IterationValues)}"; this.AddBlockStatement(intro, stm.Body); return QsStatementKind.NewQsForStatement(stm); } @@ -1125,7 +1123,7 @@ public override QsStatementKind OnForStatement(QsForStatement stm) /// public override QsStatementKind OnWhileStatement(QsWhileStatement stm) { - var intro = $"{Keywords.qsWhile.id} ({this.expressionToQs(stm.Condition)})"; + var intro = $"{Keywords.qsWhile.id} {this.expressionToQs(stm.Condition)}"; this.AddBlockStatement(intro, stm.Body); return QsStatementKind.NewQsWhileStatement(stm); } @@ -1136,7 +1134,7 @@ public override QsStatementKind OnRepeatStatement(QsRepeatStatement stm) this.SharedState.StatementComments = stm.RepeatBlock.Comments; this.AddBlockStatement(Keywords.qsRepeat.id, stm.RepeatBlock.Body); this.SharedState.StatementComments = stm.FixupBlock.Comments; - this.AddToOutput($"{Keywords.qsUntil.id} ({this.expressionToQs(stm.SuccessCondition)})"); + this.AddToOutput($"{Keywords.qsUntil.id} {this.expressionToQs(stm.SuccessCondition)}"); this.AddBlockStatement(Keywords.qsRUSfixup.id, stm.FixupBlock.Body, false); return QsStatementKind.NewQsRepeatStatement(stm); } @@ -1152,7 +1150,7 @@ public override QsStatementKind OnConditionalStatement(QsConditionalStatement st foreach (var clause in stm.ConditionalBlocks) { this.SharedState.StatementComments = clause.Item2.Comments; - var intro = $"{header} ({this.expressionToQs(clause.Item1)})"; + var intro = $"{header} {this.expressionToQs(clause.Item1)}"; this.AddBlockStatement(intro, clause.Item2.Body, false); header = Keywords.qsElif.id; } diff --git a/src/QsCompiler/Transformations/SearchAndReplace.cs b/src/QsCompiler/Transformations/SearchAndReplace.cs index 5346492ed9..79b4436877 100644 --- a/src/QsCompiler/Transformations/SearchAndReplace.cs +++ b/src/QsCompiler/Transformations/SearchAndReplace.cs @@ -479,6 +479,9 @@ internal static QsQualifiedName PrependGuid(QsQualifiedName original) => original.Namespace, "_" + Guid.NewGuid().ToString("N") + "_" + original.Name); + public static bool IsAutoGeneratedName(QsQualifiedName mangled) => + GUID.IsMatch(mangled.Name); + public static QsQualifiedName OriginalNameFromMonomorphized(QsQualifiedName mangled) => new QsQualifiedName( mangled.Namespace, diff --git a/src/QsCompiler/Transformations/SyntaxTreeTrimming.cs b/src/QsCompiler/Transformations/SyntaxTreeTrimming.cs new file mode 100644 index 0000000000..0ee3829c60 --- /dev/null +++ b/src/QsCompiler/Transformations/SyntaxTreeTrimming.cs @@ -0,0 +1,109 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Text; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.Quantum.QsCompiler.DependencyAnalysis; +using Microsoft.Quantum.QsCompiler.SyntaxTree; +using Microsoft.Quantum.QsCompiler.Transformations.Core; + +namespace Microsoft.Quantum.QsCompiler.Transformations.SyntaxTreeTrimming +{ + public static class TrimSyntaxTree + { + public static QsCompilation Apply(QsCompilation compilation, bool keepAllIntrinsics) + { + return TrimTree.Apply(compilation, keepAllIntrinsics); + } + + private class TrimTree : SyntaxTreeTransformation + { + 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 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 static bool FilterWithIntrinsics(QsNamespaceElement elem, ImmutableHashSet graphNodes) + { + if (elem is QsNamespaceElement.QsCallable call) + { + return call.Item.Specializations.Any(spec => spec.Implementation.IsIntrinsic) + || graphNodes.Contains(call.Item.FullName); + } + else + { + return true; + } + } + + private static bool Filter(QsNamespaceElement elem, ImmutableHashSet graphNodes) + { + if (elem is QsNamespaceElement.QsCallable call) + { + return graphNodes.Contains(call.Item.FullName); + } + else + { + return true; + } + } + + public class TransformationState + { + public readonly Func NamespaceElementFilter; + + public TransformationState(Func namespaceElementFilter) + { + this.NamespaceElementFilter = namespaceElementFilter; + } + } + + private TrimTree(Func namespaceElementFilter) + : base(new TransformationState(namespaceElementFilter)) + { + this.Namespaces = new NamespaceTransformation(this); + this.Statements = new StatementTransformation(this, TransformationOptions.Disabled); + this.Expressions = new ExpressionTransformation(this, TransformationOptions.Disabled); + this.Types = new TypeTransformation(this, TransformationOptions.Disabled); + } + + private class NamespaceTransformation : NamespaceTransformation + { + public NamespaceTransformation(SyntaxTreeTransformation parent) + : base(parent) + { + } + + public override QsNamespace OnNamespace(QsNamespace ns) + { + return ns.WithElements(elements => elements + .Where(this.SharedState.NamespaceElementFilter) + .ToImmutableArray()); + } + } + } + } +} diff --git a/src/QsCompiler/Transformations/TargetInstructionInference.cs b/src/QsCompiler/Transformations/TargetInstructionInference.cs index d5a250ca23..d4475faf4e 100644 --- a/src/QsCompiler/Transformations/TargetInstructionInference.cs +++ b/src/QsCompiler/Transformations/TargetInstructionInference.cs @@ -9,6 +9,7 @@ using Microsoft.Quantum.QsCompiler.ReservedKeywords; using Microsoft.Quantum.QsCompiler.SyntaxTokens; using Microsoft.Quantum.QsCompiler.SyntaxTree; +using Microsoft.Quantum.QsCompiler.Transformations.SearchAndReplace; namespace Microsoft.Quantum.QsCompiler.Transformations.Targeting { @@ -94,6 +95,7 @@ QsNamespace AddAttributes(QsNamespace ns) 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)) diff --git a/src/QuantumSdk/QuantumSdk.nuspec b/src/QuantumSdk/QuantumSdk.nuspec index f1bc0a2943..2d3d40391c 100644 --- a/src/QuantumSdk/QuantumSdk.nuspec +++ b/src/QuantumSdk/QuantumSdk.nuspec @@ -11,7 +11,7 @@ The Microsoft Quantum Sdk for developing in Q#. See: https://docs.microsoft.com/azure/quantum/qdk-relnotes/ https://github.com/microsoft/qsharp-compiler - images\qdk-nuget-icon.png + https://secure.gravatar.com/avatar/bd1f02955b2853ba0a3b1cdc2434e8ec.png © Microsoft Corporation. All rights reserved. Quantum Q# QSharp @@ -25,6 +25,5 @@ - diff --git a/src/QuantumSdk/Sdk/Sdk.props b/src/QuantumSdk/Sdk/Sdk.props index 7789c47f0f..de15b074ec 100644 --- a/src/QuantumSdk/Sdk/Sdk.props +++ b/src/QuantumSdk/Sdk/Sdk.props @@ -34,12 +34,16 @@ - + + diff --git a/src/QuantumSdk/Sdk/Sdk.targets b/src/QuantumSdk/Sdk/Sdk.targets index 33328d0a23..cb3af539de 100644 --- a/src/QuantumSdk/Sdk/Sdk.targets +++ b/src/QuantumSdk/Sdk/Sdk.targets @@ -87,12 +87,12 @@ <_QscCommandReferencesFlag Condition="@(ResolvedQSharpReferences->Count()) > 0">$(_NewLine)--references$(_NewLineIndent)"@(ResolvedQSharpReferences,'"$(_NewLineIndent)"')" <_QscCommandLoadFlag Condition="@(_PrioritizedResolvedQscReferences->Count()) > 0">$(_NewLine)--load$(_NewLineIndent)"@(_PrioritizedResolvedQscReferences,'"$(_NewLineIndent)"')" <_QscCommandRuntimeFlag>$(_NewLine)--runtime$(_NewLineIndent)$(ResolvedRuntimeCapabilities) - <_QscCommandQirGenerationFlag Condition="$(QirGeneration)">$(_NewLine)--qir$(_NewLineIndent)$(QirOutputPath) + <_QscCommandSkipMonomorphization Condition="'$(ResolvedRuntimeCapabilities)' == 'FullComputation' And $(CSharpGeneration)">$(_NewLine)--skip-monomorphization <_QscCommandPerfDataGenerationFlag Condition="$(PerfDataGeneration)">$(_NewLine)--perf$(_NewLineIndent)$(PerfDataOutputPath) <_QscCommandTargetDecompositionsFlag Condition="@(ResolvedTargetSpecificDecompositions->Count()) > 0">$(_NewLine)--target-specific-decompositions$(_NewLineIndent)"@(ResolvedTargetSpecificDecompositions,'"$(_NewLineIndent)"')" <_QscPackageLoadFallbackFoldersFlag Condition="@(ResolvedPackageLoadFallbackFolders->Count()) > 0">$(_NewLine)--package-load-fallback-folders$(_NewLineIndent)"@(ResolvedPackageLoadFallbackFolders,'"$(_NewLineIndent)"')" <_QscCommandTestNamesFlag Condition="$(ExposeReferencesViaTestNames)">$(_NewLine)--load-test-names - <_QscCommandPredefinedAssemblyProperties>$(_NewLineIndent)ProcessorArchitecture:$(ResolvedProcessorArchitecture)$(_NewLineIndent)QSharpOutputType:$(ResolvedQSharpOutputType) + <_QscCommandPredefinedAssemblyProperties>$(_NewLineIndent)AssemblyName:$(PathCompatibleAssemblyName)$(_NewLineIndent)ProcessorArchitecture:$(ResolvedProcessorArchitecture)$(_NewLineIndent)QSharpOutputType:$(ResolvedQSharpOutputType) <_QscCommandPredefinedAssemblyProperties Condition="'$(DefaultSimulator)' != ''">$(_QscCommandPredefinedAssemblyProperties)$(_NewLineIndent)DefaultSimulator:$(DefaultSimulator) <_QscCommandPredefinedAssemblyProperties Condition="'$(ExecutionTarget)' != ''">$(_QscCommandPredefinedAssemblyProperties)$(_NewLineIndent)ExecutionTarget:$(ExecutionTarget) <_QscCommandPredefinedAssemblyProperties Condition="'$(ExposeReferencesViaTestNames)'">$(_QscCommandPredefinedAssemblyProperties)$(_NewLineIndent)ExposeReferencesViaTestNames:true @@ -104,7 +104,7 @@ <_QscCommandAssemblyPropertiesFlag>$(_NewLine)--assembly-properties$(_QscCommandPredefinedAssemblyProperties) <_QscCommandAssemblyPropertiesFlag Condition="'$(QscCommandAssemblyProperties)' != ''">$(_QscCommandAssemblyPropertiesFlag)$(_NewLineIndent)$(QscCommandAssemblyProperties) $(_NewLine)$(AdditionalQscArguments) - <_QscCommandArgs>$(_QscCommandProjFlag)$(_QscCommandIsExecutableFlag)$(_QscCommandInputFlag)$(_QscCommandOutputFlag)$(_QscCommandReferencesFlag)$(_QscCommandLoadFlag)$(_QscCommandQirGenerationFlag)$(_QscCommandPerfDataGenerationFlag)$(_QscCommandRuntimeFlag)$(_QscCommandTargetDecompositionsFlag)$(_QscPackageLoadFallbackFoldersFlag)$(_QscCommandTestNamesFlag)$(_QscCommandAssemblyPropertiesFlag)$(AdditionalQscArguments) + <_QscCommandArgs>$(_QscCommandProjFlag)$(_QscCommandIsExecutableFlag)$(_QscCommandInputFlag)$(_QscCommandOutputFlag)$(_QscCommandReferencesFlag)$(_QscCommandLoadFlag)$(_QscCommandPerfDataGenerationFlag)$(_QscCommandRuntimeFlag)$(_QscCommandSkipMonomorphization)$(_QscCommandTargetDecompositionsFlag)$(_QscPackageLoadFallbackFoldersFlag)$(_QscCommandTestNamesFlag)$(_QscCommandAssemblyPropertiesFlag)$(AdditionalQscArguments) <_QscCommandArgsFile>$(QscBuildConfigOutputPath)qsc.rsp @@ -129,7 +129,7 @@ @@ -144,20 +144,22 @@ - + - $(GeneratedFilesOutputPath)Main.cs + <_DefaultEntryPoint Condition="$(QirGeneration) And '$(CSharpGeneration)' != 'true' And @(Compile->Count()) == 0">$(GeneratedFilesOutputPath)Main.cs + <_GeneratedBinary>$(GeneratedFilesOutputPath)$(PathCompatibleAssemblyName) - + - + + - +