diff --git a/src/QsCompiler/Compiler/CompilationLoader.cs b/src/QsCompiler/Compiler/CompilationLoader.cs index b430dbfa36..2a3dbfbf3d 100644 --- a/src/QsCompiler/Compiler/CompilationLoader.cs +++ b/src/QsCompiler/Compiler/CompilationLoader.cs @@ -447,8 +447,8 @@ public CompilationLoader(SourceLoader loadSources, ReferenceLoader loadReference if (this.Config.IsExecutable && this.CompilationOutput?.EntryPoints.Length == 0) { - this.Logger?.Log(WarningCode.MissingEntryPoint, Array.Empty()); - + if (this.Config.RuntimeCapabilities == RuntimeCapabilities.Unknown) this.Logger?.Log(WarningCode.MissingEntryPoint, Array.Empty()); + else this.LogAndUpdate(ref this.CompilationStatus.Validation, ErrorCode.MissingEntryPoint, Array.Empty()); } // executing the specified rewrite steps diff --git a/src/QsCompiler/Compiler/RewriteSteps/ClassicallyControlled.cs b/src/QsCompiler/Compiler/RewriteSteps/ClassicallyControlled.cs index 582a33d833..0d718936ee 100644 --- a/src/QsCompiler/Compiler/RewriteSteps/ClassicallyControlled.cs +++ b/src/QsCompiler/Compiler/RewriteSteps/ClassicallyControlled.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Linq; -using Microsoft.Quantum.QsCompiler.DataTypes; using Microsoft.Quantum.QsCompiler.SyntaxTree; using Microsoft.Quantum.QsCompiler.Transformations.ClassicallyControlled; diff --git a/src/QsCompiler/Core/NamespaceTransformation.fs b/src/QsCompiler/Core/NamespaceTransformation.fs index e258301ea6..d157e3d944 100644 --- a/src/QsCompiler/Core/NamespaceTransformation.fs +++ b/src/QsCompiler/Core/NamespaceTransformation.fs @@ -52,6 +52,9 @@ type NamespaceTransformationBase internal (options : TransformationOptions, _int abstract member OnAttribute : QsDeclarationAttribute -> QsDeclarationAttribute default this.OnAttribute att = att + abstract member OnItemName : NonNullable -> NonNullable + default this.OnItemName name = name + abstract member OnTypeItems : QsTuple -> QsTuple default this.OnTypeItems tItem = match tItem with @@ -63,10 +66,17 @@ type NamespaceTransformationBase internal (options : TransformationOptions, _int QsTupleItem << Anonymous |> Node.BuildOr original t | QsTupleItem (Named item) as original -> let loc = item.Position, item.Range + let name = this.OnItemName item.VariableName let t = this.Statements.Expressions.Types.OnType item.Type let info = this.Statements.Expressions.OnExpressionInformation item.InferredInformation - QsTupleItem << Named << LocalVariableDeclaration<_>.New info.IsMutable |> Node.BuildOr original (loc, item.VariableName, t, info.HasLocalQuantumDependency) + QsTupleItem << Named << LocalVariableDeclaration<_>.New info.IsMutable |> Node.BuildOr original (loc, name, t, info.HasLocalQuantumDependency) + abstract member OnArgumentName : QsLocalSymbol -> QsLocalSymbol + default this.OnArgumentName arg = + match arg with + | ValidName name -> ValidName |> Node.BuildOr arg (this.Statements.OnVariableName name) + | InvalidName -> arg + abstract member OnArgumentTuple : QsArgumentTuple -> QsArgumentTuple default this.OnArgumentTuple arg = match arg with @@ -75,9 +85,10 @@ type NamespaceTransformationBase internal (options : TransformationOptions, _int QsTuple |> Node.BuildOr original transformed | QsTupleItem item as original -> let loc = item.Position, item.Range + let name = this.OnArgumentName item.VariableName let t = this.Statements.Expressions.Types.OnType item.Type let info = this.Statements.Expressions.OnExpressionInformation item.InferredInformation - QsTupleItem << LocalVariableDeclaration<_>.New info.IsMutable |> Node.BuildOr original (loc, item.VariableName, t, info.HasLocalQuantumDependency) + QsTupleItem << LocalVariableDeclaration<_>.New info.IsMutable |> Node.BuildOr original (loc, name, t, info.HasLocalQuantumDependency) abstract member OnSignature : ResolvedSignature -> ResolvedSignature default this.OnSignature (s : ResolvedSignature) = diff --git a/src/QsCompiler/Core/StatementTransformation.fs b/src/QsCompiler/Core/StatementTransformation.fs index 83e5d98ce1..f8614335e2 100644 --- a/src/QsCompiler/Core/StatementTransformation.fs +++ b/src/QsCompiler/Core/StatementTransformation.fs @@ -213,14 +213,18 @@ and StatementTransformationBase internal (options : TransformationOptions, _inte abstract member OnLocation : QsNullable -> QsNullable default this.OnLocation loc = loc + abstract member OnVariableName : NonNullable -> NonNullable + default this.OnVariableName name = name + /// If DisableRebuild is set to true, this method won't walk the local variables declared by the statement. abstract member OnLocalDeclarations : LocalDeclarations -> LocalDeclarations default this.OnLocalDeclarations decl = let onLocalVariableDeclaration (local : LocalVariableDeclaration>) = let loc = local.Position, local.Range - let info = this.Expressions.OnExpressionInformation local.InferredInformation + let name = this.OnVariableName local.VariableName let varType = this.Expressions.Types.OnType local.Type - LocalVariableDeclaration.New info.IsMutable (loc, local.VariableName, varType, info.HasLocalQuantumDependency) + let info = this.Expressions.OnExpressionInformation local.InferredInformation + LocalVariableDeclaration.New info.IsMutable (loc, name, varType, info.HasLocalQuantumDependency) let variableDeclarations = decl.Variables |> Seq.map onLocalVariableDeclaration LocalDeclarations.New << ImmutableArray.CreateRange |> Node.BuildOr decl variableDeclarations diff --git a/src/QsCompiler/DataStructures/Diagnostics.fs b/src/QsCompiler/DataStructures/Diagnostics.fs index a975b60474..267bd77147 100644 --- a/src/QsCompiler/DataStructures/Diagnostics.fs +++ b/src/QsCompiler/DataStructures/Diagnostics.fs @@ -237,14 +237,15 @@ type ErrorCode = | InnerTupleInEntryPointArgument = 6234 | ArrayOfArrayInEntryPointArgument = 6235 | MultipleEntryPoints = 6236 - | InvalidEntryPointSpecialization = 6237 - | DuplicateEntryPointArgumentName = 6238 - | EntryPointInLibrary = 6239 - | InvalidTestAttributePlacement = 6240 - | InvalidExecutionTargetForTest = 6241 - | ExpectingFullNameAsAttributeArgument = 6242 - | AttributeInvalidOnSpecialization = 6243 - | AttributeInvalidOnCallable = 6244 + | MissingEntryPoint = 6237 + | InvalidEntryPointSpecialization = 6238 + | DuplicateEntryPointArgumentName = 6239 + | EntryPointInLibrary = 6240 + | InvalidTestAttributePlacement = 6241 + | InvalidExecutionTargetForTest = 6242 + | ExpectingFullNameAsAttributeArgument = 6243 + | AttributeInvalidOnSpecialization = 6244 + | AttributeInvalidOnCallable = 6245 | TypeMismatchInReturn = 6301 | TypeMismatchInValueUpdate = 6302 @@ -612,6 +613,7 @@ type DiagnosticItem = | ErrorCode.InnerTupleInEntryPointArgument -> "Anonymous tuple items or arrays of tuples are not supported in entry point arguments. All items need to be named." | ErrorCode.ArrayOfArrayInEntryPointArgument -> "Multi-dimensional arrays are not supported in entry point arguments." | ErrorCode.MultipleEntryPoints -> "Invalid entry point. An entry point {0} already exists in {1}." + | ErrorCode.MissingEntryPoint -> "Missing entry point. Execution on a quantum processor requires that a Q# entry point is defined using the @EntryPoint() attribute. Any C# driver code should be defined in a separate project." | ErrorCode.InvalidEntryPointSpecialization -> "Entry points cannot have any other specializations besides the default body." | ErrorCode.DuplicateEntryPointArgumentName -> "Invalid name for entry point argument. A similar argument name is already in use." | ErrorCode.EntryPointInLibrary -> "Invalid entry point. Only executable Q# projects can have entry points." diff --git a/src/QsCompiler/DataStructures/ReservedKeywords.fs b/src/QsCompiler/DataStructures/ReservedKeywords.fs index 0709434b72..8b8fa3e4c6 100644 --- a/src/QsCompiler/DataStructures/ReservedKeywords.fs +++ b/src/QsCompiler/DataStructures/ReservedKeywords.fs @@ -234,6 +234,9 @@ module GeneratedAttributes = module AssemblyConstants = let OutputPath = "OutputPath" let AssemblyName = "AssemblyName" + let QsharpOutputType = "ResolvedQsharpOutputType" + let QsharpExe = "QsharpExe" + let QsharpLibrary = "QsharpLibrary" let ExecutionTarget = "ResolvedExecutionTarget" let AlfredProcessor = "AlfredProcessor" let BrunoProcessor = "BrunoProcessor" diff --git a/src/QsCompiler/Transformations/CodeTransformations.cs b/src/QsCompiler/Transformations/CodeTransformations.cs index f4f5ccd0af..78ca034df1 100644 --- a/src/QsCompiler/Transformations/CodeTransformations.cs +++ b/src/QsCompiler/Transformations/CodeTransformations.cs @@ -35,8 +35,8 @@ public static QsScope GenerateAdjoint(this QsScope scope) } /// - /// Given the body of an operation, auto-generates the (content of the) controlled specialization - /// using the default name for control qubits. + /// Given the body of an operation, auto-generates the (content of the) controlled specialization using the default name + /// for control qubits. Adds the control qubits names to the list of defined variables for the scope and each subscope. /// Throws an ArgumentNullException if the given scope is null. /// public static QsScope GenerateControlled(this QsScope scope) diff --git a/src/QsCompiler/Transformations/FunctorGeneration.cs b/src/QsCompiler/Transformations/FunctorGeneration.cs index f47871d31a..14819e0977 100644 --- a/src/QsCompiler/Transformations/FunctorGeneration.cs +++ b/src/QsCompiler/Transformations/FunctorGeneration.cs @@ -18,7 +18,8 @@ namespace Microsoft.Quantum.QsCompiler.Transformations.FunctorGeneration /// /// Scope transformation that replaces each operation call within a given scope /// with a call to the operation after application of the functor given on initialization. - /// The default values used for auto-generation will be used for the additional functor arguments. + /// The default values used for auto-generation will be used for the additional functor arguments. + /// Additional functor arguments will be added to the list of defined variables for each scope. /// public class ApplyFunctorToOperationCalls : SyntaxTreeTransformation @@ -31,10 +32,10 @@ public TransformationsState(QsFunctor functor) => this.FunctorToApply = functor ?? throw new ArgumentNullException(nameof(functor)); } - public ApplyFunctorToOperationCalls(QsFunctor functor) : base(new TransformationsState(functor)) - { + { + if (functor.IsControlled) this.Statements = new AddVariableDeclarations(this, ControlQubitsDeclaration); this.StatementKinds = new IgnoreOuterBlockInConjugations(this); this.ExpressionKinds = new ExpressionKindTransformation(this); this.Types = new TypeTransformation(this, TransformationOptions.Disabled); @@ -43,8 +44,19 @@ public ApplyFunctorToOperationCalls(QsFunctor functor) // static methods for convenience + private static readonly NonNullable ControlQubitsName = + NonNullable.New(InternalUse.ControlQubitsName); + private static readonly TypedExpression ControlQubits = - SyntaxGenerator.ImmutableQubitArrayWithName(NonNullable.New(InternalUse.ControlQubitsName)); + SyntaxGenerator.ImmutableQubitArrayWithName(ControlQubitsName); + + private static readonly LocalVariableDeclaration> ControlQubitsDeclaration = + new LocalVariableDeclaration>( + ControlQubitsName, + ControlQubits.ResolvedType, + ControlQubits.InferredInformation, + QsNullable>.Null, + QsCompilerDiagnostic.DefaultRange); public static readonly Func ApplyAdjoint = new ApplyFunctorToOperationCalls(QsFunctor.Adjoint).Statements.OnScope; @@ -86,6 +98,21 @@ public override QsExpressionKind OnOp } } + /// + /// Adds the given variable declarations to the list of defined variables for each scope. + /// + public class AddVariableDeclarations + : StatementTransformation + { + private readonly IEnumerable>> AddedVariableDeclarations; + + public AddVariableDeclarations(SyntaxTreeTransformation parent, params LocalVariableDeclaration>[] addedVars) + : base(parent) => + this.AddedVariableDeclarations = addedVars ?? throw new ArgumentNullException(nameof(addedVars)); + + public override LocalDeclarations OnLocalDeclarations(LocalDeclarations decl) => + base.OnLocalDeclarations(new LocalDeclarations(decl.Variables.AddRange(this.AddedVariableDeclarations))); + } /// /// Ensures that the outer block of conjugations is ignored during transformation. diff --git a/src/QsCompiler/Transformations/SearchAndReplace.cs b/src/QsCompiler/Transformations/SearchAndReplace.cs index 8d629913a6..ba3af7efff 100644 --- a/src/QsCompiler/Transformations/SearchAndReplace.cs +++ b/src/QsCompiler/Transformations/SearchAndReplace.cs @@ -430,9 +430,12 @@ public class UniqueVariableNames public class TransformationState { private int VariableNr = 0; - private Dictionary, NonNullable> UniqueNames = + private readonly Dictionary, NonNullable> UniqueNames = new Dictionary, NonNullable>(); + internal bool TryGetUniqueName(NonNullable name, out NonNullable unique) => + this.UniqueNames.TryGetValue(name, out unique); + internal QsExpressionKind AdaptIdentifier(Identifier sym, QsNullable> tArgs) => sym is Identifier.LocalVariable varName && this.UniqueNames.TryGetValue(varName.Item, out var unique) ? QsExpressionKind.NewIdentifier(Identifier.NewLocalVariable(unique), tArgs) @@ -453,6 +456,7 @@ internal NonNullable GenerateUniqueName(NonNullable varName) public UniqueVariableNames() : base(new TransformationState()) { + this.Statements = new StatementTransformation(this); this.StatementKinds = new StatementKindTransformation(this); this.ExpressionKinds = new ExpressionKindTransformation(this); this.Types = new TypeTransformation(this, TransformationOptions.Disabled); @@ -472,6 +476,16 @@ public static NonNullable StripUniqueName(NonNullable uniqueName // helper classes + private class StatementTransformation + : StatementTransformation + { + public StatementTransformation(SyntaxTreeTransformation parent) + : base(parent) { } + + public override NonNullable OnVariableName(NonNullable name) => + this.SharedState.TryGetUniqueName(name, out var unique) ? unique : name; + } + private class StatementKindTransformation : StatementKindTransformation { diff --git a/src/QuantumSdk/DefaultItems/DefaultItems.targets b/src/QuantumSdk/DefaultItems/DefaultItems.targets index aaed1d27ab..94f06e5347 100644 --- a/src/QuantumSdk/DefaultItems/DefaultItems.targets +++ b/src/QuantumSdk/DefaultItems/DefaultItems.targets @@ -19,20 +19,20 @@ - QsharpLibrary - QsharpExe + QsharpLibrary + QsharpExe Possible values are 'Exe', or 'Library'. - AlfredProcessor - BrunoProcessor - ClementineProcessor + AlfredProcessor + BrunoProcessor + ClementineProcessor Unspecified - Possible values are 'Alfred', 'Bruno', 'Clementine', or 'Any'. + Possible values are 'Alfred', 'Bruno', 'Clementine', or 'Any'. The execution target for a Q# library needs to be 'Any'. diff --git a/src/QuantumSdk/Sdk/Sdk.targets b/src/QuantumSdk/Sdk/Sdk.targets index ba633b3e5a..ea6ff21297 100644 --- a/src/QuantumSdk/Sdk/Sdk.targets +++ b/src/QuantumSdk/Sdk/Sdk.targets @@ -77,7 +77,7 @@ <_QscCommandRuntimeFlag>--runtime $(ResolvedRuntimeCapabilities) <_QscCommandTargetPackageFlag Condition="'$(ResolvedTargetPackage)' != ''">--target-package "$(ResolvedTargetPackage)" <_QscCommandTestNamesFlag Condition="$(ExposeReferencesViaTestNames)">--load-test-names - <_QscCommandPredefinedAssemblyProperties>ResolvedExecutionTarget:$(ResolvedQsharpExecutionTarget) + <_QscCommandPredefinedAssemblyProperties>ResolvedExecutionTarget:$(ResolvedQsharpExecutionTarget) ResolvedQsharpOutputType:$(ResolvedQsharpOutputType) <_QscCommandPredefinedAssemblyProperties Condition="$(DefaultSimulator) != ''">$(_QscCommandPredefinedAssemblyProperties) DefaultSimulator:$(DefaultSimulator) <_QscCommandAssemblyPropertiesFlag>--assembly-properties $(_QscCommandPredefinedAssemblyProperties) $(QscCommandAssemblyProperties) <_QscPackageLoadFallbackFoldersFlag Condition="@(ResolvedPackageLoadFallbackFolders->Count()) > 0">--package-load-fallback-folders "@(ResolvedPackageLoadFallbackFolders,'" "')"