From adf2f1bba39ea38aa385f7a69a487c76ae9327fa Mon Sep 17 00:00:00 2001 From: Bettina Heim Date: Fri, 21 Feb 2020 12:22:38 -0800 Subject: [PATCH 1/5] adding a basic code gen test case for named item updates --- .../Circuits/CodegenTests.qs | 9 +++++ .../SimulationCodeTests.fs | 33 +++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/src/Simulation/CsharpGeneration.Tests/Circuits/CodegenTests.qs b/src/Simulation/CsharpGeneration.Tests/Circuits/CodegenTests.qs index 7b88bded726..77ad215023a 100644 --- a/src/Simulation/CsharpGeneration.Tests/Circuits/CodegenTests.qs +++ b/src/Simulation/CsharpGeneration.Tests/Circuits/CodegenTests.qs @@ -1294,7 +1294,16 @@ namespace Microsoft.Quantum.Compiler.Generics { set arr = arr w/ i <- map(arr[i]); } } + + newtype MyType1 = (i1 : Int[], i2 : Double); + newtype MyType2 = (i1 : Int, i2 : MyType1, (i3 : Int[], i4 : String)); + + function UpdateUdtItems (udt : MyType2) : MyType2 { + return udt + w/ i1 <- 0; + + } } diff --git a/src/Simulation/CsharpGeneration.Tests/SimulationCodeTests.fs b/src/Simulation/CsharpGeneration.Tests/SimulationCodeTests.fs index 64933803ba8..67574ab4a8a 100644 --- a/src/Simulation/CsharpGeneration.Tests/SimulationCodeTests.fs +++ b/src/Simulation/CsharpGeneration.Tests/SimulationCodeTests.fs @@ -193,6 +193,7 @@ namespace N1 let returnTest10 = findCallable @"returnTest10" let bitOperations = findCallable @"bitOperations" let testLengthDependency = findCallable @"testLengthDependency" + let UpdateUdtItems = findCallable @"UpdateUdtItems" let udt_args0 = findUdt @"udt_args0" let udt_args1 = findUdt @"udt_args1" @@ -2621,6 +2622,38 @@ namespace N1 [] let ``buildOperationClass - concrete functions`` () = + """ + [SourceLocation("%%%", OperationFunctor.Body, 1301,-1)] + public partial class UpdateUdtItems : Function, ICallable + { + public UpdateUdtItems(IOperationFactorym) : base(m) + { + } + + String ICallable.Name => "UpdateUdtItems"; + String ICallable.FullName => "Microsoft.Quantum.Compiler.Generics.UpdateUdtItems"; + + public static OperationInfo Info => new OperationInfo(typeof(UpdateUdtItems)); + + public override Func Body => (__in__) => + { + var udt = __in__; + return new MyType2((0L,udt.Data.Item2,(udt.Data.Item3.Item1,udt.Data.Item3.Item2))); + }; + + public override void Init() { } + + public override IApplyData __dataIn(MyType2data) => data; + public override IApplyData __dataOut(MyType2data) => data; + public static System.Threading.Tasks.Task Run(IOperationFactory __m__, MyType2 udt) + { + return __m__.Run(udt); + } + } + """ + |> testOneClass UpdateUdtItems + + """ public abstract partial class emptyFunction : Function, ICallable { From 5844d386db2c6d4c3f1480cdffecdd65b2ff301b Mon Sep 17 00:00:00 2001 From: Bettina Heim Date: Fri, 21 Feb 2020 12:25:32 -0800 Subject: [PATCH 2/5] slightly better test --- src/Simulation/CsharpGeneration.Tests/Circuits/CodegenTests.qs | 3 ++- src/Simulation/CsharpGeneration.Tests/SimulationCodeTests.fs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Simulation/CsharpGeneration.Tests/Circuits/CodegenTests.qs b/src/Simulation/CsharpGeneration.Tests/Circuits/CodegenTests.qs index 77ad215023a..8b7c42fca03 100644 --- a/src/Simulation/CsharpGeneration.Tests/Circuits/CodegenTests.qs +++ b/src/Simulation/CsharpGeneration.Tests/Circuits/CodegenTests.qs @@ -1301,7 +1301,8 @@ namespace Microsoft.Quantum.Compiler.Generics { function UpdateUdtItems (udt : MyType2) : MyType2 { return udt - w/ i1 <- 0; + w/ i1 <- 0 + w/ i4 <- "Hello"; } } diff --git a/src/Simulation/CsharpGeneration.Tests/SimulationCodeTests.fs b/src/Simulation/CsharpGeneration.Tests/SimulationCodeTests.fs index 67574ab4a8a..30b432440aa 100644 --- a/src/Simulation/CsharpGeneration.Tests/SimulationCodeTests.fs +++ b/src/Simulation/CsharpGeneration.Tests/SimulationCodeTests.fs @@ -2638,7 +2638,7 @@ namespace N1 public override Func Body => (__in__) => { var udt = __in__; - return new MyType2((0L,udt.Data.Item2,(udt.Data.Item3.Item1,udt.Data.Item3.Item2))); + return new MyType2((newMyType2((0L,udt.Data.Item2,(udt.Data.Item3.Item1,udt.Data.Item3.Item2))).Data.Item1,newMyType2((0L,udt.Data.Item2,(udt.Data.Item3.Item1,udt.Data.Item3.Item2))).Data.Item2,(newMyType2((0L,udt.Data.Item2,(udt.Data.Item3.Item1,udt.Data.Item3.Item2))).Data.Item3.Item1,"Hello"))); }; public override void Init() { } From 4e20f38c9df4fdf0dbae04ffe46ce17e4d300d47 Mon Sep 17 00:00:00 2001 From: Bettina Heim Date: Fri, 21 Feb 2020 12:59:02 -0800 Subject: [PATCH 3/5] wip --- .../CsharpGeneration/SimulationCode.fs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/Simulation/CsharpGeneration/SimulationCode.fs b/src/Simulation/CsharpGeneration/SimulationCode.fs index a574c51533c..af25637fd02 100644 --- a/src/Simulation/CsharpGeneration/SimulationCode.fs +++ b/src/Simulation/CsharpGeneration/SimulationCode.fs @@ -423,19 +423,23 @@ module SimulationCode = lhsAsQArray <.> (``ident`` "Modify", [ buildExpression accEx; captureExpression rhsEx ]) // in-place modification | _ -> lhsEx.ResolvedType.Resolution |> function | UserDefinedType udt -> - let itemName = accEx.Expression |> function - | Identifier (LocalVariable id, Null) -> id -// TODO: Diagnostics - | _ -> failwith "item access expression in copy-and-update expression for user defined type is not a suitable identifier" let name = QsQualifiedName.New (udt.Namespace, udt.Name) let decl = findUdt context name - let root = (buildExpression lhsEx) <|.|> (``ident`` "Data") + + let updatedItems = accEx.Expression |> function + | Identifier (LocalVariable id, Null) -> id.Value, captureExpression rhsEx +// TODO: Diagnostics + | _ -> failwith "item access expression in copy-and-update expression for user defined type is not a suitable identifier" + + let lhs = buildExpression lhsEx // FIXME: THIS IS BAD! WE NEED TO CONSOLIDATE FIRST! + + let root = lhs <|.|> (``ident`` "Data") let items = getAllItems root decl.Type let rec buildArg = function | QsTuple args -> args |> Seq.map buildArg |> Seq.toList |> ``tuple`` - | QsTupleItem (Named item) when item.VariableName.Value = itemName.Value -> + | QsTupleItem (Named item) when item.VariableName.Value = fst updatedItems -> items.Dequeue() |> ignore - captureExpression rhsEx + snd updatedItems | QsTupleItem _ -> items.Dequeue() ``new`` (``type`` [ justTheName context name ]) ``(`` [buildArg decl.TypeItems] ``)`` | _ -> failwith "copy-and-update expressions are currently only supported for arrays and user defined types" From 0f5292f98703ed0b9987e6cd374656cebfc3e62a Mon Sep 17 00:00:00 2001 From: Bettina Heim Date: Fri, 21 Feb 2020 14:06:59 -0800 Subject: [PATCH 4/5] that should work --- .../Circuits/CodegenTests.qs | 6 ++--- .../SimulationCodeTests.fs | 2 +- .../CsharpGeneration/SimulationCode.fs | 25 +++++++++++++------ 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/Simulation/CsharpGeneration.Tests/Circuits/CodegenTests.qs b/src/Simulation/CsharpGeneration.Tests/Circuits/CodegenTests.qs index 8b7c42fca03..72ddc4a0052 100644 --- a/src/Simulation/CsharpGeneration.Tests/Circuits/CodegenTests.qs +++ b/src/Simulation/CsharpGeneration.Tests/Circuits/CodegenTests.qs @@ -1301,9 +1301,9 @@ namespace Microsoft.Quantum.Compiler.Generics { function UpdateUdtItems (udt : MyType2) : MyType2 { return udt - w/ i1 <- 0 - w/ i4 <- "Hello"; - + w/ i1 <- -5 + w/ i4 <- "Hello" + w/ i1 <- 1; } } diff --git a/src/Simulation/CsharpGeneration.Tests/SimulationCodeTests.fs b/src/Simulation/CsharpGeneration.Tests/SimulationCodeTests.fs index 30b432440aa..1a6aed74e2b 100644 --- a/src/Simulation/CsharpGeneration.Tests/SimulationCodeTests.fs +++ b/src/Simulation/CsharpGeneration.Tests/SimulationCodeTests.fs @@ -2638,7 +2638,7 @@ namespace N1 public override Func Body => (__in__) => { var udt = __in__; - return new MyType2((newMyType2((0L,udt.Data.Item2,(udt.Data.Item3.Item1,udt.Data.Item3.Item2))).Data.Item1,newMyType2((0L,udt.Data.Item2,(udt.Data.Item3.Item1,udt.Data.Item3.Item2))).Data.Item2,(newMyType2((0L,udt.Data.Item2,(udt.Data.Item3.Item1,udt.Data.Item3.Item2))).Data.Item3.Item1,"Hello"))); + return new MyType2((1L,udt.Data.Item2,(udt.Data.Item3.Item1,"Hello"))); }; public override void Init() { } diff --git a/src/Simulation/CsharpGeneration/SimulationCode.fs b/src/Simulation/CsharpGeneration/SimulationCode.fs index af25637fd02..b06235864c4 100644 --- a/src/Simulation/CsharpGeneration/SimulationCode.fs +++ b/src/Simulation/CsharpGeneration/SimulationCode.fs @@ -426,20 +426,31 @@ module SimulationCode = let name = QsQualifiedName.New (udt.Namespace, udt.Name) let decl = findUdt context name - let updatedItems = accEx.Expression |> function - | Identifier (LocalVariable id, Null) -> id.Value, captureExpression rhsEx + let isUserDefinedType = function | UserDefinedType _ -> true | _ -> false + let getItemName = function + | Identifier (LocalVariable id, Null) -> id.Value // TODO: Diagnostics | _ -> failwith "item access expression in copy-and-update expression for user defined type is not a suitable identifier" - - let lhs = buildExpression lhsEx // FIXME: THIS IS BAD! WE NEED TO CONSOLIDATE FIRST! + let updatedItems = new Dictionary() + let rec aggregate (lhs : TypedExpression) = + match lhs.Expression with + | CopyAndUpdate (l, i, r) when l.ResolvedType.Resolution |> isUserDefinedType -> + let lhs = aggregate l // need to recur first, or make sure key is not already in dictionary + updatedItems.[getItemName i.Expression] <- captureExpression r + lhs + | _ -> lhs + let lhs = aggregate lhsEx |> buildExpression + updatedItems.[getItemName accEx.Expression] <- captureExpression rhsEx // needs to be after aggregate let root = lhs <|.|> (``ident`` "Data") let items = getAllItems root decl.Type let rec buildArg = function | QsTuple args -> args |> Seq.map buildArg |> Seq.toList |> ``tuple`` - | QsTupleItem (Named item) when item.VariableName.Value = fst updatedItems -> - items.Dequeue() |> ignore - snd updatedItems + | QsTupleItem (Named item) -> updatedItems.TryGetValue item.VariableName.Value |> function + | true, rhs -> + items.Dequeue() |> ignore + rhs + | _ -> items.Dequeue() | QsTupleItem _ -> items.Dequeue() ``new`` (``type`` [ justTheName context name ]) ``(`` [buildArg decl.TypeItems] ``)`` | _ -> failwith "copy-and-update expressions are currently only supported for arrays and user defined types" From 54371de017579f9275b32f476b498d6025f0214d Mon Sep 17 00:00:00 2001 From: Bettina Heim Date: Fri, 21 Feb 2020 15:11:19 -0800 Subject: [PATCH 5/5] adapting the test to include a check that the values are captured propertly --- src/Simulation/CsharpGeneration.Tests/Circuits/CodegenTests.qs | 3 ++- src/Simulation/CsharpGeneration.Tests/SimulationCodeTests.fs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Simulation/CsharpGeneration.Tests/Circuits/CodegenTests.qs b/src/Simulation/CsharpGeneration.Tests/Circuits/CodegenTests.qs index 72ddc4a0052..a4fe656027e 100644 --- a/src/Simulation/CsharpGeneration.Tests/Circuits/CodegenTests.qs +++ b/src/Simulation/CsharpGeneration.Tests/Circuits/CodegenTests.qs @@ -1300,9 +1300,10 @@ namespace Microsoft.Quantum.Compiler.Generics { function UpdateUdtItems (udt : MyType2) : MyType2 { + mutable arr = new Int[10]; return udt w/ i1 <- -5 - w/ i4 <- "Hello" + w/ i3 <- arr w/ i1 <- 1; } } diff --git a/src/Simulation/CsharpGeneration.Tests/SimulationCodeTests.fs b/src/Simulation/CsharpGeneration.Tests/SimulationCodeTests.fs index 1a6aed74e2b..52096e8c513 100644 --- a/src/Simulation/CsharpGeneration.Tests/SimulationCodeTests.fs +++ b/src/Simulation/CsharpGeneration.Tests/SimulationCodeTests.fs @@ -2638,7 +2638,8 @@ namespace N1 public override Func Body => (__in__) => { var udt = __in__; - return new MyType2((1L,udt.Data.Item2,(udt.Data.Item3.Item1,"Hello"))); + vararr=QArray.Create(10L); + return new MyType2((1L,udt.Data.Item2,(arr?.Copy(),udt.Data.Item3.Item2))); }; public override void Init() { }