From 259a112e44fb37029b46ba11cd2f631f82ce7e87 Mon Sep 17 00:00:00 2001 From: Anton Borissov Date: Fri, 23 May 2025 11:40:49 -0400 Subject: [PATCH 1/4] init json.cpp --- src/tools/json.cpp | 93 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 src/tools/json.cpp diff --git a/src/tools/json.cpp b/src/tools/json.cpp new file mode 100644 index 00000000..a2d7d1af --- /dev/null +++ b/src/tools/json.cpp @@ -0,0 +1,93 @@ +#include +#include "qasmtools/ast/stmt.hpp" +#include "qasmtools/parser/parser.hpp" +#include + +using json = nlohmann::json; + +/* Forward declarations */ +// class VarAccess; +// class BExpr; +// class UExpr; +// class PiExpr; +// class IntExpr; +// class RealExpr; +// class VarExpr; +// class MeasureStmt; +// class ResetStmt; +// class IfStmt; +// class UGate; +// class CNOTGate; +// class BarrierGate; +// class DeclaredGate; +// class GateDecl; +// class OracleDecl; +// class RegisterDecl; +// class AncillaDecl; +// class Program; + +json jsonify(qasmtools::ast::Stmt& st){ + json j; + return j; +} + + +json jsonify(qasmtools::ast::Program& p){ + json j; + p.foreach_stmt([&](qasmtools::ast::Stmt& st){ + j.push_back(jsonify(st)); + }); + return j; +} + +int main(int argc, char** argv) { + // using namespace staq; + using qasmtools::parser::parse_file; + + if (argc == 1) { + std::cout << "Usage: staq [PASSES/OPTIONS] FILE.qasm\n" + << "Run with --help for more information.\n"; + return 0; + } + std::string input_qasm; + + CLI::App app{"staq -- A full-stack quantum processing toolkit"}; + app.allow_extras(); + + app.add_option("FILE.qasm", input_qasm, "OpenQASM circuit") + ->required() + ->check(CLI::ExistingFile); + + CLI11_PARSE(app, argc, argv); + try { + auto prog = parse_file(input_qasm); // Default std_include=true + if (!prog) { + // This case might not be reached if parse_file throws on error, + // but good to keep for parsers that might return nullptr. + std::cerr << "Error: failed to parse \"" << input_qasm + << "\" (parser returned null).\n"; + return 1; + } + + // create json + //auto jsonified = qasmtools::ast::jsonify(*prog); + //std::cout << jsonified._json().dump() << std::endl; + json jsonified = jsonify(*prog); + std::cout << jsonified.dump() << std::endl; + return 0; + } catch (const qasmtools::parser::ParseError& e) { + std::cerr << "ParseError: " << e.what() << std::endl; + std::cerr + << "Parsing failed. The error messages above this one (if any) " + "from the parser provide details about the location of the " + "syntax error(s) in the QASM file." + << std::endl; + return 1; + } catch (const std::exception& e) { + std::cerr << "An unexpected error occurred: " << e.what() << std::endl; + return 1; + } + + return 0; +} + From 1327dfa40c1c6d4d8fd21a01fbd9559a46b95532 Mon Sep 17 00:00:00 2001 From: Anton Borissov Date: Tue, 27 May 2025 00:55:22 -0400 Subject: [PATCH 2/4] added pybindings --- pystaq/include/pystaq/pystaq_common.hpp | 1 + pystaq/staq_wrapper.cpp | 6 + src/tools/json.cpp | 202 ++++++++++++++++++++---- 3 files changed, 180 insertions(+), 29 deletions(-) diff --git a/pystaq/include/pystaq/pystaq_common.hpp b/pystaq/include/pystaq/pystaq_common.hpp index 28f368cb..29aafb61 100644 --- a/pystaq/include/pystaq/pystaq_common.hpp +++ b/pystaq/include/pystaq/pystaq_common.hpp @@ -60,6 +60,7 @@ #include "staq/output/cirq.hpp" #include "staq/output/ionq.hpp" +#include "staq/output/json.hpp" #include "staq/output/lattice_surgery.hpp" #include "staq/output/projectq.hpp" #include "staq/output/qsharp.hpp" diff --git a/pystaq/staq_wrapper.cpp b/pystaq/staq_wrapper.cpp index c383cd22..96a7e7ea 100644 --- a/pystaq/staq_wrapper.cpp +++ b/pystaq/staq_wrapper.cpp @@ -158,6 +158,11 @@ class Program { outputter.run(*prog_); return oss.str(); } + std::string to_json() { + staq::output::JSONOutputter outputter; + outputter.run(*prog_); + return outputter.json_val().dump(); + } std::string lattice_surgery() { return staq::output::lattice_surgery(*prog_); } @@ -283,6 +288,7 @@ PYBIND11_MODULE(pystaq, m) { .def("to_qsharp", &Program::to_qsharp, "Get the Q# representation") .def("to_quil", &Program::to_quil, "Get the Quil representation") .def("to_ionq", &Program::to_ionq, "Get the IonQ representation") + .def("to_json", &Program::to_json, "Get the JSON representation") .def("__repr__", [](const Program& p) { std::ostringstream oss; oss << p; diff --git a/src/tools/json.cpp b/src/tools/json.cpp index a2d7d1af..08ceb22f 100644 --- a/src/tools/json.cpp +++ b/src/tools/json.cpp @@ -1,42 +1,187 @@ +#include +#include +#include #include +#include "qasmtools/ast/decl.hpp" #include "qasmtools/ast/stmt.hpp" +#include "qasmtools/ast/var.hpp" #include "qasmtools/parser/parser.hpp" -#include using json = nlohmann::json; /* Forward declarations */ -// class VarAccess; -// class BExpr; -// class UExpr; -// class PiExpr; -// class IntExpr; -// class RealExpr; -// class VarExpr; -// class MeasureStmt; -// class ResetStmt; -// class IfStmt; -// class UGate; -// class CNOTGate; -// class BarrierGate; -// class DeclaredGate; -// class GateDecl; -// class OracleDecl; -// class RegisterDecl; -// class AncillaDecl; -// class Program; - -json jsonify(qasmtools::ast::Stmt& st){ +// [x] class VarAccess; +// [x] class BExpr,UExpr,PiExpr,IntExpr,RealExpr,VarExpr; +// [ ] class MeasureStmt,ResetStmt,IfStmt, +// [x] class UGate,CNOTGate,BarrierGate,DeclaredGate, +// [ ] class GateDecl,OracleDecl,RegisterDecl,AncillaDecl; +// [ ] class Program; + +json jsonify(qasmtools::ast::VarAccess&); +json jsonify(qasmtools::ast::Expr&); +json jsonify(qasmtools::ast::Gate&); +json jsonify(qasmtools::ast::GateDecl&); +json jsonify(qasmtools::ast::Stmt&); +json jsonify(qasmtools::ast::MeasureStmt&); +json jsonify(qasmtools::ast::ResetStmt&); +json jsonify(qasmtools::ast::OracleDecl&); +json jsonify(qasmtools::ast::RegisterDecl&); +json jsonify(qasmtools::ast::AncillaDecl&); +json jsonify(qasmtools::ast::IfStmt&); +json jsonify(qasmtools::ast::Program&); + +json jsonify(qasmtools::ast::AncillaDecl& ad) { + json j; + j["type"] = "AncillaDecl"; + j["name"] = ad.id(); + j["size"] = ad.size(); + j["is_dirty"] = (ad.is_dirty() ? 1 : 0); + return j; +} + +json jsonify(qasmtools::ast::RegisterDecl& rd) { + json j; + j["type"] = "RegisterDecl"; + j["name"] = rd.id(); + j["is_quantum"] = (rd.is_quantum() ? 1 : 0); + j["size"] = rd.size(); + return j; +} + +json jsonify(qasmtools::ast::OracleDecl& od) { + // TODO: verify that this is doing what it needs to do + json j; + j["type"] = "OracleDecl"; + j["name"] = od.fname(); + j["params"] = od.params(); + return j; +} + +json jsonify(qasmtools::ast::IfStmt& ist) { + // TODO: Improve this later. + json j; + std::stringstream in; + ist.pretty_print(in, false); + j["type"] = "IfStmt"; + j["name"] = "If"; + j["body"] = in.str(); + return j; +} + +json jsonify(qasmtools::ast::ResetStmt& rst) { + json j; + j["type"] = "ResetStmt"; + j["name"] = "Reset"; + j["qarg"] = jsonify(rst.arg()); + return j; +} + +json jsonify(qasmtools::ast::MeasureStmt& mst) { + json j; + j["type"] = "MeasureStmt"; + j["name"] = "Measurement"; + j["qarg"] = jsonify(mst.q_arg()); + j["carg"] = jsonify(mst.c_arg()); + return j; +} + +json jsonify(qasmtools::ast::VarAccess& va) { json j; + j["type"] = "VarAccess"; + j["name"] = "qubit"; + j["symbol"] = va.var(); + j["offset"] = {}; + if (va.offset().has_value()) { + j["offset"].push_back(va.offset().value()); + } return j; } +json jsonify(qasmtools::ast::Expr& expr) { + json j; + std::stringstream in; + expr.pretty_print(in); + auto ev = expr.constant_eval(); + j["type"] = "Expr"; + j["expr"] = in.str(); + j["val"] = {}; + if (ev.has_value()) { + j["val"].push_back(ev.value()); + } + return j; +} -json jsonify(qasmtools::ast::Program& p){ +json jsonify(qasmtools::ast::Gate& g) { + using namespace qasmtools::ast; json j; - p.foreach_stmt([&](qasmtools::ast::Stmt& st){ - j.push_back(jsonify(st)); - }); + j["type"] = "Gate"; + if (UGate* gd = dynamic_cast(&g)) { + j["name"] = "UGate"; + j["qargs"] = {jsonify(gd->arg())}; + j["cargs"] = {jsonify(gd->theta()), jsonify(gd->phi()), + jsonify(gd->lambda())}; + } else if (CNOTGate* gd = dynamic_cast(&g)) { + j["name"] = "CNOTGate"; + j["qargs"] = {jsonify(gd->ctrl()), jsonify(gd->tgt())}; + } else if (BarrierGate* gd = dynamic_cast(&g)) { + j["name"] = "BarrierGate"; + j["qargs"] = {}; + gd->foreach_arg( + [&j](VarAccess& va) { j["qargs"].push_back(jsonify(va)); }); + } else if (DeclaredGate* gd = dynamic_cast(&g)) { + j["name"] = gd->name(); + j["qargs"] = {}; + j["cargs"] = {}; + gd->foreach_qarg( + [&j](VarAccess& va) { j["qargs"].push_back(jsonify(va)); }); + gd->foreach_carg([&j](Expr& va) { j["cargs"].push_back(jsonify(va)); }); + } else { + throw ""; + } + return j; +} + +json jsonify(qasmtools::ast::GateDecl& gd) { + using namespace qasmtools::ast; + json j; + j["type"] = "GateDecl"; + j["name"] = gd.id(); + j["q_params"] = gd.q_params(); + j["c_params"] = gd.c_params(); + j["body"] = {}; // process the body of a GateDecl; + gd.foreach_stmt([&j](Stmt& st) { j["body"].push_back(jsonify(st)); }); + return j; +} + +json jsonify(qasmtools::ast::Stmt& st) { + using namespace qasmtools::ast; + if (GateDecl* gd = dynamic_cast(&st)) { + return jsonify(*gd); + } else if (Gate* gd = dynamic_cast(&st)) { + return jsonify(*gd); + } else if (Gate* gd = dynamic_cast(&st)) { + return jsonify(*gd); + } else if (MeasureStmt* gd = dynamic_cast(&st)) { + return jsonify(*gd); + } else if (ResetStmt* gd = dynamic_cast(&st)) { + return jsonify(*gd); + } else if (OracleDecl* gd = dynamic_cast(&st)) { + return jsonify(*gd); + } else if (RegisterDecl* gd = dynamic_cast(&st)) { + return jsonify(*gd); + } else if (AncillaDecl* gd = dynamic_cast(&st)) { + return jsonify(*gd); + } else if (IfStmt* gd = dynamic_cast(&st)) { + return jsonify(*gd); + } else { + throw ""; + } +} + +json jsonify(qasmtools::ast::Program& p) { + using namespace qasmtools::ast; + json j; + p.foreach_stmt([&](Stmt& st) { j.push_back(jsonify(st)); }); return j; } @@ -70,8 +215,8 @@ int main(int argc, char** argv) { } // create json - //auto jsonified = qasmtools::ast::jsonify(*prog); - //std::cout << jsonified._json().dump() << std::endl; + // auto jsonified = qasmtools::ast::jsonify(*prog); + // std::cout << jsonified._json().dump() << std::endl; json jsonified = jsonify(*prog); std::cout << jsonified.dump() << std::endl; return 0; @@ -90,4 +235,3 @@ int main(int argc, char** argv) { return 0; } - From dfa623f7840c20b9692b61c5f5b758395455004b Mon Sep 17 00:00:00 2001 From: Anton Borissov Date: Tue, 27 May 2025 00:57:03 -0400 Subject: [PATCH 3/4] added pybindings --- include/staq/output/json.hpp | 290 +++++++++++++++++++++++++++++++++++ 1 file changed, 290 insertions(+) create mode 100644 include/staq/output/json.hpp diff --git a/include/staq/output/json.hpp b/include/staq/output/json.hpp new file mode 100644 index 00000000..ea90f962 --- /dev/null +++ b/include/staq/output/json.hpp @@ -0,0 +1,290 @@ +/* + * This file is part of staq. + * + * Copyright (c) 2019 - 2025 softwareQ Inc. All rights reserved. + * + * MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef OUTPUT_JSON_HPP_ +#define OUTPUT_JSON_HPP_ + +#include +#include +#include +#include +#include "qasmtools/ast/decl.hpp" +#include "qasmtools/ast/stmt.hpp" +#include "qasmtools/ast/var.hpp" +#include "qasmtools/parser/parser.hpp" + +#include + +#include "qasmtools/ast/ast.hpp" + +namespace staq { +namespace output { + +using namespace qasmtools::ast; +using json = nlohmann::json; + +/** + * \class staq::output::JSONOutputter + * \brief Visitor for converting a QASM AST to JSON + */ +class JSONOutputter final : public Visitor { + public: + JSONOutputter() = default; + ~JSONOutputter() = default; + + void run(Program& prog) { prog.accept(*this); } + + void visit(UGate& gd) override { + json j; + j["type"] = "Gate"; + JSONOutputter arg0, arg1, arg2, arg3; + gd.arg().accept(arg0); + gd.arg().accept(arg1); + gd.arg().accept(arg2); + gd.arg().accept(arg3); + j["name"] = "UGate"; + j["qargs"] = {arg0.json_val()}; + j["cargs"] = {arg1.json_val(), arg2.json_val(), arg3.json_val()}; + json_.push_back(j); + } + void visit(CNOTGate& gd) override { + json j; + j["type"] = "Gate"; + JSONOutputter arg0, arg1; + gd.ctrl().accept(arg0); + gd.tgt().accept(arg1); + j["name"] = "CNOTGate"; + j["qargs"] = {arg0.json_val(), arg1.json_val()}; + } + void visit(BarrierGate& gd) override { + using namespace qasmtools::ast; + json j; + j["type"] = "Gate"; + j["name"] = "BarrierGate"; + j["qargs"] = {}; + gd.foreach_arg([&j](VarAccess& va) { + JSONOutputter jva; + va.accept(jva); + j["qargs"].push_back(jva.json_val()); + }); + } + void visit(DeclaredGate& gd) override { + using namespace qasmtools::ast; + json j; + j["type"] = "Gate"; + j["name"] = gd.name(); + j["qargs"] = {}; + j["cargs"] = {}; + gd.foreach_qarg([&j](VarAccess& va) { + JSONOutputter jva; + va.accept(jva); + j["qargs"].push_back(jva.json_val()); + }); + gd.foreach_carg([&j](Expr& va) { + JSONOutputter jva; + va.accept(jva); + j["cargs"].push_back(jva.json_val()); + }); + } + + void visit(AncillaDecl& ad) override { + json j; + j["type"] = "AncillaDecl"; + j["name"] = ad.id(); + j["size"] = ad.size(); + j["is_dirty"] = (ad.is_dirty() ? 1 : 0); + json_.push_back(j); + } + + void visit(RegisterDecl& rd) override { + json j; + j["type"] = "RegisterDecl"; + j["name"] = rd.id(); + j["is_quantum"] = (rd.is_quantum() ? 1 : 0); + j["size"] = rd.size(); + json_.push_back(j); + } + + void visit(OracleDecl& od) override { + // TODO: verify that this is doing what it needs to do + json j; + j["type"] = "OracleDecl"; + j["name"] = od.fname(); + j["params"] = od.params(); + json_.push_back(j); + } + + void visit(IfStmt& ist) { + // TODO: Improve this later. + json j; + std::stringstream in; + ist.pretty_print(in, false); + j["type"] = "IfStmt"; + j["name"] = "If"; + j["body"] = in.str(); + json_.push_back(j); + } + + void visit(ResetStmt& rst) override { + json j; + JSONOutputter arg_json_outputter; + rst.arg().accept(arg_json_outputter); + j["type"] = "ResetStmt"; + j["name"] = "Reset"; + j["qarg"] = arg_json_outputter.json_val(); + json_.push_back(j); + } + + void visit(MeasureStmt& mst) override { + json j; + JSONOutputter arg_json_1, arg_json_2; + mst.q_arg().accept(arg_json_1); + mst.c_arg().accept(arg_json_2); + j["type"] = "MeasureStmt"; + j["name"] = "Measurement"; + j["qarg"] = arg_json_1.json_val(); + j["carg"] = arg_json_2.json_val(); + json_.push_back(j); + } + + void visit(VarAccess& va) override { + json j; + j["type"] = "VarAccess"; + j["name"] = "qubit"; + j["symbol"] = va.var(); + j["offset"] = {}; + if (va.offset().has_value()) { + j["offset"].push_back(va.offset().value()); + } + json_.push_back(j); + } + + // Expressions + void visit(BExpr& e) override {}; + void visit(UExpr& e) override {}; + void visit(PiExpr& e) override {}; + void visit(IntExpr& e) override {}; + void visit(RealExpr& e) override {}; + void visit(VarExpr& e) override {}; + + void visit(Expr& expr) { + json j; + std::stringstream in; + expr.pretty_print(in); + auto ev = expr.constant_eval(); + j["type"] = "Expr"; + j["expr"] = in.str(); + j["val"] = {}; + if (ev.has_value()) { + j["val"].push_back(ev.value()); + } + json_.push_back(j); + } + + // void visit(qasmtools::ast::Gate& g) override { + // using namespace qasmtools::ast; + // json j; + // + // j["type"] = "Gate"; + // if (UGate* gd = dynamic_cast(&g)) { + // JSONOutputter arg0, arg1, arg2, arg3; + // gd->arg().accept(arg0); + // gd->arg().accept(arg1); + // gd->arg().accept(arg2); + // gd->arg().accept(arg3); + // j["name"] = "UGate"; + // j["qargs"] = {arg0.json_val()}; + // j["cargs"] = {arg1.json_val(), arg2.json_val(), arg3.json_val()}; + // } else if (CNOTGate* gd = dynamic_cast(&g)) { + // //(typeid(g) == typeid(CNOTGate)) { + // JSONOutputter arg0, arg1; + // gd->ctrl().accept(arg0); + // gd->tgt().accept(arg1); + // j["name"] = "CNOTGate"; + // j["qargs"] = {arg0.json_val(), arg1.json_val()}; + // } else if (BarrierGate* gd = dynamic_cast(&g)) { + // j["name"] = "BarrierGate"; + // j["qargs"] = {}; + // gd->foreach_arg([&j](VarAccess& va) { + // JSONOutputter jva; + // va.accept(jva); + // j["qargs"].push_back(jva.json_val()); + // }); + // } else if (DeclaredGate* gd = dynamic_cast(&g)) { + // j["name"] = gd->name(); + // j["qargs"] = {}; + // j["cargs"] = {}; + // gd->foreach_qarg([&j](VarAccess& va) { + // JSONOutputter jva; + // va.accept(jva); + // j["qargs"].push_back(jva.json_val()); + // }); + // gd->foreach_carg([&j](Expr& va) { + // JSONOutputter jva; + // va.accept(jva); + // j["cargs"].push_back(jva.json_val()); + // }); + // } else { + // throw ""; + // } + // json_.push_back(j); + // } + + void visit(GateDecl& gd) override { + using namespace qasmtools::ast; + json j; + j["type"] = "GateDecl"; + j["name"] = gd.id(); + j["q_params"] = gd.q_params(); + j["c_params"] = gd.c_params(); + j["body"] = {}; // process the body of a GateDecl; + gd.foreach_stmt([&j](Stmt& st) { + JSONOutputter jst; + st.accept(jst); + j["body"].push_back(jst.json_val()); + }); + json_.push_back(j); + } + + void visit(Program& p) override { + using namespace qasmtools::ast; + p.foreach_stmt([&](Stmt& st) { + JSONOutputter jst; + st.accept(jst); + json_.push_back(jst.json_val()); + }); + } + + json json_val() { return json_; } + + private: + json json_; +}; + +} /* namespace output */ +} /* namespace staq */ + +#endif /* OUTPUT_JSON_HPP_ */ From 752aa7bca060d2fac0191a3ec26397558978fa9a Mon Sep 17 00:00:00 2001 From: Anton Borissov Date: Wed, 28 May 2025 11:57:23 -0400 Subject: [PATCH 4/4] upd tool --- include/staq/output/json.hpp | 4 +- src/tools/json.cpp | 370 ++++++++++++++++++----------------- 2 files changed, 189 insertions(+), 185 deletions(-) diff --git a/include/staq/output/json.hpp b/include/staq/output/json.hpp index ea90f962..82e3f0ff 100644 --- a/include/staq/output/json.hpp +++ b/include/staq/output/json.hpp @@ -27,10 +27,10 @@ #ifndef OUTPUT_JSON_HPP_ #define OUTPUT_JSON_HPP_ +#include #include #include #include -#include #include "qasmtools/ast/decl.hpp" #include "qasmtools/ast/stmt.hpp" #include "qasmtools/ast/var.hpp" @@ -137,7 +137,7 @@ class JSONOutputter final : public Visitor { json_.push_back(j); } - void visit(IfStmt& ist) { + void visit(IfStmt& ist) override { // TODO: Improve this later. json j; std::stringstream in; diff --git a/src/tools/json.cpp b/src/tools/json.cpp index 08ceb22f..4f8b2a79 100644 --- a/src/tools/json.cpp +++ b/src/tools/json.cpp @@ -1,189 +1,191 @@ +#include "staq/output/json.hpp" +#include #include #include #include -#include #include "qasmtools/ast/decl.hpp" #include "qasmtools/ast/stmt.hpp" #include "qasmtools/ast/var.hpp" #include "qasmtools/parser/parser.hpp" -using json = nlohmann::json; - -/* Forward declarations */ -// [x] class VarAccess; -// [x] class BExpr,UExpr,PiExpr,IntExpr,RealExpr,VarExpr; -// [ ] class MeasureStmt,ResetStmt,IfStmt, -// [x] class UGate,CNOTGate,BarrierGate,DeclaredGate, -// [ ] class GateDecl,OracleDecl,RegisterDecl,AncillaDecl; -// [ ] class Program; - -json jsonify(qasmtools::ast::VarAccess&); -json jsonify(qasmtools::ast::Expr&); -json jsonify(qasmtools::ast::Gate&); -json jsonify(qasmtools::ast::GateDecl&); -json jsonify(qasmtools::ast::Stmt&); -json jsonify(qasmtools::ast::MeasureStmt&); -json jsonify(qasmtools::ast::ResetStmt&); -json jsonify(qasmtools::ast::OracleDecl&); -json jsonify(qasmtools::ast::RegisterDecl&); -json jsonify(qasmtools::ast::AncillaDecl&); -json jsonify(qasmtools::ast::IfStmt&); -json jsonify(qasmtools::ast::Program&); - -json jsonify(qasmtools::ast::AncillaDecl& ad) { - json j; - j["type"] = "AncillaDecl"; - j["name"] = ad.id(); - j["size"] = ad.size(); - j["is_dirty"] = (ad.is_dirty() ? 1 : 0); - return j; -} - -json jsonify(qasmtools::ast::RegisterDecl& rd) { - json j; - j["type"] = "RegisterDecl"; - j["name"] = rd.id(); - j["is_quantum"] = (rd.is_quantum() ? 1 : 0); - j["size"] = rd.size(); - return j; -} - -json jsonify(qasmtools::ast::OracleDecl& od) { - // TODO: verify that this is doing what it needs to do - json j; - j["type"] = "OracleDecl"; - j["name"] = od.fname(); - j["params"] = od.params(); - return j; -} - -json jsonify(qasmtools::ast::IfStmt& ist) { - // TODO: Improve this later. - json j; - std::stringstream in; - ist.pretty_print(in, false); - j["type"] = "IfStmt"; - j["name"] = "If"; - j["body"] = in.str(); - return j; -} - -json jsonify(qasmtools::ast::ResetStmt& rst) { - json j; - j["type"] = "ResetStmt"; - j["name"] = "Reset"; - j["qarg"] = jsonify(rst.arg()); - return j; -} - -json jsonify(qasmtools::ast::MeasureStmt& mst) { - json j; - j["type"] = "MeasureStmt"; - j["name"] = "Measurement"; - j["qarg"] = jsonify(mst.q_arg()); - j["carg"] = jsonify(mst.c_arg()); - return j; -} - -json jsonify(qasmtools::ast::VarAccess& va) { - json j; - j["type"] = "VarAccess"; - j["name"] = "qubit"; - j["symbol"] = va.var(); - j["offset"] = {}; - if (va.offset().has_value()) { - j["offset"].push_back(va.offset().value()); - } - return j; -} - -json jsonify(qasmtools::ast::Expr& expr) { - json j; - std::stringstream in; - expr.pretty_print(in); - auto ev = expr.constant_eval(); - j["type"] = "Expr"; - j["expr"] = in.str(); - j["val"] = {}; - if (ev.has_value()) { - j["val"].push_back(ev.value()); - } - return j; -} - -json jsonify(qasmtools::ast::Gate& g) { - using namespace qasmtools::ast; - json j; - j["type"] = "Gate"; - if (UGate* gd = dynamic_cast(&g)) { - j["name"] = "UGate"; - j["qargs"] = {jsonify(gd->arg())}; - j["cargs"] = {jsonify(gd->theta()), jsonify(gd->phi()), - jsonify(gd->lambda())}; - } else if (CNOTGate* gd = dynamic_cast(&g)) { - j["name"] = "CNOTGate"; - j["qargs"] = {jsonify(gd->ctrl()), jsonify(gd->tgt())}; - } else if (BarrierGate* gd = dynamic_cast(&g)) { - j["name"] = "BarrierGate"; - j["qargs"] = {}; - gd->foreach_arg( - [&j](VarAccess& va) { j["qargs"].push_back(jsonify(va)); }); - } else if (DeclaredGate* gd = dynamic_cast(&g)) { - j["name"] = gd->name(); - j["qargs"] = {}; - j["cargs"] = {}; - gd->foreach_qarg( - [&j](VarAccess& va) { j["qargs"].push_back(jsonify(va)); }); - gd->foreach_carg([&j](Expr& va) { j["cargs"].push_back(jsonify(va)); }); - } else { - throw ""; - } - return j; -} - -json jsonify(qasmtools::ast::GateDecl& gd) { - using namespace qasmtools::ast; - json j; - j["type"] = "GateDecl"; - j["name"] = gd.id(); - j["q_params"] = gd.q_params(); - j["c_params"] = gd.c_params(); - j["body"] = {}; // process the body of a GateDecl; - gd.foreach_stmt([&j](Stmt& st) { j["body"].push_back(jsonify(st)); }); - return j; -} - -json jsonify(qasmtools::ast::Stmt& st) { - using namespace qasmtools::ast; - if (GateDecl* gd = dynamic_cast(&st)) { - return jsonify(*gd); - } else if (Gate* gd = dynamic_cast(&st)) { - return jsonify(*gd); - } else if (Gate* gd = dynamic_cast(&st)) { - return jsonify(*gd); - } else if (MeasureStmt* gd = dynamic_cast(&st)) { - return jsonify(*gd); - } else if (ResetStmt* gd = dynamic_cast(&st)) { - return jsonify(*gd); - } else if (OracleDecl* gd = dynamic_cast(&st)) { - return jsonify(*gd); - } else if (RegisterDecl* gd = dynamic_cast(&st)) { - return jsonify(*gd); - } else if (AncillaDecl* gd = dynamic_cast(&st)) { - return jsonify(*gd); - } else if (IfStmt* gd = dynamic_cast(&st)) { - return jsonify(*gd); - } else { - throw ""; - } -} - -json jsonify(qasmtools::ast::Program& p) { - using namespace qasmtools::ast; - json j; - p.foreach_stmt([&](Stmt& st) { j.push_back(jsonify(st)); }); - return j; -} +// using json = nlohmann::json; +// +// /* Forward declarations */ +// // [x] class VarAccess; +// // [x] class BExpr,UExpr,PiExpr,IntExpr,RealExpr,VarExpr; +// // [ ] class MeasureStmt,ResetStmt,IfStmt, +// // [x] class UGate,CNOTGate,BarrierGate,DeclaredGate, +// // [ ] class GateDecl,OracleDecl,RegisterDecl,AncillaDecl; +// // [ ] class Program; +// +// json jsonify(qasmtools::ast::VarAccess&); +// json jsonify(qasmtools::ast::Expr&); +// json jsonify(qasmtools::ast::Gate&); +// json jsonify(qasmtools::ast::GateDecl&); +// json jsonify(qasmtools::ast::Stmt&); +// json jsonify(qasmtools::ast::MeasureStmt&); +// json jsonify(qasmtools::ast::ResetStmt&); +// json jsonify(qasmtools::ast::OracleDecl&); +// json jsonify(qasmtools::ast::RegisterDecl&); +// json jsonify(qasmtools::ast::AncillaDecl&); +// json jsonify(qasmtools::ast::IfStmt&); +// json jsonify(qasmtools::ast::Program&); +// +// json jsonify(qasmtools::ast::AncillaDecl& ad) { +// json j; +// j["type"] = "AncillaDecl"; +// j["name"] = ad.id(); +// j["size"] = ad.size(); +// j["is_dirty"] = (ad.is_dirty() ? 1 : 0); +// return j; +// } +// +// json jsonify(qasmtools::ast::RegisterDecl& rd) { +// json j; +// j["type"] = "RegisterDecl"; +// j["name"] = rd.id(); +// j["is_quantum"] = (rd.is_quantum() ? 1 : 0); +// j["size"] = rd.size(); +// return j; +// } +// +// json jsonify(qasmtools::ast::OracleDecl& od) { +// // TODO: verify that this is doing what it needs to do +// json j; +// j["type"] = "OracleDecl"; +// j["name"] = od.fname(); +// j["params"] = od.params(); +// return j; +// } +// +// json jsonify(qasmtools::ast::IfStmt& ist) { +// // TODO: Improve this later. +// json j; +// std::stringstream in; +// ist.pretty_print(in, false); +// j["type"] = "IfStmt"; +// j["name"] = "If"; +// j["body"] = in.str(); +// return j; +// } +// +// json jsonify(qasmtools::ast::ResetStmt& rst) { +// json j; +// j["type"] = "ResetStmt"; +// j["name"] = "Reset"; +// j["qarg"] = jsonify(rst.arg()); +// return j; +// } +// +// json jsonify(qasmtools::ast::MeasureStmt& mst) { +// json j; +// j["type"] = "MeasureStmt"; +// j["name"] = "Measurement"; +// j["qarg"] = jsonify(mst.q_arg()); +// j["carg"] = jsonify(mst.c_arg()); +// return j; +// } +// +// json jsonify(qasmtools::ast::VarAccess& va) { +// json j; +// j["type"] = "VarAccess"; +// j["name"] = "qubit"; +// j["symbol"] = va.var(); +// j["offset"] = {}; +// if (va.offset().has_value()) { +// j["offset"].push_back(va.offset().value()); +// } +// return j; +// } +// +// json jsonify(qasmtools::ast::Expr& expr) { +// json j; +// std::stringstream in; +// expr.pretty_print(in); +// auto ev = expr.constant_eval(); +// j["type"] = "Expr"; +// j["expr"] = in.str(); +// j["val"] = {}; +// if (ev.has_value()) { +// j["val"].push_back(ev.value()); +// } +// return j; +// } +// +// json jsonify(qasmtools::ast::Gate& g) { +// using namespace qasmtools::ast; +// json j; +// j["type"] = "Gate"; +// if (UGate* gd = dynamic_cast(&g)) { +// j["name"] = "UGate"; +// j["qargs"] = {jsonify(gd->arg())}; +// j["cargs"] = {jsonify(gd->theta()), jsonify(gd->phi()), +// jsonify(gd->lambda())}; +// } else if (CNOTGate* gd = dynamic_cast(&g)) { +// j["name"] = "CNOTGate"; +// j["qargs"] = {jsonify(gd->ctrl()), jsonify(gd->tgt())}; +// } else if (BarrierGate* gd = dynamic_cast(&g)) { +// j["name"] = "BarrierGate"; +// j["qargs"] = {}; +// gd->foreach_arg( +// [&j](VarAccess& va) { j["qargs"].push_back(jsonify(va)); }); +// } else if (DeclaredGate* gd = dynamic_cast(&g)) { +// j["name"] = gd->name(); +// j["qargs"] = {}; +// j["cargs"] = {}; +// gd->foreach_qarg( +// [&j](VarAccess& va) { j["qargs"].push_back(jsonify(va)); }); +// gd->foreach_carg([&j](Expr& va) { j["cargs"].push_back(jsonify(va)); +// }); +// } else { +// throw ""; +// } +// return j; +// } +// +// json jsonify(qasmtools::ast::GateDecl& gd) { +// using namespace qasmtools::ast; +// json j; +// j["type"] = "GateDecl"; +// j["name"] = gd.id(); +// j["q_params"] = gd.q_params(); +// j["c_params"] = gd.c_params(); +// j["body"] = {}; // process the body of a GateDecl; +// gd.foreach_stmt([&j](Stmt& st) { j["body"].push_back(jsonify(st)); }); +// return j; +// } +// +// json jsonify(qasmtools::ast::Stmt& st) { +// using namespace qasmtools::ast; +// if (GateDecl* gd = dynamic_cast(&st)) { +// return jsonify(*gd); +// } else if (Gate* gd = dynamic_cast(&st)) { +// return jsonify(*gd); +// } else if (Gate* gd = dynamic_cast(&st)) { +// return jsonify(*gd); +// } else if (MeasureStmt* gd = dynamic_cast(&st)) { +// return jsonify(*gd); +// } else if (ResetStmt* gd = dynamic_cast(&st)) { +// return jsonify(*gd); +// } else if (OracleDecl* gd = dynamic_cast(&st)) { +// return jsonify(*gd); +// } else if (RegisterDecl* gd = dynamic_cast(&st)) { +// return jsonify(*gd); +// } else if (AncillaDecl* gd = dynamic_cast(&st)) { +// return jsonify(*gd); +// } else if (IfStmt* gd = dynamic_cast(&st)) { +// return jsonify(*gd); +// } else { +// throw ""; +// } +// } +// +// json jsonify(qasmtools::ast::Program& p) { +// using namespace qasmtools::ast; +// json j; +// p.foreach_stmt([&](Stmt& st) { j.push_back(jsonify(st)); }); +// return j; +// } int main(int argc, char** argv) { // using namespace staq; @@ -214,11 +216,13 @@ int main(int argc, char** argv) { return 1; } - // create json - // auto jsonified = qasmtools::ast::jsonify(*prog); - // std::cout << jsonified._json().dump() << std::endl; - json jsonified = jsonify(*prog); - std::cout << jsonified.dump() << std::endl; + // was working before: + // json jsonified = jsonify(*prog); + // std::cout << jsonified.dump() << std::endl; + + staq::output::JSONOutputter jo; + prog->accept(jo); + std::cout << jo.json_val().dump() << std::endl; return 0; } catch (const qasmtools::parser::ParseError& e) { std::cerr << "ParseError: " << e.what() << std::endl;