コード例 #1
0
        /// <summary>
        /// Create the template output
        /// </summary>
        public virtual string TransformText()
        {
            this.Write(@"//----------------------------------------------------------------------------------------------------------------------
// <auto-generated />
// This code was generated by the Microsoft.Quantum.Qir.Runtime.Tools package.
// The purpose of this source code file is to provide an entry-point for executing a QIR program.
// It handles parsing of command line arguments, and it invokes an entry-point function exposed by the QIR program.
//----------------------------------------------------------------------------------------------------------------------

#include <fstream>
#include <iostream>
#include <map>
#include <memory>
#include <vector>

#include ""CLI11.hpp""

#include ""QirRuntime.hpp""
#include ""QirContext.hpp""

");
            foreach (var header in RuntimeInitializer.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){}
};

template<typename T>
unique_ptr<InteropArray> CreateInteropArray(vector<T>& v)
{
    unique_ptr<InteropArray> array(new InteropArray(v.size(), v.data()));
    return array;
}

template<typename S, typename D>
void TranslateVector(vector<S>& sourceVector, vector<D>& destinationVector, function<D(S&)> 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<int64_t, int64_t, int64_t>;
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<InteropRange> CreateInteropRange(RangeTuple rangeTuple)
{
    unique_ptr<InteropRange> 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<typename T>\r\n" +
                           "void FreePointerVector(vector<T*>& 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<string, bool> ");
                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<string, PauliId> ");
                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<char>(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<string, char>" +
                           " ");
                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.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(" ");
                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    CLI::App " +
                       "app(\"QIR Standalone Entry Point\");\r\n\r\n    // Initialize runtime.\r\n");
            var    initializerReader = new StringReader(RuntimeInitializer.Generate());
            string line;

            while ((line = initializerReader.ReadLine()) != null)
            {
                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.Parameters.Count > 0)
            {
                this.Write("    // Add a command line option for each entry-point parameter.\r\n");
            }
            foreach (var arg in EntryPoint.Parameters)
            {
                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.Parameters.Count > 0)
            {
                this.Write("    // Cast parsed arguments to its interop types.\r\n");
            }
            foreach (var arg in EntryPoint.Parameters)
            {
                if (arg.Type == DataType.ArrayType)
                {
                    var arrayInteropTranslator = QirCppInterop.CliOptionTypeToInteropTypeTranslator(arg.ArrayType);
                    if (arrayInteropTranslator == null)
                    {
                        this.Write("    unique_ptr<InteropArray> ");
                        this.Write(this.ToStringHelper.ToStringWithCulture(arg.UniquePtrVariableName()));
                        this.Write(" = CreateInteropArray(");
                        this.Write(this.ToStringHelper.ToStringWithCulture(arg.CliOptionVariableName()));
                        this.Write(");\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    unique_ptr<InteropArray> ");
                        this.Write(this.ToStringHelper.ToStringWithCulture(arg.UniquePtrVariableName()));
                        this.Write(" = CreateInteropArray(");
                        this.Write(this.ToStringHelper.ToStringWithCulture(arg.IntermediateVariableName()));
                        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);
                    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
                    {
                        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);
        SetOutputStream(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.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) ? "" : ","));
                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());
        }