Skip to content
This repository was archived by the owner on Jan 12, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
27be592
Added Andres's basic implementation of the Classically Controlled tra…
ScottCarda-MS Nov 23, 2019
110aada
Merge branch 'master' into sccarda/ClassicallyControlled
ScottCarda-MS Dec 2, 2019
3dc34f6
Added rewrite step
ScottCarda-MS Dec 3, 2019
97a730b
Filled in type information for injected control flow operation calls.
ScottCarda-MS Dec 4, 2019
374172c
Added logic to hoist sub-scopes into generated operators. Logic is cu…
ScottCarda-MS Dec 10, 2019
5107fe3
Changed 'operator' to 'operation'
ScottCarda-MS Dec 10, 2019
2c5f1cd
Nested if's will be processed.
ScottCarda-MS Dec 10, 2019
16d6931
Convert elif to nested if structure to allow for processing.
ScottCarda-MS Dec 10, 2019
53f9f8b
Added logic to generated parameters/arguments for the generated opera…
ScottCarda-MS Dec 11, 2019
43182e4
Added super-scope's type params to the signiture of the generated ope…
ScottCarda-MS Dec 12, 2019
e0264df
Forwarding type parameters into the generated operations.
ScottCarda-MS Dec 13, 2019
5ca3ad7
Merged in from master
ScottCarda-MS Dec 16, 2019
3bf4f6c
Updated transformation with nullable locations
ScottCarda-MS Dec 16, 2019
6e4b139
Expanded on the type param reroute transformation so that it operates…
ScottCarda-MS Dec 18, 2019
45f3060
Reorganized the reroute transform to be a self-contained transform su…
ScottCarda-MS Dec 18, 2019
863df6d
WIP
ScottCarda-MS Dec 19, 2019
a814d8c
WIP, all that's left is condition expression encapsulation and condit…
ScottCarda-MS Dec 20, 2019
ed4a5da
WIP, not going to do expression encapsulation anymore. Still need to …
ScottCarda-MS Dec 20, 2019
33b00e7
WIP, mostly finished with implementation. Need to do some cleaning up.
ScottCarda-MS Dec 20, 2019
e2c8d6e
Cleaned up code. Everything seems to be working.
ScottCarda-MS Dec 21, 2019
31ef6f9
Partially fixed a bug with generic references being separated from th…
ScottCarda-MS Jan 3, 2020
ce0d72f
Fixed minor bug with the logic that handles mutables.
ScottCarda-MS Jan 4, 2020
274a0cd
Got most of the implementation for functor support in generated contr…
ScottCarda-MS Jan 7, 2020
603cce3
Getting close, still need to use the appropriate ApplyIf for the call.
ScottCarda-MS Jan 7, 2020
6dcbd6a
The generated operations now correctly have functor support, and the …
ScottCarda-MS Jan 8, 2020
7b59dcc
Cleanup
ScottCarda-MS Jan 8, 2020
739ceb1
Fixed some line endings
ScottCarda-MS Jan 8, 2020
8dc3ba9
Basic test
ScottCarda-MS Jan 10, 2020
57d22b9
Added test to check if-else and if-elif-else structures.
ScottCarda-MS Jan 10, 2020
5dc5d89
Set up some logic to tests what calls are being made in callables.
ScottCarda-MS Jan 12, 2020
0c831ca
just more progress
ScottCarda-MS Jan 14, 2020
483db3f
Trying to make test for Elif structure. Not quite there yet.
ScottCarda-MS Jan 14, 2020
53a9db1
Pulled out some common logic.
ScottCarda-MS Jan 14, 2020
2b41f24
And and Or conditions tests
ScottCarda-MS Jan 15, 2020
f155c86
Finished off 'Hoisting' tests. Still need tests for mutable support, …
ScottCarda-MS Jan 15, 2020
30afb16
Added tests to cover mutable variables and support for generics.
ScottCarda-MS Jan 16, 2020
2d67001
Test for Adjoint functor support.
ScottCarda-MS Jan 17, 2020
4153762
Tested functor support for generated operations. Moved Classical Cont…
ScottCarda-MS Jan 18, 2020
e8e84cb
Cleaned up the names and categories. Skipped tests that are failing, …
ScottCarda-MS Jan 18, 2020
c3fd9c5
Updated Rewrite step class for transformation.
ScottCarda-MS Jan 21, 2020
7df6941
Merge pull request #282 from microsoft/sccarda/ConditionalAnd
ScottCarda-MS Jan 22, 2020
2977df0
Merge branch 'features/ClassicallyControlled' into sccarda/Classicall…
ScottCarda-MS Jan 22, 2020
087644f
getting updates from master
Jan 23, 2020
b8df44a
enabling ConvertClassicalControl if the execution target is a quantum…
Jan 23, 2020
fd3f1de
Fixed line endings
ScottCarda-MS Jan 24, 2020
7ae62c6
Fixed line endings
ScottCarda-MS Jan 24, 2020
57a6420
PR comments
ScottCarda-MS Jan 31, 2020
7900e2e
PR comments
ScottCarda-MS Feb 1, 2020
b4f4665
Merge pull request #287 from microsoft/sccarda/ClassicallyControlledU…
ScottCarda-MS Feb 1, 2020
6304aab
Merge branch 'features/ClassicallyControlled' into beheim/branching
bettinaheim Feb 2, 2020
e0bc6d9
helper function for ensuring that IRewriteSteps are executed atomic
Feb 2, 2020
c8b1bcc
Merge branch 'beheim/branching' of https://github.com/microsoft/qshar…
Feb 2, 2020
78d6d1b
getting updates from master
Feb 3, 2020
d9c5e97
Fix Unit Test Failures for Classical Control (#289)
ScottCarda-MS Feb 7, 2020
112faf6
Merge branch 'master' into beheim/branching
Feb 7, 2020
be3d813
Merge branch 'features/ClassicallyControlled' into beheim/branching
Feb 7, 2020
487fe37
fixing build failure due to option change
Feb 7, 2020
b522f7a
reenabling execution tests
Feb 7, 2020
6599f61
forgot to actually update the packages
Feb 7, 2020
433b9e4
Merge pull request #290 from microsoft/beheim/branching
ScottCarda-MS Feb 7, 2020
0762467
Removed completed ToDo's (#309)
ScottCarda-MS Feb 7, 2020
6b65781
Added precondition to the rewrite step.
ScottCarda-MS Feb 8, 2020
16ad138
Removed extra onStatement call.
ScottCarda-MS Feb 9, 2020
e6c1a1a
Addressed PR comments
ScottCarda-MS Feb 12, 2020
173c6ba
Merge branch 'sccarda/ClassicallyControlledToMaster' of https://githu…
ScottCarda-MS Feb 12, 2020
93cfc4e
Update src/QsCompiler/Compiler/CompilationLoader.cs
bettinaheim Feb 12, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/QsCompiler/CommandLineTool/Commands/Build.cs
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,8 @@ public static int Run(BuildOptions options, ConsoleLogger logger)
ProjectName = options.ProjectName,
GenerateFunctorSupport = true,
SkipSyntaxTreeTrimming = options.TrimLevel == 0,
AttemptFullPreEvaluation = options.TrimLevel > 1,
ConvertClassicalControl = options.TrimLevel >= 2,
AttemptFullPreEvaluation = options.TrimLevel > 2,
DocumentationOutputFolder = options.DocFolder,
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
Expand Down
3 changes: 2 additions & 1 deletion src/QsCompiler/CommandLineTool/Commands/Diagnose.cs
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,8 @@ public static int Run(DiagnoseOptions options, ConsoleLogger logger)
{
GenerateFunctorSupport = true,
SkipSyntaxTreeTrimming = options.TrimLevel == 0,
AttemptFullPreEvaluation = options.TrimLevel > 1,
ConvertClassicalControl = options.TrimLevel >= 2,
AttemptFullPreEvaluation = options.TrimLevel > 2,
RewriteSteps = options.Plugins?.Select(step => (step, (string)null)) ?? ImmutableArray<(string, string)>.Empty,
EnableAdditionalChecks = true
};
Expand Down
1,829 changes: 924 additions & 905 deletions src/QsCompiler/Compiler/CompilationLoader.cs

Large diffs are not rendered by default.

16 changes: 8 additions & 8 deletions src/QsCompiler/Compiler/FunctorGeneration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ private static QsTuple<LocalVariableDeclaration<QsLocalSymbol>> ControlledArg(Qs
: null;

/// <summary>
/// Given a sequence of specialziations, returns the implementation of the given kind, or null if no such specialization exists.
/// Given a sequence of specializations, returns the implementation of the given kind, or null if no such specialization exists.
/// Throws an ArgumentException if more than one specialization of that kind exist.
/// Throws an ArgumentNullException if the sequence of specializations is null, or contains any entries that are null.
/// </summary>
Expand Down Expand Up @@ -67,7 +67,7 @@ private static (QsTuple<LocalVariableDeclaration<QsLocalSymbol>>, QsScope)? Body
}

/// <summary>
/// Given a Q# callable, evaluates any functor generator directive given for its adjoint specializiation.
/// Given a Q# callable, evaluates any functor generator directive given for its adjoint specialization.
/// If the body specialization is either intrinsic or external, return the given callable unchanged.
/// Otherwise returns a new QsCallable with the adjoint specialization set to the generated implementation if it was generated,
/// or set to the original specialization if the specialization was not requested to be auto-generated.
Expand Down Expand Up @@ -96,7 +96,7 @@ private static QsCallable BuildAdjoint(this QsCallable callable)
}

/// <summary>
/// Given a Q# callable, evaluates any functor generator directive given for its controlled specializiation.
/// Given a Q# callable, evaluates any functor generator directive given for its controlled specialization.
/// If the body specialization is either intrinsic or external, return the given callable unchanged.
/// Otherwise returns a new QsCallable with the controlled specialization set to the generated implementation if it was generated,
/// or set to the original specialization if the specialization was not requested to be auto-generated.
Expand All @@ -122,7 +122,7 @@ private static QsCallable BuildControlled(this QsCallable callable)
}

/// <summary>
/// Given a Q# callable, evaluates any functor generator directive given for its controlled adjoint specializiation.
/// Given a Q# callable, evaluates any functor generator directive given for its controlled adjoint specialization.
/// If the body specialization is either intrinsic or external, return the given callable unchanged.
/// Otherwise returns a new QsCallable with the controlled adjoint specialization set to the generated implementation if it was generated,
/// or set to the original specialization if the specialization was not requested to be auto-generated.
Expand Down Expand Up @@ -153,10 +153,10 @@ private static QsCallable BuildControlledAdjoint(this QsCallable callable)
{
var ctl = callable.Specializations.GetSpecialization(QsSpecializationKind.QsControlled);
var (ctlArg, ctlImpl) = GetContent(ctl?.Implementation) ?? throw new ArgumentException("no implementation provided for controlled specialization");
void SetImplementation(QsScope impl) => ctlAdj = ctlAdj.WithImplementation(SpecializationImplementation.NewProvided(ctlArg, impl));

//if (gen.Item.IsSelfInverse) SetImplementation(ctlImpl); -> nothing to do here, we want to keep this information
if (gen.Item.IsInvert) SetImplementation(ctlImpl.GenerateAdjoint());
if (gen.Item.IsInvert)
{
ctlAdj = ctlAdj.WithImplementation(SpecializationImplementation.NewProvided(ctlArg, ctlImpl.GenerateAdjoint()));
}
}
}
return callable.WithSpecializations(specs => specs.Select(s => s.Kind == QsSpecializationKind.QsControlledAdjoint ? ctlAdj : s).ToImmutableArray());
Expand Down
2 changes: 1 addition & 1 deletion src/QsCompiler/Compiler/PluginInterface.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public struct Diagnostic
/// <summary>
/// Verifies whether a given compilation satisfies the precondition for executing this rewrite step.
/// <see cref="ImplementsPreconditionVerification"/> indicates whether or not this method is implemented.
/// If the precondition verfication succeeds, then the invocation of an implemented transformation (if any)
/// If the precondition verification succeeds, then the invocation of an implemented transformation (if any)
/// with the given compilation should complete without throwing an exception.
/// The precondition verification should never throw an exception,
/// but instead indicate if the precondition is satisfied via the returned value.
Expand Down
72 changes: 72 additions & 0 deletions src/QsCompiler/Compiler/RewriteSteps/ClassicallyControlled.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System.Collections.Generic;
using System.Linq;
using Microsoft.Quantum.QsCompiler.DataTypes;
using Microsoft.Quantum.QsCompiler.SyntaxTree;
using Microsoft.Quantum.QsCompiler.Transformations.ClassicallyControlledTransformation;


namespace Microsoft.Quantum.QsCompiler.BuiltInRewriteSteps
{
internal class ClassicallyControlled : IRewriteStep
{
public string Name => "ClassicallyControlled";
public int Priority => 10; // Not used for built-in transformations like this
public IDictionary<string, string> AssemblyConstants { get; }
public IEnumerable<IRewriteStep.Diagnostic> GeneratedDiagnostics => null;

public bool ImplementsTransformation => true;
public bool ImplementsPreconditionVerification => true;
public bool ImplementsPostconditionVerification => false;

public ClassicallyControlled()
{
AssemblyConstants = new Dictionary<string, string>();
}

public bool Transformation(QsCompilation compilation, out QsCompilation transformed)
{
transformed = ClassicallyControlledTransformation.Apply(compilation);
return true;
}

public bool PreconditionVerification(QsCompilation compilation)
{
var controlNs = compilation.Namespaces
.FirstOrDefault(ns => ns.Name.Equals(BuiltIn.ClassicallyControlledNamespace));

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

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

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

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

return requiredBuiltIns.All(builtIn => providedOperations.Any(provided => provided.Equals(builtIn)));
}

public bool PostconditionVerification(QsCompilation compilation)
{
throw new System.NotImplementedException();
}
}
}
87 changes: 87 additions & 0 deletions src/QsCompiler/Core/Dependencies.fs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ namespace Microsoft.Quantum.QsCompiler
open System.Collections.Immutable
open Microsoft.Quantum.QsCompiler.DataTypes
open Microsoft.Quantum.QsCompiler.SyntaxTree
open Microsoft.Quantum.QsCompiler.SyntaxTokens


type BuiltIn = {
Expand All @@ -21,6 +22,7 @@ type BuiltIn = {
static member IntrinsicNamespace = NonNullable<string>.New "Microsoft.Quantum.Intrinsic"
static member StandardArrayNamespace = NonNullable<string>.New "Microsoft.Quantum.Arrays"
static member DiagnosticsNamespace = NonNullable<string>.New "Microsoft.Quantum.Diagnostics"
static member ClassicallyControlledNamespace = NonNullable<string>.New "Microsoft.Quantum.Simulation.QuantumProcessor.Extensions"

/// Returns the set of namespaces that is automatically opened for each compilation.
static member NamespacesToAutoOpen = ImmutableHashSet.Create (BuiltIn.CoreNamespace)
Expand Down Expand Up @@ -85,6 +87,91 @@ type BuiltIn = {
TypeParameters = ImmutableArray.Empty
}

// hard dependencies in Microsoft.Quantum.Simulation.QuantumProcessor.Extensions

// This is expected to have type <'T>((Result, (('T => Unit), 'T)) => Unit)
static member ApplyIfZero = {
Name = "ApplyIfZero" |> NonNullable<string>.New
Namespace = BuiltIn.ClassicallyControlledNamespace
TypeParameters = ImmutableArray.Create("T" |> NonNullable<string>.New)
}

// This is expected to have type <'T>((Result, (('T => Unit is Adj), 'T)) => Unit is Adj)
static member ApplyIfZeroA = {
Name = "ApplyIfZeroA" |> NonNullable<string>.New
Namespace = BuiltIn.ClassicallyControlledNamespace
TypeParameters = ImmutableArray.Create("T" |> NonNullable<string>.New)
}

// This is expected to have type <'T>((Result, (('T => Unit is Ctl), 'T)) => Unit is Ctl)
static member ApplyIfZeroC = {
Name = "ApplyIfZeroC" |> NonNullable<string>.New
Namespace = BuiltIn.ClassicallyControlledNamespace
TypeParameters = ImmutableArray.Create("T" |> NonNullable<string>.New)
}

// This is expected to have type <'T>((Result, (('T => Unit is Adj + Ctl), 'T)) => Unit is Adj + Ctl)
static member ApplyIfZeroCA = {
Name = "ApplyIfZeroCA" |> NonNullable<string>.New
Namespace = BuiltIn.ClassicallyControlledNamespace
TypeParameters = ImmutableArray.Create("T" |> NonNullable<string>.New)
}

// This is expected to have type <'T>((Result, (('T => Unit), 'T)) => Unit)
static member ApplyIfOne = {
Name = "ApplyIfOne" |> NonNullable<string>.New
Namespace = BuiltIn.ClassicallyControlledNamespace
TypeParameters = ImmutableArray.Create("T" |> NonNullable<string>.New)
}

// This is expected to have type <'T>((Result, (('T => Unit is Adj), 'T)) => Unit is Adj)
static member ApplyIfOneA = {
Name = "ApplyIfOneA" |> NonNullable<string>.New
Namespace = BuiltIn.ClassicallyControlledNamespace
TypeParameters = ImmutableArray.Create("T" |> NonNullable<string>.New)
}

// This is expected to have type <'T>((Result, (('T => Unit is Ctl), 'T)) => Unit is Ctl)
static member ApplyIfOneC = {
Name = "ApplyIfOneC" |> NonNullable<string>.New
Namespace = BuiltIn.ClassicallyControlledNamespace
TypeParameters = ImmutableArray.Create("T" |> NonNullable<string>.New)
}

// This is expected to have type <'T>((Result, (('T => Unit is Adj + Ctl), 'T)) => Unit is Adj + Ctl)
static member ApplyIfOneCA = {
Name = "ApplyIfOneCA" |> NonNullable<string>.New
Namespace = BuiltIn.ClassicallyControlledNamespace
TypeParameters = ImmutableArray.Create("T" |> NonNullable<string>.New)
}

// This is expected to have type <'T, 'U>((Result, (('T => Unit), 'T), (('U => Unit), 'U)) => Unit)
static member ApplyIfElseR = {
Name = "ApplyIfElseR" |> NonNullable<string>.New
Namespace = BuiltIn.ClassicallyControlledNamespace
TypeParameters = ImmutableArray.Create("T" |> NonNullable<string>.New, "U" |> NonNullable<string>.New)
}

// This is expected to have type <'T, 'U>((Result, (('T => Unit is Adj), 'T), (('U => Unit is Adj), 'U)) => Unit is Adj)
static member ApplyIfElseRA = {
Name = "ApplyIfElseRA" |> NonNullable<string>.New
Namespace = BuiltIn.ClassicallyControlledNamespace
TypeParameters = ImmutableArray.Create("T" |> NonNullable<string>.New, "U" |> NonNullable<string>.New)
}

// This is expected to have type <'T, 'U>((Result, (('T => Unit is Ctl), 'T), (('U => Unit is Ctl), 'U)) => Unit is Ctl)
static member ApplyIfElseRC = {
Name = "ApplyIfElseRC" |> NonNullable<string>.New
Namespace = BuiltIn.ClassicallyControlledNamespace
TypeParameters = ImmutableArray.Create("T" |> NonNullable<string>.New, "U" |> NonNullable<string>.New)
}

// This is expected to have type <'T, 'U>((Result, (('T => Unit is Adj + Ctl), 'T), (('U => Unit is Adj + Ctl), 'U)) => Unit is Adj + Ctl)
static member ApplyIfElseRCA = {
Name = "ApplyIfElseRCA" |> NonNullable<string>.New
Namespace = BuiltIn.ClassicallyControlledNamespace
TypeParameters = ImmutableArray.Create("T" |> NonNullable<string>.New, "U" |> NonNullable<string>.New)
}

// "weak dependencies" in other namespaces (e.g. things used for code actions)

Expand Down
15 changes: 0 additions & 15 deletions src/QsCompiler/DataStructures/SyntaxExtensions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -171,21 +171,6 @@ type TypedExpression with

// utils for walking the data structure

/// Returns true if the expression contains missing expressions.
/// Returns false otherwise.
static member public ContainsMissing (ex : TypedExpression) =
match ex.TupleItems with
| Some items when items.Length > 1 -> items |> List.exists TypedExpression.ContainsMissing
| Some [] -> true
| _ -> false

/// Returns true if the expression is a call-like expression, and the arguments contain a missing expression.
/// Returns false otherwise.
static member public IsPartialApplication kind =
match kind with
| CallLikeExpression (_, args) -> args |> TypedExpression.ContainsMissing
| _ -> false

/// Returns true if the expression kind does not contain any inner expressions.
static member private IsAtomic (kind : QsExpressionKind<'E, _, _>) =
match kind with
Expand Down
11 changes: 11 additions & 0 deletions src/QsCompiler/DataStructures/SyntaxTree.fs
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,17 @@ type TypedExpression = {
member this.TypeParameterResolutions =
this.TypeArguments.ToImmutableDictionary((fun (origin, name, _) -> origin, name), (fun (_,_,t) -> t))

/// Returns true if the expression is a call-like expression, and the arguments contain a missing expression.
/// Returns false otherwise.
static member public IsPartialApplication kind =
let rec containsMissing ex =
match ex.Expression with
| MissingExpr -> true
| ValueTuple items -> items |> Seq.exists containsMissing
| _ -> false
match kind with
| CallLikeExpression (_, args) -> args |> containsMissing
| _ -> false


/// Fully resolved Q# initializer expression.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ type ConstantPropagation(callables) =

/// Returns whether the given expression should be propagated as a constant.
/// For a statement of the form "let x = [expr];", if shouldPropagate(expr) is true,
/// then we should substitute [expr] for x wherever x occurs in future code.
/// then we should substitute x with [expr] wherever x occurs in future code.
let rec shouldPropagate callables (expr : TypedExpression) =
let folder ex sub =
isLiteral callables ex ||
Expand Down
6 changes: 3 additions & 3 deletions src/QsCompiler/Optimizations/Utils/Evaluation.fs
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ and [<AbstractClass>] private ExpressionKindEvaluator(callables: ImmutableDictio
let fe = FunctionEvaluator (callables)
return! fe.evaluateFunction qualName arg types stmtsLeft |> Option.map (fun x -> x.Expression)
| CallLikeExpression (baseMethod, partialArg) ->
do! check (TypedExpression.ContainsMissing partialArg)
do! check (TypedExpression.IsPartialApplication method.Expression)
return this.Transform (CallLikeExpression (baseMethod, fillPartialArg (partialArg, arg)))
| _ -> return! None
} |? CallLikeExpression (method, arg)
Expand All @@ -229,7 +229,7 @@ and [<AbstractClass>] private ExpressionKindEvaluator(callables: ImmutableDictio
maybe {
match method.Expression with
| CallLikeExpression (baseMethod, partialArg) ->
do! check (TypedExpression.ContainsMissing partialArg)
do! check (TypedExpression.IsPartialApplication method.Expression)
return this.Transform (CallLikeExpression (baseMethod, fillPartialArg (partialArg, arg)))
| _ -> return! None
} |? CallLikeExpression (method, arg)
Expand All @@ -239,7 +239,7 @@ and [<AbstractClass>] private ExpressionKindEvaluator(callables: ImmutableDictio
maybe {
match method.Expression with
| CallLikeExpression (baseMethod, partialArg) ->
do! check (TypedExpression.ContainsMissing partialArg)
do! check (TypedExpression.IsPartialApplication method.Expression)
return this.Transform (CallLikeExpression (baseMethod, fillPartialArg (partialArg, arg)))
| _ -> return! None
} |? CallLikeExpression (method, arg)
Expand Down
12 changes: 10 additions & 2 deletions src/QsCompiler/Optimizations/Utils/HelperFunctions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -190,18 +190,26 @@ and internal defaultValue (bt: TypeKind): ExprKind option =
| _ -> None


/// Returns true if the expression contains missing expressions.
/// Returns false otherwise.
let rec private containsMissing (ex : TypedExpression) =
match ex.Expression with
| MissingExpr -> true
| ValueTuple items -> items |> Seq.exists containsMissing
| _ -> false

/// Fills a partial argument by replacing MissingExprs with the corresponding values of a tuple
let rec internal fillPartialArg (partialArg: TypedExpression, arg: TypedExpression): TypedExpression =
match partialArg with
| Missing -> arg
| Tuple items ->
let argsList =
match List.filter TypedExpression.ContainsMissing items, arg with
match List.filter containsMissing items, arg with
| [_], _ -> [arg]
| _, Tuple args -> args
| _ -> failwithf "args must be a tuple"
items |> List.mapFold (fun args t1 ->
if TypedExpression.ContainsMissing t1 then
if containsMissing t1 then
match args with
| [] -> failwithf "ran out of args"
| head :: tail -> fillPartialArg (t1, head), tail
Expand Down
Loading