From 344c36e09748563e960bc81c6757c002cee20879 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Fri, 23 Apr 2021 14:20:55 -0700 Subject: [PATCH 01/15] Create base for moving QIR driver generator. --- .../Tools/Driver/IQirSimulatorInitializer.cs | 18 ++ .../Execution/Tools/Driver/QirCppDriver.cs | 303 ++++++++++++++++++ .../Execution/Tools/Driver/QirCppDriver.tt | 5 + .../Execution/Tools/Driver/QirCppDriverEx.cs | 9 + .../Tools/Driver/QirCppDriverGenerator.cs | 24 ++ .../Tools/Microsoft.Quantum.Qir.Tools.csproj | 19 ++ 6 files changed, 378 insertions(+) create mode 100644 src/Qir/Execution/Tools/Driver/IQirSimulatorInitializer.cs create mode 100644 src/Qir/Execution/Tools/Driver/QirCppDriver.cs create mode 100644 src/Qir/Execution/Tools/Driver/QirCppDriver.tt create mode 100644 src/Qir/Execution/Tools/Driver/QirCppDriverEx.cs create mode 100644 src/Qir/Execution/Tools/Driver/QirCppDriverGenerator.cs diff --git a/src/Qir/Execution/Tools/Driver/IQirSimulatorInitializer.cs b/src/Qir/Execution/Tools/Driver/IQirSimulatorInitializer.cs new file mode 100644 index 00000000000..9895f4d191c --- /dev/null +++ b/src/Qir/Execution/Tools/Driver/IQirSimulatorInitializer.cs @@ -0,0 +1,18 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; + +namespace Microsoft.Quantum.Qir.Tools.Driver +{ + public interface IQirSimulatorInitializer + { + public void GenerateSimulatorInitialization(Stream stream); + + public IList Headers { get; } + + public IList LinkLibraries { get; } + } +} diff --git a/src/Qir/Execution/Tools/Driver/QirCppDriver.cs b/src/Qir/Execution/Tools/Driver/QirCppDriver.cs new file mode 100644 index 00000000000..2ee3d86b758 --- /dev/null +++ b/src/Qir/Execution/Tools/Driver/QirCppDriver.cs @@ -0,0 +1,303 @@ +// ------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version: 16.0.0.0 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ +namespace Microsoft.Quantum.Qir.Tools.Driver +{ + using System; + + /// + /// Class to produce the template output + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "16.0.0.0")] + public partial class QirCppDriver : QirCppDriverBase + { + /// + /// Create the template output + /// + public virtual string TransformText() + { + this.Write("//------------------------------------------------------------------------------\r" + + "\n// This code was generated by a tool.\r\n// \r\n//---------------" + + "---------------------------------------------------------------\r\n"); + return this.GenerationEnvironment.ToString(); + } + } + #region Base class + /// + /// Base class for this transformation + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "16.0.0.0")] + public class QirCppDriverBase + { + #region Fields + private global::System.Text.StringBuilder generationEnvironmentField; + private global::System.CodeDom.Compiler.CompilerErrorCollection errorsField; + private global::System.Collections.Generic.List indentLengthsField; + private string currentIndentField = ""; + private bool endsWithNewline; + private global::System.Collections.Generic.IDictionary sessionField; + #endregion + #region Properties + /// + /// The string builder that generation-time code is using to assemble generated output + /// + protected System.Text.StringBuilder GenerationEnvironment + { + get + { + if ((this.generationEnvironmentField == null)) + { + this.generationEnvironmentField = new global::System.Text.StringBuilder(); + } + return this.generationEnvironmentField; + } + set + { + this.generationEnvironmentField = value; + } + } + /// + /// The error collection for the generation process + /// + public System.CodeDom.Compiler.CompilerErrorCollection Errors + { + get + { + if ((this.errorsField == null)) + { + this.errorsField = new global::System.CodeDom.Compiler.CompilerErrorCollection(); + } + return this.errorsField; + } + } + /// + /// A list of the lengths of each indent that was added with PushIndent + /// + private System.Collections.Generic.List indentLengths + { + get + { + if ((this.indentLengthsField == null)) + { + this.indentLengthsField = new global::System.Collections.Generic.List(); + } + return this.indentLengthsField; + } + } + /// + /// Gets the current indent we use when adding lines to the output + /// + public string CurrentIndent + { + get + { + return this.currentIndentField; + } + } + /// + /// Current transformation session + /// + public virtual global::System.Collections.Generic.IDictionary Session + { + get + { + return this.sessionField; + } + set + { + this.sessionField = value; + } + } + #endregion + #region Transform-time helpers + /// + /// Write text directly into the generated output + /// + public void Write(string textToAppend) + { + if (string.IsNullOrEmpty(textToAppend)) + { + return; + } + // If we're starting off, or if the previous text ended with a newline, + // we have to append the current indent first. + if (((this.GenerationEnvironment.Length == 0) + || this.endsWithNewline)) + { + this.GenerationEnvironment.Append(this.currentIndentField); + this.endsWithNewline = false; + } + // Check if the current text ends with a newline + if (textToAppend.EndsWith(global::System.Environment.NewLine, global::System.StringComparison.CurrentCulture)) + { + this.endsWithNewline = true; + } + // This is an optimization. If the current indent is "", then we don't have to do any + // of the more complex stuff further down. + if ((this.currentIndentField.Length == 0)) + { + this.GenerationEnvironment.Append(textToAppend); + return; + } + // Everywhere there is a newline in the text, add an indent after it + textToAppend = textToAppend.Replace(global::System.Environment.NewLine, (global::System.Environment.NewLine + this.currentIndentField)); + // If the text ends with a newline, then we should strip off the indent added at the very end + // because the appropriate indent will be added when the next time Write() is called + if (this.endsWithNewline) + { + this.GenerationEnvironment.Append(textToAppend, 0, (textToAppend.Length - this.currentIndentField.Length)); + } + else + { + this.GenerationEnvironment.Append(textToAppend); + } + } + /// + /// Write text directly into the generated output + /// + public void WriteLine(string textToAppend) + { + this.Write(textToAppend); + this.GenerationEnvironment.AppendLine(); + this.endsWithNewline = true; + } + /// + /// Write formatted text directly into the generated output + /// + public void Write(string format, params object[] args) + { + this.Write(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args)); + } + /// + /// Write formatted text directly into the generated output + /// + public void WriteLine(string format, params object[] args) + { + this.WriteLine(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args)); + } + /// + /// Raise an error + /// + public void Error(string message) + { + System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError(); + error.ErrorText = message; + this.Errors.Add(error); + } + /// + /// Raise a warning + /// + public void Warning(string message) + { + System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError(); + error.ErrorText = message; + error.IsWarning = true; + this.Errors.Add(error); + } + /// + /// Increase the indent + /// + public void PushIndent(string indent) + { + if ((indent == null)) + { + throw new global::System.ArgumentNullException("indent"); + } + this.currentIndentField = (this.currentIndentField + indent); + this.indentLengths.Add(indent.Length); + } + /// + /// Remove the last indent that was added with PushIndent + /// + public string PopIndent() + { + string returnValue = ""; + if ((this.indentLengths.Count > 0)) + { + int indentLength = this.indentLengths[(this.indentLengths.Count - 1)]; + this.indentLengths.RemoveAt((this.indentLengths.Count - 1)); + if ((indentLength > 0)) + { + returnValue = this.currentIndentField.Substring((this.currentIndentField.Length - indentLength)); + this.currentIndentField = this.currentIndentField.Remove((this.currentIndentField.Length - indentLength)); + } + } + return returnValue; + } + /// + /// Remove any indentation + /// + public void ClearIndent() + { + this.indentLengths.Clear(); + this.currentIndentField = ""; + } + #endregion + #region ToString Helpers + /// + /// Utility class to produce culture-oriented representation of an object as a string. + /// + public class ToStringInstanceHelper + { + private System.IFormatProvider formatProviderField = global::System.Globalization.CultureInfo.InvariantCulture; + /// + /// Gets or sets format provider to be used by ToStringWithCulture method. + /// + public System.IFormatProvider FormatProvider + { + get + { + return this.formatProviderField ; + } + set + { + if ((value != null)) + { + this.formatProviderField = value; + } + } + } + /// + /// This is called from the compile/run appdomain to convert objects within an expression block to a string + /// + public string ToStringWithCulture(object objectToConvert) + { + if ((objectToConvert == null)) + { + throw new global::System.ArgumentNullException("objectToConvert"); + } + System.Type t = objectToConvert.GetType(); + System.Reflection.MethodInfo method = t.GetMethod("ToString", new System.Type[] { + typeof(System.IFormatProvider)}); + if ((method == null)) + { + return objectToConvert.ToString(); + } + else + { + return ((string)(method.Invoke(objectToConvert, new object[] { + this.formatProviderField }))); + } + } + } + private ToStringInstanceHelper toStringHelperField = new ToStringInstanceHelper(); + /// + /// Helper to produce culture-oriented representation of an object as a string + /// + public ToStringInstanceHelper ToStringHelper + { + get + { + return this.toStringHelperField; + } + } + #endregion + } + #endregion +} diff --git a/src/Qir/Execution/Tools/Driver/QirCppDriver.tt b/src/Qir/Execution/Tools/Driver/QirCppDriver.tt new file mode 100644 index 00000000000..8f6d92968a9 --- /dev/null +++ b/src/Qir/Execution/Tools/Driver/QirCppDriver.tt @@ -0,0 +1,5 @@ +<#@ template language="C#" linePragmas="false" #> +//------------------------------------------------------------------------------ +// This code was generated by a tool. +// +//------------------------------------------------------------------------------ diff --git a/src/Qir/Execution/Tools/Driver/QirCppDriverEx.cs b/src/Qir/Execution/Tools/Driver/QirCppDriverEx.cs new file mode 100644 index 00000000000..31f5b629731 --- /dev/null +++ b/src/Qir/Execution/Tools/Driver/QirCppDriverEx.cs @@ -0,0 +1,9 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Qir.Tools.Driver +{ + public partial class QirCppDriver + { + } +} diff --git a/src/Qir/Execution/Tools/Driver/QirCppDriverGenerator.cs b/src/Qir/Execution/Tools/Driver/QirCppDriverGenerator.cs new file mode 100644 index 00000000000..44c7ea58ea8 --- /dev/null +++ b/src/Qir/Execution/Tools/Driver/QirCppDriverGenerator.cs @@ -0,0 +1,24 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.IO; +using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; + +namespace Microsoft.Quantum.Qir.Tools.Driver +{ + public class QirCppDriverGenerator + { + private readonly IQirSimulatorInitializer SimulatorInitalizer; + + public QirCppDriverGenerator(IQirSimulatorInitializer simulatorInitializer) + { + SimulatorInitalizer = simulatorInitializer; + } + + public void GenerateDriver(EntryPointOperation entryPointOperation, Stream stream) + { + throw new NotImplementedException(); + } + } +} diff --git a/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj b/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj index 5ad95e9541e..d33e517df80 100644 --- a/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj +++ b/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj @@ -14,4 +14,23 @@ + + + TextTemplatingFilePreprocessor + QirCppDriver.cs + + + + + + + + + + True + True + QirCppDriver.tt + + + From bb38cf2fb2e4f4ab5d63c743769c01f6282d3c00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Tue, 27 Apr 2021 08:17:35 -0700 Subject: [PATCH 02/15] Added QirCppInterop. --- .../Tools/Driver/IQirDriverGenerator.cs | 4 +- .../Tools/Driver/QirCppDriverGenerator.cs | 7 +- .../Execution/Tools/Driver/QirCppInterop.cs | 140 ++++++++++++++++++ 3 files changed, 147 insertions(+), 4 deletions(-) create mode 100644 src/Qir/Execution/Tools/Driver/QirCppInterop.cs diff --git a/src/Qir/Execution/Tools/Driver/IQirDriverGenerator.cs b/src/Qir/Execution/Tools/Driver/IQirDriverGenerator.cs index 5c995bd7d0a..9f61fdbc8cf 100644 --- a/src/Qir/Execution/Tools/Driver/IQirDriverGenerator.cs +++ b/src/Qir/Execution/Tools/Driver/IQirDriverGenerator.cs @@ -9,8 +9,8 @@ namespace Microsoft.Quantum.Qir.Tools.Driver { public interface IQirDriverGenerator { - Task GenerateAsync(EntryPointOperation entryPoint, Stream stream); + public Task GenerateAsync(EntryPointOperation entryPoint, Stream stream); - string GetCommandLineArguments(EntryPointOperation entryPoint); + public string GetCommandLineArguments(EntryPointOperation entryPoint); } } diff --git a/src/Qir/Execution/Tools/Driver/QirCppDriverGenerator.cs b/src/Qir/Execution/Tools/Driver/QirCppDriverGenerator.cs index 44c7ea58ea8..e4c49a69ceb 100644 --- a/src/Qir/Execution/Tools/Driver/QirCppDriverGenerator.cs +++ b/src/Qir/Execution/Tools/Driver/QirCppDriverGenerator.cs @@ -3,11 +3,12 @@ using System; using System.IO; +using System.Threading.Tasks; using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; namespace Microsoft.Quantum.Qir.Tools.Driver { - public class QirCppDriverGenerator + public class QirCppDriverGenerator : IQirDriverGenerator { private readonly IQirSimulatorInitializer SimulatorInitalizer; @@ -16,9 +17,11 @@ public QirCppDriverGenerator(IQirSimulatorInitializer simulatorInitializer) SimulatorInitalizer = simulatorInitializer; } - public void GenerateDriver(EntryPointOperation entryPointOperation, Stream stream) + public async Task GenerateAsync(EntryPointOperation entryPointOperation, Stream stream) { throw new NotImplementedException(); } + + public string GetCommandLineArguments(EntryPointOperation entryPoint) => throw new NotImplementedException(); } } diff --git a/src/Qir/Execution/Tools/Driver/QirCppInterop.cs b/src/Qir/Execution/Tools/Driver/QirCppInterop.cs new file mode 100644 index 00000000000..5eed6794199 --- /dev/null +++ b/src/Qir/Execution/Tools/Driver/QirCppInterop.cs @@ -0,0 +1,140 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; + +#nullable enable + +namespace Microsoft.Quantum.Qir.Tools.Driver +{ + internal static class QirCppInterop + { + public static string? CliOptionVariableDefaultValue(DataType? dataType) => + dataType switch + { + DataType.BoolType => "0x0", + DataType.IntegerType => "0", + DataType.DoubleType => "0.0", + DataType.PauliType => "PauliId::PauliId_I", + DataType.RangeType => null, + DataType.ResultType => "0x0", + DataType.StringType => null, + DataType.ArrayType => null, + _ => throw new ArgumentException($"Invalid data type: {dataType}") + }; + + public static string CliOptionVariableType(DataType? dataType) => + dataType switch + { + DataType.BoolType => "char", + DataType.IntegerType => "int64_t", + DataType.DoubleType => "double_t", + DataType.PauliType => "PauliId", + DataType.RangeType => "RangeTuple", + DataType.ResultType => "char", + DataType.StringType => "string", + DataType.ArrayType => throw new NotSupportedException($"{DataType.ArrayType} does not match to a specific CLI option variable type"), + _ => throw new ArgumentException($"Invalid data type: {dataType}") + }; + + public static string InteropType(DataType dataType) => + dataType switch + { + DataType.BoolType => "char", + DataType.IntegerType => "int64_t", + DataType.DoubleType => "double", + DataType.PauliType => "char", + DataType.RangeType => "InteropRange*", + DataType.ResultType => "char", + DataType.StringType => "const char*", + DataType.ArrayType => "InteropArray*", + _ => throw new ArgumentException($"Invalid data type: {dataType}") + }; + + public static string? TransformerMapName(DataType? dataType) => + dataType switch + { + DataType.BoolType => "BoolAsCharMap", + DataType.IntegerType => null, + DataType.DoubleType => null, + DataType.PauliType => "PauliMap", + DataType.RangeType => null, + DataType.ResultType => "ResultAsCharMap", + DataType.StringType => null, + DataType.ArrayType => null, + _ => throw new ArgumentException($"Invalid data type: {dataType}") + }; + } + internal class CppArgument + { + private readonly Argument Argument; + + public CppArgument(Argument argument) + { + Argument = argument; + } + + public DataType? ArrayType => Argument.ArrayType; + + public string CliOptionDescription() => + $"Option to provide a value for the {Argument.Name} parameter"; + + public string CliOptionName() + { + if (String.IsNullOrEmpty(Argument.Name)) + { + throw new InvalidOperationException($"Invalid argument name '{Argument.Name}'"); + } + + return Argument.Name.Length == 1 ? $"-{Argument.Name}" : $"--{Argument.Name}"; + } + + public string CliOptionVariableName() => $"{Argument.Name}Cli"; + + public string? CliOptionVariableDefaultValue() => QirCppInterop.CliOptionVariableDefaultValue(Argument.Type); + + public string CliOptionVariableType() => + Argument.Type switch + { + DataType.ArrayType => $"vector<{QirCppInterop.CliOptionVariableType(Argument.ArrayType)}>", + _ => QirCppInterop.CliOptionVariableType(Argument.Type) + }; + + public string IntermediateVariableName() => $"{Argument.Name}Intermediate"; + + public string InteropVariableName() => $"{Argument.Name}Interop"; + + public string InteropType() => QirCppInterop.InteropType(Argument.Type); + + public string? TransformerMapName() => + Argument.Type switch + { + DataType.ArrayType => QirCppInterop.TransformerMapName(Argument.ArrayType), + _ => QirCppInterop.TransformerMapName(Argument.Type) + }; + + public DataType Type => Argument.Type; + } + + internal class CppEntryPointOperation + { + public List Arguments; + + private readonly EntryPointOperation EntryPoint; + + public CppEntryPointOperation(EntryPointOperation entryPointOperation) + { + EntryPoint = entryPointOperation; + Arguments = entryPointOperation.Arguments.Select(arg => new CppArgument(arg)).ToList(); + } + + public bool ContainsArgumentType(DataType type) => Arguments.Where(arg => arg.Type == type).Any(); + + public bool ContainsArrayType(DataType type) => Arguments.Where(arg => arg.ArrayType == type).Any(); + + public string Name => EntryPoint.Name; + } +} From 40327486a2284fa0ba69fd512df891249f65c411 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Tue, 27 Apr 2021 20:30:23 -0700 Subject: [PATCH 03/15] Added more structure. --- .../QirDriverGeneratorTests.cs | 9 ++++++ .../Tools/Driver/IQirSimulatorInitializer.cs | 3 +- .../Execution/Tools/Driver/QirCppDriver.cs | 30 +++++++++++++++++-- .../Execution/Tools/Driver/QirCppDriver.tt | 22 ++++++++++++++ .../Execution/Tools/Driver/QirCppDriverEx.cs | 10 +++++++ .../Tools/Driver/QirCppDriverGenerator.cs | 7 ++++- 6 files changed, 76 insertions(+), 5 deletions(-) create mode 100644 src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirDriverGeneratorTests.cs diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirDriverGeneratorTests.cs b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirDriverGeneratorTests.cs new file mode 100644 index 00000000000..f51500cf3f5 --- /dev/null +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirDriverGeneratorTests.cs @@ -0,0 +1,9 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Tests.Microsoft.Quantum.Qir.Tools +{ + public class QirDriverGeneratorTests + { + } +} diff --git a/src/Qir/Execution/Tools/Driver/IQirSimulatorInitializer.cs b/src/Qir/Execution/Tools/Driver/IQirSimulatorInitializer.cs index 9895f4d191c..72e75de3593 100644 --- a/src/Qir/Execution/Tools/Driver/IQirSimulatorInitializer.cs +++ b/src/Qir/Execution/Tools/Driver/IQirSimulatorInitializer.cs @@ -9,7 +9,8 @@ namespace Microsoft.Quantum.Qir.Tools.Driver { public interface IQirSimulatorInitializer { - public void GenerateSimulatorInitialization(Stream stream); + public Task GenerateAsync(Stream stream); + public string GenerateString(); public IList Headers { get; } diff --git a/src/Qir/Execution/Tools/Driver/QirCppDriver.cs b/src/Qir/Execution/Tools/Driver/QirCppDriver.cs index 2ee3d86b758..561203b8327 100644 --- a/src/Qir/Execution/Tools/Driver/QirCppDriver.cs +++ b/src/Qir/Execution/Tools/Driver/QirCppDriver.cs @@ -9,6 +9,7 @@ // ------------------------------------------------------------------------------ namespace Microsoft.Quantum.Qir.Tools.Driver { + using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; using System; /// @@ -22,9 +23,32 @@ public partial class QirCppDriver : QirCppDriverBase /// public virtual string TransformText() { - this.Write("//------------------------------------------------------------------------------\r" + - "\n// This code was generated by a tool.\r\n// \r\n//---------------" + - "---------------------------------------------------------------\r\n"); + this.Write(@"//------------------------------------------------------------------------------ +// This code was generated by a tool. +// +//------------------------------------------------------------------------------ + +#include +#include +#include +#include +#include + +#include ""CLI11.hpp"" + +#include ""QirRuntime.hpp"" + +#include ""QirContext.hpp"" +#include ""SimFactory.hpp"" + +using namespace Microsoft::Quantum; +using namespace std; + +int main(int argc, char* argv[]) +{ + return 0; +} +"); return this.GenerationEnvironment.ToString(); } } diff --git a/src/Qir/Execution/Tools/Driver/QirCppDriver.tt b/src/Qir/Execution/Tools/Driver/QirCppDriver.tt index 8f6d92968a9..043af9263c4 100644 --- a/src/Qir/Execution/Tools/Driver/QirCppDriver.tt +++ b/src/Qir/Execution/Tools/Driver/QirCppDriver.tt @@ -1,5 +1,27 @@ <#@ template language="C#" linePragmas="false" #> +<#@ import namespace="Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint" #> //------------------------------------------------------------------------------ // This code was generated by a tool. // //------------------------------------------------------------------------------ + +#include +#include +#include +#include +#include + +#include "CLI11.hpp" + +#include "QirRuntime.hpp" + +#include "QirContext.hpp" +#include "SimFactory.hpp" + +using namespace Microsoft::Quantum; +using namespace std; + +int main(int argc, char* argv[]) +{ + return 0; +} diff --git a/src/Qir/Execution/Tools/Driver/QirCppDriverEx.cs b/src/Qir/Execution/Tools/Driver/QirCppDriverEx.cs index 31f5b629731..dfb8b2b012a 100644 --- a/src/Qir/Execution/Tools/Driver/QirCppDriverEx.cs +++ b/src/Qir/Execution/Tools/Driver/QirCppDriverEx.cs @@ -1,9 +1,19 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; + namespace Microsoft.Quantum.Qir.Tools.Driver { public partial class QirCppDriver { + private CppEntryPointOperation EntryPoint; + private IQirSimulatorInitializer SimulatorInitializer; + + public QirCppDriver(EntryPointOperation entryPoint, IQirSimulatorInitializer simulatorInitializer) + { + EntryPoint = new CppEntryPointOperation(entryPoint); + SimulatorInitializer = simulatorInitializer; + } } } diff --git a/src/Qir/Execution/Tools/Driver/QirCppDriverGenerator.cs b/src/Qir/Execution/Tools/Driver/QirCppDriverGenerator.cs index e4c49a69ceb..da83765a67e 100644 --- a/src/Qir/Execution/Tools/Driver/QirCppDriverGenerator.cs +++ b/src/Qir/Execution/Tools/Driver/QirCppDriverGenerator.cs @@ -3,6 +3,7 @@ using System; using System.IO; +using System.Text; using System.Threading.Tasks; using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; @@ -19,7 +20,11 @@ public QirCppDriverGenerator(IQirSimulatorInitializer simulatorInitializer) public async Task GenerateAsync(EntryPointOperation entryPointOperation, Stream stream) { - throw new NotImplementedException(); + var qirCppDriver = new QirCppDriver(entryPointOperation, SimulatorInitalizer); + var cppSource = qirCppDriver.TransformText(); + await stream.WriteAsync(Encoding.UTF8.GetBytes(cppSource)); + await stream.FlushAsync(); + stream.Position = 0; } public string GetCommandLineArguments(EntryPointOperation entryPoint) => throw new NotImplementedException(); From 2f9d62945e5962f94169bdab5876926dabdbd8d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Wed, 28 Apr 2021 00:29:12 -0700 Subject: [PATCH 04/15] Set test infra. --- .../QirDriverGeneratorTests.cs | 50 +++++++++++ .../FullStateDriverGenerator/UseNoArgs.cpp | 70 +++++++++++++++ .../FullStateDriverGenerator/UseResultArg.cpp | 86 +++++++++++++++++++ .../Tests.Microsoft.Quantum.Qir.Tools.csproj | 9 ++ .../Tools/Driver/IQirDriverGenerator.cs | 2 + .../Tools/Driver/IQirSimulatorInitializer.cs | 1 + .../Execution/Tools/Driver/QirCppDriverEx.cs | 3 +- .../Tools/Driver/QirCppDriverGenerator.cs | 9 +- .../Driver/QirFullStateDriverGenerator.cs | 18 ++-- .../QirFullStateSimulatorInitializer.cs | 34 ++++++++ 10 files changed, 272 insertions(+), 10 deletions(-) create mode 100644 src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseNoArgs.cpp create mode 100644 src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArg.cpp create mode 100644 src/Qir/Execution/Tools/Driver/QirFullStateSimulatorInitializer.cs diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirDriverGeneratorTests.cs b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirDriverGeneratorTests.cs index f51500cf3f5..de8c96178d8 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirDriverGeneratorTests.cs +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirDriverGeneratorTests.cs @@ -1,9 +1,59 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +using System.Collections.Generic; +using System.IO; +using System.Text; + +using Xunit; + +using Microsoft.Quantum.Qir.Tools.Driver; +using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; + namespace Tests.Microsoft.Quantum.Qir.Tools { public class QirDriverGeneratorTests { + private static string TestArtifactsDirectory = Path.Combine("TestArtifacts", "FullStateDriverGenerator"); + private static string TestCasesDirectory = Path.Combine("TestCases", "FullStateDriverGenerator"); + private static IDictionary TestCases = + new Dictionary + { + { + "UseNoArgs", + new EntryPointOperation{Name = "UseNoArgs"} + }, + { + "UseResultArg", + new EntryPointOperation + { + Name = "UseResultArg", + Arguments = new List{new Argument{ Name = "ResultArg", Type = DataType.ResultType}} + } + } + }; + + [Theory] + [InlineData("UseNoArgs")] + [InlineData("UseResultArg")] + public void GenerateFullStateSimulatorDriver(string testCase) + { + var entryPointOperation = TestCases[testCase]; + var driverGenerator = new QirFullStateDriverGenerator(); + var driverFileName = $"{testCase}.cpp"; + var verificationCppSourceCode = File.ReadAllText(Path.Combine(TestCasesDirectory, driverFileName)); + if (!Directory.Exists(TestArtifactsDirectory)) + { + Directory.CreateDirectory(TestArtifactsDirectory); + } + + var generatedStream = File.Create(Path.Combine(TestArtifactsDirectory, driverFileName)); + driverGenerator.GenerateAsync(entryPointOperation, generatedStream).Wait(); + var generatedStreamReader = new StreamReader(generatedStream, Encoding.UTF8); + var generatedCppSourceCode = generatedStreamReader.ReadToEnd(); + // TODO: Compare strings. + generatedStream.Close(); + + } } } diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseNoArgs.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseNoArgs.cpp new file mode 100644 index 00000000000..bcb2afc2fc9 --- /dev/null +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseNoArgs.cpp @@ -0,0 +1,70 @@ +//------------------------------------------------------------------------------ +// This code was generated by a tool. +// +//------------------------------------------------------------------------------ +// +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#include +#include +#include +#include +#include + +#include "CLI11.hpp" + +#include "QirContext.hpp" +#include "QirRuntime.hpp" +#include "SimFactory.hpp" + +using namespace Microsoft::Quantum; +using namespace std; + + +// This is the function corresponding to the QIR entry-point. +extern "C" void UseNoArgs( // NOLINT + +); + + +int main(int argc, char* argv[]) +{ + CLI::App app("QIR Standalone Entry Point Inputs Reference"); + + // Initialize simulator. + unique_ptr sim = CreateFullstateSimulator(); + QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); + + // Add the --simulation-output options. + // N.B. This option should be present in all standalone drivers. + string simulationOutputFile; + CLI::Option* simulationOutputFileOpt = app.add_option( + "--simulation-output", simulationOutputFile, + "File where the output produced during the simulation is written"); + + // With all the options added, parse arguments from the command line. + CLI11_PARSE(app, argc, argv); + + // Redirect the simulator output from std::cout if the --simulation-output option is present. + ostream* simulatorOutputStream = &cout; + ofstream simulationOutputFileStream; + if (!simulationOutputFileOpt->empty()) + { + simulationOutputFileStream.open(simulationOutputFile); + SetOutputStream(simulationOutputFileStream); + simulatorOutputStream = &simulationOutputFileStream; + } + + // Run simulation and write the output of the operation to the corresponding stream. + UseNoArgs( + + ); + + + simulatorOutputStream->flush(); + if (simulationOutputFileStream.is_open()) + { + simulationOutputFileStream.close(); + } +} diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArg.cpp new file mode 100644 index 00000000000..90437295ce6 --- /dev/null +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArg.cpp @@ -0,0 +1,86 @@ +//------------------------------------------------------------------------------ +// This code was generated by a tool. +// +//------------------------------------------------------------------------------ +// +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#include +#include +#include +#include +#include + +#include "CLI11.hpp" + +#include "QirContext.hpp" +#include "QirRuntime.hpp" +#include "SimFactory.hpp" + +using namespace Microsoft::Quantum; +using namespace std; + + +// This is the function corresponding to the QIR entry-point. +extern "C" void UseResultArg( // NOLINT + char ResultArgInteropValue +); + + +const char InteropResultZeroAsChar = 0x0; +const char InteropResultOneAsChar = 0x1; +map ResultAsCharMap{ + {"0", InteropResultZeroAsChar}, + {"Zero", InteropResultZeroAsChar}, + {"1", InteropResultOneAsChar}, + {"One", InteropResultOneAsChar} +}; + +int main(int argc, char* argv[]) +{ + CLI::App app("QIR Standalone Entry Point Inputs Reference"); + + // Initialize simulator. + unique_ptr sim = CreateFullstateSimulator(); + QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); + + // Add the --simulation-output options. + // N.B. This option should be present in all standalone drivers. + string simulationOutputFile; + CLI::Option* simulationOutputFileOpt = app.add_option( + "--simulation-output", simulationOutputFile, + "File where the output produced during the simulation is written"); + + char ResultArgCliValue; + ResultArgCliValue = InteropResultZeroAsChar; + app.add_option("--ResultArg", ResultArgCliValue, "A Result value for the ResultArg argument")->required() + ->transform(CLI::CheckedTransformer(ResultAsCharMap, CLI::ignore_case)); + + // With all the options added, parse arguments from the command line. + CLI11_PARSE(app, argc, argv); + + char ResultArgInteropValue = ResultArgCliValue; + + // Redirect the simulator output from std::cout if the --simulation-output option is present. + ostream* simulatorOutputStream = &cout; + ofstream simulationOutputFileStream; + if (!simulationOutputFileOpt->empty()) + { + simulationOutputFileStream.open(simulationOutputFile); + SetOutputStream(simulationOutputFileStream); + simulatorOutputStream = &simulationOutputFileStream; + } + + // Run simulation and write the output of the operation to the corresponding stream. + UseResultArg( + ResultArgInteropValue + ); + + + simulatorOutputStream->flush(); + if (simulationOutputFileStream.is_open()) + { + simulationOutputFileStream.close(); + } +} diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/Tests.Microsoft.Quantum.Qir.Tools.csproj b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/Tests.Microsoft.Quantum.Qir.Tools.csproj index 55ffaa29bd4..861e7e26d75 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/Tests.Microsoft.Quantum.Qir.Tools.csproj +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/Tests.Microsoft.Quantum.Qir.Tools.csproj @@ -17,4 +17,13 @@ + + + Always + + + Always + + + diff --git a/src/Qir/Execution/Tools/Driver/IQirDriverGenerator.cs b/src/Qir/Execution/Tools/Driver/IQirDriverGenerator.cs index 9f61fdbc8cf..81a53189407 100644 --- a/src/Qir/Execution/Tools/Driver/IQirDriverGenerator.cs +++ b/src/Qir/Execution/Tools/Driver/IQirDriverGenerator.cs @@ -11,6 +11,8 @@ public interface IQirDriverGenerator { public Task GenerateAsync(EntryPointOperation entryPoint, Stream stream); + public string GenerateString(EntryPointOperation entryPoint); + public string GetCommandLineArguments(EntryPointOperation entryPoint); } } diff --git a/src/Qir/Execution/Tools/Driver/IQirSimulatorInitializer.cs b/src/Qir/Execution/Tools/Driver/IQirSimulatorInitializer.cs index 72e75de3593..a80223efe99 100644 --- a/src/Qir/Execution/Tools/Driver/IQirSimulatorInitializer.cs +++ b/src/Qir/Execution/Tools/Driver/IQirSimulatorInitializer.cs @@ -10,6 +10,7 @@ namespace Microsoft.Quantum.Qir.Tools.Driver public interface IQirSimulatorInitializer { public Task GenerateAsync(Stream stream); + public string GenerateString(); public IList Headers { get; } diff --git a/src/Qir/Execution/Tools/Driver/QirCppDriverEx.cs b/src/Qir/Execution/Tools/Driver/QirCppDriverEx.cs index dfb8b2b012a..a9918d6b9f8 100644 --- a/src/Qir/Execution/Tools/Driver/QirCppDriverEx.cs +++ b/src/Qir/Execution/Tools/Driver/QirCppDriverEx.cs @@ -8,7 +8,8 @@ namespace Microsoft.Quantum.Qir.Tools.Driver public partial class QirCppDriver { private CppEntryPointOperation EntryPoint; - private IQirSimulatorInitializer SimulatorInitializer; + + public readonly IQirSimulatorInitializer SimulatorInitializer; public QirCppDriver(EntryPointOperation entryPoint, IQirSimulatorInitializer simulatorInitializer) { diff --git a/src/Qir/Execution/Tools/Driver/QirCppDriverGenerator.cs b/src/Qir/Execution/Tools/Driver/QirCppDriverGenerator.cs index da83765a67e..705c155a32b 100644 --- a/src/Qir/Execution/Tools/Driver/QirCppDriverGenerator.cs +++ b/src/Qir/Execution/Tools/Driver/QirCppDriverGenerator.cs @@ -20,13 +20,18 @@ public QirCppDriverGenerator(IQirSimulatorInitializer simulatorInitializer) public async Task GenerateAsync(EntryPointOperation entryPointOperation, Stream stream) { - var qirCppDriver = new QirCppDriver(entryPointOperation, SimulatorInitalizer); - var cppSource = qirCppDriver.TransformText(); + var cppSource = GenerateString(entryPointOperation); await stream.WriteAsync(Encoding.UTF8.GetBytes(cppSource)); await stream.FlushAsync(); stream.Position = 0; } + public string GenerateString(EntryPointOperation entryPointOperation) + { + var qirCppDriver = new QirCppDriver(entryPointOperation, SimulatorInitalizer); + return qirCppDriver.TransformText(); + } + public string GetCommandLineArguments(EntryPointOperation entryPoint) => throw new NotImplementedException(); } } diff --git a/src/Qir/Execution/Tools/Driver/QirFullStateDriverGenerator.cs b/src/Qir/Execution/Tools/Driver/QirFullStateDriverGenerator.cs index e09ac1196c1..f0dad1889ee 100644 --- a/src/Qir/Execution/Tools/Driver/QirFullStateDriverGenerator.cs +++ b/src/Qir/Execution/Tools/Driver/QirFullStateDriverGenerator.cs @@ -3,21 +3,25 @@ using System.IO; using System.Threading.Tasks; -using Microsoft.Quantum.QsCompiler; using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; namespace Microsoft.Quantum.Qir.Tools.Driver { public class QirFullStateDriverGenerator: IQirDriverGenerator { - public async Task GenerateAsync(EntryPointOperation entryPoint, Stream stream) + private readonly QirCppDriverGenerator DriverGenerator; + public QirFullStateDriverGenerator() { - await Task.Run(() => QirDriverGeneration.GenerateQirDriverCpp(entryPoint, stream)); + DriverGenerator = new QirCppDriverGenerator(new QirFullStateSimulatorInitializer()); } - public string GetCommandLineArguments(EntryPointOperation entryPoint) - { - return QirDriverGeneration.GenerateCommandLineArguments(entryPoint.Arguments); - } + public async Task GenerateAsync(EntryPointOperation entryPoint, Stream stream) => + await DriverGenerator.GenerateAsync(entryPoint, stream); + + public string GenerateString(EntryPointOperation entryPoint) => + DriverGenerator.GenerateString(entryPoint); + + public string GetCommandLineArguments(EntryPointOperation entryPoint) => + DriverGenerator.GetCommandLineArguments(entryPoint); } } diff --git a/src/Qir/Execution/Tools/Driver/QirFullStateSimulatorInitializer.cs b/src/Qir/Execution/Tools/Driver/QirFullStateSimulatorInitializer.cs new file mode 100644 index 00000000000..2622a6eccae --- /dev/null +++ b/src/Qir/Execution/Tools/Driver/QirFullStateSimulatorInitializer.cs @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Threading.Tasks; + +namespace Microsoft.Quantum.Qir.Tools.Driver +{ + public class QirFullStateSimulatorInitializer : IQirSimulatorInitializer + { + public async Task GenerateAsync(Stream stream) + { + var simulatorInitializerSourceCode = this.GenerateString(); + await stream.WriteAsync(Encoding.UTF8.GetBytes(simulatorInitializerSourceCode)); + await stream.FlushAsync(); + stream.Position = 0; + } + public string GenerateString() + { + // TODO: Implement. + return String.Empty; + } + + public IList Headers => new List { + "QirContext.hpp", + "SimFactory.hpp" + }; + + public IList LinkLibraries => new List(); + } +} From 7bb963069ff48a743d2e93984e37b04b63dc19ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Wed, 28 Apr 2021 01:19:57 -0700 Subject: [PATCH 05/15] Changed QirCppInterop.cs to use extension methods. --- .../Execution/Tools/Driver/QirCppDriver.cs | 22 ++++-- .../Execution/Tools/Driver/QirCppDriver.tt | 10 ++- .../Execution/Tools/Driver/QirCppDriverEx.cs | 4 +- .../Execution/Tools/Driver/QirCppInterop.cs | 73 +++++++------------ 4 files changed, 54 insertions(+), 55 deletions(-) diff --git a/src/Qir/Execution/Tools/Driver/QirCppDriver.cs b/src/Qir/Execution/Tools/Driver/QirCppDriver.cs index 561203b8327..dc5a40f40f9 100644 --- a/src/Qir/Execution/Tools/Driver/QirCppDriver.cs +++ b/src/Qir/Execution/Tools/Driver/QirCppDriver.cs @@ -37,18 +37,28 @@ public virtual string TransformText() #include ""CLI11.hpp"" #include ""QirRuntime.hpp"" - #include ""QirContext.hpp"" + #include ""SimFactory.hpp"" using namespace Microsoft::Quantum; using namespace std; -int main(int argc, char* argv[]) -{ - return 0; -} -"); +extern ""C"" void "); + this.Write(this.ToStringHelper.ToStringWithCulture(EntryPoint.Name)); + this.Write("(\r\n"); + for (int i = 0; i < EntryPoint.Arguments.Count; i++) { + var arg = EntryPoint.Arguments[i]; + var isLastArg = i == (EntryPoint.Arguments.Count-1); + this.Write(" "); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.InteropType())); + this.Write(" "); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.Name)); + this.Write(this.ToStringHelper.ToStringWithCulture((isLastArg) ? "" : ",")); + this.Write("\r\n"); + } + this.Write("); // QIR interop function.\r\n\r\nint main(int argc, char* argv[])\r\n{\r\n return 0;" + + "\r\n}\r\n"); return this.GenerationEnvironment.ToString(); } } diff --git a/src/Qir/Execution/Tools/Driver/QirCppDriver.tt b/src/Qir/Execution/Tools/Driver/QirCppDriver.tt index 043af9263c4..e5a568d4491 100644 --- a/src/Qir/Execution/Tools/Driver/QirCppDriver.tt +++ b/src/Qir/Execution/Tools/Driver/QirCppDriver.tt @@ -14,13 +14,21 @@ #include "CLI11.hpp" #include "QirRuntime.hpp" - #include "QirContext.hpp" + #include "SimFactory.hpp" using namespace Microsoft::Quantum; using namespace std; +extern "C" void <#= EntryPoint.Name #>( +<# for (int i = 0; i < EntryPoint.Arguments.Count; i++) { + var arg = EntryPoint.Arguments[i]; + var isLastArg = i == (EntryPoint.Arguments.Count-1); #> + <#= arg.InteropType() #> <#= arg.Name #><#= (isLastArg) ? "" : "," #> +<# } #> +); // QIR interop function. + int main(int argc, char* argv[]) { return 0; diff --git a/src/Qir/Execution/Tools/Driver/QirCppDriverEx.cs b/src/Qir/Execution/Tools/Driver/QirCppDriverEx.cs index a9918d6b9f8..5ac19200871 100644 --- a/src/Qir/Execution/Tools/Driver/QirCppDriverEx.cs +++ b/src/Qir/Execution/Tools/Driver/QirCppDriverEx.cs @@ -7,13 +7,13 @@ namespace Microsoft.Quantum.Qir.Tools.Driver { public partial class QirCppDriver { - private CppEntryPointOperation EntryPoint; + public readonly EntryPointOperation EntryPoint; public readonly IQirSimulatorInitializer SimulatorInitializer; public QirCppDriver(EntryPointOperation entryPoint, IQirSimulatorInitializer simulatorInitializer) { - EntryPoint = new CppEntryPointOperation(entryPoint); + EntryPoint = entryPoint; SimulatorInitializer = simulatorInitializer; } } diff --git a/src/Qir/Execution/Tools/Driver/QirCppInterop.cs b/src/Qir/Execution/Tools/Driver/QirCppInterop.cs index 5eed6794199..4057c0065ae 100644 --- a/src/Qir/Execution/Tools/Driver/QirCppInterop.cs +++ b/src/Qir/Execution/Tools/Driver/QirCppInterop.cs @@ -68,73 +68,54 @@ public static string InteropType(DataType dataType) => _ => throw new ArgumentException($"Invalid data type: {dataType}") }; } - internal class CppArgument - { - private readonly Argument Argument; - - public CppArgument(Argument argument) - { - Argument = argument; - } - public DataType? ArrayType => Argument.ArrayType; - - public string CliOptionDescription() => - $"Option to provide a value for the {Argument.Name} parameter"; + internal static class ArgumentCppExtensions + { + public static string CliOptionDescription(this Argument @this) => + $"Option to provide a value for the {@this.Name} parameter"; - public string CliOptionName() + public static string CliOptionName(this Argument @this) { - if (String.IsNullOrEmpty(Argument.Name)) + if (String.IsNullOrEmpty(@this.Name)) { - throw new InvalidOperationException($"Invalid argument name '{Argument.Name}'"); + throw new InvalidOperationException($"Invalid argument name '{@this.Name}'"); } - return Argument.Name.Length == 1 ? $"-{Argument.Name}" : $"--{Argument.Name}"; + return @this.Name.Length == 1 ? $"-{@this.Name}" : $"--{@this.Name}"; } - public string CliOptionVariableName() => $"{Argument.Name}Cli"; + public static string CliOptionVariableName(this Argument @this) => $"{@this.Name}Cli"; - public string? CliOptionVariableDefaultValue() => QirCppInterop.CliOptionVariableDefaultValue(Argument.Type); + public static string? CliOptionVariableDefaultValue(this Argument @this) => + QirCppInterop.CliOptionVariableDefaultValue(@this.Type); - public string CliOptionVariableType() => - Argument.Type switch + public static string CliOptionVariableType(this Argument @this) => + @this.Type switch { - DataType.ArrayType => $"vector<{QirCppInterop.CliOptionVariableType(Argument.ArrayType)}>", - _ => QirCppInterop.CliOptionVariableType(Argument.Type) + DataType.ArrayType => $"vector<{QirCppInterop.CliOptionVariableType(@this.ArrayType)}>", + _ => QirCppInterop.CliOptionVariableType(@this.Type) }; - public string IntermediateVariableName() => $"{Argument.Name}Intermediate"; + public static string IntermediateVariableName(this Argument @this) => $"{@this.Name}Intermediate"; - public string InteropVariableName() => $"{Argument.Name}Interop"; + public static string InteropVariableName(this Argument @this) => $"{@this.Name}Interop"; - public string InteropType() => QirCppInterop.InteropType(Argument.Type); + public static string InteropType(this Argument @this) => QirCppInterop.InteropType(@this.Type); - public string? TransformerMapName() => - Argument.Type switch + public static string? TransformerMapName(this Argument @this) => + @this.Type switch { - DataType.ArrayType => QirCppInterop.TransformerMapName(Argument.ArrayType), - _ => QirCppInterop.TransformerMapName(Argument.Type) + DataType.ArrayType => QirCppInterop.TransformerMapName(@this.ArrayType), + _ => QirCppInterop.TransformerMapName(@this.Type) }; - - public DataType Type => Argument.Type; } - internal class CppEntryPointOperation + internal static class EntryPointOperationCppExtension { - public List Arguments; - - private readonly EntryPointOperation EntryPoint; - - public CppEntryPointOperation(EntryPointOperation entryPointOperation) - { - EntryPoint = entryPointOperation; - Arguments = entryPointOperation.Arguments.Select(arg => new CppArgument(arg)).ToList(); - } - - public bool ContainsArgumentType(DataType type) => Arguments.Where(arg => arg.Type == type).Any(); - - public bool ContainsArrayType(DataType type) => Arguments.Where(arg => arg.ArrayType == type).Any(); + public static bool ContainsArgumentType(this EntryPointOperation @this, DataType type) => + @this.Arguments.Where(arg => arg.Type == type).Any(); - public string Name => EntryPoint.Name; + public static bool ContainsArrayType(this EntryPointOperation @this, DataType type) => + @this.Arguments.Where(arg => arg.ArrayType == type).Any(); } } From 9b2bf52e0abf5852f3d6103c82c908f4ded6a1f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Wed, 28 Apr 2021 04:19:31 -0700 Subject: [PATCH 06/15] Full template implemented. --- .../Tools/Driver/IQirDriverGenerator.cs | 2 - .../Tools/Driver/IQirSimulatorInitializer.cs | 4 +- .../Execution/Tools/Driver/QirCppDriver.cs | 245 +++++++++++++++++- .../Execution/Tools/Driver/QirCppDriver.tt | 207 ++++++++++++++- .../Tools/Driver/QirCppDriverGenerator.cs | 9 +- .../Execution/Tools/Driver/QirCppInterop.cs | 86 +++--- .../Driver/QirFullStateDriverGenerator.cs | 3 - .../QirFullStateSimulatorInitializer.cs | 15 +- 8 files changed, 500 insertions(+), 71 deletions(-) diff --git a/src/Qir/Execution/Tools/Driver/IQirDriverGenerator.cs b/src/Qir/Execution/Tools/Driver/IQirDriverGenerator.cs index 81a53189407..9f61fdbc8cf 100644 --- a/src/Qir/Execution/Tools/Driver/IQirDriverGenerator.cs +++ b/src/Qir/Execution/Tools/Driver/IQirDriverGenerator.cs @@ -11,8 +11,6 @@ public interface IQirDriverGenerator { public Task GenerateAsync(EntryPointOperation entryPoint, Stream stream); - public string GenerateString(EntryPointOperation entryPoint); - public string GetCommandLineArguments(EntryPointOperation entryPoint); } } diff --git a/src/Qir/Execution/Tools/Driver/IQirSimulatorInitializer.cs b/src/Qir/Execution/Tools/Driver/IQirSimulatorInitializer.cs index a80223efe99..4b8e1de5146 100644 --- a/src/Qir/Execution/Tools/Driver/IQirSimulatorInitializer.cs +++ b/src/Qir/Execution/Tools/Driver/IQirSimulatorInitializer.cs @@ -9,9 +9,7 @@ namespace Microsoft.Quantum.Qir.Tools.Driver { public interface IQirSimulatorInitializer { - public Task GenerateAsync(Stream stream); - - public string GenerateString(); + public IList GenerateSourceCode(); public IList Headers { get; } diff --git a/src/Qir/Execution/Tools/Driver/QirCppDriver.cs b/src/Qir/Execution/Tools/Driver/QirCppDriver.cs index dc5a40f40f9..674eb9b2627 100644 --- a/src/Qir/Execution/Tools/Driver/QirCppDriver.cs +++ b/src/Qir/Execution/Tools/Driver/QirCppDriver.cs @@ -39,12 +39,108 @@ public virtual string TransformText() #include ""QirRuntime.hpp"" #include ""QirContext.hpp"" -#include ""SimFactory.hpp"" +"); + foreach (var header in SimulatorInitializer.Headers) { + this.Write("#include \""); + this.Write(this.ToStringHelper.ToStringWithCulture(header)); + this.Write("\"\r\n"); + } + this.Write("\r\nusing namespace Microsoft::Quantum;\r\nusing namespace std;\r\n"); + if (EntryPoint.ContainsArgumentType(DataType.ArrayType)) { + this.Write(@" +// Auxiliary functions for interop with Q# Array type. +struct InteropArray +{ + int64_t Size; + void* Data; + + InteropArray(int64_t size, void* data) : + Size(size), + Data(data){} +}; -using namespace Microsoft::Quantum; -using namespace std; +template +unique_ptr CreateInteropArray(vector& v) +{ + unique_ptr array(new InteropArray(v.size(), v.data())); + return array; +} -extern ""C"" void "); +template +void TranslateVector(vector& sourceVector, vector& destinationVector, function translationFunction) +{ + destinationVector.resize(sourceVector.size()); + transform(sourceVector.begin(), sourceVector.end(), destinationVector.begin(), translationFunction); +} +"); + } + if (EntryPoint.ContainsArgumentType(DataType.RangeType) || EntryPoint.ContainsArrayType(DataType.RangeType)) { + this.Write(@" +// Auxiliary functions for interop with Q# Range type. +using RangeTuple = tuple; +struct InteropRange +{ + int64_t Start; + int64_t Step; + int64_t End; + + InteropRange() : + Start(0), + Step(0), + End(0){} + + InteropRange(RangeTuple rangeTuple) : + Start(get<0>(rangeTuple)), + Step(get<1>(rangeTuple)), + End(get<2>(rangeTuple)){} +}; + +unique_ptr CreateInteropRange(RangeTuple rangeTuple) +{ + unique_ptr range(new InteropRange(rangeTuple)); + return range; +} + +InteropRange* TranslateRangeTupleToInteropRangePointer(RangeTuple& rangeTuple) +{ + InteropRange* range = new InteropRange(rangeTuple); + return range; +} +"); + } + if (EntryPoint.ContainsArrayType(DataType.RangeType)) { + this.Write("\r\n// Auxiliary functions for interop with Q# Range[] type\r\ntemplate\r\n" + + "void FreePointerVector(vector& v)\r\n{\r\n for (auto p : v)\r\n {\r\n d" + + "elete p;\r\n }\r\n}\r\n"); + } + if (EntryPoint.ContainsArgumentType(DataType.BoolType) || EntryPoint.ContainsArrayType(DataType.BoolType)) { + this.Write("\r\n// Auxiliary functions for interop with Q# Bool type.\r\nconst char InteropFalseA" + + "sChar = 0x0;\r\nconst char InteropTrueAsChar = 0x1;\r\nmap "); + this.Write(this.ToStringHelper.ToStringWithCulture(QirCppInterop.CliOptionTransformerMapName(DataType.BoolType))); + this.Write("{\r\n {\"0\", InteropFalseAsChar},\r\n {\"false\", InteropFalseAsChar},\r\n {\"1\", " + + "InteropTrueAsChar},\r\n {\"true\", InteropTrueAsChar}\r\n};\r\n"); + } + if (EntryPoint.ContainsArgumentType(DataType.PauliType) || EntryPoint.ContainsArrayType(DataType.PauliType)) { + this.Write("\r\n// Auxiliary functions for interop with Q# Pauli type.\r\nmap "); + this.Write(this.ToStringHelper.ToStringWithCulture(QirCppInterop.CliOptionTransformerMapName(DataType.PauliType))); + this.Write("{\r\n {\"PauliI\", PauliId::PauliId_I},\r\n {\"PauliX\", PauliId::PauliId_X},\r\n " + + "{\"PauliY\", PauliId::PauliId_Y},\r\n {\"PauliZ\", PauliId::PauliId_Z}\r\n};\r\n\r\nchar " + + "TranslatePauliToChar(PauliId& pauli)\r\n{\r\n return static_cast(pauli);\r\n}" + + "\r\n"); + } + if (EntryPoint.ContainsArgumentType(DataType.ResultType) || EntryPoint.ContainsArrayType(DataType.ResultType)) { + this.Write("\r\n// Auxiliary functions for interop with Q# Result type.\r\nconst char InteropResu" + + "ltZeroAsChar = 0x0;\r\nconst char InteropResultOneAsChar = 0x1;\r\nmap" + + " "); + this.Write(this.ToStringHelper.ToStringWithCulture(QirCppInterop.CliOptionTransformerMapName(DataType.ResultType))); + this.Write("{\r\n {\"0\", InteropResultZeroAsChar},\r\n {\"Zero\", InteropResultZeroAsChar},\r\n " + + " {\"1\", InteropResultOneAsChar},\r\n {\"One\", InteropResultOneAsChar}\r\n};\r\n"); + } + if (EntryPoint.ContainsArgumentType(DataType.StringType) || EntryPoint.ContainsArrayType(DataType.StringType)) { + this.Write("\r\n// Auxiliary functions for interop with Q# String type.\r\nconst char* TranslateS" + + "tringToCharBuffer(string& s)\r\n{\r\n return s.c_str();\r\n}\r\n"); + } + this.Write("\r\nextern \"C\" void "); this.Write(this.ToStringHelper.ToStringWithCulture(EntryPoint.Name)); this.Write("(\r\n"); for (int i = 0; i < EntryPoint.Arguments.Count; i++) { @@ -57,8 +153,145 @@ public virtual string TransformText() this.Write(this.ToStringHelper.ToStringWithCulture((isLastArg) ? "" : ",")); this.Write("\r\n"); } - this.Write("); // QIR interop function.\r\n\r\nint main(int argc, char* argv[])\r\n{\r\n return 0;" + - "\r\n}\r\n"); + this.Write("); // QIR interop function.\r\n\r\nint main(int argc, char* argv[])\r\n{\r\n CLI::App " + + "app(\"QIR Standalone Entry Point\");\r\n\r\n // Initialize simulator.\r\n"); + foreach (var line in SimulatorInitializer.GenerateSourceCode()) { + this.Write(" "); + this.Write(this.ToStringHelper.ToStringWithCulture(line)); + this.Write("\r\n"); + } + this.Write(@" + // Add the --simulation-output option. + string simulationOutputFile; + CLI::Option* simulationOutputFileOpt = app.add_option( + ""--simulation-output"", + simulationOutputFile, + ""File where the output produced during the simulation is written""); + +"); + if (EntryPoint.Arguments.Count > 0) { + this.Write(" // Add a command line option for each entry-point argument.\r\n"); + } + foreach (var arg in EntryPoint.Arguments) { + this.Write(" "); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.CliOptionType())); + this.Write(" "); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.CliOptionVariableName())); + this.Write(";\r\n"); + if (arg.CliOptionVariableDefaultValue() != null) { + this.Write(" "); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.CliOptionVariableName())); + this.Write(" = "); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.CliOptionVariableDefaultValue())); + this.Write(";\r\n"); + } + this.Write(" app.add_option(\""); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.CliOptionName())); + this.Write("\", "); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.CliOptionVariableName())); + this.Write(", \""); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.CliOptionDescription())); + this.Write("\")\r\n ->required()"); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.CliOptionTransformerMapName() != null ? "" : ";")); + this.Write("\r\n"); + if (arg.CliOptionTransformerMapName() != null) { + this.Write(" ->transform(CLI::CheckedTransformer("); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.CliOptionTransformerMapName())); + this.Write(", CLI::ignore_case));\r\n"); + } + this.Write("\r\n"); + } + this.Write(" // After all the options have been added, parse arguments from the command li" + + "ne.\r\n CLI11_PARSE(app, argc, argv);\r\n\r\n"); + if (EntryPoint.Arguments.Count > 0) { + this.Write(" // Cast parsed arguments to its interop types.\r\n"); + } + foreach (var arg in EntryPoint.Arguments) { + var interopTranslator = QirCppInterop.CliOptionTypeToInteropTypeTranslator(arg.Type); + if (arg.Type == DataType.ArrayType) { + var arrayInteropTranslator = QirCppInterop.CliOptionTypeToInteropTypeTranslator(arg.ArrayType); + if (arrayInteropTranslator == null) { + this.Write(" "); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.InteropType())); + this.Write(" "); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.InteropVariableName())); + this.Write(" = CreateInteropArray("); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.CliOptionVariableName())); + this.Write(").get();\r\n"); + } + else { + var arrayCliOptionType = QirCppInterop.CliOptionType(arg.ArrayType); + var arrayInteropType = QirCppInterop.InteropType(arg.ArrayType); + this.Write(" vector<"); + this.Write(this.ToStringHelper.ToStringWithCulture(arrayInteropType)); + this.Write("> "); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.IntermediateVariableName())); + this.Write(";\r\n TranslateVector<"); + this.Write(this.ToStringHelper.ToStringWithCulture(arrayCliOptionType)); + this.Write(", "); + this.Write(this.ToStringHelper.ToStringWithCulture(arrayInteropType)); + this.Write(">("); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.CliOptionVariableName())); + this.Write(", "); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.IntermediateVariableName())); + this.Write(", "); + this.Write(this.ToStringHelper.ToStringWithCulture(arrayInteropTranslator)); + this.Write(");\r\n "); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.InteropType())); + this.Write(" "); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.InteropVariableName())); + this.Write(" = CreateInteropArray("); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.IntermediateVariableName())); + this.Write(").get();\r\n"); + } + } + else if (interopTranslator == null) { + this.Write(" "); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.InteropType())); + this.Write(" "); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.InteropVariableName())); + this.Write(" = "); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.CliOptionVariableName())); + this.Write(";\r\n"); + } + else if (interopTranslator != null) { + this.Write(" "); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.InteropType())); + this.Write(" "); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.InteropVariableName())); + this.Write(" = "); + this.Write(this.ToStringHelper.ToStringWithCulture(interopTranslator)); + this.Write("("); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.CliOptionVariableName())); + this.Write(");\r\n"); + } + this.Write("\r\n"); + } + this.Write(@" // Redirect the simulator output from std::cout if the --simulation-output option is present. + ostream* simulatorOutputStream = &cout; + ofstream simulationOutputFileStream; + if (!simulationOutputFileOpt->empty()) + { + simulationOutputFileStream.open(simulationOutputFile); + Microsoft::Quantum::OutputStream::Set(simulationOutputFileStream); + simulatorOutputStream = &simulationOutputFileStream; + } + + // Execute the entry point operation. + "); + this.Write(this.ToStringHelper.ToStringWithCulture(EntryPoint.Name)); + this.Write("(\r\n"); + for (int i = 0; i < EntryPoint.Arguments.Count; i++) { + var arg = EntryPoint.Arguments[i]; + var isLastArg = i == (EntryPoint.Arguments.Count-1); + this.Write(" "); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.InteropVariableName())); + this.Write(this.ToStringHelper.ToStringWithCulture((isLastArg) ? "" : ",")); + this.Write("\r\n"); + } + this.Write(" );\r\n\r\n // Flush the output of the simulation.\r\n simulatorOutputStream->" + + "flush();\r\n if (simulationOutputFileStream.is_open())\r\n {\r\n simulati" + + "onOutputFileStream.close();\r\n }\r\n\r\n return 0;\r\n}\r\n"); return this.GenerationEnvironment.ToString(); } } diff --git a/src/Qir/Execution/Tools/Driver/QirCppDriver.tt b/src/Qir/Execution/Tools/Driver/QirCppDriver.tt index e5a568d4491..00d43c7a12b 100644 --- a/src/Qir/Execution/Tools/Driver/QirCppDriver.tt +++ b/src/Qir/Execution/Tools/Driver/QirCppDriver.tt @@ -16,10 +16,131 @@ #include "QirRuntime.hpp" #include "QirContext.hpp" -#include "SimFactory.hpp" +<# foreach (var header in SimulatorInitializer.Headers) { #> +#include "<#= header #>" +<# } #> using namespace Microsoft::Quantum; using namespace std; +<# if (EntryPoint.ContainsArgumentType(DataType.ArrayType)) { #> + +// Auxiliary functions for interop with Q# Array type. +struct InteropArray +{ + int64_t Size; + void* Data; + + InteropArray(int64_t size, void* data) : + Size(size), + Data(data){} +}; + +template +unique_ptr CreateInteropArray(vector& v) +{ + unique_ptr array(new InteropArray(v.size(), v.data())); + return array; +} + +template +void TranslateVector(vector& sourceVector, vector& destinationVector, function translationFunction) +{ + destinationVector.resize(sourceVector.size()); + transform(sourceVector.begin(), sourceVector.end(), destinationVector.begin(), translationFunction); +} +<# } #> +<# if (EntryPoint.ContainsArgumentType(DataType.RangeType) || EntryPoint.ContainsArrayType(DataType.RangeType)) { #> + +// Auxiliary functions for interop with Q# Range type. +using RangeTuple = tuple; +struct InteropRange +{ + int64_t Start; + int64_t Step; + int64_t End; + + InteropRange() : + Start(0), + Step(0), + End(0){} + + InteropRange(RangeTuple rangeTuple) : + Start(get<0>(rangeTuple)), + Step(get<1>(rangeTuple)), + End(get<2>(rangeTuple)){} +}; + +unique_ptr CreateInteropRange(RangeTuple rangeTuple) +{ + unique_ptr range(new InteropRange(rangeTuple)); + return range; +} + +InteropRange* TranslateRangeTupleToInteropRangePointer(RangeTuple& rangeTuple) +{ + InteropRange* range = new InteropRange(rangeTuple); + return range; +} +<# } #> +<# if (EntryPoint.ContainsArrayType(DataType.RangeType)) { #> + +// Auxiliary functions for interop with Q# Range[] type +template +void FreePointerVector(vector& v) +{ + for (auto p : v) + { + delete p; + } +} +<# } #> +<# if (EntryPoint.ContainsArgumentType(DataType.BoolType) || EntryPoint.ContainsArrayType(DataType.BoolType)) { #> + +// Auxiliary functions for interop with Q# Bool type. +const char InteropFalseAsChar = 0x0; +const char InteropTrueAsChar = 0x1; +map <#= QirCppInterop.CliOptionTransformerMapName(DataType.BoolType) #>{ + {"0", InteropFalseAsChar}, + {"false", InteropFalseAsChar}, + {"1", InteropTrueAsChar}, + {"true", InteropTrueAsChar} +}; +<# } #> +<# if (EntryPoint.ContainsArgumentType(DataType.PauliType) || EntryPoint.ContainsArrayType(DataType.PauliType)) { #> + +// Auxiliary functions for interop with Q# Pauli type. +map <#= QirCppInterop.CliOptionTransformerMapName(DataType.PauliType) #>{ + {"PauliI", PauliId::PauliId_I}, + {"PauliX", PauliId::PauliId_X}, + {"PauliY", PauliId::PauliId_Y}, + {"PauliZ", PauliId::PauliId_Z} +}; + +char TranslatePauliToChar(PauliId& pauli) +{ + return static_cast(pauli); +} +<# } #> +<# if (EntryPoint.ContainsArgumentType(DataType.ResultType) || EntryPoint.ContainsArrayType(DataType.ResultType)) { #> + +// Auxiliary functions for interop with Q# Result type. +const char InteropResultZeroAsChar = 0x0; +const char InteropResultOneAsChar = 0x1; +map <#= QirCppInterop.CliOptionTransformerMapName(DataType.ResultType) #>{ + {"0", InteropResultZeroAsChar}, + {"Zero", InteropResultZeroAsChar}, + {"1", InteropResultOneAsChar}, + {"One", InteropResultOneAsChar} +}; +<# } #> +<# if (EntryPoint.ContainsArgumentType(DataType.StringType) || EntryPoint.ContainsArrayType(DataType.StringType)) { #> + +// Auxiliary functions for interop with Q# String type. +const char* TranslateStringToCharBuffer(string& s) +{ + return s.c_str(); +} +<# } #> extern "C" void <#= EntryPoint.Name #>( <# for (int i = 0; i < EntryPoint.Arguments.Count; i++) { @@ -31,5 +152,89 @@ extern "C" void <#= EntryPoint.Name #>( int main(int argc, char* argv[]) { + CLI::App app("QIR Standalone Entry Point"); + + // Initialize simulator. +<# foreach (var line in SimulatorInitializer.GenerateSourceCode()) { #> + <#= line #> +<# } #> + + // Add the --simulation-output option. + string simulationOutputFile; + CLI::Option* simulationOutputFileOpt = app.add_option( + "--simulation-output", + simulationOutputFile, + "File where the output produced during the simulation is written"); + +<# if (EntryPoint.Arguments.Count > 0) { #> + // Add a command line option for each entry-point argument. +<# } #> +<# foreach (var arg in EntryPoint.Arguments) { #> + <#= arg.CliOptionType() #> <#= arg.CliOptionVariableName() #>; +<# if (arg.CliOptionVariableDefaultValue() != null) { #> + <#= arg.CliOptionVariableName() #> = <#= arg.CliOptionVariableDefaultValue() #>; +<# } #> + app.add_option("<#= arg.CliOptionName() #>", <#= arg.CliOptionVariableName() #>, "<#= arg.CliOptionDescription() #>") + ->required()<#= arg.CliOptionTransformerMapName() != null ? "" : ";" #> +<# if (arg.CliOptionTransformerMapName() != null) { #> + ->transform(CLI::CheckedTransformer(<#= arg.CliOptionTransformerMapName() #>, CLI::ignore_case)); +<# } #> + +<# } #> + // After all the options have been added, parse arguments from the command line. + CLI11_PARSE(app, argc, argv); + +<# if (EntryPoint.Arguments.Count > 0) { #> + // Cast parsed arguments to its interop types. +<# } #> +<# foreach (var arg in EntryPoint.Arguments) { + var interopTranslator = QirCppInterop.CliOptionTypeToInteropTypeTranslator(arg.Type);#> +<# if (arg.Type == DataType.ArrayType) { + var arrayInteropTranslator = QirCppInterop.CliOptionTypeToInteropTypeTranslator(arg.ArrayType); #> +<# if (arrayInteropTranslator == null) { #> + <#= arg.InteropType() #> <#= arg.InteropVariableName() #> = CreateInteropArray(<#= arg.CliOptionVariableName() #>).get(); +<# } #> +<# else { + var arrayCliOptionType = QirCppInterop.CliOptionType(arg.ArrayType); + var arrayInteropType = QirCppInterop.InteropType(arg.ArrayType); #> + vector<<#= arrayInteropType #>> <#= arg.IntermediateVariableName() #>; + TranslateVector<<#= arrayCliOptionType #>, <#= arrayInteropType #>>(<#= arg.CliOptionVariableName() #>, <#= arg.IntermediateVariableName() #>, <#= arrayInteropTranslator #>); + <#= arg.InteropType() #> <#= arg.InteropVariableName() #> = CreateInteropArray(<#= arg.IntermediateVariableName() #>).get(); +<# } #> +<# } #> +<# else if (interopTranslator == null) { #> + <#= arg.InteropType() #> <#= arg.InteropVariableName() #> = <#= arg.CliOptionVariableName() #>; +<# } #> +<# else if (interopTranslator != null) { #> + <#= arg.InteropType() #> <#= arg.InteropVariableName() #> = <#= interopTranslator #>(<#= arg.CliOptionVariableName() #>); +<# } #> + +<# } #> + // Redirect the simulator output from std::cout if the --simulation-output option is present. + ostream* simulatorOutputStream = &cout; + ofstream simulationOutputFileStream; + if (!simulationOutputFileOpt->empty()) + { + simulationOutputFileStream.open(simulationOutputFile); + Microsoft::Quantum::OutputStream::Set(simulationOutputFileStream); + simulatorOutputStream = &simulationOutputFileStream; + } + + // Execute the entry point operation. + <#= EntryPoint.Name #>( +<# for (int i = 0; i < EntryPoint.Arguments.Count; i++) { + var arg = EntryPoint.Arguments[i]; + var isLastArg = i == (EntryPoint.Arguments.Count-1); #> + <#= arg.InteropVariableName() #><#= (isLastArg) ? "" : "," #> +<# } #> + ); + + // Flush the output of the simulation. + simulatorOutputStream->flush(); + if (simulationOutputFileStream.is_open()) + { + simulationOutputFileStream.close(); + } + return 0; } diff --git a/src/Qir/Execution/Tools/Driver/QirCppDriverGenerator.cs b/src/Qir/Execution/Tools/Driver/QirCppDriverGenerator.cs index 705c155a32b..da83765a67e 100644 --- a/src/Qir/Execution/Tools/Driver/QirCppDriverGenerator.cs +++ b/src/Qir/Execution/Tools/Driver/QirCppDriverGenerator.cs @@ -20,18 +20,13 @@ public QirCppDriverGenerator(IQirSimulatorInitializer simulatorInitializer) public async Task GenerateAsync(EntryPointOperation entryPointOperation, Stream stream) { - var cppSource = GenerateString(entryPointOperation); + var qirCppDriver = new QirCppDriver(entryPointOperation, SimulatorInitalizer); + var cppSource = qirCppDriver.TransformText(); await stream.WriteAsync(Encoding.UTF8.GetBytes(cppSource)); await stream.FlushAsync(); stream.Position = 0; } - public string GenerateString(EntryPointOperation entryPointOperation) - { - var qirCppDriver = new QirCppDriver(entryPointOperation, SimulatorInitalizer); - return qirCppDriver.TransformText(); - } - public string GetCommandLineArguments(EntryPointOperation entryPoint) => throw new NotImplementedException(); } } diff --git a/src/Qir/Execution/Tools/Driver/QirCppInterop.cs b/src/Qir/Execution/Tools/Driver/QirCppInterop.cs index 4057c0065ae..ee9cdf448eb 100644 --- a/src/Qir/Execution/Tools/Driver/QirCppInterop.cs +++ b/src/Qir/Execution/Tools/Driver/QirCppInterop.cs @@ -12,21 +12,21 @@ namespace Microsoft.Quantum.Qir.Tools.Driver { internal static class QirCppInterop { - public static string? CliOptionVariableDefaultValue(DataType? dataType) => + public static string? CliOptionTransformerMapName(DataType? dataType) => dataType switch { - DataType.BoolType => "0x0", - DataType.IntegerType => "0", - DataType.DoubleType => "0.0", - DataType.PauliType => "PauliId::PauliId_I", + DataType.BoolType => "BoolAsCharMap", + DataType.IntegerType => null, + DataType.DoubleType => null, + DataType.PauliType => "PauliMap", DataType.RangeType => null, - DataType.ResultType => "0x0", + DataType.ResultType => "ResultAsCharMap", DataType.StringType => null, DataType.ArrayType => null, _ => throw new ArgumentException($"Invalid data type: {dataType}") }; - public static string CliOptionVariableType(DataType? dataType) => + public static string CliOptionType(DataType? dataType) => dataType switch { DataType.BoolType => "char", @@ -40,33 +40,47 @@ public static string CliOptionVariableType(DataType? dataType) => _ => throw new ArgumentException($"Invalid data type: {dataType}") }; - public static string InteropType(DataType dataType) => + public static string? CliOptionTypeToInteropTypeTranslator(DataType? dataType) => dataType switch { - DataType.BoolType => "char", - DataType.IntegerType => "int64_t", - DataType.DoubleType => "double", - DataType.PauliType => "char", - DataType.RangeType => "InteropRange*", - DataType.ResultType => "char", - DataType.StringType => "const char*", - DataType.ArrayType => "InteropArray*", + DataType.BoolType => null, + DataType.IntegerType => null, + DataType.DoubleType => null, + DataType.PauliType => "TranslatePauliToChar", + DataType.RangeType => "TranslateRangeTupleToInteropRangePointer", + DataType.ResultType => null, + DataType.StringType => "TranslateStringToCharBuffer", + DataType.ArrayType => throw new NotSupportedException($"{DataType.ArrayType} does not match to a specific CLI option variable type"), _ => throw new ArgumentException($"Invalid data type: {dataType}") }; - public static string? TransformerMapName(DataType? dataType) => + public static string? CliOptionVariableDefaultValue(DataType? dataType) => dataType switch { - DataType.BoolType => "BoolAsCharMap", - DataType.IntegerType => null, - DataType.DoubleType => null, - DataType.PauliType => "PauliMap", + DataType.BoolType => "InteropFalseAsChar", + DataType.IntegerType => "0", + DataType.DoubleType => "0.0", + DataType.PauliType => "PauliId::PauliId_I", DataType.RangeType => null, - DataType.ResultType => "ResultAsCharMap", + DataType.ResultType => "InteropResultZeroAsChar", DataType.StringType => null, DataType.ArrayType => null, _ => throw new ArgumentException($"Invalid data type: {dataType}") }; + + public static string InteropType(DataType? dataType) => + dataType switch + { + DataType.BoolType => "char", + DataType.IntegerType => "int64_t", + DataType.DoubleType => "double_t", + DataType.PauliType => "char", + DataType.RangeType => "InteropRange*", + DataType.ResultType => "char", + DataType.StringType => "const char*", + DataType.ArrayType => "InteropArray*", + _ => throw new ArgumentException($"Invalid data type: {dataType}") + }; } internal static class ArgumentCppExtensions @@ -84,30 +98,30 @@ public static string CliOptionName(this Argument @this) return @this.Name.Length == 1 ? $"-{@this.Name}" : $"--{@this.Name}"; } - public static string CliOptionVariableName(this Argument @this) => $"{@this.Name}Cli"; - - public static string? CliOptionVariableDefaultValue(this Argument @this) => - QirCppInterop.CliOptionVariableDefaultValue(@this.Type); + public static string? CliOptionTransformerMapName(this Argument @this) => + @this.Type switch + { + DataType.ArrayType => QirCppInterop.CliOptionTransformerMapName(@this.ArrayType), + _ => QirCppInterop.CliOptionTransformerMapName(@this.Type) + }; - public static string CliOptionVariableType(this Argument @this) => + public static string CliOptionType(this Argument @this) => @this.Type switch { - DataType.ArrayType => $"vector<{QirCppInterop.CliOptionVariableType(@this.ArrayType)}>", - _ => QirCppInterop.CliOptionVariableType(@this.Type) + DataType.ArrayType => $"vector<{QirCppInterop.CliOptionType(@this.ArrayType)}>", + _ => QirCppInterop.CliOptionType(@this.Type) }; + public static string CliOptionVariableName(this Argument @this) => $"{@this.Name}Cli"; + + public static string? CliOptionVariableDefaultValue(this Argument @this) => + QirCppInterop.CliOptionVariableDefaultValue(@this.Type); + public static string IntermediateVariableName(this Argument @this) => $"{@this.Name}Intermediate"; public static string InteropVariableName(this Argument @this) => $"{@this.Name}Interop"; public static string InteropType(this Argument @this) => QirCppInterop.InteropType(@this.Type); - - public static string? TransformerMapName(this Argument @this) => - @this.Type switch - { - DataType.ArrayType => QirCppInterop.TransformerMapName(@this.ArrayType), - _ => QirCppInterop.TransformerMapName(@this.Type) - }; } internal static class EntryPointOperationCppExtension diff --git a/src/Qir/Execution/Tools/Driver/QirFullStateDriverGenerator.cs b/src/Qir/Execution/Tools/Driver/QirFullStateDriverGenerator.cs index f0dad1889ee..17bc77c170c 100644 --- a/src/Qir/Execution/Tools/Driver/QirFullStateDriverGenerator.cs +++ b/src/Qir/Execution/Tools/Driver/QirFullStateDriverGenerator.cs @@ -18,9 +18,6 @@ public QirFullStateDriverGenerator() public async Task GenerateAsync(EntryPointOperation entryPoint, Stream stream) => await DriverGenerator.GenerateAsync(entryPoint, stream); - public string GenerateString(EntryPointOperation entryPoint) => - DriverGenerator.GenerateString(entryPoint); - public string GetCommandLineArguments(EntryPointOperation entryPoint) => DriverGenerator.GetCommandLineArguments(entryPoint); } diff --git a/src/Qir/Execution/Tools/Driver/QirFullStateSimulatorInitializer.cs b/src/Qir/Execution/Tools/Driver/QirFullStateSimulatorInitializer.cs index 2622a6eccae..8a9a69a494f 100644 --- a/src/Qir/Execution/Tools/Driver/QirFullStateSimulatorInitializer.cs +++ b/src/Qir/Execution/Tools/Driver/QirFullStateSimulatorInitializer.cs @@ -11,21 +11,10 @@ namespace Microsoft.Quantum.Qir.Tools.Driver { public class QirFullStateSimulatorInitializer : IQirSimulatorInitializer { - public async Task GenerateAsync(Stream stream) - { - var simulatorInitializerSourceCode = this.GenerateString(); - await stream.WriteAsync(Encoding.UTF8.GetBytes(simulatorInitializerSourceCode)); - await stream.FlushAsync(); - stream.Position = 0; - } - public string GenerateString() - { - // TODO: Implement. - return String.Empty; - } + // TODO: Implement. + public IList GenerateSourceCode() => new List(); public IList Headers => new List { - "QirContext.hpp", "SimFactory.hpp" }; From feca638232fd807464420c3cfb53b9779936bf7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Wed, 28 Apr 2021 04:25:49 -0700 Subject: [PATCH 07/15] Update test cases. --- .../FullStateDriverGenerator/UseNoArgs.cpp | 35 +++++-------- .../FullStateDriverGenerator/UseResultArg.cpp | 51 +++++++++---------- .../Execution/Tools/Driver/QirCppDriver.cs | 2 +- .../Execution/Tools/Driver/QirCppDriver.tt | 2 +- 4 files changed, 41 insertions(+), 49 deletions(-) diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseNoArgs.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseNoArgs.cpp index bcb2afc2fc9..f1013e391ae 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseNoArgs.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseNoArgs.cpp @@ -2,9 +2,6 @@ // This code was generated by a tool. // //------------------------------------------------------------------------------ -// -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. #include #include @@ -14,36 +11,31 @@ #include "CLI11.hpp" -#include "QirContext.hpp" #include "QirRuntime.hpp" +#include "QirContext.hpp" + #include "SimFactory.hpp" using namespace Microsoft::Quantum; using namespace std; - - -// This is the function corresponding to the QIR entry-point. -extern "C" void UseNoArgs( // NOLINT - -); +extern "C" void UseNoArgs( +); // QIR interop function. int main(int argc, char* argv[]) { - CLI::App app("QIR Standalone Entry Point Inputs Reference"); + CLI::App app("QIR Standalone Entry Point"); // Initialize simulator. - unique_ptr sim = CreateFullstateSimulator(); - QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); - // Add the --simulation-output options. - // N.B. This option should be present in all standalone drivers. + // Add the --simulation-output option. string simulationOutputFile; CLI::Option* simulationOutputFileOpt = app.add_option( - "--simulation-output", simulationOutputFile, + "--simulation-output", + simulationOutputFile, "File where the output produced during the simulation is written"); - // With all the options added, parse arguments from the command line. + // After all the options have been added, parse arguments from the command line. CLI11_PARSE(app, argc, argv); // Redirect the simulator output from std::cout if the --simulation-output option is present. @@ -52,19 +44,20 @@ int main(int argc, char* argv[]) if (!simulationOutputFileOpt->empty()) { simulationOutputFileStream.open(simulationOutputFile); - SetOutputStream(simulationOutputFileStream); + Microsoft::Quantum::OutputStream::Set(simulationOutputFileStream); simulatorOutputStream = &simulationOutputFileStream; } - // Run simulation and write the output of the operation to the corresponding stream. + // Execute the entry point operation. UseNoArgs( - ); - + // Flush the output of the simulation. simulatorOutputStream->flush(); if (simulationOutputFileStream.is_open()) { simulationOutputFileStream.close(); } + + return 0; } diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArg.cpp index 90437295ce6..a5c80ad6f7d 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArg.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArg.cpp @@ -2,9 +2,6 @@ // This code was generated by a tool. // //------------------------------------------------------------------------------ -// -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. #include #include @@ -14,20 +11,15 @@ #include "CLI11.hpp" -#include "QirContext.hpp" #include "QirRuntime.hpp" +#include "QirContext.hpp" + #include "SimFactory.hpp" using namespace Microsoft::Quantum; using namespace std; - - -// This is the function corresponding to the QIR entry-point. -extern "C" void UseResultArg( // NOLINT - char ResultArgInteropValue -); - +// Auxiliary functions for interop with Q# Result type. const char InteropResultZeroAsChar = 0x0; const char InteropResultOneAsChar = 0x1; map ResultAsCharMap{ @@ -37,30 +29,35 @@ map ResultAsCharMap{ {"One", InteropResultOneAsChar} }; +extern "C" void UseResultArg( + char ResultArg +); // QIR interop function. + int main(int argc, char* argv[]) { - CLI::App app("QIR Standalone Entry Point Inputs Reference"); + CLI::App app("QIR Standalone Entry Point"); // Initialize simulator. - unique_ptr sim = CreateFullstateSimulator(); - QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); - // Add the --simulation-output options. - // N.B. This option should be present in all standalone drivers. + // Add the --simulation-output option. string simulationOutputFile; CLI::Option* simulationOutputFileOpt = app.add_option( - "--simulation-output", simulationOutputFile, + "--simulation-output", + simulationOutputFile, "File where the output produced during the simulation is written"); - char ResultArgCliValue; - ResultArgCliValue = InteropResultZeroAsChar; - app.add_option("--ResultArg", ResultArgCliValue, "A Result value for the ResultArg argument")->required() + // Add a command line option for each entry-point argument. + char ResultArgCli; + ResultArgCli = InteropResultZeroAsChar; + app.add_option("--ResultArg", ResultArgCli, "Option to provide a value for the ResultArg parameter") + ->required() ->transform(CLI::CheckedTransformer(ResultAsCharMap, CLI::ignore_case)); - // With all the options added, parse arguments from the command line. + // After all the options have been added, parse arguments from the command line. CLI11_PARSE(app, argc, argv); - char ResultArgInteropValue = ResultArgCliValue; + // Cast parsed arguments to its interop types. + char ResultArgInterop = ResultArgCli; // Redirect the simulator output from std::cout if the --simulation-output option is present. ostream* simulatorOutputStream = &cout; @@ -68,19 +65,21 @@ int main(int argc, char* argv[]) if (!simulationOutputFileOpt->empty()) { simulationOutputFileStream.open(simulationOutputFile); - SetOutputStream(simulationOutputFileStream); + Microsoft::Quantum::OutputStream::Set(simulationOutputFileStream); simulatorOutputStream = &simulationOutputFileStream; } - // Run simulation and write the output of the operation to the corresponding stream. + // Execute the entry point operation. UseResultArg( - ResultArgInteropValue + ResultArgInterop ); - + // Flush the output of the simulation. simulatorOutputStream->flush(); if (simulationOutputFileStream.is_open()) { simulationOutputFileStream.close(); } + + return 0; } diff --git a/src/Qir/Execution/Tools/Driver/QirCppDriver.cs b/src/Qir/Execution/Tools/Driver/QirCppDriver.cs index 674eb9b2627..c5020e5672b 100644 --- a/src/Qir/Execution/Tools/Driver/QirCppDriver.cs +++ b/src/Qir/Execution/Tools/Driver/QirCppDriver.cs @@ -284,7 +284,7 @@ unique_ptr CreateInteropRange(RangeTuple rangeTuple) for (int i = 0; i < EntryPoint.Arguments.Count; i++) { var arg = EntryPoint.Arguments[i]; var isLastArg = i == (EntryPoint.Arguments.Count-1); - this.Write(" "); + this.Write(" "); this.Write(this.ToStringHelper.ToStringWithCulture(arg.InteropVariableName())); this.Write(this.ToStringHelper.ToStringWithCulture((isLastArg) ? "" : ",")); this.Write("\r\n"); diff --git a/src/Qir/Execution/Tools/Driver/QirCppDriver.tt b/src/Qir/Execution/Tools/Driver/QirCppDriver.tt index 00d43c7a12b..1033e75f1e4 100644 --- a/src/Qir/Execution/Tools/Driver/QirCppDriver.tt +++ b/src/Qir/Execution/Tools/Driver/QirCppDriver.tt @@ -225,7 +225,7 @@ int main(int argc, char* argv[]) <# for (int i = 0; i < EntryPoint.Arguments.Count; i++) { var arg = EntryPoint.Arguments[i]; var isLastArg = i == (EntryPoint.Arguments.Count-1); #> - <#= arg.InteropVariableName() #><#= (isLastArg) ? "" : "," #> + <#= arg.InteropVariableName() #><#= (isLastArg) ? "" : "," #> <# } #> ); From 8e822d994e9874b7ca366dad196483a89fc69aae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Wed, 28 Apr 2021 14:57:59 -0700 Subject: [PATCH 08/15] Implemented initializer. --- .../FullStateDriverGenerator/UseNoArgs.cpp | 2 + .../FullStateDriverGenerator/UseResultArg.cpp | 2 + .../QirCppFullStateSimulatorInitializer.cs | 302 ++++++++++++++++++ .../QirCppFullStateSimulatorInitializer.tt | 3 + .../QirFullStateSimulatorInitializer.cs | 12 +- .../Tools/Microsoft.Quantum.Qir.Tools.csproj | 11 +- 6 files changed, 329 insertions(+), 3 deletions(-) create mode 100644 src/Qir/Execution/Tools/Driver/QirCppFullStateSimulatorInitializer.cs create mode 100644 src/Qir/Execution/Tools/Driver/QirCppFullStateSimulatorInitializer.tt diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseNoArgs.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseNoArgs.cpp index f1013e391ae..4d5d776a1d9 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseNoArgs.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseNoArgs.cpp @@ -27,6 +27,8 @@ int main(int argc, char* argv[]) CLI::App app("QIR Standalone Entry Point"); // Initialize simulator. + unique_ptr sim = CreateFullstateSimulator(); + QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); // Add the --simulation-output option. string simulationOutputFile; diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArg.cpp index a5c80ad6f7d..e6aec6d1f5b 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArg.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArg.cpp @@ -38,6 +38,8 @@ int main(int argc, char* argv[]) CLI::App app("QIR Standalone Entry Point"); // Initialize simulator. + unique_ptr sim = CreateFullstateSimulator(); + QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); // Add the --simulation-output option. string simulationOutputFile; diff --git a/src/Qir/Execution/Tools/Driver/QirCppFullStateSimulatorInitializer.cs b/src/Qir/Execution/Tools/Driver/QirCppFullStateSimulatorInitializer.cs new file mode 100644 index 00000000000..44939338006 --- /dev/null +++ b/src/Qir/Execution/Tools/Driver/QirCppFullStateSimulatorInitializer.cs @@ -0,0 +1,302 @@ +// ------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version: 16.0.0.0 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ +namespace Microsoft.Quantum.Qir.Tools.Driver +{ + using System; + + /// + /// Class to produce the template output + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "16.0.0.0")] + public partial class QirCppFullStateSimulatorInitializer : QirCppFullStateSimulatorInitializerBase + { + /// + /// Create the template output + /// + public virtual string TransformText() + { + this.Write("unique_ptr sim = CreateFullstateSimulator();\r\nQirContextScope qir" + + "ctx(sim.get(), false /*trackAllocatedObjects*/);"); + return this.GenerationEnvironment.ToString(); + } + } + #region Base class + /// + /// Base class for this transformation + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "16.0.0.0")] + public class QirCppFullStateSimulatorInitializerBase + { + #region Fields + private global::System.Text.StringBuilder generationEnvironmentField; + private global::System.CodeDom.Compiler.CompilerErrorCollection errorsField; + private global::System.Collections.Generic.List indentLengthsField; + private string currentIndentField = ""; + private bool endsWithNewline; + private global::System.Collections.Generic.IDictionary sessionField; + #endregion + #region Properties + /// + /// The string builder that generation-time code is using to assemble generated output + /// + protected System.Text.StringBuilder GenerationEnvironment + { + get + { + if ((this.generationEnvironmentField == null)) + { + this.generationEnvironmentField = new global::System.Text.StringBuilder(); + } + return this.generationEnvironmentField; + } + set + { + this.generationEnvironmentField = value; + } + } + /// + /// The error collection for the generation process + /// + public System.CodeDom.Compiler.CompilerErrorCollection Errors + { + get + { + if ((this.errorsField == null)) + { + this.errorsField = new global::System.CodeDom.Compiler.CompilerErrorCollection(); + } + return this.errorsField; + } + } + /// + /// A list of the lengths of each indent that was added with PushIndent + /// + private System.Collections.Generic.List indentLengths + { + get + { + if ((this.indentLengthsField == null)) + { + this.indentLengthsField = new global::System.Collections.Generic.List(); + } + return this.indentLengthsField; + } + } + /// + /// Gets the current indent we use when adding lines to the output + /// + public string CurrentIndent + { + get + { + return this.currentIndentField; + } + } + /// + /// Current transformation session + /// + public virtual global::System.Collections.Generic.IDictionary Session + { + get + { + return this.sessionField; + } + set + { + this.sessionField = value; + } + } + #endregion + #region Transform-time helpers + /// + /// Write text directly into the generated output + /// + public void Write(string textToAppend) + { + if (string.IsNullOrEmpty(textToAppend)) + { + return; + } + // If we're starting off, or if the previous text ended with a newline, + // we have to append the current indent first. + if (((this.GenerationEnvironment.Length == 0) + || this.endsWithNewline)) + { + this.GenerationEnvironment.Append(this.currentIndentField); + this.endsWithNewline = false; + } + // Check if the current text ends with a newline + if (textToAppend.EndsWith(global::System.Environment.NewLine, global::System.StringComparison.CurrentCulture)) + { + this.endsWithNewline = true; + } + // This is an optimization. If the current indent is "", then we don't have to do any + // of the more complex stuff further down. + if ((this.currentIndentField.Length == 0)) + { + this.GenerationEnvironment.Append(textToAppend); + return; + } + // Everywhere there is a newline in the text, add an indent after it + textToAppend = textToAppend.Replace(global::System.Environment.NewLine, (global::System.Environment.NewLine + this.currentIndentField)); + // If the text ends with a newline, then we should strip off the indent added at the very end + // because the appropriate indent will be added when the next time Write() is called + if (this.endsWithNewline) + { + this.GenerationEnvironment.Append(textToAppend, 0, (textToAppend.Length - this.currentIndentField.Length)); + } + else + { + this.GenerationEnvironment.Append(textToAppend); + } + } + /// + /// Write text directly into the generated output + /// + public void WriteLine(string textToAppend) + { + this.Write(textToAppend); + this.GenerationEnvironment.AppendLine(); + this.endsWithNewline = true; + } + /// + /// Write formatted text directly into the generated output + /// + public void Write(string format, params object[] args) + { + this.Write(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args)); + } + /// + /// Write formatted text directly into the generated output + /// + public void WriteLine(string format, params object[] args) + { + this.WriteLine(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args)); + } + /// + /// Raise an error + /// + public void Error(string message) + { + System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError(); + error.ErrorText = message; + this.Errors.Add(error); + } + /// + /// Raise a warning + /// + public void Warning(string message) + { + System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError(); + error.ErrorText = message; + error.IsWarning = true; + this.Errors.Add(error); + } + /// + /// Increase the indent + /// + public void PushIndent(string indent) + { + if ((indent == null)) + { + throw new global::System.ArgumentNullException("indent"); + } + this.currentIndentField = (this.currentIndentField + indent); + this.indentLengths.Add(indent.Length); + } + /// + /// Remove the last indent that was added with PushIndent + /// + public string PopIndent() + { + string returnValue = ""; + if ((this.indentLengths.Count > 0)) + { + int indentLength = this.indentLengths[(this.indentLengths.Count - 1)]; + this.indentLengths.RemoveAt((this.indentLengths.Count - 1)); + if ((indentLength > 0)) + { + returnValue = this.currentIndentField.Substring((this.currentIndentField.Length - indentLength)); + this.currentIndentField = this.currentIndentField.Remove((this.currentIndentField.Length - indentLength)); + } + } + return returnValue; + } + /// + /// Remove any indentation + /// + public void ClearIndent() + { + this.indentLengths.Clear(); + this.currentIndentField = ""; + } + #endregion + #region ToString Helpers + /// + /// Utility class to produce culture-oriented representation of an object as a string. + /// + public class ToStringInstanceHelper + { + private System.IFormatProvider formatProviderField = global::System.Globalization.CultureInfo.InvariantCulture; + /// + /// Gets or sets format provider to be used by ToStringWithCulture method. + /// + public System.IFormatProvider FormatProvider + { + get + { + return this.formatProviderField ; + } + set + { + if ((value != null)) + { + this.formatProviderField = value; + } + } + } + /// + /// This is called from the compile/run appdomain to convert objects within an expression block to a string + /// + public string ToStringWithCulture(object objectToConvert) + { + if ((objectToConvert == null)) + { + throw new global::System.ArgumentNullException("objectToConvert"); + } + System.Type t = objectToConvert.GetType(); + System.Reflection.MethodInfo method = t.GetMethod("ToString", new System.Type[] { + typeof(System.IFormatProvider)}); + if ((method == null)) + { + return objectToConvert.ToString(); + } + else + { + return ((string)(method.Invoke(objectToConvert, new object[] { + this.formatProviderField }))); + } + } + } + private ToStringInstanceHelper toStringHelperField = new ToStringInstanceHelper(); + /// + /// Helper to produce culture-oriented representation of an object as a string + /// + public ToStringInstanceHelper ToStringHelper + { + get + { + return this.toStringHelperField; + } + } + #endregion + } + #endregion +} diff --git a/src/Qir/Execution/Tools/Driver/QirCppFullStateSimulatorInitializer.tt b/src/Qir/Execution/Tools/Driver/QirCppFullStateSimulatorInitializer.tt new file mode 100644 index 00000000000..275994cf4af --- /dev/null +++ b/src/Qir/Execution/Tools/Driver/QirCppFullStateSimulatorInitializer.tt @@ -0,0 +1,3 @@ +<#@ template language="C#" linePragmas="false" #> +unique_ptr sim = CreateFullstateSimulator(); +QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); \ No newline at end of file diff --git a/src/Qir/Execution/Tools/Driver/QirFullStateSimulatorInitializer.cs b/src/Qir/Execution/Tools/Driver/QirFullStateSimulatorInitializer.cs index 8a9a69a494f..41530c2ba43 100644 --- a/src/Qir/Execution/Tools/Driver/QirFullStateSimulatorInitializer.cs +++ b/src/Qir/Execution/Tools/Driver/QirFullStateSimulatorInitializer.cs @@ -11,8 +11,16 @@ namespace Microsoft.Quantum.Qir.Tools.Driver { public class QirFullStateSimulatorInitializer : IQirSimulatorInitializer { - // TODO: Implement. - public IList GenerateSourceCode() => new List(); + public IList GenerateSourceCode() + { + var simulatorInitializer = new QirCppFullStateSimulatorInitializer(); + var sourceCode = simulatorInitializer.TransformText(); + var lines = sourceCode.Split( + new[] { "\r\n", "\r", "\n" }, + StringSplitOptions.None); + + return new List(lines); + } public IList Headers => new List { "SimFactory.hpp" diff --git a/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj b/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj index 75255b51955..bccc46f0b04 100644 --- a/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj +++ b/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj @@ -19,6 +19,10 @@ TextTemplatingFilePreprocessor QirCppDriver.cs + + TextTemplatingFilePreprocessor + QirCppFullStateSimulatorInitializer.cs + @@ -27,10 +31,15 @@ - True + False True QirCppDriver.tt + + False + True + QirCppFullStateSimulatorInitializer.tt + From 4929b7667553db097a657d008bcf9aa3f03afd68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Thu, 29 Apr 2021 21:33:17 -0700 Subject: [PATCH 09/15] Use string reader. --- .../Tools/Driver/IQirSimulatorInitializer.cs | 2 +- src/Qir/Execution/Tools/Driver/QirCppDriver.cs | 5 ++++- src/Qir/Execution/Tools/Driver/QirCppDriver.tt | 5 ++++- .../Tools/Driver/QirFullStateSimulatorInitializer.cs | 11 +---------- .../Tools/Microsoft.Quantum.Qir.Tools.csproj | 2 +- 5 files changed, 11 insertions(+), 14 deletions(-) diff --git a/src/Qir/Execution/Tools/Driver/IQirSimulatorInitializer.cs b/src/Qir/Execution/Tools/Driver/IQirSimulatorInitializer.cs index 4b8e1de5146..1ed263c814d 100644 --- a/src/Qir/Execution/Tools/Driver/IQirSimulatorInitializer.cs +++ b/src/Qir/Execution/Tools/Driver/IQirSimulatorInitializer.cs @@ -9,7 +9,7 @@ namespace Microsoft.Quantum.Qir.Tools.Driver { public interface IQirSimulatorInitializer { - public IList GenerateSourceCode(); + public string Generate(); public IList Headers { get; } diff --git a/src/Qir/Execution/Tools/Driver/QirCppDriver.cs b/src/Qir/Execution/Tools/Driver/QirCppDriver.cs index c5020e5672b..9d62f93f301 100644 --- a/src/Qir/Execution/Tools/Driver/QirCppDriver.cs +++ b/src/Qir/Execution/Tools/Driver/QirCppDriver.cs @@ -9,6 +9,7 @@ // ------------------------------------------------------------------------------ namespace Microsoft.Quantum.Qir.Tools.Driver { + using System.IO; using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; using System; @@ -155,7 +156,9 @@ unique_ptr CreateInteropRange(RangeTuple rangeTuple) } this.Write("); // QIR interop function.\r\n\r\nint main(int argc, char* argv[])\r\n{\r\n CLI::App " + "app(\"QIR Standalone Entry Point\");\r\n\r\n // Initialize simulator.\r\n"); - foreach (var line in SimulatorInitializer.GenerateSourceCode()) { + var initializerReader = new StringReader(SimulatorInitializer.Generate()); + string line; + while((line = initializerReader.ReadLine()) != null) { this.Write(" "); this.Write(this.ToStringHelper.ToStringWithCulture(line)); this.Write("\r\n"); diff --git a/src/Qir/Execution/Tools/Driver/QirCppDriver.tt b/src/Qir/Execution/Tools/Driver/QirCppDriver.tt index 1033e75f1e4..e92875ebcb1 100644 --- a/src/Qir/Execution/Tools/Driver/QirCppDriver.tt +++ b/src/Qir/Execution/Tools/Driver/QirCppDriver.tt @@ -1,4 +1,5 @@ <#@ template language="C#" linePragmas="false" #> +<#@ import namespace="System.IO" #> <#@ import namespace="Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint" #> //------------------------------------------------------------------------------ // This code was generated by a tool. @@ -155,7 +156,9 @@ int main(int argc, char* argv[]) CLI::App app("QIR Standalone Entry Point"); // Initialize simulator. -<# foreach (var line in SimulatorInitializer.GenerateSourceCode()) { #> +<# var initializerReader = new StringReader(SimulatorInitializer.Generate()); + string line; + while((line = initializerReader.ReadLine()) != null) { #> <#= line #> <# } #> diff --git a/src/Qir/Execution/Tools/Driver/QirFullStateSimulatorInitializer.cs b/src/Qir/Execution/Tools/Driver/QirFullStateSimulatorInitializer.cs index 41530c2ba43..12bea984368 100644 --- a/src/Qir/Execution/Tools/Driver/QirFullStateSimulatorInitializer.cs +++ b/src/Qir/Execution/Tools/Driver/QirFullStateSimulatorInitializer.cs @@ -11,16 +11,7 @@ namespace Microsoft.Quantum.Qir.Tools.Driver { public class QirFullStateSimulatorInitializer : IQirSimulatorInitializer { - public IList GenerateSourceCode() - { - var simulatorInitializer = new QirCppFullStateSimulatorInitializer(); - var sourceCode = simulatorInitializer.TransformText(); - var lines = sourceCode.Split( - new[] { "\r\n", "\r", "\n" }, - StringSplitOptions.None); - - return new List(lines); - } + public string Generate() => new QirCppFullStateSimulatorInitializer().TransformText(); public IList Headers => new List { "SimFactory.hpp" diff --git a/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj b/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj index bccc46f0b04..5f295e41ed0 100644 --- a/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj +++ b/src/Qir/Execution/Tools/Microsoft.Quantum.Qir.Tools.csproj @@ -31,7 +31,7 @@ - False + True True QirCppDriver.tt From 73abea80cb6fc52c63a9d53d3d8645ac2bc69f4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Fri, 30 Apr 2021 09:49:59 -0700 Subject: [PATCH 10/15] Fixed issues by changes in Bond schema. --- .../QirDriverGeneratorTests.cs | 4 +-- .../Execution/Tools/Driver/QirCppDriver.cs | 24 ++++++++--------- .../Execution/Tools/Driver/QirCppDriver.tt | 24 ++++++++--------- .../Execution/Tools/Driver/QirCppDriverEx.cs | 2 +- .../Tools/Driver/QirCppDriverGenerator.cs | 4 +-- .../Execution/Tools/Driver/QirCppInterop.cs | 26 +++++++++---------- .../Driver/QirFullStateDriverGenerator.cs | 4 +-- 7 files changed, 44 insertions(+), 44 deletions(-) diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirDriverGeneratorTests.cs b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirDriverGeneratorTests.cs index de8c96178d8..05d67b8dc44 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirDriverGeneratorTests.cs +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirDriverGeneratorTests.cs @@ -8,7 +8,7 @@ using Xunit; using Microsoft.Quantum.Qir.Tools.Driver; -using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; +using Microsoft.Quantum.QsCompiler.BondSchemas.Execution; namespace Tests.Microsoft.Quantum.Qir.Tools { @@ -28,7 +28,7 @@ public class QirDriverGeneratorTests new EntryPointOperation { Name = "UseResultArg", - Arguments = new List{new Argument{ Name = "ResultArg", Type = DataType.ResultType}} + Parameters = new List{new Parameter{ Name = "ResultArg", Type = DataType.ResultType}} } } }; diff --git a/src/Qir/Execution/Tools/Driver/QirCppDriver.cs b/src/Qir/Execution/Tools/Driver/QirCppDriver.cs index 9d62f93f301..2d2969cebaf 100644 --- a/src/Qir/Execution/Tools/Driver/QirCppDriver.cs +++ b/src/Qir/Execution/Tools/Driver/QirCppDriver.cs @@ -10,7 +10,7 @@ namespace Microsoft.Quantum.Qir.Tools.Driver { using System.IO; - using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; + using Microsoft.Quantum.QsCompiler.BondSchemas.Execution; using System; /// @@ -144,9 +144,9 @@ unique_ptr CreateInteropRange(RangeTuple rangeTuple) this.Write("\r\nextern \"C\" void "); this.Write(this.ToStringHelper.ToStringWithCulture(EntryPoint.Name)); this.Write("(\r\n"); - for (int i = 0; i < EntryPoint.Arguments.Count; i++) { - var arg = EntryPoint.Arguments[i]; - var isLastArg = i == (EntryPoint.Arguments.Count-1); + for (int i = 0; i < EntryPoint.Parameters.Count; i++) { + var arg = EntryPoint.Parameters[i]; + var isLastArg = i == (EntryPoint.Parameters.Count-1); this.Write(" "); this.Write(this.ToStringHelper.ToStringWithCulture(arg.InteropType())); this.Write(" "); @@ -172,10 +172,10 @@ unique_ptr CreateInteropRange(RangeTuple rangeTuple) ""File where the output produced during the simulation is written""); "); - if (EntryPoint.Arguments.Count > 0) { - this.Write(" // Add a command line option for each entry-point argument.\r\n"); + if (EntryPoint.Parameters.Count > 0) { + this.Write(" // Add a command line option for each entry-point parameter.\r\n"); } - foreach (var arg in EntryPoint.Arguments) { + foreach (var arg in EntryPoint.Parameters) { this.Write(" "); this.Write(this.ToStringHelper.ToStringWithCulture(arg.CliOptionType())); this.Write(" "); @@ -206,10 +206,10 @@ unique_ptr CreateInteropRange(RangeTuple rangeTuple) } this.Write(" // After all the options have been added, parse arguments from the command li" + "ne.\r\n CLI11_PARSE(app, argc, argv);\r\n\r\n"); - if (EntryPoint.Arguments.Count > 0) { + if (EntryPoint.Parameters.Count > 0) { this.Write(" // Cast parsed arguments to its interop types.\r\n"); } - foreach (var arg in EntryPoint.Arguments) { + foreach (var arg in EntryPoint.Parameters) { var interopTranslator = QirCppInterop.CliOptionTypeToInteropTypeTranslator(arg.Type); if (arg.Type == DataType.ArrayType) { var arrayInteropTranslator = QirCppInterop.CliOptionTypeToInteropTypeTranslator(arg.ArrayType); @@ -284,9 +284,9 @@ unique_ptr CreateInteropRange(RangeTuple rangeTuple) "); this.Write(this.ToStringHelper.ToStringWithCulture(EntryPoint.Name)); this.Write("(\r\n"); - for (int i = 0; i < EntryPoint.Arguments.Count; i++) { - var arg = EntryPoint.Arguments[i]; - var isLastArg = i == (EntryPoint.Arguments.Count-1); + for (int i = 0; i < EntryPoint.Parameters.Count; i++) { + var arg = EntryPoint.Parameters[i]; + var isLastArg = i == (EntryPoint.Parameters.Count-1); this.Write(" "); this.Write(this.ToStringHelper.ToStringWithCulture(arg.InteropVariableName())); this.Write(this.ToStringHelper.ToStringWithCulture((isLastArg) ? "" : ",")); diff --git a/src/Qir/Execution/Tools/Driver/QirCppDriver.tt b/src/Qir/Execution/Tools/Driver/QirCppDriver.tt index e92875ebcb1..aa80a81b270 100644 --- a/src/Qir/Execution/Tools/Driver/QirCppDriver.tt +++ b/src/Qir/Execution/Tools/Driver/QirCppDriver.tt @@ -1,6 +1,6 @@ <#@ template language="C#" linePragmas="false" #> <#@ import namespace="System.IO" #> -<#@ import namespace="Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint" #> +<#@ import namespace="Microsoft.Quantum.QsCompiler.BondSchemas.Execution" #> //------------------------------------------------------------------------------ // This code was generated by a tool. // @@ -144,9 +144,9 @@ const char* TranslateStringToCharBuffer(string& s) <# } #> extern "C" void <#= EntryPoint.Name #>( -<# for (int i = 0; i < EntryPoint.Arguments.Count; i++) { - var arg = EntryPoint.Arguments[i]; - var isLastArg = i == (EntryPoint.Arguments.Count-1); #> +<# for (int i = 0; i < EntryPoint.Parameters.Count; i++) { + var arg = EntryPoint.Parameters[i]; + var isLastArg = i == (EntryPoint.Parameters.Count-1); #> <#= arg.InteropType() #> <#= arg.Name #><#= (isLastArg) ? "" : "," #> <# } #> ); // QIR interop function. @@ -169,10 +169,10 @@ int main(int argc, char* argv[]) simulationOutputFile, "File where the output produced during the simulation is written"); -<# if (EntryPoint.Arguments.Count > 0) { #> - // Add a command line option for each entry-point argument. +<# if (EntryPoint.Parameters.Count > 0) { #> + // Add a command line option for each entry-point parameter. <# } #> -<# foreach (var arg in EntryPoint.Arguments) { #> +<# foreach (var arg in EntryPoint.Parameters) { #> <#= arg.CliOptionType() #> <#= arg.CliOptionVariableName() #>; <# if (arg.CliOptionVariableDefaultValue() != null) { #> <#= arg.CliOptionVariableName() #> = <#= arg.CliOptionVariableDefaultValue() #>; @@ -187,10 +187,10 @@ int main(int argc, char* argv[]) // After all the options have been added, parse arguments from the command line. CLI11_PARSE(app, argc, argv); -<# if (EntryPoint.Arguments.Count > 0) { #> +<# if (EntryPoint.Parameters.Count > 0) { #> // Cast parsed arguments to its interop types. <# } #> -<# foreach (var arg in EntryPoint.Arguments) { +<# foreach (var arg in EntryPoint.Parameters) { var interopTranslator = QirCppInterop.CliOptionTypeToInteropTypeTranslator(arg.Type);#> <# if (arg.Type == DataType.ArrayType) { var arrayInteropTranslator = QirCppInterop.CliOptionTypeToInteropTypeTranslator(arg.ArrayType); #> @@ -225,9 +225,9 @@ int main(int argc, char* argv[]) // Execute the entry point operation. <#= EntryPoint.Name #>( -<# for (int i = 0; i < EntryPoint.Arguments.Count; i++) { - var arg = EntryPoint.Arguments[i]; - var isLastArg = i == (EntryPoint.Arguments.Count-1); #> +<# for (int i = 0; i < EntryPoint.Parameters.Count; i++) { + var arg = EntryPoint.Parameters[i]; + var isLastArg = i == (EntryPoint.Parameters.Count-1); #> <#= arg.InteropVariableName() #><#= (isLastArg) ? "" : "," #> <# } #> ); diff --git a/src/Qir/Execution/Tools/Driver/QirCppDriverEx.cs b/src/Qir/Execution/Tools/Driver/QirCppDriverEx.cs index 5ac19200871..7c05fba2b3e 100644 --- a/src/Qir/Execution/Tools/Driver/QirCppDriverEx.cs +++ b/src/Qir/Execution/Tools/Driver/QirCppDriverEx.cs @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; +using Microsoft.Quantum.QsCompiler.BondSchemas.Execution; namespace Microsoft.Quantum.Qir.Tools.Driver { diff --git a/src/Qir/Execution/Tools/Driver/QirCppDriverGenerator.cs b/src/Qir/Execution/Tools/Driver/QirCppDriverGenerator.cs index da83765a67e..dbe25138048 100644 --- a/src/Qir/Execution/Tools/Driver/QirCppDriverGenerator.cs +++ b/src/Qir/Execution/Tools/Driver/QirCppDriverGenerator.cs @@ -5,7 +5,7 @@ using System.IO; using System.Text; using System.Threading.Tasks; -using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; +using Microsoft.Quantum.QsCompiler.BondSchemas.Execution; namespace Microsoft.Quantum.Qir.Tools.Driver { @@ -27,6 +27,6 @@ public async Task GenerateAsync(EntryPointOperation entryPointOperation, Stream stream.Position = 0; } - public string GetCommandLineArguments(EntryPointOperation entryPoint) => throw new NotImplementedException(); + public string GetCommandLineArguments(ExecutionInformation executionInformation) => throw new NotImplementedException(); } } diff --git a/src/Qir/Execution/Tools/Driver/QirCppInterop.cs b/src/Qir/Execution/Tools/Driver/QirCppInterop.cs index ee9cdf448eb..472cbf47727 100644 --- a/src/Qir/Execution/Tools/Driver/QirCppInterop.cs +++ b/src/Qir/Execution/Tools/Driver/QirCppInterop.cs @@ -4,7 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; -using Microsoft.Quantum.QsCompiler.BondSchemas.EntryPoint; +using Microsoft.Quantum.QsCompiler.BondSchemas.Execution; #nullable enable @@ -85,51 +85,51 @@ public static string InteropType(DataType? dataType) => internal static class ArgumentCppExtensions { - public static string CliOptionDescription(this Argument @this) => + public static string CliOptionDescription(this Parameter @this) => $"Option to provide a value for the {@this.Name} parameter"; - public static string CliOptionName(this Argument @this) + public static string CliOptionName(this Parameter @this) { if (String.IsNullOrEmpty(@this.Name)) { - throw new InvalidOperationException($"Invalid argument name '{@this.Name}'"); + throw new InvalidOperationException($"Invalid parameter name '{@this.Name}'"); } return @this.Name.Length == 1 ? $"-{@this.Name}" : $"--{@this.Name}"; } - public static string? CliOptionTransformerMapName(this Argument @this) => + public static string? CliOptionTransformerMapName(this Parameter @this) => @this.Type switch { DataType.ArrayType => QirCppInterop.CliOptionTransformerMapName(@this.ArrayType), _ => QirCppInterop.CliOptionTransformerMapName(@this.Type) }; - public static string CliOptionType(this Argument @this) => + public static string CliOptionType(this Parameter @this) => @this.Type switch { DataType.ArrayType => $"vector<{QirCppInterop.CliOptionType(@this.ArrayType)}>", _ => QirCppInterop.CliOptionType(@this.Type) }; - public static string CliOptionVariableName(this Argument @this) => $"{@this.Name}Cli"; + public static string CliOptionVariableName(this Parameter @this) => $"{@this.Name}Cli"; - public static string? CliOptionVariableDefaultValue(this Argument @this) => + public static string? CliOptionVariableDefaultValue(this Parameter @this) => QirCppInterop.CliOptionVariableDefaultValue(@this.Type); - public static string IntermediateVariableName(this Argument @this) => $"{@this.Name}Intermediate"; + public static string IntermediateVariableName(this Parameter @this) => $"{@this.Name}Intermediate"; - public static string InteropVariableName(this Argument @this) => $"{@this.Name}Interop"; + public static string InteropVariableName(this Parameter @this) => $"{@this.Name}Interop"; - public static string InteropType(this Argument @this) => QirCppInterop.InteropType(@this.Type); + public static string InteropType(this Parameter @this) => QirCppInterop.InteropType(@this.Type); } internal static class EntryPointOperationCppExtension { public static bool ContainsArgumentType(this EntryPointOperation @this, DataType type) => - @this.Arguments.Where(arg => arg.Type == type).Any(); + @this.Parameters.Where(arg => arg.Type == type).Any(); public static bool ContainsArrayType(this EntryPointOperation @this, DataType type) => - @this.Arguments.Where(arg => arg.ArrayType == type).Any(); + @this.Parameters.Where(arg => arg.ArrayType == type).Any(); } } diff --git a/src/Qir/Execution/Tools/Driver/QirFullStateDriverGenerator.cs b/src/Qir/Execution/Tools/Driver/QirFullStateDriverGenerator.cs index 3d2b77f29ee..8f98b4a80f9 100644 --- a/src/Qir/Execution/Tools/Driver/QirFullStateDriverGenerator.cs +++ b/src/Qir/Execution/Tools/Driver/QirFullStateDriverGenerator.cs @@ -19,7 +19,7 @@ public QirFullStateDriverGenerator() public async Task GenerateAsync(EntryPointOperation entryPoint, Stream stream) => await DriverGenerator.GenerateAsync(entryPoint, stream); - public string GetCommandLineArguments(EntryPointOperation entryPoint) => - DriverGenerator.GetCommandLineArguments(entryPoint); + public string GetCommandLineArguments(ExecutionInformation executionInformation) => + DriverGenerator.GetCommandLineArguments(executionInformation); } } From ebd12595f1cc7050c86f9f155ddfa2354e5556e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Fri, 30 Apr 2021 10:09:02 -0700 Subject: [PATCH 11/15] Moved implementation for GetCommandLineArguments. --- .../Tools/Driver/QirCppDriverGenerator.cs | 126 +++++++++++++++++- 1 file changed, 125 insertions(+), 1 deletion(-) diff --git a/src/Qir/Execution/Tools/Driver/QirCppDriverGenerator.cs b/src/Qir/Execution/Tools/Driver/QirCppDriverGenerator.cs index dbe25138048..a9a8233464b 100644 --- a/src/Qir/Execution/Tools/Driver/QirCppDriverGenerator.cs +++ b/src/Qir/Execution/Tools/Driver/QirCppDriverGenerator.cs @@ -2,7 +2,9 @@ // Licensed under the MIT License. using System; +using System.Collections.Generic; using System.IO; +using System.Linq; using System.Text; using System.Threading.Tasks; using Microsoft.Quantum.QsCompiler.BondSchemas.Execution; @@ -13,6 +15,8 @@ public class QirCppDriverGenerator : IQirDriverGenerator { private readonly IQirSimulatorInitializer SimulatorInitalizer; + private delegate string StringConversion(ArgumentValue value); + public QirCppDriverGenerator(IQirSimulatorInitializer simulatorInitializer) { SimulatorInitalizer = simulatorInitializer; @@ -27,6 +31,126 @@ public async Task GenerateAsync(EntryPointOperation entryPointOperation, Stream stream.Position = 0; } - public string GetCommandLineArguments(ExecutionInformation executionInformation) => throw new NotImplementedException(); + public string GetCommandLineArguments(ExecutionInformation executionInformation) + { + // Sort arguments by position. + var sortedArguments = executionInformation.EntryPoint.Parameters.OrderBy(arg => arg.Position); + var argumentBuilder = new StringBuilder(); + foreach (var arg in sortedArguments) + { + if (argumentBuilder.Length != 0) + { + argumentBuilder.Append(' '); + } + + argumentBuilder.Append($"--{arg.Name}").Append(' ').Append(GetArgumentValueString(arg, executionInformation.ArgumentValues[arg.Name])); + } + + return argumentBuilder.ToString(); + } + + private static string GetArgumentValueString(Parameter argument, ArgumentValue argumentValue) + { + // Today, only the first argument value in the array will be used. + return argument.Type switch + { + DataType.BoolType => GetBoolValueString(argumentValue), + DataType.DoubleType => GetDoubleValueString(argumentValue), + DataType.IntegerType => GetIntegerValueString(argumentValue), + DataType.PauliType => GetPauliValueString(argumentValue), + DataType.RangeType => GetRangeValueString(argumentValue), + DataType.ResultType => GetResultValueString(argumentValue), + DataType.StringType => GetStringValueString(argumentValue), + DataType.ArrayType => GetArrayValueString(argument.ArrayType, argumentValue.Array), + _ => throw new ArgumentException($"Unsupported data type {argument.Type}") + }; + } + + private static string GetArrayValueString(DataType? arrayType, IList arrayValue) + { + static string ConvertArray(IList list, StringConversion conversion) => + string.Join(' ', list.Select(item => conversion.Invoke(item))); + + return arrayType switch + { + DataType.BoolType => ConvertArray(arrayValue, GetBoolValueString), + DataType.DoubleType => ConvertArray(arrayValue, GetDoubleValueString), + DataType.IntegerType => ConvertArray(arrayValue, GetIntegerValueString), + DataType.PauliType => ConvertArray(arrayValue, GetPauliValueString), + DataType.RangeType => ConvertArray(arrayValue, GetRangeValueString), + DataType.ResultType => ConvertArray(arrayValue, GetResultValueString), + DataType.StringType => ConvertArray(arrayValue, GetStringValueString), + _ => throw new ArgumentException($"Unsupported array data type {arrayType}") + }; + } + + private static string GetResultValueString(ArgumentValue value) + { + if (value?.Result == null) + { + throw new ArgumentNullException("Cannot convert null result value to string."); + } + return value.Result == ResultValue.One ? "1" : "0"; + } + + private static string GetRangeValueString(ArgumentValue value) + { + if (value?.Range == null) + { + throw new ArgumentNullException("Cannot convert null range value to string."); + } + var rangeValue = value.Range; + return $"{rangeValue.Start} {rangeValue.Step} {rangeValue.End}"; + } + + private static string GetStringValueString(ArgumentValue value) + { + if (value?.String == null) + { + throw new ArgumentNullException("Cannot convert null string value to string."); + } + + return $"\"{value.String}\""; + } + + private static string GetBoolValueString(ArgumentValue value) + { + if (value?.Bool == null) + { + throw new ArgumentNullException("Cannot convert null bool value to string."); + } + + return value.Bool.ToString().ToLower(); + } + + private static string GetPauliValueString(ArgumentValue value) + { + if (value?.Pauli == null) + { + throw new ArgumentNullException("Cannot convert null pauli value to string."); + } + + return value.Pauli.ToString().ToLower(); + } + + private static string GetDoubleValueString(ArgumentValue value) + { + if (value?.Double == null) + { + throw new ArgumentNullException("Cannot convert null double value to string."); + } + + return value.Double.ToString().ToLower(); + } + + private static string GetIntegerValueString(ArgumentValue value) + { + if (value?.Integer == null) + { + throw new ArgumentNullException("Cannot convert null integer value to string."); + } + + return value.Integer.ToString().ToLower(); + } } } From 7bee591a8c143e650f4de81aa40cde8bbc03c896 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Fri, 30 Apr 2021 10:34:06 -0700 Subject: [PATCH 12/15] Add test cases. --- .../QirDriverGeneratorTests.cs | 11 +- .../FullStateDriverGenerator/UseBoolArg.cpp | 87 +++++++++++ .../UseBoolArrayArg.cpp | 110 ++++++++++++++ .../FullStateDriverGenerator/UseDoubleArg.cpp | 76 ++++++++++ .../UseDoubleArrayArg.cpp | 101 +++++++++++++ .../UseIntegerArg.cpp | 76 ++++++++++ .../UseIntegerArrayArg.cpp | 101 +++++++++++++ .../FullStateDriverGenerator/UseMiscArgs.cpp | 88 +++++++++++ .../FullStateDriverGenerator/UsePauliArg.cpp | 90 +++++++++++ .../UsePauliArrayArg.cpp | 115 ++++++++++++++ .../FullStateDriverGenerator/UseRangeArg.cpp | 106 +++++++++++++ .../UseRangeArrayArg.cpp | 140 ++++++++++++++++++ .../FullStateDriverGenerator/UseResultArg.cpp | 2 +- .../UseResultArrayArg.cpp | 111 ++++++++++++++ .../FullStateDriverGenerator/UseStringArg.cpp | 80 ++++++++++ .../Tests.Microsoft.Quantum.Qir.Tools.csproj | 39 +++++ 16 files changed, 1331 insertions(+), 2 deletions(-) create mode 100644 src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseBoolArg.cpp create mode 100644 src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseBoolArrayArg.cpp create mode 100644 src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseDoubleArg.cpp create mode 100644 src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseDoubleArrayArg.cpp create mode 100644 src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseIntegerArg.cpp create mode 100644 src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseIntegerArrayArg.cpp create mode 100644 src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseMiscArgs.cpp create mode 100644 src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UsePauliArg.cpp create mode 100644 src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UsePauliArrayArg.cpp create mode 100644 src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseRangeArg.cpp create mode 100644 src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseRangeArrayArg.cpp create mode 100644 src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArrayArg.cpp create mode 100644 src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseStringArg.cpp diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirDriverGeneratorTests.cs b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirDriverGeneratorTests.cs index 05d67b8dc44..432813d69b0 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirDriverGeneratorTests.cs +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirDriverGeneratorTests.cs @@ -23,6 +23,14 @@ public class QirDriverGeneratorTests "UseNoArgs", new EntryPointOperation{Name = "UseNoArgs"} }, + { + "UseBoolArg", + new EntryPointOperation + { + Name = "UseBoolArg", + Parameters = new List{new Parameter{ Name = "BoolArg", Type = DataType.BoolType}} + } + }, { "UseResultArg", new EntryPointOperation @@ -35,6 +43,7 @@ public class QirDriverGeneratorTests [Theory] [InlineData("UseNoArgs")] + [InlineData("UseBoolArg")] [InlineData("UseResultArg")] public void GenerateFullStateSimulatorDriver(string testCase) { @@ -51,7 +60,7 @@ public void GenerateFullStateSimulatorDriver(string testCase) driverGenerator.GenerateAsync(entryPointOperation, generatedStream).Wait(); var generatedStreamReader = new StreamReader(generatedStream, Encoding.UTF8); var generatedCppSourceCode = generatedStreamReader.ReadToEnd(); - // TODO: Compare strings. + Assert.Equal(verificationCppSourceCode, generatedCppSourceCode); generatedStream.Close(); } diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseBoolArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseBoolArg.cpp new file mode 100644 index 00000000000..501f9a266ae --- /dev/null +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseBoolArg.cpp @@ -0,0 +1,87 @@ +//------------------------------------------------------------------------------ +// This code was generated by a tool. +// +//------------------------------------------------------------------------------ + +#include +#include +#include +#include +#include + +#include "CLI11.hpp" + +#include "QirRuntime.hpp" +#include "QirContext.hpp" + +#include "SimFactory.hpp" + +using namespace Microsoft::Quantum; +using namespace std; + +// Auxiliary functions for interop with Q# Bool type. +const char InteropFalseAsChar = 0x0; +const char InteropTrueAsChar = 0x1; +map BoolAsCharMap{ + {"0", InteropFalseAsChar}, + {"false", InteropFalseAsChar}, + {"1", InteropTrueAsChar}, + {"true", InteropTrueAsChar} +}; + +extern "C" void UseBoolArg( + char BoolArg +); // QIR interop function. + +int main(int argc, char* argv[]) +{ + CLI::App app("QIR Standalone Entry Point"); + + // Initialize simulator. + unique_ptr sim = CreateFullstateSimulator(); + QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); + + // Add the --simulation-output option. + string simulationOutputFile; + CLI::Option* simulationOutputFileOpt = app.add_option( + "--simulation-output", + simulationOutputFile, + "File where the output produced during the simulation is written"); + + // Add a command line option for each entry-point parameter. + char BoolArgCli; + BoolArgCli = InteropFalseAsChar; + app.add_option("--BoolArg", BoolArgCli, "Option to provide a value for the BoolArg parameter") + ->required() + ->transform(CLI::CheckedTransformer(BoolAsCharMap, CLI::ignore_case)); + + // After all the options have been added, parse arguments from the command line. + CLI11_PARSE(app, argc, argv); + + // Cast parsed arguments to its interop types. + char BoolArgInterop = BoolArgCli; + + // Redirect the simulator output from std::cout if the --simulation-output option is present. + ostream* simulatorOutputStream = &cout; + ofstream simulationOutputFileStream; + if (!simulationOutputFileOpt->empty()) + { + simulationOutputFileStream.open(simulationOutputFile); + Microsoft::Quantum::OutputStream::Set(simulationOutputFileStream); + simulatorOutputStream = &simulationOutputFileStream; + } + + // Execute the entry point operation. + UseBoolArg( + BoolArgInterop + ); + + // Flush the output of the simulation. + simulatorOutputStream->flush(); + if (simulationOutputFileStream.is_open()) + { + simulationOutputFileStream.close(); + } + + return 0; +} diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseBoolArrayArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseBoolArrayArg.cpp new file mode 100644 index 00000000000..bf7d49b63fe --- /dev/null +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseBoolArrayArg.cpp @@ -0,0 +1,110 @@ +//------------------------------------------------------------------------------ +// This code was generated by a tool. +// +//------------------------------------------------------------------------------ +// +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#include +#include +#include +#include +#include + +#include "CLI11.hpp" + +#include "QirContext.hpp" +#include "QirRuntime.hpp" +#include "SimFactory.hpp" + +using namespace Microsoft::Quantum; +using namespace std; + + +struct InteropArray +{ + int64_t Size; + void* Data; + + InteropArray(int64_t size, void* data) : + Size(size), + Data(data){} +}; + +template +unique_ptr CreateInteropArray(vector& v) +{ + unique_ptr array(new InteropArray(v.size(), v.data())); + return array; +} + +template +void TranslateVector(vector& sourceVector, vector& destinationVector, function translationFunction) +{ + destinationVector.resize(sourceVector.size()); + transform(sourceVector.begin(), sourceVector.end(), destinationVector.begin(), translationFunction); +} + +// This is the function corresponding to the QIR entry-point. +extern "C" void UseBoolArrayArgWithValues( // NOLINT + InteropArray* BoolArrayArgInteropValue +); + + +const char InteropFalseAsChar = 0x0; +const char InteropTrueAsChar = 0x1; +map BoolAsCharMap{ + {"0", InteropFalseAsChar}, + {"false", InteropFalseAsChar}, + {"1", InteropTrueAsChar}, + {"true", InteropTrueAsChar}}; + +int main(int argc, char* argv[]) +{ + CLI::App app("QIR Standalone Entry Point Inputs Reference"); + + // Initialize simulator. + unique_ptr sim = CreateFullstateSimulator(); + QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); + + // Add the --simulation-output options. + // N.B. This option should be present in all standalone drivers. + string simulationOutputFile; + CLI::Option* simulationOutputFileOpt = app.add_option( + "--simulation-output", simulationOutputFile, + "File where the output produced during the simulation is written"); + + vector BoolArrayArgCliValue; + app.add_option("--BoolArrayArg", BoolArrayArgCliValue, "A bool array value for the BoolArrayArg argument")->required() + ->transform(CLI::CheckedTransformer(BoolAsCharMap, CLI::ignore_case)); + + // With all the options added, parse arguments from the command line. + CLI11_PARSE(app, argc, argv); + + // Translate values to its final form after parsing. + // Create an interop array of values. + unique_ptr BoolArrayArgInteropValue = CreateInteropArray(BoolArrayArgCliValue); + + // Redirect the simulator output from std::cout if the --simulation-output option is present. + ostream* simulatorOutputStream = &cout; + ofstream simulationOutputFileStream; + if (!simulationOutputFileOpt->empty()) + { + simulationOutputFileStream.open(simulationOutputFile); + SetOutputStream(simulationOutputFileStream); + simulatorOutputStream = &simulationOutputFileStream; + } + + // Run simulation and write the output of the operation to the corresponding stream. + UseBoolArrayArgWithValues( + BoolArrayArgInteropValue.get() + ); + + + simulatorOutputStream->flush(); + if (simulationOutputFileStream.is_open()) + { + simulationOutputFileStream.close(); + } +} diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseDoubleArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseDoubleArg.cpp new file mode 100644 index 00000000000..de3249a5eab --- /dev/null +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseDoubleArg.cpp @@ -0,0 +1,76 @@ +//------------------------------------------------------------------------------ +// This code was generated by a tool. +// +//------------------------------------------------------------------------------ +// +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#include +#include +#include +#include +#include + +#include "CLI11.hpp" + +#include "QirContext.hpp" +#include "QirRuntime.hpp" +#include "SimFactory.hpp" + +using namespace Microsoft::Quantum; +using namespace std; + + +// This is the function corresponding to the QIR entry-point. +extern "C" void UseDoubleArgWithValues( // NOLINT + double DoubleArgInteropValue +); + + +int main(int argc, char* argv[]) +{ + CLI::App app("QIR Standalone Entry Point Inputs Reference"); + + // Initialize simulator. + unique_ptr sim = CreateFullstateSimulator(); + QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); + + // Add the --simulation-output options. + // N.B. This option should be present in all standalone drivers. + string simulationOutputFile; + CLI::Option* simulationOutputFileOpt = app.add_option( + "--simulation-output", simulationOutputFile, + "File where the output produced during the simulation is written"); + + double_t DoubleArgCliValue; + DoubleArgCliValue = 0.0; + app.add_option("--DoubleArg", DoubleArgCliValue, "A double value for the DoubleArg argument")->required(); + + // With all the options added, parse arguments from the command line. + CLI11_PARSE(app, argc, argv); + + double_t DoubleArgInteropValue = DoubleArgCliValue; + + // Redirect the simulator output from std::cout if the --simulation-output option is present. + ostream* simulatorOutputStream = &cout; + ofstream simulationOutputFileStream; + if (!simulationOutputFileOpt->empty()) + { + simulationOutputFileStream.open(simulationOutputFile); + SetOutputStream(simulationOutputFileStream); + simulatorOutputStream = &simulationOutputFileStream; + } + + // Run simulation and write the output of the operation to the corresponding stream. + UseDoubleArgWithValues( + DoubleArgInteropValue + ); + + + simulatorOutputStream->flush(); + if (simulationOutputFileStream.is_open()) + { + simulationOutputFileStream.close(); + } +} diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseDoubleArrayArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseDoubleArrayArg.cpp new file mode 100644 index 00000000000..892a379d732 --- /dev/null +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseDoubleArrayArg.cpp @@ -0,0 +1,101 @@ +//------------------------------------------------------------------------------ +// This code was generated by a tool. +// +//------------------------------------------------------------------------------ +// +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#include +#include +#include +#include +#include + +#include "CLI11.hpp" + +#include "QirContext.hpp" +#include "QirRuntime.hpp" +#include "SimFactory.hpp" + +using namespace Microsoft::Quantum; +using namespace std; + + +struct InteropArray +{ + int64_t Size; + void* Data; + + InteropArray(int64_t size, void* data) : + Size(size), + Data(data){} +}; + +template +unique_ptr CreateInteropArray(vector& v) +{ + unique_ptr array(new InteropArray(v.size(), v.data())); + return array; +} + +template +void TranslateVector(vector& sourceVector, vector& destinationVector, function translationFunction) +{ + destinationVector.resize(sourceVector.size()); + transform(sourceVector.begin(), sourceVector.end(), destinationVector.begin(), translationFunction); +} + +// This is the function corresponding to the QIR entry-point. +extern "C" void UseDoubleArrayArgWithValues( // NOLINT + InteropArray* DoubleArrayArgInteropValue +); + + +int main(int argc, char* argv[]) +{ + CLI::App app("QIR Standalone Entry Point Inputs Reference"); + + // Initialize simulator. + unique_ptr sim = CreateFullstateSimulator(); + QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); + + // Add the --simulation-output options. + // N.B. This option should be present in all standalone drivers. + string simulationOutputFile; + CLI::Option* simulationOutputFileOpt = app.add_option( + "--simulation-output", simulationOutputFile, + "File where the output produced during the simulation is written"); + + vector DoubleArrayArgCliValue; + app.add_option("--DoubleArrayArg", DoubleArrayArgCliValue, "A double array value for the DoubleArrayArg argument")->required(); + + // With all the options added, parse arguments from the command line. + CLI11_PARSE(app, argc, argv); + + // Translate values to its final form after parsing. + // Create an interop array of values. + unique_ptr DoubleArrayArgInteropValue = CreateInteropArray(DoubleArrayArgCliValue); + + // Redirect the simulator output from std::cout if the --simulation-output option is present. + ostream* simulatorOutputStream = &cout; + ofstream simulationOutputFileStream; + if (!simulationOutputFileOpt->empty()) + { + simulationOutputFileStream.open(simulationOutputFile); + SetOutputStream(simulationOutputFileStream); + simulatorOutputStream = &simulationOutputFileStream; + } + + // Run simulation and write the output of the operation to the corresponding stream. + UseDoubleArrayArgWithValues( + DoubleArrayArgInteropValue.get() + ); + + + simulatorOutputStream->flush(); + if (simulationOutputFileStream.is_open()) + { + simulationOutputFileStream.close(); + } +} diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseIntegerArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseIntegerArg.cpp new file mode 100644 index 00000000000..cfec6a208a5 --- /dev/null +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseIntegerArg.cpp @@ -0,0 +1,76 @@ +//------------------------------------------------------------------------------ +// This code was generated by a tool. +// +//------------------------------------------------------------------------------ +// +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#include +#include +#include +#include +#include + +#include "CLI11.hpp" + +#include "QirContext.hpp" +#include "QirRuntime.hpp" +#include "SimFactory.hpp" + +using namespace Microsoft::Quantum; +using namespace std; + + +// This is the function corresponding to the QIR entry-point. +extern "C" void UseIntegerArgWithValues( // NOLINT + int64_t IntegerArgInteropValue +); + + +int main(int argc, char* argv[]) +{ + CLI::App app("QIR Standalone Entry Point Inputs Reference"); + + // Initialize simulator. + unique_ptr sim = CreateFullstateSimulator(); + QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); + + // Add the --simulation-output options. + // N.B. This option should be present in all standalone drivers. + string simulationOutputFile; + CLI::Option* simulationOutputFileOpt = app.add_option( + "--simulation-output", simulationOutputFile, + "File where the output produced during the simulation is written"); + + int64_t IntegerArgCliValue; + IntegerArgCliValue = 0; + app.add_option("--IntegerArg", IntegerArgCliValue, "A integer value for the IntegerArg argument")->required(); + + // With all the options added, parse arguments from the command line. + CLI11_PARSE(app, argc, argv); + + int64_t IntegerArgInteropValue = IntegerArgCliValue; + + // Redirect the simulator output from std::cout if the --simulation-output option is present. + ostream* simulatorOutputStream = &cout; + ofstream simulationOutputFileStream; + if (!simulationOutputFileOpt->empty()) + { + simulationOutputFileStream.open(simulationOutputFile); + SetOutputStream(simulationOutputFileStream); + simulatorOutputStream = &simulationOutputFileStream; + } + + // Run simulation and write the output of the operation to the corresponding stream. + UseIntegerArgWithValues( + IntegerArgInteropValue + ); + + + simulatorOutputStream->flush(); + if (simulationOutputFileStream.is_open()) + { + simulationOutputFileStream.close(); + } +} diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseIntegerArrayArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseIntegerArrayArg.cpp new file mode 100644 index 00000000000..41c5c808226 --- /dev/null +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseIntegerArrayArg.cpp @@ -0,0 +1,101 @@ +//------------------------------------------------------------------------------ +// This code was generated by a tool. +// +//------------------------------------------------------------------------------ +// +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#include +#include +#include +#include +#include + +#include "CLI11.hpp" + +#include "QirContext.hpp" +#include "QirRuntime.hpp" +#include "SimFactory.hpp" + +using namespace Microsoft::Quantum; +using namespace std; + + +struct InteropArray +{ + int64_t Size; + void* Data; + + InteropArray(int64_t size, void* data) : + Size(size), + Data(data){} +}; + +template +unique_ptr CreateInteropArray(vector& v) +{ + unique_ptr array(new InteropArray(v.size(), v.data())); + return array; +} + +template +void TranslateVector(vector& sourceVector, vector& destinationVector, function translationFunction) +{ + destinationVector.resize(sourceVector.size()); + transform(sourceVector.begin(), sourceVector.end(), destinationVector.begin(), translationFunction); +} + +// This is the function corresponding to the QIR entry-point. +extern "C" void UseIntegerArrayArgWithValues( // NOLINT + InteropArray* IntegerArrayArgInteropValue +); + + +int main(int argc, char* argv[]) +{ + CLI::App app("QIR Standalone Entry Point Inputs Reference"); + + // Initialize simulator. + unique_ptr sim = CreateFullstateSimulator(); + QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); + + // Add the --simulation-output options. + // N.B. This option should be present in all standalone drivers. + string simulationOutputFile; + CLI::Option* simulationOutputFileOpt = app.add_option( + "--simulation-output", simulationOutputFile, + "File where the output produced during the simulation is written"); + + vector IntegerArrayArgCliValue; + app.add_option("--IntegerArrayArg", IntegerArrayArgCliValue, "A integer array value for the IntegerArrayArg argument")->required(); + + // With all the options added, parse arguments from the command line. + CLI11_PARSE(app, argc, argv); + + // Translate values to its final form after parsing. + // Create an interop array of values. + unique_ptr IntegerArrayArgInteropValue = CreateInteropArray(IntegerArrayArgCliValue); + + // Redirect the simulator output from std::cout if the --simulation-output option is present. + ostream* simulatorOutputStream = &cout; + ofstream simulationOutputFileStream; + if (!simulationOutputFileOpt->empty()) + { + simulationOutputFileStream.open(simulationOutputFile); + SetOutputStream(simulationOutputFileStream); + simulatorOutputStream = &simulationOutputFileStream; + } + + // Run simulation and write the output of the operation to the corresponding stream. + UseIntegerArrayArgWithValues( + IntegerArrayArgInteropValue.get() + ); + + + simulatorOutputStream->flush(); + if (simulationOutputFileStream.is_open()) + { + simulationOutputFileStream.close(); + } +} diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseMiscArgs.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseMiscArgs.cpp new file mode 100644 index 00000000000..bdb3c09cdf9 --- /dev/null +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseMiscArgs.cpp @@ -0,0 +1,88 @@ +//------------------------------------------------------------------------------ +// This code was generated by a tool. +// +//------------------------------------------------------------------------------ +// +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#include +#include +#include +#include +#include + +#include "CLI11.hpp" + +#include "QirContext.hpp" +#include "QirRuntime.hpp" +#include "SimFactory.hpp" + +using namespace Microsoft::Quantum; +using namespace std; + + +// This is the function corresponding to the QIR entry-point. +extern "C" void UseMiscArgs( // NOLINT + int64_t IntegerArgInteropValue, + const char* StringArgInteropValue +); + + + +const char* TranslateStringToCharBuffer(string& s) +{ + return s.c_str(); +} +int main(int argc, char* argv[]) +{ + CLI::App app("QIR Standalone Entry Point Inputs Reference"); + + // Initialize simulator. + unique_ptr sim = CreateFullstateSimulator(); + QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); + + // Add the --simulation-output options. + // N.B. This option should be present in all standalone drivers. + string simulationOutputFile; + CLI::Option* simulationOutputFileOpt = app.add_option( + "--simulation-output", simulationOutputFile, + "File where the output produced during the simulation is written"); + + int64_t IntegerArgCliValue; + IntegerArgCliValue = 0; + app.add_option("--IntegerArg", IntegerArgCliValue, "A integer value for the IntegerArg argument")->required(); + + string StringArgCliValue; + app.add_option("--StringArg", StringArgCliValue, "A String value for the StringArg argument")->required(); + + // With all the options added, parse arguments from the command line. + CLI11_PARSE(app, argc, argv); + + int64_t IntegerArgInteropValue = IntegerArgCliValue; + + string StringArgInteropValue = StringArgCliValue; + + // Redirect the simulator output from std::cout if the --simulation-output option is present. + ostream* simulatorOutputStream = &cout; + ofstream simulationOutputFileStream; + if (!simulationOutputFileOpt->empty()) + { + simulationOutputFileStream.open(simulationOutputFile); + SetOutputStream(simulationOutputFileStream); + simulatorOutputStream = &simulationOutputFileStream; + } + + // Run simulation and write the output of the operation to the corresponding stream. + UseMiscArgs( + IntegerArgInteropValue, + StringArgInteropValue.c_str() + ); + + + simulatorOutputStream->flush(); + if (simulationOutputFileStream.is_open()) + { + simulationOutputFileStream.close(); + } +} diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UsePauliArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UsePauliArg.cpp new file mode 100644 index 00000000000..4b7aa9f256e --- /dev/null +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UsePauliArg.cpp @@ -0,0 +1,90 @@ +//------------------------------------------------------------------------------ +// This code was generated by a tool. +// +//------------------------------------------------------------------------------ +// +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#include +#include +#include +#include +#include + +#include "CLI11.hpp" + +#include "QirContext.hpp" +#include "QirRuntime.hpp" +#include "SimFactory.hpp" + +using namespace Microsoft::Quantum; +using namespace std; + + +// This is the function corresponding to the QIR entry-point. +extern "C" void UsePauliArgWithValues( // NOLINT + char PauliArgInteropValue +); + + +map PauliMap{ + {"PauliI", PauliId::PauliId_I}, + {"PauliX", PauliId::PauliId_X}, + {"PauliY", PauliId::PauliId_Y}, + {"PauliZ", PauliId::PauliId_Z}}; + + +char TranslatePauliToChar(PauliId& pauli) +{ + return static_cast(pauli); +} + +int main(int argc, char* argv[]) +{ + CLI::App app("QIR Standalone Entry Point Inputs Reference"); + + // Initialize simulator. + unique_ptr sim = CreateFullstateSimulator(); + QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); + + // Add the --simulation-output options. + // N.B. This option should be present in all standalone drivers. + string simulationOutputFile; + CLI::Option* simulationOutputFileOpt = app.add_option( + "--simulation-output", simulationOutputFile, + "File where the output produced during the simulation is written"); + + PauliId PauliArgCliValue; + PauliArgCliValue = PauliId::PauliId_I; + app.add_option("--PauliArg", PauliArgCliValue, "A Pauli value for the PauliArg argument")->required() + ->transform(CLI::CheckedTransformer(PauliMap, CLI::ignore_case)); + + // With all the options added, parse arguments from the command line. + CLI11_PARSE(app, argc, argv); + + // Translate a PauliID value to its char representation. + char PauliArgInteropValue = TranslatePauliToChar(PauliArgCliValue); + + // Redirect the simulator output from std::cout if the --simulation-output option is present. + ostream* simulatorOutputStream = &cout; + ofstream simulationOutputFileStream; + if (!simulationOutputFileOpt->empty()) + { + simulationOutputFileStream.open(simulationOutputFile); + SetOutputStream(simulationOutputFileStream); + simulatorOutputStream = &simulationOutputFileStream; + } + + // Run simulation and write the output of the operation to the corresponding stream. + UsePauliArgWithValues( + PauliArgInteropValue + ); + + + simulatorOutputStream->flush(); + if (simulationOutputFileStream.is_open()) + { + simulationOutputFileStream.close(); + } +} diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UsePauliArrayArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UsePauliArrayArg.cpp new file mode 100644 index 00000000000..e03a11beb57 --- /dev/null +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UsePauliArrayArg.cpp @@ -0,0 +1,115 @@ +//------------------------------------------------------------------------------ +// This code was generated by a tool. +// +//------------------------------------------------------------------------------ +// +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#include +#include +#include +#include +#include + +#include "CLI11.hpp" + +#include "QirContext.hpp" +#include "QirRuntime.hpp" +#include "SimFactory.hpp" + +using namespace Microsoft::Quantum; +using namespace std; + + +struct InteropArray +{ + int64_t Size; + void* Data; + + InteropArray(int64_t size, void* data) : + Size(size), + Data(data){} +}; + +template +unique_ptr CreateInteropArray(vector& v) +{ + unique_ptr array(new InteropArray(v.size(), v.data())); + return array; +} + +template +void TranslateVector(vector& sourceVector, vector& destinationVector, function translationFunction) +{ + destinationVector.resize(sourceVector.size()); + transform(sourceVector.begin(), sourceVector.end(), destinationVector.begin(), translationFunction); +} + +// This is the function corresponding to the QIR entry-point. +extern "C" void UsePauliArrayArgWithValues( // NOLINT + InteropArray* PauliArrayArgInteropValue +); + + +map PauliMap{ + {"PauliI", PauliId::PauliId_I}, + {"PauliX", PauliId::PauliId_X}, + {"PauliY", PauliId::PauliId_Y}, + {"PauliZ", PauliId::PauliId_Z}}; + + +char TranslatePauliToChar(PauliId& pauli) +{ + return static_cast(pauli); +} + +int main(int argc, char* argv[]) +{ + CLI::App app("QIR Standalone Entry Point Inputs Reference"); + + // Initialize simulator. + unique_ptr sim = CreateFullstateSimulator(); + QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); + + // Add the --simulation-output options. + // N.B. This option should be present in all standalone drivers. + string simulationOutputFile; + CLI::Option* simulationOutputFileOpt = app.add_option( + "--simulation-output", simulationOutputFile, + "File where the output produced during the simulation is written"); + + std::vector PauliArrayArgCliValue; + app.add_option("--PauliArrayArg", PauliArrayArgCliValue, "A Pauli array value for the PauliArrayArg argument")->required() + ->transform(CLI::CheckedTransformer(PauliMap, CLI::ignore_case)); + + // With all the options added, parse arguments from the command line. + CLI11_PARSE(app, argc, argv); + + // Create an interop array of Pauli values represented as chars. + vector PauliArrayArgIntermediateValue; + TranslateVector(PauliArrayArgCliValue, PauliArrayArgIntermediateValue, TranslatePauliToChar); + unique_ptr PauliArrayArgInteropValue = CreateInteropArray(PauliArrayArgIntermediateValue); + + // Redirect the simulator output from std::cout if the --simulation-output option is present. + ostream* simulatorOutputStream = &cout; + ofstream simulationOutputFileStream; + if (!simulationOutputFileOpt->empty()) + { + simulationOutputFileStream.open(simulationOutputFile); + SetOutputStream(simulationOutputFileStream); + simulatorOutputStream = &simulationOutputFileStream; + } + + // Run simulation and write the output of the operation to the corresponding stream. + UsePauliArrayArgWithValues( + PauliArrayArgInteropValue.get() + ); + + + simulatorOutputStream->flush(); + if (simulationOutputFileStream.is_open()) + { + simulationOutputFileStream.close(); + } +} diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseRangeArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseRangeArg.cpp new file mode 100644 index 00000000000..0481d1ab14a --- /dev/null +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseRangeArg.cpp @@ -0,0 +1,106 @@ +//------------------------------------------------------------------------------ +// This code was generated by a tool. +// +//------------------------------------------------------------------------------ +// +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#include +#include +#include +#include +#include + +#include "CLI11.hpp" + +#include "QirContext.hpp" +#include "QirRuntime.hpp" +#include "SimFactory.hpp" + +using namespace Microsoft::Quantum; +using namespace std; + + +using RangeTuple = tuple; +struct InteropRange +{ + int64_t Start; + int64_t Step; + int64_t End; + + InteropRange() : + Start(0), + Step(0), + End(0){} + + InteropRange(RangeTuple rangeTuple) : + Start(get<0>(rangeTuple)), + Step(get<1>(rangeTuple)), + End(get<2>(rangeTuple)){} +}; + +unique_ptr CreateInteropRange(RangeTuple rangeTuple) +{ + unique_ptr range(new InteropRange(rangeTuple)); + return range; +} + +InteropRange* TranslateRangeTupleToInteropRangePointer(RangeTuple& rangeTuple) +{ + InteropRange* range = new InteropRange(rangeTuple); + return range; +} + +// This is the function corresponding to the QIR entry-point. +extern "C" void UseRangeArgWithValues( // NOLINT + InteropRange* RangeArgInteropValue +); + + +int main(int argc, char* argv[]) +{ + CLI::App app("QIR Standalone Entry Point Inputs Reference"); + + // Initialize simulator. + unique_ptr sim = CreateFullstateSimulator(); + QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); + + // Add the --simulation-output options. + // N.B. This option should be present in all standalone drivers. + string simulationOutputFile; + CLI::Option* simulationOutputFileOpt = app.add_option( + "--simulation-output", simulationOutputFile, + "File where the output produced during the simulation is written"); + + RangeTuple RangeArgCliValue; + app.add_option("--RangeArg", RangeArgCliValue, "A Range (start, step, end) value for the RangeArg argument")->required(); + + // With all the options added, parse arguments from the command line. + CLI11_PARSE(app, argc, argv); + + // Create an interop range. + unique_ptr RangeArgInteropValue = CreateInteropRange(RangeArgCliValue); + + // Redirect the simulator output from std::cout if the --simulation-output option is present. + ostream* simulatorOutputStream = &cout; + ofstream simulationOutputFileStream; + if (!simulationOutputFileOpt->empty()) + { + simulationOutputFileStream.open(simulationOutputFile); + SetOutputStream(simulationOutputFileStream); + simulatorOutputStream = &simulationOutputFileStream; + } + + // Run simulation and write the output of the operation to the corresponding stream. + UseRangeArgWithValues( + RangeArgInteropValue.get() + ); + + + simulatorOutputStream->flush(); + if (simulationOutputFileStream.is_open()) + { + simulationOutputFileStream.close(); + } +} diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseRangeArrayArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseRangeArrayArg.cpp new file mode 100644 index 00000000000..fd94f3bad50 --- /dev/null +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseRangeArrayArg.cpp @@ -0,0 +1,140 @@ +//------------------------------------------------------------------------------ +// This code was generated by a tool. +// +//------------------------------------------------------------------------------ +// +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#include +#include +#include +#include +#include + +#include "CLI11.hpp" + +#include "QirContext.hpp" +#include "QirRuntime.hpp" +#include "SimFactory.hpp" + +using namespace Microsoft::Quantum; +using namespace std; + + +struct InteropArray +{ + int64_t Size; + void* Data; + + InteropArray(int64_t size, void* data) : + Size(size), + Data(data){} +}; + +template +unique_ptr CreateInteropArray(vector& v) +{ + unique_ptr array(new InteropArray(v.size(), v.data())); + return array; +} + +template +void TranslateVector(vector& sourceVector, vector& destinationVector, function translationFunction) +{ + destinationVector.resize(sourceVector.size()); + transform(sourceVector.begin(), sourceVector.end(), destinationVector.begin(), translationFunction); +} + +using RangeTuple = tuple; +struct InteropRange +{ + int64_t Start; + int64_t Step; + int64_t End; + + InteropRange() : + Start(0), + Step(0), + End(0){} + + InteropRange(RangeTuple rangeTuple) : + Start(get<0>(rangeTuple)), + Step(get<1>(rangeTuple)), + End(get<2>(rangeTuple)){} +}; + +unique_ptr CreateInteropRange(RangeTuple rangeTuple) +{ + unique_ptr range(new InteropRange(rangeTuple)); + return range; +} + +InteropRange* TranslateRangeTupleToInteropRangePointer(RangeTuple& rangeTuple) +{ + InteropRange* range = new InteropRange(rangeTuple); + return range; +} + +template +void FreePointerVector(vector& v) +{ + for (auto p : v) + { + delete p; + } +} + +// This is the function corresponding to the QIR entry-point. +extern "C" void UseRangeArrayArgWithValues( // NOLINT + InteropArray* RangeArrayArgInteropValue +); + + +int main(int argc, char* argv[]) +{ + CLI::App app("QIR Standalone Entry Point Inputs Reference"); + + // Initialize simulator. + unique_ptr sim = CreateFullstateSimulator(); + QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); + + // Add the --simulation-output options. + // N.B. This option should be present in all standalone drivers. + string simulationOutputFile; + CLI::Option* simulationOutputFileOpt = app.add_option( + "--simulation-output", simulationOutputFile, + "File where the output produced during the simulation is written"); + + vector RangeArrayArgCliValue; + app.add_option("--RangeArrayArg", RangeArrayArgCliValue, "A Range array value for the RangeArrayArg argument")->required(); + + // With all the options added, parse arguments from the command line. + CLI11_PARSE(app, argc, argv); + + vector RangeArrayArgIntermediateValue; + TranslateVector(RangeArrayArgCliValue, RangeArrayArgIntermediateValue, TranslateRangeTupleToInteropRangePointer); + unique_ptr RangeArrayArgInteropValue = CreateInteropArray(RangeArrayArgIntermediateValue); + + // Redirect the simulator output from std::cout if the --simulation-output option is present. + ostream* simulatorOutputStream = &cout; + ofstream simulationOutputFileStream; + if (!simulationOutputFileOpt->empty()) + { + simulationOutputFileStream.open(simulationOutputFile); + SetOutputStream(simulationOutputFileStream); + simulatorOutputStream = &simulationOutputFileStream; + } + + // Run simulation and write the output of the operation to the corresponding stream. + UseRangeArrayArgWithValues( + RangeArrayArgInteropValue.get() + ); + + + simulatorOutputStream->flush(); + if (simulationOutputFileStream.is_open()) + { + simulationOutputFileStream.close(); + } +} diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArg.cpp index e6aec6d1f5b..800181ede3b 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArg.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArg.cpp @@ -48,7 +48,7 @@ int main(int argc, char* argv[]) simulationOutputFile, "File where the output produced during the simulation is written"); - // Add a command line option for each entry-point argument. + // Add a command line option for each entry-point parameter. char ResultArgCli; ResultArgCli = InteropResultZeroAsChar; app.add_option("--ResultArg", ResultArgCli, "Option to provide a value for the ResultArg parameter") diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArrayArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArrayArg.cpp new file mode 100644 index 00000000000..eb10cb2c3b4 --- /dev/null +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArrayArg.cpp @@ -0,0 +1,111 @@ +//------------------------------------------------------------------------------ +// This code was generated by a tool. +// +//------------------------------------------------------------------------------ +// +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#include +#include +#include +#include +#include + +#include "CLI11.hpp" + +#include "QirContext.hpp" +#include "QirRuntime.hpp" +#include "SimFactory.hpp" + +using namespace Microsoft::Quantum; +using namespace std; + + +struct InteropArray +{ + int64_t Size; + void* Data; + + InteropArray(int64_t size, void* data) : + Size(size), + Data(data){} +}; + +template +unique_ptr CreateInteropArray(vector& v) +{ + unique_ptr array(new InteropArray(v.size(), v.data())); + return array; +} + +template +void TranslateVector(vector& sourceVector, vector& destinationVector, function translationFunction) +{ + destinationVector.resize(sourceVector.size()); + transform(sourceVector.begin(), sourceVector.end(), destinationVector.begin(), translationFunction); +} + +// This is the function corresponding to the QIR entry-point. +extern "C" void UseResultArrayArgWithValues( // NOLINT + InteropArray* ResultArrayArgInteropValue +); + + +const char InteropResultZeroAsChar = 0x0; +const char InteropResultOneAsChar = 0x1; +map ResultAsCharMap{ + {"0", InteropResultZeroAsChar}, + {"Zero", InteropResultZeroAsChar}, + {"1", InteropResultOneAsChar}, + {"One", InteropResultOneAsChar} +}; + +int main(int argc, char* argv[]) +{ + CLI::App app("QIR Standalone Entry Point Inputs Reference"); + + // Initialize simulator. + unique_ptr sim = CreateFullstateSimulator(); + QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); + + // Add the --simulation-output options. + // N.B. This option should be present in all standalone drivers. + string simulationOutputFile; + CLI::Option* simulationOutputFileOpt = app.add_option( + "--simulation-output", simulationOutputFile, + "File where the output produced during the simulation is written"); + + vector ResultArrayArgCliValue; + app.add_option("--ResultArrayArg", ResultArrayArgCliValue, "A Result array value for the ResultArrayArg argument")->required() + ->transform(CLI::CheckedTransformer(ResultAsCharMap, CLI::ignore_case)); + + // With all the options added, parse arguments from the command line. + CLI11_PARSE(app, argc, argv); + + // Translate values to its final form after parsing. + // Create an interop array of values. + unique_ptr ResultArrayArgInteropValue = CreateInteropArray(ResultArrayArgCliValue); + + // Redirect the simulator output from std::cout if the --simulation-output option is present. + ostream* simulatorOutputStream = &cout; + ofstream simulationOutputFileStream; + if (!simulationOutputFileOpt->empty()) + { + simulationOutputFileStream.open(simulationOutputFile); + SetOutputStream(simulationOutputFileStream); + simulatorOutputStream = &simulationOutputFileStream; + } + + // Run simulation and write the output of the operation to the corresponding stream. + UseResultArrayArgWithValues( + ResultArrayArgInteropValue.get() + ); + + + simulatorOutputStream->flush(); + if (simulationOutputFileStream.is_open()) + { + simulationOutputFileStream.close(); + } +} diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseStringArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseStringArg.cpp new file mode 100644 index 00000000000..6dae3fe59b7 --- /dev/null +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseStringArg.cpp @@ -0,0 +1,80 @@ +//------------------------------------------------------------------------------ +// This code was generated by a tool. +// +//------------------------------------------------------------------------------ +// +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#include +#include +#include +#include +#include + +#include "CLI11.hpp" + +#include "QirContext.hpp" +#include "QirRuntime.hpp" +#include "SimFactory.hpp" + +using namespace Microsoft::Quantum; +using namespace std; + + +// This is the function corresponding to the QIR entry-point. +extern "C" void UseStringArgWithValues( // NOLINT + const char* StringArgInteropValue +); + + + +const char* TranslateStringToCharBuffer(string& s) +{ + return s.c_str(); +} +int main(int argc, char* argv[]) +{ + CLI::App app("QIR Standalone Entry Point Inputs Reference"); + + // Initialize simulator. + unique_ptr sim = CreateFullstateSimulator(); + QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); + + // Add the --simulation-output options. + // N.B. This option should be present in all standalone drivers. + string simulationOutputFile; + CLI::Option* simulationOutputFileOpt = app.add_option( + "--simulation-output", simulationOutputFile, + "File where the output produced during the simulation is written"); + + string StringArgCliValue; + app.add_option("--StringArg", StringArgCliValue, "A String value for the StringArg argument")->required(); + + // With all the options added, parse arguments from the command line. + CLI11_PARSE(app, argc, argv); + + string StringArgInteropValue = StringArgCliValue; + + // Redirect the simulator output from std::cout if the --simulation-output option is present. + ostream* simulatorOutputStream = &cout; + ofstream simulationOutputFileStream; + if (!simulationOutputFileOpt->empty()) + { + simulationOutputFileStream.open(simulationOutputFile); + SetOutputStream(simulationOutputFileStream); + simulatorOutputStream = &simulationOutputFileStream; + } + + // Run simulation and write the output of the operation to the corresponding stream. + UseStringArgWithValues( + StringArgInteropValue.c_str() + ); + + + simulatorOutputStream->flush(); + if (simulationOutputFileStream.is_open()) + { + simulationOutputFileStream.close(); + } +} diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/Tests.Microsoft.Quantum.Qir.Tools.csproj b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/Tests.Microsoft.Quantum.Qir.Tools.csproj index 861e7e26d75..cd9a3d60202 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/Tests.Microsoft.Quantum.Qir.Tools.csproj +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/Tests.Microsoft.Quantum.Qir.Tools.csproj @@ -18,12 +18,51 @@ + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + Always + + Always + + + Always + + + Always + + + Always + Always + + Always + + + Always + From 69d4faa4b39b51482114f4441ab2dd7d287f46dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Fri, 30 Apr 2021 14:24:41 -0700 Subject: [PATCH 13/15] Fix driver compilation issues. --- .../FullStateDriverGenerator/UseBoolArg.cpp | 2 +- .../FullStateDriverGenerator/UseNoArgs.cpp | 2 +- .../FullStateDriverGenerator/UseResultArg.cpp | 2 +- src/Qir/Execution/Tools/Driver/QirCppDriver.cs | 12 +++++++----- src/Qir/Execution/Tools/Driver/QirCppDriver.tt | 14 ++++++++------ 5 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseBoolArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseBoolArg.cpp index 501f9a266ae..ac2d8510044 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseBoolArg.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseBoolArg.cpp @@ -67,7 +67,7 @@ int main(int argc, char* argv[]) if (!simulationOutputFileOpt->empty()) { simulationOutputFileStream.open(simulationOutputFile); - Microsoft::Quantum::OutputStream::Set(simulationOutputFileStream); + SetOutputStream(simulationOutputFileStream); simulatorOutputStream = &simulationOutputFileStream; } diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseNoArgs.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseNoArgs.cpp index 4d5d776a1d9..eb6597a7f4f 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseNoArgs.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseNoArgs.cpp @@ -46,7 +46,7 @@ int main(int argc, char* argv[]) if (!simulationOutputFileOpt->empty()) { simulationOutputFileStream.open(simulationOutputFile); - Microsoft::Quantum::OutputStream::Set(simulationOutputFileStream); + SetOutputStream(simulationOutputFileStream); simulatorOutputStream = &simulationOutputFileStream; } diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArg.cpp index 800181ede3b..516888b83b0 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArg.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArg.cpp @@ -67,7 +67,7 @@ int main(int argc, char* argv[]) if (!simulationOutputFileOpt->empty()) { simulationOutputFileStream.open(simulationOutputFile); - Microsoft::Quantum::OutputStream::Set(simulationOutputFileStream); + SetOutputStream(simulationOutputFileStream); simulatorOutputStream = &simulationOutputFileStream; } diff --git a/src/Qir/Execution/Tools/Driver/QirCppDriver.cs b/src/Qir/Execution/Tools/Driver/QirCppDriver.cs index 2d2969cebaf..c3db2209059 100644 --- a/src/Qir/Execution/Tools/Driver/QirCppDriver.cs +++ b/src/Qir/Execution/Tools/Driver/QirCppDriver.cs @@ -210,7 +210,6 @@ unique_ptr CreateInteropRange(RangeTuple rangeTuple) this.Write(" // Cast parsed arguments to its interop types.\r\n"); } foreach (var arg in EntryPoint.Parameters) { - var interopTranslator = QirCppInterop.CliOptionTypeToInteropTypeTranslator(arg.Type); if (arg.Type == DataType.ArrayType) { var arrayInteropTranslator = QirCppInterop.CliOptionTypeToInteropTypeTranslator(arg.ArrayType); if (arrayInteropTranslator == null) { @@ -222,7 +221,7 @@ unique_ptr CreateInteropRange(RangeTuple rangeTuple) this.Write(this.ToStringHelper.ToStringWithCulture(arg.CliOptionVariableName())); this.Write(").get();\r\n"); } - else { + else { var arrayCliOptionType = QirCppInterop.CliOptionType(arg.ArrayType); var arrayInteropType = QirCppInterop.InteropType(arg.ArrayType); this.Write(" vector<"); @@ -248,7 +247,9 @@ unique_ptr CreateInteropRange(RangeTuple rangeTuple) this.Write(").get();\r\n"); } } - else if (interopTranslator == null) { + else { + var interopTranslator = QirCppInterop.CliOptionTypeToInteropTypeTranslator(arg.Type); + if (interopTranslator == null) { this.Write(" "); this.Write(this.ToStringHelper.ToStringWithCulture(arg.InteropType())); this.Write(" "); @@ -257,7 +258,7 @@ unique_ptr CreateInteropRange(RangeTuple rangeTuple) this.Write(this.ToStringHelper.ToStringWithCulture(arg.CliOptionVariableName())); this.Write(";\r\n"); } - else if (interopTranslator != null) { + else { this.Write(" "); this.Write(this.ToStringHelper.ToStringWithCulture(arg.InteropType())); this.Write(" "); @@ -267,6 +268,7 @@ unique_ptr CreateInteropRange(RangeTuple rangeTuple) this.Write("("); this.Write(this.ToStringHelper.ToStringWithCulture(arg.CliOptionVariableName())); this.Write(");\r\n"); + } } this.Write("\r\n"); } @@ -276,7 +278,7 @@ unique_ptr CreateInteropRange(RangeTuple rangeTuple) if (!simulationOutputFileOpt->empty()) { simulationOutputFileStream.open(simulationOutputFile); - Microsoft::Quantum::OutputStream::Set(simulationOutputFileStream); + SetOutputStream(simulationOutputFileStream); simulatorOutputStream = &simulationOutputFileStream; } diff --git a/src/Qir/Execution/Tools/Driver/QirCppDriver.tt b/src/Qir/Execution/Tools/Driver/QirCppDriver.tt index aa80a81b270..96eebf6792a 100644 --- a/src/Qir/Execution/Tools/Driver/QirCppDriver.tt +++ b/src/Qir/Execution/Tools/Driver/QirCppDriver.tt @@ -190,14 +190,13 @@ int main(int argc, char* argv[]) <# if (EntryPoint.Parameters.Count > 0) { #> // Cast parsed arguments to its interop types. <# } #> -<# foreach (var arg in EntryPoint.Parameters) { - var interopTranslator = QirCppInterop.CliOptionTypeToInteropTypeTranslator(arg.Type);#> +<# foreach (var arg in EntryPoint.Parameters) { #> <# if (arg.Type == DataType.ArrayType) { var arrayInteropTranslator = QirCppInterop.CliOptionTypeToInteropTypeTranslator(arg.ArrayType); #> <# if (arrayInteropTranslator == null) { #> <#= arg.InteropType() #> <#= arg.InteropVariableName() #> = CreateInteropArray(<#= arg.CliOptionVariableName() #>).get(); <# } #> -<# else { +<# else { var arrayCliOptionType = QirCppInterop.CliOptionType(arg.ArrayType); var arrayInteropType = QirCppInterop.InteropType(arg.ArrayType); #> vector<<#= arrayInteropType #>> <#= arg.IntermediateVariableName() #>; @@ -205,12 +204,15 @@ int main(int argc, char* argv[]) <#= arg.InteropType() #> <#= arg.InteropVariableName() #> = CreateInteropArray(<#= arg.IntermediateVariableName() #>).get(); <# } #> <# } #> -<# else if (interopTranslator == null) { #> +<# else { + var interopTranslator = QirCppInterop.CliOptionTypeToInteropTypeTranslator(arg.Type); #> +<# if (interopTranslator == null) { #> <#= arg.InteropType() #> <#= arg.InteropVariableName() #> = <#= arg.CliOptionVariableName() #>; <# } #> -<# else if (interopTranslator != null) { #> +<# else { #> <#= arg.InteropType() #> <#= arg.InteropVariableName() #> = <#= interopTranslator #>(<#= arg.CliOptionVariableName() #>); <# } #> +<# } #> <# } #> // Redirect the simulator output from std::cout if the --simulation-output option is present. @@ -219,7 +221,7 @@ int main(int argc, char* argv[]) if (!simulationOutputFileOpt->empty()) { simulationOutputFileStream.open(simulationOutputFile); - Microsoft::Quantum::OutputStream::Set(simulationOutputFileStream); + SetOutputStream(simulationOutputFileStream); simulatorOutputStream = &simulationOutputFileStream; } From dc024561d02b4b05ce0e08fc4d9a96a50dbbef02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Fri, 30 Apr 2021 18:35:35 -0700 Subject: [PATCH 14/15] Fixed compilation warnings. --- .../Execution/Tools/Driver/QirCppDriver.cs | 21 ++++++++++--------- .../Execution/Tools/Driver/QirCppDriver.tt | 5 +++-- .../Execution/Tools/Driver/QirCppInterop.cs | 2 ++ 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/Qir/Execution/Tools/Driver/QirCppDriver.cs b/src/Qir/Execution/Tools/Driver/QirCppDriver.cs index c3db2209059..807f959095b 100644 --- a/src/Qir/Execution/Tools/Driver/QirCppDriver.cs +++ b/src/Qir/Execution/Tools/Driver/QirCppDriver.cs @@ -213,13 +213,11 @@ unique_ptr CreateInteropRange(RangeTuple rangeTuple) if (arg.Type == DataType.ArrayType) { var arrayInteropTranslator = QirCppInterop.CliOptionTypeToInteropTypeTranslator(arg.ArrayType); if (arrayInteropTranslator == null) { - this.Write(" "); - this.Write(this.ToStringHelper.ToStringWithCulture(arg.InteropType())); - this.Write(" "); - this.Write(this.ToStringHelper.ToStringWithCulture(arg.InteropVariableName())); + this.Write(" unique_ptr "); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.UniquePtrVariableName())); this.Write(" = CreateInteropArray("); this.Write(this.ToStringHelper.ToStringWithCulture(arg.CliOptionVariableName())); - this.Write(").get();\r\n"); + this.Write(");\r\n"); } else { var arrayCliOptionType = QirCppInterop.CliOptionType(arg.ArrayType); @@ -238,14 +236,17 @@ unique_ptr CreateInteropRange(RangeTuple rangeTuple) this.Write(this.ToStringHelper.ToStringWithCulture(arg.IntermediateVariableName())); this.Write(", "); this.Write(this.ToStringHelper.ToStringWithCulture(arrayInteropTranslator)); - this.Write(");\r\n "); - this.Write(this.ToStringHelper.ToStringWithCulture(arg.InteropType())); - this.Write(" "); - this.Write(this.ToStringHelper.ToStringWithCulture(arg.InteropVariableName())); + this.Write(");\r\n unique_ptr "); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.UniquePtrVariableName())); this.Write(" = CreateInteropArray("); this.Write(this.ToStringHelper.ToStringWithCulture(arg.IntermediateVariableName())); - this.Write(").get();\r\n"); + this.Write(");\r\n"); } + this.Write(" InteropArray* "); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.InteropVariableName())); + this.Write(" = "); + this.Write(this.ToStringHelper.ToStringWithCulture(arg.UniquePtrVariableName())); + this.Write(".get();\r\n"); } else { var interopTranslator = QirCppInterop.CliOptionTypeToInteropTypeTranslator(arg.Type); diff --git a/src/Qir/Execution/Tools/Driver/QirCppDriver.tt b/src/Qir/Execution/Tools/Driver/QirCppDriver.tt index 96eebf6792a..a99fa9716e7 100644 --- a/src/Qir/Execution/Tools/Driver/QirCppDriver.tt +++ b/src/Qir/Execution/Tools/Driver/QirCppDriver.tt @@ -194,15 +194,16 @@ int main(int argc, char* argv[]) <# if (arg.Type == DataType.ArrayType) { var arrayInteropTranslator = QirCppInterop.CliOptionTypeToInteropTypeTranslator(arg.ArrayType); #> <# if (arrayInteropTranslator == null) { #> - <#= arg.InteropType() #> <#= arg.InteropVariableName() #> = CreateInteropArray(<#= arg.CliOptionVariableName() #>).get(); + unique_ptr <#= arg.UniquePtrVariableName() #> = CreateInteropArray(<#= arg.CliOptionVariableName() #>); <# } #> <# else { var arrayCliOptionType = QirCppInterop.CliOptionType(arg.ArrayType); var arrayInteropType = QirCppInterop.InteropType(arg.ArrayType); #> vector<<#= arrayInteropType #>> <#= arg.IntermediateVariableName() #>; TranslateVector<<#= arrayCliOptionType #>, <#= arrayInteropType #>>(<#= arg.CliOptionVariableName() #>, <#= arg.IntermediateVariableName() #>, <#= arrayInteropTranslator #>); - <#= arg.InteropType() #> <#= arg.InteropVariableName() #> = CreateInteropArray(<#= arg.IntermediateVariableName() #>).get(); + unique_ptr <#= arg.UniquePtrVariableName() #> = CreateInteropArray(<#= arg.IntermediateVariableName() #>); <# } #> + InteropArray* <#= arg.InteropVariableName() #> = <#= arg.UniquePtrVariableName() #>.get(); <# } #> <# else { var interopTranslator = QirCppInterop.CliOptionTypeToInteropTypeTranslator(arg.Type); #> diff --git a/src/Qir/Execution/Tools/Driver/QirCppInterop.cs b/src/Qir/Execution/Tools/Driver/QirCppInterop.cs index 472cbf47727..b4da38b9676 100644 --- a/src/Qir/Execution/Tools/Driver/QirCppInterop.cs +++ b/src/Qir/Execution/Tools/Driver/QirCppInterop.cs @@ -122,6 +122,8 @@ public static string CliOptionType(this Parameter @this) => public static string InteropVariableName(this Parameter @this) => $"{@this.Name}Interop"; public static string InteropType(this Parameter @this) => QirCppInterop.InteropType(@this.Type); + + public static string UniquePtrVariableName(this Parameter @this) => $"{@this.Name}UniquePtr"; } internal static class EntryPointOperationCppExtension From b522ff4fdd6e877383049bdf05f381c5c536fdc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Fri, 30 Apr 2021 20:09:42 -0700 Subject: [PATCH 15/15] Added test cases. --- .../QirDriverGeneratorTests.cs | 113 ++++++++++++++ .../UseBoolArrayArg.cpp | 54 +++---- .../FullStateDriverGenerator/UseDoubleArg.cpp | 46 +++--- .../UseDoubleArrayArg.cpp | 48 +++--- .../UseIntegerArg.cpp | 46 +++--- .../UseIntegerArrayArg.cpp | 48 +++--- .../FullStateDriverGenerator/UseMiscArgs.cpp | 138 ++++++++++++++---- .../FullStateDriverGenerator/UsePauliArg.cpp | 54 +++---- .../UsePauliArrayArg.cpp | 58 ++++---- .../FullStateDriverGenerator/UseRangeArg.cpp | 46 +++--- .../UseRangeArrayArg.cpp | 52 ++++--- .../UseResultArrayArg.cpp | 51 +++---- .../FullStateDriverGenerator/UseStringArg.cpp | 49 ++++--- 13 files changed, 506 insertions(+), 297 deletions(-) diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirDriverGeneratorTests.cs b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirDriverGeneratorTests.cs index 432813d69b0..f4f92e66a4e 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirDriverGeneratorTests.cs +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/QirDriverGeneratorTests.cs @@ -31,6 +31,78 @@ public class QirDriverGeneratorTests Parameters = new List{new Parameter{ Name = "BoolArg", Type = DataType.BoolType}} } }, + { + "UseBoolArrayArg", + new EntryPointOperation + { + Name = "UseBoolArrayArg", + Parameters = new List{new Parameter{ Name = "BoolArrayArg", Type = DataType.ArrayType, ArrayType = DataType.BoolType}} + } + }, + { + "UseDoubleArg", + new EntryPointOperation + { + Name = "UseDoublArg", + Parameters = new List{new Parameter{ Name = "DoubleArg", Type = DataType.DoubleType}} + } + }, + { + "UseDoubleArrayArg", + new EntryPointOperation + { + Name = "UseDoubleArrayArg", + Parameters = new List{new Parameter{ Name = "DoubleArrayArg", Type = DataType.ArrayType, ArrayType = DataType.DoubleType}} + } + }, + { + "UseIntegerArg", + new EntryPointOperation + { + Name = "UseIntegerArg", + Parameters = new List{new Parameter{ Name = "IntegerArg", Type = DataType.IntegerType}} + } + }, + { + "UseIntegerArrayArg", + new EntryPointOperation + { + Name = "UseIntegerArrayArg", + Parameters = new List{new Parameter{ Name = "IntegerArrayArg", Type = DataType.ArrayType, ArrayType = DataType.IntegerType}} + } + }, + { + "UsePauliArg", + new EntryPointOperation + { + Name = "UsePauliArg", + Parameters = new List{new Parameter{ Name = "PauliArg", Type = DataType.PauliType}} + } + }, + { + "UsePauliArrayArg", + new EntryPointOperation + { + Name = "UsePauliArrayArg", + Parameters = new List{new Parameter{ Name = "PauliArrayArg", Type = DataType.ArrayType, ArrayType = DataType.PauliType}} + } + }, + { + "UseRangeArg", + new EntryPointOperation + { + Name = "UseRangeArg", + Parameters = new List{new Parameter{ Name = "RangeArg", Type = DataType.RangeType}} + } + }, + { + "UseRangeArrayArg", + new EntryPointOperation + { + Name = "UseRangeArrayArg", + Parameters = new List{new Parameter{ Name = "RangeArrayArg", Type = DataType.ArrayType, ArrayType = DataType.RangeType}} + } + }, { "UseResultArg", new EntryPointOperation @@ -38,13 +110,54 @@ public class QirDriverGeneratorTests Name = "UseResultArg", Parameters = new List{new Parameter{ Name = "ResultArg", Type = DataType.ResultType}} } + }, + { + "UseResultArrayArg", + new EntryPointOperation + { + Name = "UseResultArrayArg", + Parameters = new List{new Parameter{ Name = "ResultArrayArg", Type = DataType.ArrayType, ArrayType = DataType.ResultType}} + } + }, + { + "UseStringArg", + new EntryPointOperation + { + Name = "UseStringArg", + Parameters = new List{new Parameter{ Name = "StringArg", Type = DataType.StringType}} + } + }, + { + "UseMiscArgs", + new EntryPointOperation + { + Name = "UseMiscArgs", + Parameters = new List{ + new Parameter{ Name = "BoolArg", Type = DataType.BoolType}, + new Parameter{ Name = "IntegerArrayArg", Position = 1, Type = DataType.ArrayType, ArrayType = DataType.IntegerType}, + new Parameter{ Name = "RangeArg", Position = 2, Type = DataType.RangeType}, + new Parameter{ Name = "StringArg", Position = 3, Type = DataType.StringType} + } + } } }; [Theory] [InlineData("UseNoArgs")] [InlineData("UseBoolArg")] + [InlineData("UseBoolArrayArg")] + [InlineData("UseDoubleArg")] + [InlineData("UseDoubleArrayArg")] + [InlineData("UseIntegerArg")] + [InlineData("UseIntegerArrayArg")] + [InlineData("UsePauliArg")] + [InlineData("UsePauliArrayArg")] + [InlineData("UseRangeArg")] + [InlineData("UseRangeArrayArg")] [InlineData("UseResultArg")] + [InlineData("UseResultArrayArg")] + [InlineData("UseStringArg")] + [InlineData("UseMiscArgs")] public void GenerateFullStateSimulatorDriver(string testCase) { var entryPointOperation = TestCases[testCase]; diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseBoolArrayArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseBoolArrayArg.cpp index bf7d49b63fe..49ba88538d7 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseBoolArrayArg.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseBoolArrayArg.cpp @@ -2,9 +2,6 @@ // This code was generated by a tool. // //------------------------------------------------------------------------------ -// -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. #include #include @@ -14,14 +11,15 @@ #include "CLI11.hpp" -#include "QirContext.hpp" #include "QirRuntime.hpp" +#include "QirContext.hpp" + #include "SimFactory.hpp" using namespace Microsoft::Quantum; using namespace std; - +// Auxiliary functions for interop with Q# Array type. struct InteropArray { int64_t Size; @@ -46,45 +44,47 @@ void TranslateVector(vector& sourceVector, vector& destinationVector, func transform(sourceVector.begin(), sourceVector.end(), destinationVector.begin(), translationFunction); } -// This is the function corresponding to the QIR entry-point. -extern "C" void UseBoolArrayArgWithValues( // NOLINT - InteropArray* BoolArrayArgInteropValue -); - - +// Auxiliary functions for interop with Q# Bool type. const char InteropFalseAsChar = 0x0; const char InteropTrueAsChar = 0x1; map BoolAsCharMap{ {"0", InteropFalseAsChar}, {"false", InteropFalseAsChar}, {"1", InteropTrueAsChar}, - {"true", InteropTrueAsChar}}; + {"true", InteropTrueAsChar} +}; + +extern "C" void UseBoolArrayArg( + InteropArray* BoolArrayArg +); // QIR interop function. int main(int argc, char* argv[]) { - CLI::App app("QIR Standalone Entry Point Inputs Reference"); + CLI::App app("QIR Standalone Entry Point"); // Initialize simulator. unique_ptr sim = CreateFullstateSimulator(); QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); - // Add the --simulation-output options. - // N.B. This option should be present in all standalone drivers. + // Add the --simulation-output option. string simulationOutputFile; CLI::Option* simulationOutputFileOpt = app.add_option( - "--simulation-output", simulationOutputFile, + "--simulation-output", + simulationOutputFile, "File where the output produced during the simulation is written"); - vector BoolArrayArgCliValue; - app.add_option("--BoolArrayArg", BoolArrayArgCliValue, "A bool array value for the BoolArrayArg argument")->required() + // Add a command line option for each entry-point parameter. + vector BoolArrayArgCli; + app.add_option("--BoolArrayArg", BoolArrayArgCli, "Option to provide a value for the BoolArrayArg parameter") + ->required() ->transform(CLI::CheckedTransformer(BoolAsCharMap, CLI::ignore_case)); - // With all the options added, parse arguments from the command line. + // After all the options have been added, parse arguments from the command line. CLI11_PARSE(app, argc, argv); - // Translate values to its final form after parsing. - // Create an interop array of values. - unique_ptr BoolArrayArgInteropValue = CreateInteropArray(BoolArrayArgCliValue); + // Cast parsed arguments to its interop types. + unique_ptr BoolArrayArgUniquePtr = CreateInteropArray(BoolArrayArgCli); + InteropArray* BoolArrayArgInterop = BoolArrayArgUniquePtr.get(); // Redirect the simulator output from std::cout if the --simulation-output option is present. ostream* simulatorOutputStream = &cout; @@ -96,15 +96,17 @@ int main(int argc, char* argv[]) simulatorOutputStream = &simulationOutputFileStream; } - // Run simulation and write the output of the operation to the corresponding stream. - UseBoolArrayArgWithValues( - BoolArrayArgInteropValue.get() + // Execute the entry point operation. + UseBoolArrayArg( + BoolArrayArgInterop ); - + // Flush the output of the simulation. simulatorOutputStream->flush(); if (simulationOutputFileStream.is_open()) { simulationOutputFileStream.close(); } + + return 0; } diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseDoubleArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseDoubleArg.cpp index de3249a5eab..c07687f1e4e 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseDoubleArg.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseDoubleArg.cpp @@ -2,9 +2,6 @@ // This code was generated by a tool. // //------------------------------------------------------------------------------ -// -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. #include #include @@ -14,43 +11,44 @@ #include "CLI11.hpp" -#include "QirContext.hpp" #include "QirRuntime.hpp" +#include "QirContext.hpp" + #include "SimFactory.hpp" using namespace Microsoft::Quantum; using namespace std; - - -// This is the function corresponding to the QIR entry-point. -extern "C" void UseDoubleArgWithValues( // NOLINT - double DoubleArgInteropValue -); +extern "C" void UseDoublArg( + double_t DoubleArg +); // QIR interop function. int main(int argc, char* argv[]) { - CLI::App app("QIR Standalone Entry Point Inputs Reference"); + CLI::App app("QIR Standalone Entry Point"); // Initialize simulator. unique_ptr sim = CreateFullstateSimulator(); QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); - // Add the --simulation-output options. - // N.B. This option should be present in all standalone drivers. + // Add the --simulation-output option. string simulationOutputFile; CLI::Option* simulationOutputFileOpt = app.add_option( - "--simulation-output", simulationOutputFile, + "--simulation-output", + simulationOutputFile, "File where the output produced during the simulation is written"); - double_t DoubleArgCliValue; - DoubleArgCliValue = 0.0; - app.add_option("--DoubleArg", DoubleArgCliValue, "A double value for the DoubleArg argument")->required(); + // Add a command line option for each entry-point parameter. + double_t DoubleArgCli; + DoubleArgCli = 0.0; + app.add_option("--DoubleArg", DoubleArgCli, "Option to provide a value for the DoubleArg parameter") + ->required(); - // With all the options added, parse arguments from the command line. + // After all the options have been added, parse arguments from the command line. CLI11_PARSE(app, argc, argv); - double_t DoubleArgInteropValue = DoubleArgCliValue; + // Cast parsed arguments to its interop types. + double_t DoubleArgInterop = DoubleArgCli; // Redirect the simulator output from std::cout if the --simulation-output option is present. ostream* simulatorOutputStream = &cout; @@ -62,15 +60,17 @@ int main(int argc, char* argv[]) simulatorOutputStream = &simulationOutputFileStream; } - // Run simulation and write the output of the operation to the corresponding stream. - UseDoubleArgWithValues( - DoubleArgInteropValue + // Execute the entry point operation. + UseDoublArg( + DoubleArgInterop ); - + // Flush the output of the simulation. simulatorOutputStream->flush(); if (simulationOutputFileStream.is_open()) { simulationOutputFileStream.close(); } + + return 0; } diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseDoubleArrayArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseDoubleArrayArg.cpp index 892a379d732..707c2095bc9 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseDoubleArrayArg.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseDoubleArrayArg.cpp @@ -2,9 +2,6 @@ // This code was generated by a tool. // //------------------------------------------------------------------------------ -// -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. #include #include @@ -14,14 +11,15 @@ #include "CLI11.hpp" -#include "QirContext.hpp" #include "QirRuntime.hpp" +#include "QirContext.hpp" + #include "SimFactory.hpp" using namespace Microsoft::Quantum; using namespace std; - +// Auxiliary functions for interop with Q# Array type. struct InteropArray { int64_t Size; @@ -46,36 +44,36 @@ void TranslateVector(vector& sourceVector, vector& destinationVector, func transform(sourceVector.begin(), sourceVector.end(), destinationVector.begin(), translationFunction); } -// This is the function corresponding to the QIR entry-point. -extern "C" void UseDoubleArrayArgWithValues( // NOLINT - InteropArray* DoubleArrayArgInteropValue -); - +extern "C" void UseDoubleArrayArg( + InteropArray* DoubleArrayArg +); // QIR interop function. int main(int argc, char* argv[]) { - CLI::App app("QIR Standalone Entry Point Inputs Reference"); + CLI::App app("QIR Standalone Entry Point"); // Initialize simulator. unique_ptr sim = CreateFullstateSimulator(); QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); - // Add the --simulation-output options. - // N.B. This option should be present in all standalone drivers. + // Add the --simulation-output option. string simulationOutputFile; CLI::Option* simulationOutputFileOpt = app.add_option( - "--simulation-output", simulationOutputFile, + "--simulation-output", + simulationOutputFile, "File where the output produced during the simulation is written"); - vector DoubleArrayArgCliValue; - app.add_option("--DoubleArrayArg", DoubleArrayArgCliValue, "A double array value for the DoubleArrayArg argument")->required(); + // Add a command line option for each entry-point parameter. + vector DoubleArrayArgCli; + app.add_option("--DoubleArrayArg", DoubleArrayArgCli, "Option to provide a value for the DoubleArrayArg parameter") + ->required(); - // With all the options added, parse arguments from the command line. + // After all the options have been added, parse arguments from the command line. CLI11_PARSE(app, argc, argv); - // Translate values to its final form after parsing. - // Create an interop array of values. - unique_ptr DoubleArrayArgInteropValue = CreateInteropArray(DoubleArrayArgCliValue); + // Cast parsed arguments to its interop types. + unique_ptr DoubleArrayArgUniquePtr = CreateInteropArray(DoubleArrayArgCli); + InteropArray* DoubleArrayArgInterop = DoubleArrayArgUniquePtr.get(); // Redirect the simulator output from std::cout if the --simulation-output option is present. ostream* simulatorOutputStream = &cout; @@ -87,15 +85,17 @@ int main(int argc, char* argv[]) simulatorOutputStream = &simulationOutputFileStream; } - // Run simulation and write the output of the operation to the corresponding stream. - UseDoubleArrayArgWithValues( - DoubleArrayArgInteropValue.get() + // Execute the entry point operation. + UseDoubleArrayArg( + DoubleArrayArgInterop ); - + // Flush the output of the simulation. simulatorOutputStream->flush(); if (simulationOutputFileStream.is_open()) { simulationOutputFileStream.close(); } + + return 0; } diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseIntegerArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseIntegerArg.cpp index cfec6a208a5..6d4d4614f9a 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseIntegerArg.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseIntegerArg.cpp @@ -2,9 +2,6 @@ // This code was generated by a tool. // //------------------------------------------------------------------------------ -// -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. #include #include @@ -14,43 +11,44 @@ #include "CLI11.hpp" -#include "QirContext.hpp" #include "QirRuntime.hpp" +#include "QirContext.hpp" + #include "SimFactory.hpp" using namespace Microsoft::Quantum; using namespace std; - - -// This is the function corresponding to the QIR entry-point. -extern "C" void UseIntegerArgWithValues( // NOLINT - int64_t IntegerArgInteropValue -); +extern "C" void UseIntegerArg( + int64_t IntegerArg +); // QIR interop function. int main(int argc, char* argv[]) { - CLI::App app("QIR Standalone Entry Point Inputs Reference"); + CLI::App app("QIR Standalone Entry Point"); // Initialize simulator. unique_ptr sim = CreateFullstateSimulator(); QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); - // Add the --simulation-output options. - // N.B. This option should be present in all standalone drivers. + // Add the --simulation-output option. string simulationOutputFile; CLI::Option* simulationOutputFileOpt = app.add_option( - "--simulation-output", simulationOutputFile, + "--simulation-output", + simulationOutputFile, "File where the output produced during the simulation is written"); - int64_t IntegerArgCliValue; - IntegerArgCliValue = 0; - app.add_option("--IntegerArg", IntegerArgCliValue, "A integer value for the IntegerArg argument")->required(); + // Add a command line option for each entry-point parameter. + int64_t IntegerArgCli; + IntegerArgCli = 0; + app.add_option("--IntegerArg", IntegerArgCli, "Option to provide a value for the IntegerArg parameter") + ->required(); - // With all the options added, parse arguments from the command line. + // After all the options have been added, parse arguments from the command line. CLI11_PARSE(app, argc, argv); - int64_t IntegerArgInteropValue = IntegerArgCliValue; + // Cast parsed arguments to its interop types. + int64_t IntegerArgInterop = IntegerArgCli; // Redirect the simulator output from std::cout if the --simulation-output option is present. ostream* simulatorOutputStream = &cout; @@ -62,15 +60,17 @@ int main(int argc, char* argv[]) simulatorOutputStream = &simulationOutputFileStream; } - // Run simulation and write the output of the operation to the corresponding stream. - UseIntegerArgWithValues( - IntegerArgInteropValue + // Execute the entry point operation. + UseIntegerArg( + IntegerArgInterop ); - + // Flush the output of the simulation. simulatorOutputStream->flush(); if (simulationOutputFileStream.is_open()) { simulationOutputFileStream.close(); } + + return 0; } diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseIntegerArrayArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseIntegerArrayArg.cpp index 41c5c808226..e3cc2f8bf60 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseIntegerArrayArg.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseIntegerArrayArg.cpp @@ -2,9 +2,6 @@ // This code was generated by a tool. // //------------------------------------------------------------------------------ -// -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. #include #include @@ -14,14 +11,15 @@ #include "CLI11.hpp" -#include "QirContext.hpp" #include "QirRuntime.hpp" +#include "QirContext.hpp" + #include "SimFactory.hpp" using namespace Microsoft::Quantum; using namespace std; - +// Auxiliary functions for interop with Q# Array type. struct InteropArray { int64_t Size; @@ -46,36 +44,36 @@ void TranslateVector(vector& sourceVector, vector& destinationVector, func transform(sourceVector.begin(), sourceVector.end(), destinationVector.begin(), translationFunction); } -// This is the function corresponding to the QIR entry-point. -extern "C" void UseIntegerArrayArgWithValues( // NOLINT - InteropArray* IntegerArrayArgInteropValue -); - +extern "C" void UseIntegerArrayArg( + InteropArray* IntegerArrayArg +); // QIR interop function. int main(int argc, char* argv[]) { - CLI::App app("QIR Standalone Entry Point Inputs Reference"); + CLI::App app("QIR Standalone Entry Point"); // Initialize simulator. unique_ptr sim = CreateFullstateSimulator(); QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); - // Add the --simulation-output options. - // N.B. This option should be present in all standalone drivers. + // Add the --simulation-output option. string simulationOutputFile; CLI::Option* simulationOutputFileOpt = app.add_option( - "--simulation-output", simulationOutputFile, + "--simulation-output", + simulationOutputFile, "File where the output produced during the simulation is written"); - vector IntegerArrayArgCliValue; - app.add_option("--IntegerArrayArg", IntegerArrayArgCliValue, "A integer array value for the IntegerArrayArg argument")->required(); + // Add a command line option for each entry-point parameter. + vector IntegerArrayArgCli; + app.add_option("--IntegerArrayArg", IntegerArrayArgCli, "Option to provide a value for the IntegerArrayArg parameter") + ->required(); - // With all the options added, parse arguments from the command line. + // After all the options have been added, parse arguments from the command line. CLI11_PARSE(app, argc, argv); - // Translate values to its final form after parsing. - // Create an interop array of values. - unique_ptr IntegerArrayArgInteropValue = CreateInteropArray(IntegerArrayArgCliValue); + // Cast parsed arguments to its interop types. + unique_ptr IntegerArrayArgUniquePtr = CreateInteropArray(IntegerArrayArgCli); + InteropArray* IntegerArrayArgInterop = IntegerArrayArgUniquePtr.get(); // Redirect the simulator output from std::cout if the --simulation-output option is present. ostream* simulatorOutputStream = &cout; @@ -87,15 +85,17 @@ int main(int argc, char* argv[]) simulatorOutputStream = &simulationOutputFileStream; } - // Run simulation and write the output of the operation to the corresponding stream. - UseIntegerArrayArgWithValues( - IntegerArrayArgInteropValue.get() + // Execute the entry point operation. + UseIntegerArrayArg( + IntegerArrayArgInterop ); - + // Flush the output of the simulation. simulatorOutputStream->flush(); if (simulationOutputFileStream.is_open()) { simulationOutputFileStream.close(); } + + return 0; } diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseMiscArgs.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseMiscArgs.cpp index bdb3c09cdf9..28373859dbf 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseMiscArgs.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseMiscArgs.cpp @@ -2,9 +2,6 @@ // This code was generated by a tool. // //------------------------------------------------------------------------------ -// -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. #include #include @@ -14,54 +11,139 @@ #include "CLI11.hpp" -#include "QirContext.hpp" #include "QirRuntime.hpp" +#include "QirContext.hpp" + #include "SimFactory.hpp" using namespace Microsoft::Quantum; using namespace std; - -// This is the function corresponding to the QIR entry-point. -extern "C" void UseMiscArgs( // NOLINT - int64_t IntegerArgInteropValue, - const char* StringArgInteropValue -); +// Auxiliary functions for interop with Q# Array type. +struct InteropArray +{ + int64_t Size; + void* Data; + + InteropArray(int64_t size, void* data) : + Size(size), + Data(data){} +}; + +template +unique_ptr CreateInteropArray(vector& v) +{ + unique_ptr array(new InteropArray(v.size(), v.data())); + return array; +} + +template +void TranslateVector(vector& sourceVector, vector& destinationVector, function translationFunction) +{ + destinationVector.resize(sourceVector.size()); + transform(sourceVector.begin(), sourceVector.end(), destinationVector.begin(), translationFunction); +} +// Auxiliary functions for interop with Q# Range type. +using RangeTuple = tuple; +struct InteropRange +{ + int64_t Start; + int64_t Step; + int64_t End; + + InteropRange() : + Start(0), + Step(0), + End(0){} + + InteropRange(RangeTuple rangeTuple) : + Start(get<0>(rangeTuple)), + Step(get<1>(rangeTuple)), + End(get<2>(rangeTuple)){} +}; + +unique_ptr CreateInteropRange(RangeTuple rangeTuple) +{ + unique_ptr range(new InteropRange(rangeTuple)); + return range; +} +InteropRange* TranslateRangeTupleToInteropRangePointer(RangeTuple& rangeTuple) +{ + InteropRange* range = new InteropRange(rangeTuple); + return range; +} +// Auxiliary functions for interop with Q# Bool type. +const char InteropFalseAsChar = 0x0; +const char InteropTrueAsChar = 0x1; +map BoolAsCharMap{ + {"0", InteropFalseAsChar}, + {"false", InteropFalseAsChar}, + {"1", InteropTrueAsChar}, + {"true", InteropTrueAsChar} +}; + +// Auxiliary functions for interop with Q# String type. const char* TranslateStringToCharBuffer(string& s) { return s.c_str(); } + +extern "C" void UseMiscArgs( + char BoolArg, + InteropArray* IntegerArrayArg, + InteropRange* RangeArg, + const char* StringArg +); // QIR interop function. + int main(int argc, char* argv[]) { - CLI::App app("QIR Standalone Entry Point Inputs Reference"); + CLI::App app("QIR Standalone Entry Point"); // Initialize simulator. unique_ptr sim = CreateFullstateSimulator(); QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); - // Add the --simulation-output options. - // N.B. This option should be present in all standalone drivers. + // Add the --simulation-output option. string simulationOutputFile; CLI::Option* simulationOutputFileOpt = app.add_option( - "--simulation-output", simulationOutputFile, + "--simulation-output", + simulationOutputFile, "File where the output produced during the simulation is written"); - int64_t IntegerArgCliValue; - IntegerArgCliValue = 0; - app.add_option("--IntegerArg", IntegerArgCliValue, "A integer value for the IntegerArg argument")->required(); + // Add a command line option for each entry-point parameter. + char BoolArgCli; + BoolArgCli = InteropFalseAsChar; + app.add_option("--BoolArg", BoolArgCli, "Option to provide a value for the BoolArg parameter") + ->required() + ->transform(CLI::CheckedTransformer(BoolAsCharMap, CLI::ignore_case)); - string StringArgCliValue; - app.add_option("--StringArg", StringArgCliValue, "A String value for the StringArg argument")->required(); + vector IntegerArrayArgCli; + app.add_option("--IntegerArrayArg", IntegerArrayArgCli, "Option to provide a value for the IntegerArrayArg parameter") + ->required(); - // With all the options added, parse arguments from the command line. + RangeTuple RangeArgCli; + app.add_option("--RangeArg", RangeArgCli, "Option to provide a value for the RangeArg parameter") + ->required(); + + string StringArgCli; + app.add_option("--StringArg", StringArgCli, "Option to provide a value for the StringArg parameter") + ->required(); + + // After all the options have been added, parse arguments from the command line. CLI11_PARSE(app, argc, argv); - int64_t IntegerArgInteropValue = IntegerArgCliValue; + // Cast parsed arguments to its interop types. + char BoolArgInterop = BoolArgCli; + + unique_ptr IntegerArrayArgUniquePtr = CreateInteropArray(IntegerArrayArgCli); + InteropArray* IntegerArrayArgInterop = IntegerArrayArgUniquePtr.get(); - string StringArgInteropValue = StringArgCliValue; + InteropRange* RangeArgInterop = TranslateRangeTupleToInteropRangePointer(RangeArgCli); + + const char* StringArgInterop = TranslateStringToCharBuffer(StringArgCli); // Redirect the simulator output from std::cout if the --simulation-output option is present. ostream* simulatorOutputStream = &cout; @@ -73,16 +155,20 @@ int main(int argc, char* argv[]) simulatorOutputStream = &simulationOutputFileStream; } - // Run simulation and write the output of the operation to the corresponding stream. + // Execute the entry point operation. UseMiscArgs( - IntegerArgInteropValue, - StringArgInteropValue.c_str() + BoolArgInterop, + IntegerArrayArgInterop, + RangeArgInterop, + StringArgInterop ); - + // Flush the output of the simulation. simulatorOutputStream->flush(); if (simulationOutputFileStream.is_open()) { simulationOutputFileStream.close(); } + + return 0; } diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UsePauliArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UsePauliArg.cpp index 4b7aa9f256e..134db56ea44 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UsePauliArg.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UsePauliArg.cpp @@ -2,9 +2,6 @@ // This code was generated by a tool. // //------------------------------------------------------------------------------ -// -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. #include #include @@ -14,57 +11,58 @@ #include "CLI11.hpp" -#include "QirContext.hpp" #include "QirRuntime.hpp" +#include "QirContext.hpp" + #include "SimFactory.hpp" using namespace Microsoft::Quantum; using namespace std; - - -// This is the function corresponding to the QIR entry-point. -extern "C" void UsePauliArgWithValues( // NOLINT - char PauliArgInteropValue -); - +// Auxiliary functions for interop with Q# Pauli type. map PauliMap{ {"PauliI", PauliId::PauliId_I}, {"PauliX", PauliId::PauliId_X}, {"PauliY", PauliId::PauliId_Y}, - {"PauliZ", PauliId::PauliId_Z}}; - + {"PauliZ", PauliId::PauliId_Z} +}; char TranslatePauliToChar(PauliId& pauli) { return static_cast(pauli); } +extern "C" void UsePauliArg( + char PauliArg +); // QIR interop function. + int main(int argc, char* argv[]) { - CLI::App app("QIR Standalone Entry Point Inputs Reference"); + CLI::App app("QIR Standalone Entry Point"); // Initialize simulator. unique_ptr sim = CreateFullstateSimulator(); QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); - // Add the --simulation-output options. - // N.B. This option should be present in all standalone drivers. + // Add the --simulation-output option. string simulationOutputFile; CLI::Option* simulationOutputFileOpt = app.add_option( - "--simulation-output", simulationOutputFile, + "--simulation-output", + simulationOutputFile, "File where the output produced during the simulation is written"); - PauliId PauliArgCliValue; - PauliArgCliValue = PauliId::PauliId_I; - app.add_option("--PauliArg", PauliArgCliValue, "A Pauli value for the PauliArg argument")->required() + // Add a command line option for each entry-point parameter. + PauliId PauliArgCli; + PauliArgCli = PauliId::PauliId_I; + app.add_option("--PauliArg", PauliArgCli, "Option to provide a value for the PauliArg parameter") + ->required() ->transform(CLI::CheckedTransformer(PauliMap, CLI::ignore_case)); - // With all the options added, parse arguments from the command line. + // After all the options have been added, parse arguments from the command line. CLI11_PARSE(app, argc, argv); - // Translate a PauliID value to its char representation. - char PauliArgInteropValue = TranslatePauliToChar(PauliArgCliValue); + // Cast parsed arguments to its interop types. + char PauliArgInterop = TranslatePauliToChar(PauliArgCli); // Redirect the simulator output from std::cout if the --simulation-output option is present. ostream* simulatorOutputStream = &cout; @@ -76,15 +74,17 @@ int main(int argc, char* argv[]) simulatorOutputStream = &simulationOutputFileStream; } - // Run simulation and write the output of the operation to the corresponding stream. - UsePauliArgWithValues( - PauliArgInteropValue + // Execute the entry point operation. + UsePauliArg( + PauliArgInterop ); - + // Flush the output of the simulation. simulatorOutputStream->flush(); if (simulationOutputFileStream.is_open()) { simulationOutputFileStream.close(); } + + return 0; } diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UsePauliArrayArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UsePauliArrayArg.cpp index e03a11beb57..22b27411fe6 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UsePauliArrayArg.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UsePauliArrayArg.cpp @@ -2,9 +2,6 @@ // This code was generated by a tool. // //------------------------------------------------------------------------------ -// -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. #include #include @@ -14,14 +11,15 @@ #include "CLI11.hpp" -#include "QirContext.hpp" #include "QirRuntime.hpp" +#include "QirContext.hpp" + #include "SimFactory.hpp" using namespace Microsoft::Quantum; using namespace std; - +// Auxiliary functions for interop with Q# Array type. struct InteropArray { int64_t Size; @@ -46,50 +44,52 @@ void TranslateVector(vector& sourceVector, vector& destinationVector, func transform(sourceVector.begin(), sourceVector.end(), destinationVector.begin(), translationFunction); } -// This is the function corresponding to the QIR entry-point. -extern "C" void UsePauliArrayArgWithValues( // NOLINT - InteropArray* PauliArrayArgInteropValue -); - - +// Auxiliary functions for interop with Q# Pauli type. map PauliMap{ {"PauliI", PauliId::PauliId_I}, {"PauliX", PauliId::PauliId_X}, {"PauliY", PauliId::PauliId_Y}, - {"PauliZ", PauliId::PauliId_Z}}; - + {"PauliZ", PauliId::PauliId_Z} +}; char TranslatePauliToChar(PauliId& pauli) { return static_cast(pauli); } +extern "C" void UsePauliArrayArg( + InteropArray* PauliArrayArg +); // QIR interop function. + int main(int argc, char* argv[]) { - CLI::App app("QIR Standalone Entry Point Inputs Reference"); + CLI::App app("QIR Standalone Entry Point"); // Initialize simulator. unique_ptr sim = CreateFullstateSimulator(); QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); - // Add the --simulation-output options. - // N.B. This option should be present in all standalone drivers. + // Add the --simulation-output option. string simulationOutputFile; CLI::Option* simulationOutputFileOpt = app.add_option( - "--simulation-output", simulationOutputFile, + "--simulation-output", + simulationOutputFile, "File where the output produced during the simulation is written"); - std::vector PauliArrayArgCliValue; - app.add_option("--PauliArrayArg", PauliArrayArgCliValue, "A Pauli array value for the PauliArrayArg argument")->required() + // Add a command line option for each entry-point parameter. + vector PauliArrayArgCli; + app.add_option("--PauliArrayArg", PauliArrayArgCli, "Option to provide a value for the PauliArrayArg parameter") + ->required() ->transform(CLI::CheckedTransformer(PauliMap, CLI::ignore_case)); - // With all the options added, parse arguments from the command line. + // After all the options have been added, parse arguments from the command line. CLI11_PARSE(app, argc, argv); - // Create an interop array of Pauli values represented as chars. - vector PauliArrayArgIntermediateValue; - TranslateVector(PauliArrayArgCliValue, PauliArrayArgIntermediateValue, TranslatePauliToChar); - unique_ptr PauliArrayArgInteropValue = CreateInteropArray(PauliArrayArgIntermediateValue); + // Cast parsed arguments to its interop types. + vector PauliArrayArgIntermediate; + TranslateVector(PauliArrayArgCli, PauliArrayArgIntermediate, TranslatePauliToChar); + unique_ptr PauliArrayArgUniquePtr = CreateInteropArray(PauliArrayArgIntermediate); + InteropArray* PauliArrayArgInterop = PauliArrayArgUniquePtr.get(); // Redirect the simulator output from std::cout if the --simulation-output option is present. ostream* simulatorOutputStream = &cout; @@ -101,15 +101,17 @@ int main(int argc, char* argv[]) simulatorOutputStream = &simulationOutputFileStream; } - // Run simulation and write the output of the operation to the corresponding stream. - UsePauliArrayArgWithValues( - PauliArrayArgInteropValue.get() + // Execute the entry point operation. + UsePauliArrayArg( + PauliArrayArgInterop ); - + // Flush the output of the simulation. simulatorOutputStream->flush(); if (simulationOutputFileStream.is_open()) { simulationOutputFileStream.close(); } + + return 0; } diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseRangeArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseRangeArg.cpp index 0481d1ab14a..3b89eb0ab7c 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseRangeArg.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseRangeArg.cpp @@ -2,9 +2,6 @@ // This code was generated by a tool. // //------------------------------------------------------------------------------ -// -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. #include #include @@ -14,14 +11,15 @@ #include "CLI11.hpp" -#include "QirContext.hpp" #include "QirRuntime.hpp" +#include "QirContext.hpp" + #include "SimFactory.hpp" using namespace Microsoft::Quantum; using namespace std; - +// Auxiliary functions for interop with Q# Range type. using RangeTuple = tuple; struct InteropRange { @@ -52,35 +50,35 @@ InteropRange* TranslateRangeTupleToInteropRangePointer(RangeTuple& rangeTuple) return range; } -// This is the function corresponding to the QIR entry-point. -extern "C" void UseRangeArgWithValues( // NOLINT - InteropRange* RangeArgInteropValue -); - +extern "C" void UseRangeArg( + InteropRange* RangeArg +); // QIR interop function. int main(int argc, char* argv[]) { - CLI::App app("QIR Standalone Entry Point Inputs Reference"); + CLI::App app("QIR Standalone Entry Point"); // Initialize simulator. unique_ptr sim = CreateFullstateSimulator(); QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); - // Add the --simulation-output options. - // N.B. This option should be present in all standalone drivers. + // Add the --simulation-output option. string simulationOutputFile; CLI::Option* simulationOutputFileOpt = app.add_option( - "--simulation-output", simulationOutputFile, + "--simulation-output", + simulationOutputFile, "File where the output produced during the simulation is written"); - RangeTuple RangeArgCliValue; - app.add_option("--RangeArg", RangeArgCliValue, "A Range (start, step, end) value for the RangeArg argument")->required(); + // Add a command line option for each entry-point parameter. + RangeTuple RangeArgCli; + app.add_option("--RangeArg", RangeArgCli, "Option to provide a value for the RangeArg parameter") + ->required(); - // With all the options added, parse arguments from the command line. + // After all the options have been added, parse arguments from the command line. CLI11_PARSE(app, argc, argv); - // Create an interop range. - unique_ptr RangeArgInteropValue = CreateInteropRange(RangeArgCliValue); + // Cast parsed arguments to its interop types. + InteropRange* RangeArgInterop = TranslateRangeTupleToInteropRangePointer(RangeArgCli); // Redirect the simulator output from std::cout if the --simulation-output option is present. ostream* simulatorOutputStream = &cout; @@ -92,15 +90,17 @@ int main(int argc, char* argv[]) simulatorOutputStream = &simulationOutputFileStream; } - // Run simulation and write the output of the operation to the corresponding stream. - UseRangeArgWithValues( - RangeArgInteropValue.get() + // Execute the entry point operation. + UseRangeArg( + RangeArgInterop ); - + // Flush the output of the simulation. simulatorOutputStream->flush(); if (simulationOutputFileStream.is_open()) { simulationOutputFileStream.close(); } + + return 0; } diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseRangeArrayArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseRangeArrayArg.cpp index fd94f3bad50..354999a5251 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseRangeArrayArg.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseRangeArrayArg.cpp @@ -2,9 +2,6 @@ // This code was generated by a tool. // //------------------------------------------------------------------------------ -// -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. #include #include @@ -14,14 +11,15 @@ #include "CLI11.hpp" -#include "QirContext.hpp" #include "QirRuntime.hpp" +#include "QirContext.hpp" + #include "SimFactory.hpp" using namespace Microsoft::Quantum; using namespace std; - +// Auxiliary functions for interop with Q# Array type. struct InteropArray { int64_t Size; @@ -46,6 +44,7 @@ void TranslateVector(vector& sourceVector, vector& destinationVector, func transform(sourceVector.begin(), sourceVector.end(), destinationVector.begin(), translationFunction); } +// Auxiliary functions for interop with Q# Range type. using RangeTuple = tuple; struct InteropRange { @@ -76,6 +75,7 @@ InteropRange* TranslateRangeTupleToInteropRangePointer(RangeTuple& rangeTuple) return range; } +// Auxiliary functions for interop with Q# Range[] type template void FreePointerVector(vector& v) { @@ -85,36 +85,38 @@ void FreePointerVector(vector& v) } } -// This is the function corresponding to the QIR entry-point. -extern "C" void UseRangeArrayArgWithValues( // NOLINT - InteropArray* RangeArrayArgInteropValue -); - +extern "C" void UseRangeArrayArg( + InteropArray* RangeArrayArg +); // QIR interop function. int main(int argc, char* argv[]) { - CLI::App app("QIR Standalone Entry Point Inputs Reference"); + CLI::App app("QIR Standalone Entry Point"); // Initialize simulator. unique_ptr sim = CreateFullstateSimulator(); QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); - // Add the --simulation-output options. - // N.B. This option should be present in all standalone drivers. + // Add the --simulation-output option. string simulationOutputFile; CLI::Option* simulationOutputFileOpt = app.add_option( - "--simulation-output", simulationOutputFile, + "--simulation-output", + simulationOutputFile, "File where the output produced during the simulation is written"); - vector RangeArrayArgCliValue; - app.add_option("--RangeArrayArg", RangeArrayArgCliValue, "A Range array value for the RangeArrayArg argument")->required(); + // Add a command line option for each entry-point parameter. + vector RangeArrayArgCli; + app.add_option("--RangeArrayArg", RangeArrayArgCli, "Option to provide a value for the RangeArrayArg parameter") + ->required(); - // With all the options added, parse arguments from the command line. + // After all the options have been added, parse arguments from the command line. CLI11_PARSE(app, argc, argv); - vector RangeArrayArgIntermediateValue; - TranslateVector(RangeArrayArgCliValue, RangeArrayArgIntermediateValue, TranslateRangeTupleToInteropRangePointer); - unique_ptr RangeArrayArgInteropValue = CreateInteropArray(RangeArrayArgIntermediateValue); + // Cast parsed arguments to its interop types. + vector RangeArrayArgIntermediate; + TranslateVector(RangeArrayArgCli, RangeArrayArgIntermediate, TranslateRangeTupleToInteropRangePointer); + unique_ptr RangeArrayArgUniquePtr = CreateInteropArray(RangeArrayArgIntermediate); + InteropArray* RangeArrayArgInterop = RangeArrayArgUniquePtr.get(); // Redirect the simulator output from std::cout if the --simulation-output option is present. ostream* simulatorOutputStream = &cout; @@ -126,15 +128,17 @@ int main(int argc, char* argv[]) simulatorOutputStream = &simulationOutputFileStream; } - // Run simulation and write the output of the operation to the corresponding stream. - UseRangeArrayArgWithValues( - RangeArrayArgInteropValue.get() + // Execute the entry point operation. + UseRangeArrayArg( + RangeArrayArgInterop ); - + // Flush the output of the simulation. simulatorOutputStream->flush(); if (simulationOutputFileStream.is_open()) { simulationOutputFileStream.close(); } + + return 0; } diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArrayArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArrayArg.cpp index eb10cb2c3b4..2f5f36c09e1 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArrayArg.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseResultArrayArg.cpp @@ -2,9 +2,6 @@ // This code was generated by a tool. // //------------------------------------------------------------------------------ -// -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. #include #include @@ -14,14 +11,15 @@ #include "CLI11.hpp" -#include "QirContext.hpp" #include "QirRuntime.hpp" +#include "QirContext.hpp" + #include "SimFactory.hpp" using namespace Microsoft::Quantum; using namespace std; - +// Auxiliary functions for interop with Q# Array type. struct InteropArray { int64_t Size; @@ -46,12 +44,7 @@ void TranslateVector(vector& sourceVector, vector& destinationVector, func transform(sourceVector.begin(), sourceVector.end(), destinationVector.begin(), translationFunction); } -// This is the function corresponding to the QIR entry-point. -extern "C" void UseResultArrayArgWithValues( // NOLINT - InteropArray* ResultArrayArgInteropValue -); - - +// Auxiliary functions for interop with Q# Result type. const char InteropResultZeroAsChar = 0x0; const char InteropResultOneAsChar = 0x1; map ResultAsCharMap{ @@ -61,31 +54,37 @@ map ResultAsCharMap{ {"One", InteropResultOneAsChar} }; +extern "C" void UseResultArrayArg( + InteropArray* ResultArrayArg +); // QIR interop function. + int main(int argc, char* argv[]) { - CLI::App app("QIR Standalone Entry Point Inputs Reference"); + CLI::App app("QIR Standalone Entry Point"); // Initialize simulator. unique_ptr sim = CreateFullstateSimulator(); QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); - // Add the --simulation-output options. - // N.B. This option should be present in all standalone drivers. + // Add the --simulation-output option. string simulationOutputFile; CLI::Option* simulationOutputFileOpt = app.add_option( - "--simulation-output", simulationOutputFile, + "--simulation-output", + simulationOutputFile, "File where the output produced during the simulation is written"); - vector ResultArrayArgCliValue; - app.add_option("--ResultArrayArg", ResultArrayArgCliValue, "A Result array value for the ResultArrayArg argument")->required() + // Add a command line option for each entry-point parameter. + vector ResultArrayArgCli; + app.add_option("--ResultArrayArg", ResultArrayArgCli, "Option to provide a value for the ResultArrayArg parameter") + ->required() ->transform(CLI::CheckedTransformer(ResultAsCharMap, CLI::ignore_case)); - // With all the options added, parse arguments from the command line. + // After all the options have been added, parse arguments from the command line. CLI11_PARSE(app, argc, argv); - // Translate values to its final form after parsing. - // Create an interop array of values. - unique_ptr ResultArrayArgInteropValue = CreateInteropArray(ResultArrayArgCliValue); + // Cast parsed arguments to its interop types. + unique_ptr ResultArrayArgUniquePtr = CreateInteropArray(ResultArrayArgCli); + InteropArray* ResultArrayArgInterop = ResultArrayArgUniquePtr.get(); // Redirect the simulator output from std::cout if the --simulation-output option is present. ostream* simulatorOutputStream = &cout; @@ -97,15 +96,17 @@ int main(int argc, char* argv[]) simulatorOutputStream = &simulationOutputFileStream; } - // Run simulation and write the output of the operation to the corresponding stream. - UseResultArrayArgWithValues( - ResultArrayArgInteropValue.get() + // Execute the entry point operation. + UseResultArrayArg( + ResultArrayArgInterop ); - + // Flush the output of the simulation. simulatorOutputStream->flush(); if (simulationOutputFileStream.is_open()) { simulationOutputFileStream.close(); } + + return 0; } diff --git a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseStringArg.cpp b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseStringArg.cpp index 6dae3fe59b7..bdfc37c878b 100644 --- a/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseStringArg.cpp +++ b/src/Qir/Execution/Tests.Microsoft.Quantum.Qir.Tools/TestCases/FullStateDriverGenerator/UseStringArg.cpp @@ -2,9 +2,6 @@ // This code was generated by a tool. // //------------------------------------------------------------------------------ -// -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. #include #include @@ -14,47 +11,49 @@ #include "CLI11.hpp" -#include "QirContext.hpp" #include "QirRuntime.hpp" +#include "QirContext.hpp" + #include "SimFactory.hpp" using namespace Microsoft::Quantum; using namespace std; - - -// This is the function corresponding to the QIR entry-point. -extern "C" void UseStringArgWithValues( // NOLINT - const char* StringArgInteropValue -); - - +// Auxiliary functions for interop with Q# String type. const char* TranslateStringToCharBuffer(string& s) { return s.c_str(); } + +extern "C" void UseStringArg( + const char* StringArg +); // QIR interop function. + int main(int argc, char* argv[]) { - CLI::App app("QIR Standalone Entry Point Inputs Reference"); + CLI::App app("QIR Standalone Entry Point"); // Initialize simulator. unique_ptr sim = CreateFullstateSimulator(); QirContextScope qirctx(sim.get(), false /*trackAllocatedObjects*/); - // Add the --simulation-output options. - // N.B. This option should be present in all standalone drivers. + // Add the --simulation-output option. string simulationOutputFile; CLI::Option* simulationOutputFileOpt = app.add_option( - "--simulation-output", simulationOutputFile, + "--simulation-output", + simulationOutputFile, "File where the output produced during the simulation is written"); - string StringArgCliValue; - app.add_option("--StringArg", StringArgCliValue, "A String value for the StringArg argument")->required(); + // Add a command line option for each entry-point parameter. + string StringArgCli; + app.add_option("--StringArg", StringArgCli, "Option to provide a value for the StringArg parameter") + ->required(); - // With all the options added, parse arguments from the command line. + // After all the options have been added, parse arguments from the command line. CLI11_PARSE(app, argc, argv); - string StringArgInteropValue = StringArgCliValue; + // Cast parsed arguments to its interop types. + const char* StringArgInterop = TranslateStringToCharBuffer(StringArgCli); // Redirect the simulator output from std::cout if the --simulation-output option is present. ostream* simulatorOutputStream = &cout; @@ -66,15 +65,17 @@ int main(int argc, char* argv[]) simulatorOutputStream = &simulationOutputFileStream; } - // Run simulation and write the output of the operation to the corresponding stream. - UseStringArgWithValues( - StringArgInteropValue.c_str() + // Execute the entry point operation. + UseStringArg( + StringArgInterop ); - + // Flush the output of the simulation. simulatorOutputStream->flush(); if (simulationOutputFileStream.is_open()) { simulationOutputFileStream.close(); } + + return 0; }