Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tree-gen classes can now dump to JSON #166

Merged
merged 27 commits into from
Dec 6, 2023
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
3ae5674
Updated to use the latest commit ID for tree-gen/json_dumper.
rturrado Nov 16, 2023
044f1a7
Updated v3x parsing tests to check the JSON dump.
rturrado Nov 16, 2023
9b753fa
Updated to use the latest commit ID for tree-gen/json_dumper.
rturrado Nov 20, 2023
f7a7650
Renamed res/v1x/parsing folders by changing dashes to underscores, be…
rturrado Nov 23, 2023
6679d09
ParseResult and AnalysisResult now have to_json methods.
rturrado Nov 23, 2023
d1211a0
Moved 'to_json' function template to cqasm-utils.
rturrado Nov 23, 2023
56cfe1d
Fixed res/v1x/parsing/grammar failing tests.
rturrado Nov 24, 2023
3f7f67b
Trying to fix GitHub Actions Docker job.
rturrado Nov 24, 2023
f45b439
include/cqasm-utils.hpp: fixed join string in to_json function.
rturrado Nov 28, 2023
c0bd6fe
Merge branch 'develop' into json_dumper
rturrado Nov 28, 2023
9ac5449
register_instruction only admits 2 parameters for v3x.
rturrado Nov 28, 2023
df6d421
Changed 'self.analyzer' calls to 'self.analyze'.
rturrado Nov 28, 2023
7d2d9cc
Fixed param types for measure instruction at src/v3x/cqasm.cpp defaul…
rturrado Nov 29, 2023
586ec3c
Fixed circular imports in python/module/cqasm/{v1x,v3x}/primitives.py.
rturrado Nov 29, 2023
2c07286
Fixed python/module/cqasm/v3x/__init__.py analyze_file and analyze_s…
rturrado Nov 29, 2023
d5d1a6d
Fixed src/{v1x,v3x}/cqasm-py.cpp.
rturrado Nov 29, 2023
313126d
Fixed python/module/cqasm/{v1x,v3x}/__init__.py.
rturrado Nov 29, 2023
cc8fe27
Implemented parse_file_to_json, parse_string_to_json, analyze_file_to…
rturrado Nov 29, 2023
ec45e3a
Fixed block comments in cqasm-py.cpp files.
rturrado Nov 29, 2023
41cc9a7
Semantic AST root node is called Program, not Root.
rturrado Nov 29, 2023
37ce2db
Removed debug prints.
rturrado Nov 29, 2023
de9ed3d
Trying to fix GitHub Actions conda job.
rturrado Nov 29, 2023
f085965
Removed double import.
rturrado Dec 5, 2023
b7bde2a
Merge branch 'develop' into json_dumper
rturrado Dec 5, 2023
4db1aea
Removed pyproject.toml.
rturrado Dec 5, 2023
e6243c2
Removed duplicated ~V1xAnalyzer().
rturrado Dec 5, 2023
17aec50
Fixed errors in test/cqasm-utils.cpp.
rturrado Dec 5, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ jobs:
miniconda-version: "latest"
show-channel-urls: true
- name: Install conda dependencies
run: conda install conda-build conda-verify -y
run: conda install conda-build conda-verify numpy -y
- name: Build & test
run: conda build python/conda
- name: Install
Expand Down
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ RUN apt-get -qq update && \
ADD . /libqasm

WORKDIR /libqasm
RUN conan profile detect
RUN conan build . -s:h compiler.cppstd=20 -o libqasm/*:build_tests=True -o libqasm/*:compat=True -o libqasm/*:tree_gen_build_tests=True -o libqasm/*:asan_enabled=True -b missing
RUN conan profile detect --force
RUN conan build . -pr=./conan/profiles/tests-debug-compat -b missing

WORKDIR /libqasm/build/Release
RUN ctest -C Release --output-on-failure
Expand Down
26 changes: 21 additions & 5 deletions include/cqasm-utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@

#pragma once

#include <fmt/format.h>
#include <sstream> // ostringstream
#include <string>

namespace cqasm {

/**
* Namespace for various utility functions.
*/
namespace utils {
namespace cqasm::utils {

/**
* Makes a string lowercase.
Expand All @@ -23,5 +23,21 @@ std::string to_lowercase(const std::string &name);
*/
bool equal_case_insensitive(const std::string &lhs, const std::string &rhs);

} // namespace utils
} // namespace cqasm
/**
* Returns a string with a JSON representation of a ParseResult or an AnalysisResult.
*/
template <typename Result>
std::string to_json(const Result &result) {
if (!result.errors.empty()) {
return fmt::format(R"({{"errors":["{}"]}})", // first quote of first error message, and
// last quote of last error message
fmt::join(result.errors, R"(",")")); // last quote of any intermediate error message, and
// first quote of the following
} else {
std::ostringstream oss{};
result.root->dump_json(oss);
return oss.str();
}
}

} // namespace cqasm::utils
75 changes: 75 additions & 0 deletions include/v1x/cqasm-analysis-result.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#pragma once

#include "cqasm-ast.hpp"
#include "cqasm-semantic.hpp"

#include <stdexcept> // runtime_error
#include <iosfwd> // ostream
#include <string>
#include <vector>


/**
* Namespace for the \ref cqasm::analyzer::Analyzer "Analyzer" class and support classes.
*/
namespace cqasm::v1x::analyzer {


/**
* Exception thrown by AnalysisResult::unwrap() when the cQASM file fails to
* parse.
*/
class AnalysisFailed: public std::runtime_error {
public:
AnalysisFailed() : std::runtime_error("cQASM analysis failed") {};
};


/**
* Analysis result class.
*
* An object of this type is returned by the various `analyze*()` methods of the Analyzer class.
* There are three possibilities.
*
* - Analysis was successful.
* In this case, \ref errors is empty, and \ref root contains a valid \ref semantic::Program "Program" tree.
* - Analysis failed.
* In this case, there is at least one string in \ref errors.
* \ref root may be an empty reference, a partial tree, or even a complete but somehow invalid tree.
* - Analysis failed spectacularly with an internal error,
* in which case an exception is thrown instead of this object being returned.
*
* If you don't want to manage printing error messages yourself and would like an exception upon failure in all cases,
* you can call unwrap() on the returned object.
*/
class AnalysisResult {
public:
/**
* Root node of the semantic tree, if analysis was successful.
* The node may be empty or incomplete if errors is nonempty;
* use unwrap() to ensure it's complete if you just want to use it and
* don't care about things like pretty-printing error messages for your users
* in a different way than what unwrap() does for you.
*/
ast::One<semantic::Program> root;

/**
* List of accumulated errors.
* Analysis was successful if and only if `errors.empty()`.
*/
std::vector<std::string> errors;

/**
* "Unwraps" the result (as you would in Rust) to get the program node or an exception.
* The exception is always an AnalysisFailed, deriving from std::runtime_error.
* The actual error messages are in this case first written to the given output stream, defaulting to stderr.
*/
ast::One<semantic::Program> unwrap(std::ostream &out = std::cerr) const;

/**
* Returns a string with a JSON representation of the AnalysisResult.
*/
std::string to_json() const;
};

} // namespace cqasm::v1x::analyzer
58 changes: 2 additions & 56 deletions include/v1x/cqasm-analyzer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,75 +9,21 @@

#pragma once

#include "cqasm-analysis-result.hpp"
#include "cqasm-ast.hpp"
#include "cqasm-parse-helper.hpp"
#include "cqasm-resolver.hpp"
#include "cqasm-semantic.hpp"

#include <cstdio>
#include <functional>
#include <string>

/**
* Namespace for the \ref cqasm::analyzer::Analyzer "Analyzer" class and
* support classes.
*/
namespace cqasm::v1x::analyzer {

/**
* Exception thrown by AnalysisResult::unwrap() when the cQASM file fails to
* parse.
*/
class AnalysisFailed: public std::runtime_error {
public:
AnalysisFailed() : std::runtime_error("cQASM analysis failed") {};
};

/**
* Analysis result class.
*
* An object of this type is returned by the various `analyze*()` methods of
* the Analyzer class. There are three possibilities.
*
* - Analysis was successful. In this case, \ref errors is empty, and
* \ref root contains a valid \ref semantic::Program "Program" tree.
* - Analysis failed. In this case, there is at least one string in
* \ref errors. \ref root may be an empty reference, a partial tree,
* or even a complete but somehow invalid tree.
* - Analysis failed spectacularly with an internal error, in which case an
* exception is thrown instead of this object being returned.
*
* If you don't want to manage printing error messages yourself and would like
* an exception upon failure in all cases, you can call unwrap() on the
* returned object.
*/
class AnalysisResult {
public:

/**
* Root node of the semantic tree, if analysis was successful. The node may
* be empty or incomplete if errors is nonempty; use unwrap() to ensure it's
* complete if you just want to use it and don't care about things like
* pretty-printing error messages for your users in a different way than
* what unwrap() does for you.
*/
ast::One<semantic::Program> root;

/**
* List of accumulated errors. Analysis was successful if and only if
* `errors.empty()`.
*/
std::vector<std::string> errors;

/**
* "Unwraps" the result (as you would in Rust) to get the program node or
* an exception. The exception is always an AnalysisFailed, deriving from
* std::runtime_error. The actual error messages are in this case first
* written to the given output stream, defaulting to stderr.
*/
ast::One<semantic::Program> unwrap(std::ostream &out = std::cerr) const;

};

/**
* Main class used for analyzing cQASM files.
*
Expand Down
8 changes: 6 additions & 2 deletions include/v1x/cqasm-parse-result.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
#include "cqasm-annotations.hpp"
#include "cqasm-ast.hpp"

#include <cstdio>
#include <string>
#include <vector>


/**
Expand All @@ -22,7 +23,6 @@ namespace cqasm::v1x::parser {
*/
class ParseResult {
public:

/**
* Root node of the AST, if analysis was sufficiently successful.
* This may be set even if parsing was not ENTIRELY successful,
Expand All @@ -36,6 +36,10 @@ class ParseResult {
*/
std::vector<std::string> errors;

/**
* Returns a string with a JSON representation of the ParseResult.
*/
std::string to_json() const;
};

} // namespace cqasm::v1x::parser
57 changes: 33 additions & 24 deletions include/v1x/cqasm-py.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@
#include <vector>

// Forward declarations for internal types.
namespace cqasm::v1x::analyzer { class Analyzer; }
namespace cqasm::v1x::analyzer {
class Analyzer;
}


/**
* Main class for parsing and analyzing cQASM files with the v1.x API.
Expand All @@ -23,7 +26,7 @@ class V1xAnalyzer {
/**
* Reference to the actual C++ analyzer that this wraps.
*/
std::unique_ptr<cqasm::v1x::analyzer::Analyzer> a;
std::unique_ptr<cqasm::v1x::analyzer::Analyzer> analyzer;

public:
/**
Expand All @@ -36,10 +39,9 @@ class V1xAnalyzer {
* the initial mappings and functions are not configurable at all.
* The defaults for these are always used.
*/
explicit V1xAnalyzer(
const std::string &max_version = "1.0",
bool without_defaults = false
);
explicit V1xAnalyzer(const std::string &max_version = "1.0", bool without_defaults = false);

~V1xAnalyzer();

/**
* Registers an instruction type.
Expand All @@ -58,10 +60,7 @@ class V1xAnalyzer {
* Registers an error model.
* The arguments are passed straight to error_model::ErrorModel's constructor.
*/
void register_error_model(
const std::string &name,
const std::string &param_types = ""
);
void register_error_model(const std::string &name, const std::string &param_types = "");

/**
* Only parses the given file.
Expand All @@ -71,18 +70,23 @@ class V1xAnalyzer {
* of which the first is always present and is the CBOR serialization of the v1.x AST.
* Any additional strings represent error messages.
*/
static std::vector<std::string> parse_file(
const std::string &filename
);
static std::vector<std::string> parse_file(const std::string &filename);

/**
* Counterpart of parse_file that returns a string with a JSON representation of the ParseResult.
*/
static std::string parse_file_to_json(const std::string &filename);

/**
* Same as parse_file(), but instead receives the file contents directly.
* The filename, if specified, is only used when reporting errors.
*/
static std::vector<std::string> parse_string(
const std::string &data,
const std::string &filename = "<unknown>"
);
static std::vector<std::string> parse_string(const std::string &data, const std::string &filename = "<unknown>");

/**
* Counterpart of parse_string that returns a string with a JSON representation of the ParseResult.
*/
static std::string parse_string_to_json(const std::string &data, const std::string &filename = "<unknown>");

/**
* Parses and analyzes the given file.
Expand All @@ -93,16 +97,21 @@ class V1xAnalyzer {
* of which the first is always present and is the CBOR serialization of the v1.x semantic tree.
* Any additional strings represent error messages.
*/
std::vector<std::string> analyze_file(
const std::string &filename
) const;
std::vector<std::string> analyze_file(const std::string &filename) const;

/**
* Counterpart of analyze_file that returns a string with a JSON representation of the AnalysisResult.
*/
std::string analyze_file_to_json(const std::string &filename) const;

/**
* Same as analyze_file(), but instead receives the file contents directly.
* The filename, if specified, is only used when reporting errors.
*/
std::vector<std::string> analyze_string(
const std::string &data,
const std::string &filename = "<unknown>"
) const;
std::vector<std::string> analyze_string(const std::string &data, const std::string &filename = "<unknown>") const;

/**
* Counterpart of analyze_string that returns a string with a JSON representation of the AnalysisResult.
*/
std::string analyze_string_to_json(const std::string &data, const std::string &filename = "<unknown>") const;
};
Loading
Loading