From f7b48a389a53edba92ea9ad7e28a7624c573a746 Mon Sep 17 00:00:00 2001 From: rturrado <68099809+rturrado@users.noreply.github.com> Date: Tue, 14 Nov 2023 20:00:00 +0100 Subject: [PATCH 01/31] Defined V1xAnalyzer and V3xAnalyzer in python/module/cqasm/{v1x,v3x}. --- python/module/cqasm/v1x/__init__.py | 5 +++-- python/module/cqasm/v3x/__init__.py | 5 +++-- test/v3x/python/__init__.py | 0 3 files changed, 6 insertions(+), 4 deletions(-) create mode 100644 test/v3x/python/__init__.py diff --git a/python/module/cqasm/v1x/__init__.py b/python/module/cqasm/v1x/__init__.py index 812dabf5..7f2e786c 100644 --- a/python/module/cqasm/v1x/__init__.py +++ b/python/module/cqasm/v1x/__init__.py @@ -1,6 +1,7 @@ -import libQasm; +import libQasm -class Analyzer(libQasm.V1xAnalyzer): + +class V1xAnalyzer(libQasm.V1xAnalyzer): @staticmethod def parse_file(*args): diff --git a/python/module/cqasm/v3x/__init__.py b/python/module/cqasm/v3x/__init__.py index da1dede7..865f0f66 100644 --- a/python/module/cqasm/v3x/__init__.py +++ b/python/module/cqasm/v3x/__init__.py @@ -1,6 +1,7 @@ -import libQasm; +import libQasm -class Analyzer(libQasm.V3xAnalyzer): + +class V3xAnalyzer(libQasm.V3xAnalyzer): @staticmethod def parse_file(*args): diff --git a/test/v3x/python/__init__.py b/test/v3x/python/__init__.py new file mode 100644 index 00000000..e69de29b From 9ea3b591f7b02da26d40ac2f96f0c97bc4e36850 Mon Sep 17 00:00:00 2001 From: rturrado <68099809+rturrado@users.noreply.github.com> Date: Tue, 14 Nov 2023 20:00:52 +0100 Subject: [PATCH 02/31] Minor aesthetic change for setting SWIG_FILE. --- python/CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index 05e8c5e5..026b02df 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -94,7 +94,9 @@ set(CMAKE_CXX_EXTENSIONS OFF) #=============================================================================# # Configure SWIG. -set(SWIG_FILE "${CMAKE_CURRENT_SOURCE_DIR}/libQasm.i") +set(SWIG_FILE + "${CMAKE_CURRENT_SOURCE_DIR}/libQasm.i" +) set_source_files_properties("${SWIG_FILE}" PROPERTIES CPLUSPLUS ON From c430589d429375758e5dd57cf5c45524b11aeb72 Mon Sep 17 00:00:00 2001 From: rturrado <68099809+rturrado@users.noreply.github.com> Date: Tue, 14 Nov 2023 20:03:40 +0100 Subject: [PATCH 03/31] API is now analyze_file and analyze_string. Implemented v3x default_analyzer. --- include/v1x/cqasm-analyzer.hpp | 4 +-- include/v1x/cqasm.hpp | 4 +-- include/v3x/cqasm-analyzer.hpp | 2 +- include/v3x/cqasm.hpp | 2 +- src/v1x/cqasm-analyzer.cpp | 4 +-- src/v1x/cqasm.cpp | 8 +++--- src/v3x/cqasm-analyzer.cpp | 2 +- src/v3x/cqasm.cpp | 45 ++++++++++++++++++++++++++++------ test/v1x/tutorial.cpp | 2 +- 9 files changed, 51 insertions(+), 22 deletions(-) diff --git a/include/v1x/cqasm-analyzer.hpp b/include/v1x/cqasm-analyzer.hpp index 07cbf17b..d86a1991 100644 --- a/include/v1x/cqasm-analyzer.hpp +++ b/include/v1x/cqasm-analyzer.hpp @@ -310,13 +310,13 @@ class Analyzer { /** * Parses and analyzes the given file. */ - AnalysisResult analyze(const std::string &filename) const; + AnalysisResult analyze_file(const std::string &filename) const; /** * Parses and analyzes the given file pointer. * The optional filename argument will be used only for error messages. */ - AnalysisResult analyze(FILE *file, const std::string &filename = "") const; + AnalysisResult analyze_file(FILE *file, const std::string &filename = "") const; /** * Parses and analyzes the given string. diff --git a/include/v1x/cqasm.hpp b/include/v1x/cqasm.hpp index 757037ae..3e031d9f 100644 --- a/include/v1x/cqasm.hpp +++ b/include/v1x/cqasm.hpp @@ -25,7 +25,7 @@ namespace v1x { * Parses and analyzes the given file path with the default analyzer, * dumping error messages to stderr and throwing an analyzer::AnalysisFailed on failure. */ -tree::One analyze( +tree::One analyze_file( const std::string &file_path, const std::string &api_version = "1.0" ); @@ -35,7 +35,7 @@ tree::One analyze( * error messages to stderr and throwing an analyzer::AnalysisFailed on failure. * The optional file_name is only used for error messages. */ -tree::One analyze( +tree::One analyze_file( FILE *fp, const std::string &file_name = "", const std::string &api_version = "1.0" diff --git a/include/v3x/cqasm-analyzer.hpp b/include/v3x/cqasm-analyzer.hpp index 3dfb5b28..4571f132 100644 --- a/include/v3x/cqasm-analyzer.hpp +++ b/include/v3x/cqasm-analyzer.hpp @@ -163,7 +163,7 @@ class Analyzer { /** * Parses and analyzes the given file. */ - [[nodiscard]] AnalysisResult analyze(const std::string &filename); + [[nodiscard]] AnalysisResult analyze_file(const std::string &filename); /** * Parses and analyzes the given string. diff --git a/include/v3x/cqasm.hpp b/include/v3x/cqasm.hpp index a4b19ddb..cd5f9900 100644 --- a/include/v3x/cqasm.hpp +++ b/include/v3x/cqasm.hpp @@ -25,7 +25,7 @@ namespace v3x { * Parses and analyzes the given file path with the default analyzer, * dumping error messages to stderr and throwing an analyzer::AnalysisFailed on failure. */ -tree::One analyze( +tree::One analyze_file( const std::string &file_path, const std::string &api_version = "3.0" ); diff --git a/src/v1x/cqasm-analyzer.cpp b/src/v1x/cqasm-analyzer.cpp index ec91fb5c..9819d4ad 100644 --- a/src/v1x/cqasm-analyzer.cpp +++ b/src/v1x/cqasm-analyzer.cpp @@ -525,7 +525,7 @@ AnalysisResult Analyzer::analyze( /** * Parses and analyzes the given file. */ -AnalysisResult Analyzer::analyze(const std::string &filename) const { +AnalysisResult Analyzer::analyze_file(const std::string &filename) const { return analyze( [=](){ return version::parse_file(filename); }, [=](){ return parser::parse_file(filename); } @@ -536,7 +536,7 @@ AnalysisResult Analyzer::analyze(const std::string &filename) const { * Parses and analyzes the given file pointer. The optional filename * argument will be used only for error messages. */ -AnalysisResult Analyzer::analyze(FILE *file, const std::string &filename) const { +AnalysisResult Analyzer::analyze_file(FILE *file, const std::string &filename) const { return analyze( [=](){ return version::parse_file(file, filename); }, [=](){ return parser::parse_file(file, filename); } diff --git a/src/v1x/cqasm.cpp b/src/v1x/cqasm.cpp index 7393a384..c9482118 100644 --- a/src/v1x/cqasm.cpp +++ b/src/v1x/cqasm.cpp @@ -17,11 +17,11 @@ namespace v1x { * Parses and analyzes the given file path with the default analyzer, * dumping error messages to stderr and throwing an analyzer::AnalysisFailed on failure. */ -tree::One analyze( +tree::One analyze_file( const std::string &file_path, const std::string &api_version ) { - return default_analyzer(api_version).analyze(file_path).unwrap(); + return default_analyzer(api_version).analyze_file(file_path).unwrap(); } /** @@ -29,12 +29,12 @@ tree::One analyze( * dumping error messages to stderr and throwing an analyzer::AnalysisFailed on failure. * The optional file_name is only used for error messages. */ -tree::One analyze( +tree::One analyze_file( FILE *fp, const std::string &file_name, const std::string &api_version ) { - return default_analyzer(api_version).analyze(fp, file_name).unwrap(); + return default_analyzer(api_version).analyze_file(fp, file_name).unwrap(); } /** diff --git a/src/v3x/cqasm-analyzer.cpp b/src/v3x/cqasm-analyzer.cpp index dfe66cd0..f30ab9d0 100644 --- a/src/v3x/cqasm-analyzer.cpp +++ b/src/v3x/cqasm-analyzer.cpp @@ -130,7 +130,7 @@ AnalysisResult Analyzer::analyze( /** * Parses and analyzes the given file. */ -AnalysisResult Analyzer::analyze(const std::string &filename) { +AnalysisResult Analyzer::analyze_file(const std::string &filename) { return analyze( [=](){ return version::parse_file(filename); }, [=](){ return parser::parse_file(filename); } diff --git a/src/v3x/cqasm.cpp b/src/v3x/cqasm.cpp index 03e99056..ca3fc821 100644 --- a/src/v3x/cqasm.cpp +++ b/src/v3x/cqasm.cpp @@ -19,14 +19,14 @@ namespace cqasm::v3x { * Parses and analyzes the given file path with the default analyzer, * dumping error messages to stderr and throwing an analyzer::AnalysisFailed on failure. */ -tree::One analyze( +tree::One analyze_file( const std::string &file_path, const std::string &api_version ) { return cqasm::v3x::default_analyzer(api_version).analyze( - [&file_path]() { return version::parse_file(file_path); }, - [&file_path]() { return cqasm::v3x::parser::parse_file(file_path); } - ).unwrap(); + [&file_path]() { return version::parse_file(file_path); }, + [&file_path]() { return cqasm::v3x::parser::parse_file(file_path); } + ).unwrap(); } /** @@ -40,16 +40,45 @@ tree::One analyze_string( const std::string &api_version ) { return cqasm::v3x::default_analyzer(api_version).analyze( - [&data, &file_name]() { return version::parse_string(data, file_name); }, - [&data, &file_name]() { return cqasm::v3x::parser::parse_string(data, file_name); } - ).unwrap(); + [&data, &file_name]() { return version::parse_string(data, file_name); }, + [&data, &file_name]() { return cqasm::v3x::parser::parse_string(data, file_name); } + ).unwrap(); } /** * Constructs an Analyzer object with the defaults for cQASM 3.0 already loaded into it. */ analyzer::Analyzer default_analyzer(const std::string &api_version) { - return analyzer::Analyzer{ api_version }; + analyzer::Analyzer analyzer{ api_version }; + + analyzer.register_default_mappings(); + + analyzer.register_instruction("cnot", "QQ"); + analyzer.register_instruction("cnot", "VV"); + analyzer.register_instruction("cr", "QQr"); + analyzer.register_instruction("crk", "QQi"); + analyzer.register_instruction("cz", "QQ"); + analyzer.register_instruction("h", "Q"); + analyzer.register_instruction("h", "V"); + analyzer.register_instruction("i", "Q"); + analyzer.register_instruction("measure", "QB", true); // qubit - bit + analyzer.register_instruction("measure", "VW", true); // qubit array - bit array + analyzer.register_instruction("measure", "VB", true); // qubit array - bit + analyzer.register_instruction("measure", "QW", true); // qubit - bit array + analyzer.register_instruction("mx90", "Q"); + analyzer.register_instruction("my90", "Q"); + analyzer.register_instruction("rx", "Qr"); + analyzer.register_instruction("ry", "Qr"); + analyzer.register_instruction("rz", "Qr"); + analyzer.register_instruction("s", "Q"); + analyzer.register_instruction("sdag", "Q"); + analyzer.register_instruction("x", "Q"); + analyzer.register_instruction("x90", "Q"); + analyzer.register_instruction("y", "Q"); + analyzer.register_instruction("y90", "Q"); + analyzer.register_instruction("z", "Q"); + + return analyzer; } } // namespace cqasm::v3x diff --git a/test/v1x/tutorial.cpp b/test/v1x/tutorial.cpp index e0484d26..47633701 100644 --- a/test/v1x/tutorial.cpp +++ b/test/v1x/tutorial.cpp @@ -13,7 +13,7 @@ TEST(tutorial, tutorial) { // (cqasm::tree::One to be specific), or the // error messages printed to stderr and a cq1x::analysis::AnalysisError // exception (derived from std::runtime_error) on failure. - auto result = cq1x::analyze("res/v1x/grover.cq"); + auto result = cq1x::analyze_file("res/v1x/grover.cq"); // There is also an overload for a FILE* directly (with an optional second // argument for the filename used in error messages to refer back to the From 00f33cd9f78bbe9bc0d1c1ca7563e585fc47e4c4 Mon Sep 17 00:00:00 2001 From: rturrado <68099809+rturrado@users.noreply.github.com> Date: Tue, 14 Nov 2023 20:05:14 +0100 Subject: [PATCH 04/31] Renamed 'a' to 'analyzer' for V1xAnalyzer and V3xAnalyzer. --- include/v1x/cqasm-py.hpp | 5 ++++- include/v3x/cqasm-py.hpp | 7 +++++-- src/v1x/cqasm-py.cpp | 16 ++++++++-------- src/v3x/cqasm-py.cpp | 12 ++++++------ 4 files changed, 23 insertions(+), 17 deletions(-) diff --git a/include/v1x/cqasm-py.hpp b/include/v1x/cqasm-py.hpp index 1e9730f2..6fbc0146 100644 --- a/include/v1x/cqasm-py.hpp +++ b/include/v1x/cqasm-py.hpp @@ -13,6 +13,9 @@ #include #include +#include "cqasm-analyzer.hpp" + + // Forward declarations for internal types. namespace cqasm::v1x::analyzer { class Analyzer; } @@ -23,7 +26,7 @@ class V1xAnalyzer { /** * Reference to the actual C++ analyzer that this wraps. */ - std::unique_ptr a; + std::unique_ptr analyzer; public: /** diff --git a/include/v3x/cqasm-py.hpp b/include/v3x/cqasm-py.hpp index 6b008f5a..18a51f7d 100644 --- a/include/v3x/cqasm-py.hpp +++ b/include/v3x/cqasm-py.hpp @@ -13,6 +13,9 @@ #include #include +#include "cqasm-analyzer.hpp" + + // Forward declarations for internal types. namespace cqasm::v3x::analyzer { class Analyzer; } @@ -23,7 +26,7 @@ class V3xAnalyzer { /** * Reference to the actual C++ analyzer that this wraps. */ - std::unique_ptr a; + std::unique_ptr analyzer; public: /** @@ -38,7 +41,7 @@ class V3xAnalyzer { */ V3xAnalyzer( const std::string &max_version = "3.0", - bool without_defaults=false + bool without_defaults = false ); /** diff --git a/src/v1x/cqasm-py.cpp b/src/v1x/cqasm-py.cpp index d544a51a..add5cd8a 100644 --- a/src/v1x/cqasm-py.cpp +++ b/src/v1x/cqasm-py.cpp @@ -3,9 +3,9 @@ */ #include "cqasm-version.hpp" +#include "v1x/cqasm-parse-helper.hpp" #include "v1x/cqasm-py.hpp" #include "v1x/cqasm.hpp" -#include "v1x/cqasm-parse-helper.hpp" #include @@ -23,10 +23,10 @@ namespace v1x = cqasm::v1x; */ V1xAnalyzer::V1xAnalyzer(const std::string &max_version, bool without_defaults) { if (without_defaults) { - a = std::make_unique(max_version); - a->register_default_functions_and_mappings(); + analyzer = std::make_unique(max_version); + analyzer->register_default_functions_and_mappings(); } else { - a = std::make_unique(v1x::default_analyzer(max_version)); + analyzer = std::make_unique(v1x::default_analyzer(max_version)); } } @@ -42,7 +42,7 @@ void V1xAnalyzer::register_instruction( bool allow_reused_qubits, bool allow_different_index_sizes ) { - a->register_instruction( + analyzer->register_instruction( name, param_types, allow_conditional, @@ -60,7 +60,7 @@ void V1xAnalyzer::register_error_model( const std::string &name, const std::string ¶m_types ) { - a->register_error_model(name, param_types); + analyzer->register_error_model(name, param_types); } /** @@ -106,7 +106,7 @@ std::vector V1xAnalyzer::parse_string( [[nodiscard]] std::vector V1xAnalyzer::analyze_file( const std::string &filename ) const { - auto result = a->analyze( + auto result = analyzer->analyze( [=](){ return cqasm::version::parse_file(filename); }, [=](){ return v1x::parser::parse_file(filename); } ); @@ -123,7 +123,7 @@ std::vector V1xAnalyzer::parse_string( const std::string &data, const std::string &filename ) const { - auto result = a->analyze( + auto result = analyzer->analyze( [=](){ return cqasm::version::parse_string(data, filename); }, [=](){ return v1x::parser::parse_string(data, filename); } ); diff --git a/src/v3x/cqasm-py.cpp b/src/v3x/cqasm-py.cpp index ec03aa1a..6c735967 100644 --- a/src/v3x/cqasm-py.cpp +++ b/src/v3x/cqasm-py.cpp @@ -23,10 +23,10 @@ namespace v3x = cqasm::v3x; */ V3xAnalyzer::V3xAnalyzer(const std::string &max_version, bool without_defaults) { if (without_defaults) { - a = std::make_unique(max_version); - a->register_default_mappings(); + analyzer = std::make_unique(max_version); + analyzer->register_default_mappings(); } else { - a = std::make_unique(v3x::default_analyzer(max_version)); + analyzer = std::make_unique(v3x::default_analyzer(max_version)); } } @@ -39,7 +39,7 @@ void V3xAnalyzer::register_instruction( const std::string ¶m_types, bool request_qubit_and_bit_indices_have_same_size ) { - a->register_instruction( + analyzer->register_instruction( name, param_types, request_qubit_and_bit_indices_have_same_size @@ -89,7 +89,7 @@ std::vector V3xAnalyzer::parse_string( std::vector V3xAnalyzer::analyze_file( const std::string &filename ) const { - auto result = a->analyze( + auto result = analyzer->analyze( [=](){ return cqasm::version::parse_file(filename); }, [=](){ return v3x::parser::parse_file(filename); } ); @@ -106,7 +106,7 @@ std::vector V3xAnalyzer::analyze_string( const std::string &data, const std::string &filename ) const { - auto result = a->analyze( + auto result = analyzer->analyze( [=](){ return cqasm::version::parse_string(data, filename); }, [=](){ return v3x::parser::parse_string(data, filename); } ); From aab4937916fd9db2dd5d4e732278046c9a03253f Mon Sep 17 00:00:00 2001 From: rturrado <68099809+rturrado@users.noreply.github.com> Date: Tue, 14 Nov 2023 20:05:57 +0100 Subject: [PATCH 05/31] Added 'cqasm.v3x' package to the list of packages in setup.py. --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 7ccd58a2..503d0bac 100755 --- a/setup.py +++ b/setup.py @@ -188,7 +188,7 @@ def initialize_options(self): 'Topic :: Scientific/Engineering' ], - packages=['libQasm', 'cqasm', 'cqasm.v1x'], + packages=['libQasm', 'cqasm', 'cqasm.v1x', 'cqasm.v3x'], package_dir={'': 'pybuild/module'}, # NOTE: the library build process is completely overridden to let CMake handle it. From d0d964417763d3994ac19b1369d8389bc22fd2a4 Mon Sep 17 00:00:00 2001 From: rturrado <68099809+rturrado@users.noreply.github.com> Date: Tue, 14 Nov 2023 20:07:05 +0100 Subject: [PATCH 06/31] Renamed libdir to lib_dir. Changed import line into three lines, as suggested by clang-tidy. --- python/python_lib.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/python/python_lib.py b/python/python_lib.py index 31e8c6ce..84a94bee 100644 --- a/python/python_lib.py +++ b/python/python_lib.py @@ -1,12 +1,14 @@ -import sysconfig, sys, os +import os +import sys +import sysconfig name = 'python' + ''.join(map(str, sys.version_info[0:2])) debug = sys.argv[1].lower() == 'debug' -libdir = os.path.join(os.path.dirname(sysconfig.get_paths()['include']), 'libs') +lib_dir = os.path.join(os.path.dirname(sysconfig.get_paths()['include']), 'libs') options = [] -for entry in os.listdir(libdir): +for entry in os.listdir(lib_dir): entry = entry.lower() if not entry.startswith(name): continue @@ -24,4 +26,4 @@ else: # if there are multiple, no idea how to choose which. options.sort() - print(os.path.join(libdir, options[0])) + print(os.path.join(lib_dir, options[0])) From 9d2fff33832854a8df0f88ce00d2cc7fd43fd2ef Mon Sep 17 00:00:00 2001 From: rturrado <68099809+rturrado@users.noreply.github.com> Date: Tue, 14 Nov 2023 20:07:50 +0100 Subject: [PATCH 07/31] Applied some clang-tidy suggestions. --- test/parsing-tools.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/parsing-tools.py b/test/parsing-tools.py index 11c1f690..7921da6b 100644 --- a/test/parsing-tools.py +++ b/test/parsing-tools.py @@ -34,6 +34,7 @@ def diff(): diff() print('Leaving %s...' % sub) + def gild_all(): is_test_dir = False for t in ('ast', 'semantic.1.0', 'semantic.1.1', 'semantic.1.2'): @@ -48,6 +49,7 @@ def gild_all(): gild_all() print('Leaving %s...' % sub) + cmd = sys.argv[1] if cmd == 'run': @@ -74,7 +76,7 @@ def gild_all(): local['cp']('-f', 'semantic.actual.txt', 'semantic.golden.txt') elif cmd == 'gild-all': - gild_all(); + gild_all() else: print('unknown command') From 47580326fff457fc15ee967c5aee8e6cb4925330 Mon Sep 17 00:00:00 2001 From: rturrado <68099809+rturrado@users.noreply.github.com> Date: Tue, 14 Nov 2023 20:08:55 +0100 Subject: [PATCH 08/31] Initialized members in the order in which they are defined, as suggested by clang-tidy. --- include/v10/libQasm.hpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/v10/libQasm.hpp b/include/v10/libQasm.hpp index e6872b49..32bda2e7 100644 --- a/include/v10/libQasm.hpp +++ b/include/v10/libQasm.hpp @@ -11,7 +11,10 @@ class libQasm { public: - libQasm() : parse_result_{ 0 }, qasm_rep_{} {} + libQasm() + : qasm_rep_{} + , parse_result_{ 0 } + {} void parse_string(const std::string &qasm_str) { compiler::QasmSemanticChecker sm(qasm_str); From 1ae0033a77d0292471827af70faa3a0ff18ea8a3 Mon Sep 17 00:00:00 2001 From: rturrado <68099809+rturrado@users.noreply.github.com> Date: Tue, 14 Nov 2023 20:09:42 +0100 Subject: [PATCH 09/31] Sorted list of directories. Also tried to make the file more readable, while not changing its rendered output. --- python/README.md | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/python/README.md b/python/README.md index d1dde2d9..a604dcbd 100644 --- a/python/README.md +++ b/python/README.md @@ -5,22 +5,21 @@ aside from the `setup.py` file living in the root directory. File/directory list: - - `libQasm.i`: SWIG directives for the bindings. + - `CMakeLists.txt`: SWIG and the Python extension build are handled by CMake, + so it can make everything's linked together properly. + Don't use this file directly. + It's intended to be added by the root `CMakeLists.txt`, + and only when the build is orchestrated by `setup.py`. - - `libQasm`: represents the Python module excluding the extension. Any Python - files in here will be included in the Python install. + - `conda`: contains the conda recipe for libqasm, + in case you're using that rather than pip to manage your Python packages. + It mostly just defers to `setup.py`, + but will help you set up the build dependencies regardless of your platform. - - `conda`: contains the conda recipe for libqasm, in case you're using that - rather than pip to manage your Python packages. It mostly just defers to - `setup.py`, but will help you set up the build dependencies regardless of - your platform. + - `libQasm`: represents the Python module excluding the extension. + Any Python files in here will be included in the Python install. - - `CMakeLists.txt`: SWIG and the Python extension build are handled by CMake, - so it can make everything's linked together properly. Don't use this file - directly; it's intended to be added by the root `CMakeLists.txt`, and only - when the build is orchestrated by `setup.py`. - - - `python_lib.py`: helper script for CMake to find the Python library to link - against, because FindPYTHON often picks the wrong one, especially in venvs. + - `libQasm.i`: SWIG directives for the bindings. - - `compat`: helper scripts for CMake to make old CMake versions work. + - `python_lib.py`: helper script for CMake to find the Python library to link against, + because FindPYTHON often picks the wrong one, especially in virtual environments. \ No newline at end of file From 0cf85326ed4cee1e405cbf0422187bd6dfa011d2 Mon Sep 17 00:00:00 2001 From: rturrado <68099809+rturrado@users.noreply.github.com> Date: Tue, 14 Nov 2023 20:10:53 +0100 Subject: [PATCH 10/31] Changed test classes to start with 'Test'. Changed qasminterface to qasm_interface. --- test/v10/python/test_cqasm.py | 4 ++-- test/v10/python/test_init.py | 8 ++++---- test/v10/python/test_interface.py | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/test/v10/python/test_cqasm.py b/test/v10/python/test_cqasm.py index 15a6f136..81fb1708 100644 --- a/test/v10/python/test_cqasm.py +++ b/test/v10/python/test_cqasm.py @@ -1,7 +1,7 @@ -from .test_init import LibQasmTest +from .test_init import TestLibQasm -class TestQasm(LibQasmTest): +class TestQasm(TestLibQasm): def test_bare_minimum(self): lib_qasm = self._generic_test_steps('bare_minimum') parse_res = lib_qasm.getParseResult() diff --git a/test/v10/python/test_init.py b/test/v10/python/test_init.py index 60c35653..ac1e5a6a 100644 --- a/test/v10/python/test_init.py +++ b/test/v10/python/test_init.py @@ -1,15 +1,15 @@ import os import unittest -import libQasm as qasminterface +import libQasm as qasm_interface -class LibQasmTest(unittest.TestCase): +class TestLibQasm(unittest.TestCase): @staticmethod def _generic_test_steps(file_name): base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) data_file = os.path.join(base_dir, '..', '..', 'res', 'v10', file_name + '.qasm') - lib_qasm = qasminterface.libQasm() + lib_qasm = qasm_interface.libQasm() lib_qasm.parse_file(data_file) return lib_qasm @@ -19,6 +19,6 @@ def _generic_test_steps_as_string(file_name): data_file = os.path.join(base_dir, '..', '..', 'res', 'v10', file_name + '.qasm') with open(data_file, 'r') as qasm_file: qasm_string = qasm_file.read() - lib_qasm = qasminterface.libQasm() + lib_qasm = qasm_interface.libQasm() lib_qasm.parse_string(qasm_string) return lib_qasm diff --git a/test/v10/python/test_interface.py b/test/v10/python/test_interface.py index d28e6fab..11cd1346 100644 --- a/test/v10/python/test_interface.py +++ b/test/v10/python/test_interface.py @@ -1,7 +1,7 @@ -from .test_init import LibQasmTest +from .test_init import TestLibQasm -class TestInterface(LibQasmTest): +class TestInterface(TestLibQasm): def test_version_number(self): lib_qasm = self._generic_test_steps('bare_minimum') qasm_representation = lib_qasm.getQasmRepresentation() From f8b218e493e22d7f0a42959b4746d9a2fbad1981 Mon Sep 17 00:00:00 2001 From: rturrado <68099809+rturrado@users.noreply.github.com> Date: Tue, 14 Nov 2023 20:11:26 +0100 Subject: [PATCH 11/31] Added 'v3x/cqasm-py.hpp' to libQasm.i. --- python/libQasm.i | 2 ++ 1 file changed, 2 insertions(+) diff --git a/python/libQasm.i b/python/libQasm.i index a7cf18a1..2acc2e0a 100644 --- a/python/libQasm.i +++ b/python/libQasm.i @@ -11,6 +11,7 @@ #include "v10/qasm_ast.hpp" #include "v10/libQasm.hpp" #include "v1x/cqasm-py.hpp" +#include "v3x/cqasm-py.hpp" %} %include "exception.i" @@ -49,6 +50,7 @@ namespace std { %include "v10/qasm_ast.hpp" %include "v10/libQasm.hpp" %include "v1x/cqasm-py.hpp" +%include "v3x/cqasm-py.hpp" namespace std { %template(subcircuit_vector) vector>; From 72f315fce307549d7928cdcd0d50ab43ca998eca Mon Sep 17 00:00:00 2001 From: rturrado <68099809+rturrado@users.noreply.github.com> Date: Tue, 14 Nov 2023 20:12:22 +0100 Subject: [PATCH 12/31] Created test/v3x/{cpp,python} folders. Added test_v3x_analyzer.py. --- test/main.cpp | 2 +- test/v3x/CMakeLists.txt | 5 +---- test/v3x/cpp/CMakeLists.txt | 4 ++++ test/v3x/{ => cpp}/cqasm-parse-helper.cpp | 0 test/v3x/{ => cpp}/parsing.cpp | 0 test/v3x/{ => cpp}/parsing.hpp | 0 test/v3x/python/test_v3x_analyzer.py | 14 ++++++++++++++ 7 files changed, 20 insertions(+), 5 deletions(-) create mode 100644 test/v3x/cpp/CMakeLists.txt rename test/v3x/{ => cpp}/cqasm-parse-helper.cpp (100%) rename test/v3x/{ => cpp}/parsing.cpp (100%) rename test/v3x/{ => cpp}/parsing.hpp (100%) create mode 100644 test/v3x/python/test_v3x_analyzer.py diff --git a/test/main.cpp b/test/main.cpp index f5b26c7b..f28d13f4 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -1,5 +1,5 @@ #include "v1x/parsing.hpp" -#include "v3x/parsing.hpp" +#include "v3x/cpp/parsing.hpp" #include #include diff --git a/test/v3x/CMakeLists.txt b/test/v3x/CMakeLists.txt index 46aab07e..2322a85f 100644 --- a/test/v3x/CMakeLists.txt +++ b/test/v3x/CMakeLists.txt @@ -1,4 +1 @@ -target_sources(${PROJECT_NAME}_test PRIVATE - "${CMAKE_CURRENT_SOURCE_DIR}/cqasm-parse-helper.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/parsing.cpp" -) +add_subdirectory(cpp) diff --git a/test/v3x/cpp/CMakeLists.txt b/test/v3x/cpp/CMakeLists.txt new file mode 100644 index 00000000..46aab07e --- /dev/null +++ b/test/v3x/cpp/CMakeLists.txt @@ -0,0 +1,4 @@ +target_sources(${PROJECT_NAME}_test PRIVATE + "${CMAKE_CURRENT_SOURCE_DIR}/cqasm-parse-helper.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/parsing.cpp" +) diff --git a/test/v3x/cqasm-parse-helper.cpp b/test/v3x/cpp/cqasm-parse-helper.cpp similarity index 100% rename from test/v3x/cqasm-parse-helper.cpp rename to test/v3x/cpp/cqasm-parse-helper.cpp diff --git a/test/v3x/parsing.cpp b/test/v3x/cpp/parsing.cpp similarity index 100% rename from test/v3x/parsing.cpp rename to test/v3x/cpp/parsing.cpp diff --git a/test/v3x/parsing.hpp b/test/v3x/cpp/parsing.hpp similarity index 100% rename from test/v3x/parsing.hpp rename to test/v3x/cpp/parsing.hpp diff --git a/test/v3x/python/test_v3x_analyzer.py b/test/v3x/python/test_v3x_analyzer.py new file mode 100644 index 00000000..b55f5954 --- /dev/null +++ b/test/v3x/python/test_v3x_analyzer.py @@ -0,0 +1,14 @@ +import unittest + +import libQasm + + +class TestV3xAnalyzer(unittest.TestCase): + def parse_string(self): + program_str = "version 3;qubit[5] q;bit[5] b;h q[0:4];b = measure q" + ret = libQasm.V3xAnalyzer.parse_string(program_str) + self.assertEqual(ret, "") + + +if __name__ == '__main__': + unittest.main() From bb87ccde8983286439278f86ab91122b5fa5840c Mon Sep 17 00:00:00 2001 From: rturrado <68099809+rturrado@users.noreply.github.com> Date: Tue, 14 Nov 2023 20:13:12 +0100 Subject: [PATCH 13/31] Changed pyproject.toml to pytest.ini. When I run pytest, it is not finding test/v3x/python/test_v3x_analyzer.py. --- pyproject.toml | 4 ---- pytest.ini | 5 +++++ 2 files changed, 5 insertions(+), 4 deletions(-) delete mode 100644 pyproject.toml create mode 100644 pytest.ini diff --git a/pyproject.toml b/pyproject.toml deleted file mode 100644 index 017effe6..00000000 --- a/pyproject.toml +++ /dev/null @@ -1,4 +0,0 @@ -[tool.pytest.ini_options] -testpaths = [ - "test/v10/python" -] diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 00000000..c4abf539 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,5 @@ +[pytest] +testpaths = + "test/v10/python" + "test/v3x/python" +python_files = test_*.py From c5ae663c31845fff779687ed0897aecec876d6f5 Mon Sep 17 00:00:00 2001 From: rturrado <68099809+rturrado@users.noreply.github.com> Date: Fri, 24 Nov 2023 18:47:40 +0100 Subject: [PATCH 14/31] Moved test/v10/python/test_init.py to 'test', and added 'test/v3x/python/test_v3x_analyzer.py'. TODO: have 'TestV3xAnalyzer::parse_string' recognized when running pytest, and implement it. --- test/__init__.py | 0 test/main.cpp | 2 +- test/parsing-tools.py | 1 - test/{v10/python => }/test_init.py | 12 ++++++++---- test/v10/python/test_cqasm.py | 2 +- test/v10/python/test_interface.py | 2 +- test/v1x/CMakeLists.txt | 5 +---- test/v1x/cpp/CMakeLists.txt | 4 ++++ test/v1x/{ => cpp}/parsing.cpp | 0 test/v1x/{ => cpp}/parsing.hpp | 0 test/v1x/{ => cpp}/tutorial.cpp | 0 test/v3x/__init__.py | 0 test/v3x/python/test_v3x_analyzer.py | 14 +++++--------- 13 files changed, 21 insertions(+), 21 deletions(-) create mode 100644 test/__init__.py rename test/{v10/python => }/test_init.py (67%) create mode 100644 test/v1x/cpp/CMakeLists.txt rename test/v1x/{ => cpp}/parsing.cpp (100%) rename test/v1x/{ => cpp}/parsing.hpp (100%) rename test/v1x/{ => cpp}/tutorial.cpp (100%) create mode 100644 test/v3x/__init__.py diff --git a/test/__init__.py b/test/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test/main.cpp b/test/main.cpp index f28d13f4..a9ecaaf8 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -1,4 +1,4 @@ -#include "v1x/parsing.hpp" +#include "v1x/cpp/parsing.hpp" #include "v3x/cpp/parsing.hpp" #include diff --git a/test/parsing-tools.py b/test/parsing-tools.py index 7921da6b..1a93b996 100644 --- a/test/parsing-tools.py +++ b/test/parsing-tools.py @@ -1,4 +1,3 @@ - import sys import os diff --git a/test/v10/python/test_init.py b/test/test_init.py similarity index 67% rename from test/v10/python/test_init.py rename to test/test_init.py index ac1e5a6a..dcfbcaed 100644 --- a/test/v10/python/test_init.py +++ b/test/test_init.py @@ -1,24 +1,28 @@ import os import unittest -import libQasm as qasm_interface - class TestLibQasm(unittest.TestCase): @staticmethod def _generic_test_steps(file_name): + import libQasm as qasm_interface base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) - data_file = os.path.join(base_dir, '..', '..', 'res', 'v10', file_name + '.qasm') + data_file = os.path.join(base_dir, 'res', 'v10', file_name + '.qasm') lib_qasm = qasm_interface.libQasm() lib_qasm.parse_file(data_file) return lib_qasm @staticmethod def _generic_test_steps_as_string(file_name): + import libQasm as qasm_interface base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) - data_file = os.path.join(base_dir, '..', '..', 'res', 'v10', file_name + '.qasm') + data_file = os.path.join(base_dir, 'res', 'v10', file_name + '.qasm') with open(data_file, 'r') as qasm_file: qasm_string = qasm_file.read() lib_qasm = qasm_interface.libQasm() lib_qasm.parse_string(qasm_string) return lib_qasm + + @staticmethod + def _get_v3x_analyzer(): + return libQasm.V3xAnalyzer diff --git a/test/v10/python/test_cqasm.py b/test/v10/python/test_cqasm.py index 81fb1708..32b0c636 100644 --- a/test/v10/python/test_cqasm.py +++ b/test/v10/python/test_cqasm.py @@ -1,4 +1,4 @@ -from .test_init import TestLibQasm +from ...test_init import TestLibQasm class TestQasm(TestLibQasm): diff --git a/test/v10/python/test_interface.py b/test/v10/python/test_interface.py index 11cd1346..e1407e64 100644 --- a/test/v10/python/test_interface.py +++ b/test/v10/python/test_interface.py @@ -1,4 +1,4 @@ -from .test_init import TestLibQasm +from ...test_init import TestLibQasm class TestInterface(TestLibQasm): diff --git a/test/v1x/CMakeLists.txt b/test/v1x/CMakeLists.txt index 4abf3c73..2322a85f 100644 --- a/test/v1x/CMakeLists.txt +++ b/test/v1x/CMakeLists.txt @@ -1,4 +1 @@ -target_sources(${PROJECT_NAME}_test PRIVATE - "${CMAKE_CURRENT_SOURCE_DIR}/parsing.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/tutorial.cpp" -) +add_subdirectory(cpp) diff --git a/test/v1x/cpp/CMakeLists.txt b/test/v1x/cpp/CMakeLists.txt new file mode 100644 index 00000000..4abf3c73 --- /dev/null +++ b/test/v1x/cpp/CMakeLists.txt @@ -0,0 +1,4 @@ +target_sources(${PROJECT_NAME}_test PRIVATE + "${CMAKE_CURRENT_SOURCE_DIR}/parsing.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/tutorial.cpp" +) diff --git a/test/v1x/parsing.cpp b/test/v1x/cpp/parsing.cpp similarity index 100% rename from test/v1x/parsing.cpp rename to test/v1x/cpp/parsing.cpp diff --git a/test/v1x/parsing.hpp b/test/v1x/cpp/parsing.hpp similarity index 100% rename from test/v1x/parsing.hpp rename to test/v1x/cpp/parsing.hpp diff --git a/test/v1x/tutorial.cpp b/test/v1x/cpp/tutorial.cpp similarity index 100% rename from test/v1x/tutorial.cpp rename to test/v1x/cpp/tutorial.cpp diff --git a/test/v3x/__init__.py b/test/v3x/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test/v3x/python/test_v3x_analyzer.py b/test/v3x/python/test_v3x_analyzer.py index b55f5954..daa73937 100644 --- a/test/v3x/python/test_v3x_analyzer.py +++ b/test/v3x/python/test_v3x_analyzer.py @@ -1,14 +1,10 @@ -import unittest +from ...test_init import TestLibQasm -import libQasm - -class TestV3xAnalyzer(unittest.TestCase): +# TODO: have this test recognized when running pytest, and implement it +class TestV3xAnalyzer(TestLibQasm): def parse_string(self): program_str = "version 3;qubit[5] q;bit[5] b;h q[0:4];b = measure q" - ret = libQasm.V3xAnalyzer.parse_string(program_str) + v3x_analyzer = self._get_v3x_analyzer() + ret = v3x_analyzer.parse_string(program_str) self.assertEqual(ret, "") - - -if __name__ == '__main__': - unittest.main() From 9b2074144d33d7daccb56235bd05c1fd1fe73a68 Mon Sep 17 00:00:00 2001 From: rturrado <68099809+rturrado@users.noreply.github.com> Date: Sun, 26 Nov 2023 17:27:28 +0100 Subject: [PATCH 15/31] Trying to fix GitHub Actions Python jobs. --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0b5f9af2..85a9fcfc 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -112,7 +112,7 @@ jobs: with: python-version: "3.11" - name: Install Python dependencies - run: python -m pip install --upgrade pip numpy pytest setuptools wheel + run: python -m pip install --upgrade pip conan numpy pytest setuptools wheel - name: Install SWIG, and set build type (Linux) if: matrix.os == 'ubuntu-latest' run: | From 778b44d21120c490fbd1add117370823b0921bae Mon Sep 17 00:00:00 2001 From: rturrado <68099809+rturrado@users.noreply.github.com> Date: Sun, 26 Nov 2023 18:25:06 +0100 Subject: [PATCH 16/31] Trying to fix GitHub Actions Python (macos-latest) job. --- include/v3x/ScannerAntlr.hpp | 2 ++ include/v3x/cqasm-parse-helper.hpp | 1 - src/v3x/ScannerAntlr.cpp | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/include/v3x/ScannerAntlr.hpp b/include/v3x/ScannerAntlr.hpp index e4e38014..3b15b9d0 100644 --- a/include/v3x/ScannerAntlr.hpp +++ b/include/v3x/ScannerAntlr.hpp @@ -6,6 +6,8 @@ #include // unique_ptr #include +namespace antlr4 { class ANTLRInputStream; } + namespace cqasm::v3x::parser { diff --git a/include/v3x/cqasm-parse-helper.hpp b/include/v3x/cqasm-parse-helper.hpp index a6d7cb09..dcc03b1e 100644 --- a/include/v3x/cqasm-parse-helper.hpp +++ b/include/v3x/cqasm-parse-helper.hpp @@ -10,7 +10,6 @@ #include "v3x/cqasm-parse-result.hpp" #include "v3x/ScannerAntlr.hpp" -#include #include // unique_ptr #include diff --git a/src/v3x/ScannerAntlr.cpp b/src/v3x/ScannerAntlr.cpp index 36dd56f3..d3e65504 100644 --- a/src/v3x/ScannerAntlr.cpp +++ b/src/v3x/ScannerAntlr.cpp @@ -5,6 +5,7 @@ #include "v3x/CqasmParser.h" #include "v3x/ScannerAntlr.hpp" +#include #include #include From 48468ee39287b5a1de250138fcb0e7c226b84752 Mon Sep 17 00:00:00 2001 From: rturrado <68099809+rturrado@users.noreply.github.com> Date: Sun, 26 Nov 2023 19:00:51 +0100 Subject: [PATCH 17/31] Trying to fix GitHub Actions Python (macos-latest) job. We are trying to avoid including 'antlr4-runtime.h' from some header files that are being included at the same time that a conflicting Python header. The conflicting Python header contains some defines, e.g., STRING, that 'antlr4-runtime.h' uses as enumeration values. The build process substitutes those defines in the 'antlr4-runtime.h' code, resulting in many build errors. --- include/v3x/BuildCustomAstVisitor.hpp | 7 +++---- include/v3x/BuildTreeGenAstVisitor.hpp | 4 ++-- include/v3x/ScannerAntlr.hpp | 3 ++- src/v3x/BuildTreeGenAstVisitor.cpp | 1 + src/v3x/ScannerAntlr.cpp | 1 + src/v3x/cqasm-parse-helper.cpp | 5 +++-- 6 files changed, 12 insertions(+), 9 deletions(-) diff --git a/include/v3x/BuildCustomAstVisitor.hpp b/include/v3x/BuildCustomAstVisitor.hpp index 3df9ad02..d9e8098e 100644 --- a/include/v3x/BuildCustomAstVisitor.hpp +++ b/include/v3x/BuildCustomAstVisitor.hpp @@ -3,13 +3,12 @@ #include "cqasm-ast.hpp" #include "v3x/CqasmParser.h" #include "v3x/CqasmParserVisitor.h" -#include "v3x/CustomErrorListener.hpp" - -#include // Token - #include +namespace antlr4 { class Token; } +namespace cqasm::v3x::parser { class CustomErrorListener; } + namespace cqasm::v3x::parser { diff --git a/include/v3x/BuildTreeGenAstVisitor.hpp b/include/v3x/BuildTreeGenAstVisitor.hpp index 125607e8..75559874 100644 --- a/include/v3x/BuildTreeGenAstVisitor.hpp +++ b/include/v3x/BuildTreeGenAstVisitor.hpp @@ -3,10 +3,10 @@ #include "v3x/BuildCustomAstVisitor.hpp" #include "v3x/CqasmParser.h" #include "v3x/CqasmParserVisitor.h" -#include "v3x/CustomErrorListener.hpp" - #include +namespace cqasm::v3x::parser { class CustomErrorListener; } + namespace cqasm::v3x::parser { diff --git a/include/v3x/ScannerAntlr.hpp b/include/v3x/ScannerAntlr.hpp index 3b15b9d0..05951c2f 100644 --- a/include/v3x/ScannerAntlr.hpp +++ b/include/v3x/ScannerAntlr.hpp @@ -1,12 +1,13 @@ #pragma once #include "v3x/BuildCustomAstVisitor.hpp" -#include "v3x/CustomErrorListener.hpp" +#include "v3x/cqasm-parse-result.hpp" #include // unique_ptr #include namespace antlr4 { class ANTLRInputStream; } +namespace cqasm::v3x::parser { class CustomErrorListener; } namespace cqasm::v3x::parser { diff --git a/src/v3x/BuildTreeGenAstVisitor.cpp b/src/v3x/BuildTreeGenAstVisitor.cpp index cc141f2e..cf07d604 100644 --- a/src/v3x/BuildTreeGenAstVisitor.cpp +++ b/src/v3x/BuildTreeGenAstVisitor.cpp @@ -2,6 +2,7 @@ #include "cqasm-tree.hpp" #include "v3x/cqasm-ast.hpp" #include "v3x/BuildTreeGenAstVisitor.hpp" +#include "v3x/CustomErrorListener.hpp" #include // for_each #include diff --git a/src/v3x/ScannerAntlr.cpp b/src/v3x/ScannerAntlr.cpp index d3e65504..4d75399f 100644 --- a/src/v3x/ScannerAntlr.cpp +++ b/src/v3x/ScannerAntlr.cpp @@ -3,6 +3,7 @@ #include "v3x/BuildTreeGenAstVisitor.hpp" #include "v3x/CqasmLexer.h" #include "v3x/CqasmParser.h" +#include "v3x/CustomErrorListener.hpp" #include "v3x/ScannerAntlr.hpp" #include diff --git a/src/v3x/cqasm-parse-helper.cpp b/src/v3x/cqasm-parse-helper.cpp index 587cd49e..0d8185cf 100644 --- a/src/v3x/cqasm-parse-helper.cpp +++ b/src/v3x/cqasm-parse-helper.cpp @@ -2,10 +2,11 @@ * Implementation for \ref include/v3x/cqasm-parse-helper.hpp "v3x/cqasm-parse-helper.hpp". */ -#include "v3x/cqasm-parse-result.hpp" #include "v3x/BuildTreeGenAstVisitor.hpp" -#include "v3x/cqasm-parse-helper.hpp" +#include "v3x/CustomErrorListener.hpp" #include "v3x/ScannerAntlr.hpp" +#include "v3x/cqasm-parse-helper.hpp" +#include "v3x/cqasm-parse-result.hpp" namespace cqasm::v3x::parser { From d9c66f416663e0a86edf3b01929c4f0de9236966 Mon Sep 17 00:00:00 2001 From: rturrado <68099809+rturrado@users.noreply.github.com> Date: Sun, 26 Nov 2023 19:48:38 +0100 Subject: [PATCH 18/31] Trying to fix GitHub Actions Python (macos-latest) job. We are trying to avoid including 'antlr4-runtime.h' from some header files that are being included at the same time that a conflicting Python header. The conflicting Python header contains some defines, e.g., STRING, that 'antlr4-runtime.h' uses as enumeration values. The build process substitutes those defines in the 'antlr4-runtime.h' code, resulting in many build errors. --- include/v1x/cqasm-py.hpp | 9 +++++++-- include/v3x/cqasm-py.hpp | 11 ++++++++--- src/v1x/cqasm-py.cpp | 8 ++++++++ src/v3x/cqasm-py.cpp | 10 +++++++++- 4 files changed, 32 insertions(+), 6 deletions(-) diff --git a/include/v1x/cqasm-py.hpp b/include/v1x/cqasm-py.hpp index 6fbc0146..9299024f 100644 --- a/include/v1x/cqasm-py.hpp +++ b/include/v1x/cqasm-py.hpp @@ -13,8 +13,6 @@ #include #include -#include "cqasm-analyzer.hpp" - // Forward declarations for internal types. namespace cqasm::v1x::analyzer { class Analyzer; } @@ -44,6 +42,13 @@ class V1xAnalyzer { bool without_defaults = false ); + /** + * std::unique_ptr requires T to be a complete class for the ~T operation. + * Since we are using a forward declaration for Analyzer, we need to declare ~T in the header file, + * and implement it in the source file. + */ + ~V1xAnalyzer(); + /** * Registers an instruction type. * The arguments are passed straight to instruction::Instruction's constructor. diff --git a/include/v3x/cqasm-py.hpp b/include/v3x/cqasm-py.hpp index 18a51f7d..38db5817 100644 --- a/include/v3x/cqasm-py.hpp +++ b/include/v3x/cqasm-py.hpp @@ -13,8 +13,6 @@ #include #include -#include "cqasm-analyzer.hpp" - // Forward declarations for internal types. namespace cqasm::v3x::analyzer { class Analyzer; } @@ -39,11 +37,18 @@ class V3xAnalyzer { * the initial mappings and functions are not configurable at all. * The defaults for these are always used. */ - V3xAnalyzer( + explicit V3xAnalyzer( const std::string &max_version = "3.0", bool without_defaults = false ); + /** + * std::unique_ptr requires T to be a complete class for the ~T operation. + * Since we are using a forward declaration for Analyzer, we need to declare ~T in the header file, + * and implement it in the source file. + */ + ~V3xAnalyzer(); + /** * Registers an instruction type. * The arguments are passed straight to instruction::Instruction's constructor. diff --git a/src/v1x/cqasm-py.cpp b/src/v1x/cqasm-py.cpp index add5cd8a..5ad2281b 100644 --- a/src/v1x/cqasm-py.cpp +++ b/src/v1x/cqasm-py.cpp @@ -3,6 +3,7 @@ */ #include "cqasm-version.hpp" +#include "v1x/cqasm-analyzer.hpp" #include "v1x/cqasm-parse-helper.hpp" #include "v1x/cqasm-py.hpp" #include "v1x/cqasm.hpp" @@ -30,6 +31,13 @@ V1xAnalyzer::V1xAnalyzer(const std::string &max_version, bool without_defaults) } } +/** + * std::unique_ptr requires T to be a complete class for the ~T operation. + * Since we are using a forward declaration for Analyzer, we need to declare ~T in the header file, + * and implement it in the source file. + */ +V1xAnalyzer::~V1xAnalyzer() = default; + /** * Registers an instruction type. * The arguments are passed straight to instruction::Instruction's constructor. diff --git a/src/v3x/cqasm-py.cpp b/src/v3x/cqasm-py.cpp index 6c735967..7157ceb2 100644 --- a/src/v3x/cqasm-py.cpp +++ b/src/v3x/cqasm-py.cpp @@ -3,9 +3,10 @@ */ #include "cqasm-version.hpp" +#include "v3x/cqasm-analyzer.hpp" +#include "v3x/cqasm-parse-helper.hpp" #include "v3x/cqasm-py.hpp" #include "v3x/cqasm.hpp" -#include "v3x/cqasm-parse-helper.hpp" #include @@ -30,6 +31,13 @@ V3xAnalyzer::V3xAnalyzer(const std::string &max_version, bool without_defaults) } } +/** + * std::unique_ptr requires T to be a complete class for the ~T operation. + * Since we are using a forward declaration for Analyzer, we need to declare ~T in the header file, + * and implement it in the source file. + */ +V3xAnalyzer::~V3xAnalyzer() = default; + /** * Registers an instruction type. * The arguments are passed straight to instruction::Instruction's constructor. From 5334247e4be78e2151c95f1def0405c3370ff338 Mon Sep 17 00:00:00 2001 From: rturrado <68099809+rturrado@users.noreply.github.com> Date: Tue, 28 Nov 2023 15:12:35 +0100 Subject: [PATCH 19/31] Added array versions for all the gates in the default analyzer. --- src/v3x/cqasm.cpp | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/src/v3x/cqasm.cpp b/src/v3x/cqasm.cpp index ca3fc821..ef6cfc1a 100644 --- a/src/v3x/cqasm.cpp +++ b/src/v3x/cqasm.cpp @@ -54,29 +54,52 @@ analyzer::Analyzer default_analyzer(const std::string &api_version) { analyzer.register_default_mappings(); analyzer.register_instruction("cnot", "QQ"); + analyzer.register_instruction("cnot", "QV"); + analyzer.register_instruction("cnot", "VQ"); analyzer.register_instruction("cnot", "VV"); analyzer.register_instruction("cr", "QQr"); + analyzer.register_instruction("cr", "QVr"); + analyzer.register_instruction("cr", "VQr"); + analyzer.register_instruction("cr", "VVr"); analyzer.register_instruction("crk", "QQi"); + analyzer.register_instruction("crk", "QVi"); + analyzer.register_instruction("crk", "VQi"); + analyzer.register_instruction("crk", "VVi"); analyzer.register_instruction("cz", "QQ"); + analyzer.register_instruction("cz", "QV"); + analyzer.register_instruction("cz", "VQ"); + analyzer.register_instruction("cz", "VV"); analyzer.register_instruction("h", "Q"); analyzer.register_instruction("h", "V"); analyzer.register_instruction("i", "Q"); - analyzer.register_instruction("measure", "QB", true); // qubit - bit - analyzer.register_instruction("measure", "VW", true); // qubit array - bit array - analyzer.register_instruction("measure", "VB", true); // qubit array - bit - analyzer.register_instruction("measure", "QW", true); // qubit - bit array + analyzer.register_instruction("measure", "QB", true); + analyzer.register_instruction("measure", "VW", true); + analyzer.register_instruction("measure", "VB", true); + analyzer.register_instruction("measure", "QW", true); analyzer.register_instruction("mx90", "Q"); + analyzer.register_instruction("mx90", "V"); analyzer.register_instruction("my90", "Q"); + analyzer.register_instruction("my90", "V"); analyzer.register_instruction("rx", "Qr"); + analyzer.register_instruction("rx", "Vr"); analyzer.register_instruction("ry", "Qr"); + analyzer.register_instruction("ry", "Vr"); analyzer.register_instruction("rz", "Qr"); + analyzer.register_instruction("rz", "Vr"); analyzer.register_instruction("s", "Q"); + analyzer.register_instruction("s", "V"); analyzer.register_instruction("sdag", "Q"); + analyzer.register_instruction("sdag", "V"); analyzer.register_instruction("x", "Q"); + analyzer.register_instruction("x", "V"); analyzer.register_instruction("x90", "Q"); + analyzer.register_instruction("x90", "V"); analyzer.register_instruction("y", "Q"); + analyzer.register_instruction("y", "V"); analyzer.register_instruction("y90", "Q"); + analyzer.register_instruction("y90", "V"); analyzer.register_instruction("z", "Q"); + analyzer.register_instruction("z", "V"); return analyzer; } From 644132b7974d4a61adb6144a098d3854d2ef7e14 Mon Sep 17 00:00:00 2001 From: rturrado <68099809+rturrado@users.noreply.github.com> Date: Tue, 28 Nov 2023 15:31:19 +0100 Subject: [PATCH 20/31] test_parse_string is now recognized when running pytest. We still have the same problem though as we have for the json_parser branch: AttributeError: module 'libQasm' has no attribute 'V3xAnalyzer'. --- test/test_init.py | 10 +++++----- test/v3x/python/test_v3x_analyzer.py | 3 +-- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/test/test_init.py b/test/test_init.py index dcfbcaed..08b98220 100644 --- a/test/test_init.py +++ b/test/test_init.py @@ -1,28 +1,28 @@ import os import unittest +import libQasm + class TestLibQasm(unittest.TestCase): @staticmethod def _generic_test_steps(file_name): - import libQasm as qasm_interface base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) data_file = os.path.join(base_dir, 'res', 'v10', file_name + '.qasm') - lib_qasm = qasm_interface.libQasm() + lib_qasm = libQasm.libQasm() lib_qasm.parse_file(data_file) return lib_qasm @staticmethod def _generic_test_steps_as_string(file_name): - import libQasm as qasm_interface base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) data_file = os.path.join(base_dir, 'res', 'v10', file_name + '.qasm') with open(data_file, 'r') as qasm_file: qasm_string = qasm_file.read() - lib_qasm = qasm_interface.libQasm() + lib_qasm = libQasm.libQasm() lib_qasm.parse_string(qasm_string) return lib_qasm @staticmethod def _get_v3x_analyzer(): - return libQasm.V3xAnalyzer + return libQasm.V3xAnalyzer() diff --git a/test/v3x/python/test_v3x_analyzer.py b/test/v3x/python/test_v3x_analyzer.py index daa73937..fb308f1e 100644 --- a/test/v3x/python/test_v3x_analyzer.py +++ b/test/v3x/python/test_v3x_analyzer.py @@ -1,9 +1,8 @@ from ...test_init import TestLibQasm -# TODO: have this test recognized when running pytest, and implement it class TestV3xAnalyzer(TestLibQasm): - def parse_string(self): + def test_parse_string(self): program_str = "version 3;qubit[5] q;bit[5] b;h q[0:4];b = measure q" v3x_analyzer = self._get_v3x_analyzer() ret = v3x_analyzer.parse_string(program_str) From 6aa2491e56224371cb2ec4814e58ede12b729948 Mon Sep 17 00:00:00 2001 From: rturrado <68099809+rturrado@users.noreply.github.com> Date: Tue, 28 Nov 2023 15:52:29 +0100 Subject: [PATCH 21/31] register_instruction only admits 2 parameters for v3x. --- src/v3x/cqasm.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/v3x/cqasm.cpp b/src/v3x/cqasm.cpp index ef6cfc1a..188a950b 100644 --- a/src/v3x/cqasm.cpp +++ b/src/v3x/cqasm.cpp @@ -72,10 +72,10 @@ analyzer::Analyzer default_analyzer(const std::string &api_version) { analyzer.register_instruction("h", "Q"); analyzer.register_instruction("h", "V"); analyzer.register_instruction("i", "Q"); - analyzer.register_instruction("measure", "QB", true); - analyzer.register_instruction("measure", "VW", true); - analyzer.register_instruction("measure", "VB", true); - analyzer.register_instruction("measure", "QW", true); + analyzer.register_instruction("measure", "QB"); + analyzer.register_instruction("measure", "VW"); + analyzer.register_instruction("measure", "VB"); + analyzer.register_instruction("measure", "QW"); analyzer.register_instruction("mx90", "Q"); analyzer.register_instruction("mx90", "V"); analyzer.register_instruction("my90", "Q"); From 4560a40a337917441a1cd673ef4d0dc4ab17ac98 Mon Sep 17 00:00:00 2001 From: rturrado <68099809+rturrado@users.noreply.github.com> Date: Wed, 29 Nov 2023 12:44:10 +0100 Subject: [PATCH 22/31] Fixed issue: `AttributeError: 'string' object has no attribute 'encode'. With code: return ast.Program.deserialize(retval[0].encode("utf-8", errors="surrogateescape")) We are now converting retval[0] to a string before encoding. --- python/module/cqasm/v1x/__init__.py | 47 ++++++++++++++++++----------- python/module/cqasm/v3x/__init__.py | 47 ++++++++++++++++++----------- 2 files changed, 58 insertions(+), 36 deletions(-) diff --git a/python/module/cqasm/v1x/__init__.py b/python/module/cqasm/v1x/__init__.py index 7f2e786c..5bc19796 100644 --- a/python/module/cqasm/v1x/__init__.py +++ b/python/module/cqasm/v1x/__init__.py @@ -1,35 +1,46 @@ import libQasm -class V1xAnalyzer(libQasm.V1xAnalyzer): +class Analyzer(libQasm.V1xAnalyzer): @staticmethod def parse_file(*args): - retval = libQasm.V1xAnalyzer.parse_file(*args) - if len(retval) == 1: + ret = libQasm.V1xAnalyzer.parse_file(*args) + if len(ret) == 1: import cqasm.v1x.ast as ast - return ast.Root.deserialize(retval[0].encode("utf-8", errors="surrogateescape")) - return list(retval[1:]) + serialized_ast_str = str(ret[0]) + serialized_ast_bytes = serialized_ast_str.encode(encoding='utf-8', errors="surrogateescape") + deserialized_ast = ast.Root.deserialize(serialized_ast_bytes) + return deserialized_ast + return list(ret[1:]) @staticmethod def parse_string(*args): - retval = libQasm.V1xAnalyzer.parse_string(*args) - if len(retval) == 1: + ret = libQasm.V1xAnalyzer.parse_string(*args) + if len(ret) == 1: import cqasm.v1x.ast as ast - return ast.Root.deserialize(retval[0].encode("utf-8", errors="surrogateescape")) - return list(retval[1:]) + serialized_ast_str = str(ret[0]) + serialized_ast_bytes = serialized_ast_str.encode(encoding='utf-8', errors="surrogateescape") + deserialized_ast = ast.Root.deserialize(serialized_ast_bytes) + return deserialized_ast + return list(ret[1:]) def analyze_file(self, *args): - retval = super().analyze_file(*args) - if len(retval) == 1: + ret = super().analyze_file(*args) + if len(ret) == 1: import cqasm.v1x.semantic as semantic - print(retval[0].encode("utf-8", errors="surrogateescape")) - return semantic.Program.deserialize(retval[0].encode("utf-8", errors="surrogateescape")) - return list(retval[1:]) + serialized_ast_str = str(ret[0]) + serialized_ast_bytes = serialized_ast_str.encode(encoding='utf-8', errors="surrogateescape") + deserialized_ast = semantic.Root.deserialize(serialized_ast_bytes) + return deserialized_ast + return list(ret[1:]) def analyze_string(self, *args): - retval = super().analyze_string(*args) - if len(retval) == 1: + ret = super().analyze_string(*args) + if len(ret) == 1: import cqasm.v1x.semantic as semantic - return semantic.Program.deserialize(retval[0].encode("utf-8", errors="surrogateescape")) - return list(retval[1:]) + serialized_ast_str = str(ret[0]) + serialized_ast_bytes = serialized_ast_str.encode(encoding='utf-8', errors="surrogateescape") + deserialized_ast = semantic.Root.deserialize(serialized_ast_bytes) + return deserialized_ast + return list(ret[1:]) diff --git a/python/module/cqasm/v3x/__init__.py b/python/module/cqasm/v3x/__init__.py index 865f0f66..f25bbb05 100644 --- a/python/module/cqasm/v3x/__init__.py +++ b/python/module/cqasm/v3x/__init__.py @@ -1,35 +1,46 @@ import libQasm -class V3xAnalyzer(libQasm.V3xAnalyzer): +class Analyzer(libQasm.V3xAnalyzer): @staticmethod def parse_file(*args): - retval = libQasm.V3xAnalyzer.parse_file(*args) - if len(retval) == 1: + ret = libQasm.V3xAnalyzer.parse_file(*args) + if len(ret) == 1: import cqasm.v3x.ast as ast - return ast.Root.deserialize(retval[0].encode("utf-8", errors="surrogateescape")) - return list(retval[1:]) + serialized_ast_str = str(ret[0]) + serialized_ast_bytes = serialized_ast_str.encode(encoding='utf-8', errors="surrogateescape") + deserialized_ast = ast.Root.deserialize(serialized_ast_bytes) + return deserialized_ast + return list(ret[1:]) @staticmethod def parse_string(*args): - retval = libQasm.V3xAnalyzer.parse_string(*args) - if len(retval) == 1: + ret = libQasm.V3xAnalyzer.parse_string(*args) + if len(ret) == 1: import cqasm.v3x.ast as ast - return ast.Root.deserialize(retval[0].encode("utf-8", errors="surrogateescape")) - return list(retval[1:]) + serialized_ast_str = str(ret[0]) + serialized_ast_bytes = serialized_ast_str.encode(encoding='utf-8', errors="surrogateescape") + deserialized_ast = ast.Root.deserialize(serialized_ast_bytes) + return deserialized_ast + return list(ret[1:]) def analyze_file(self, *args): - retval = super().analyze_file(*args) - if len(retval) == 1: + ret = super().analyze_file(*args) + if len(ret) == 1: import cqasm.v3x.semantic as semantic - print(retval[0].encode("utf-8", errors="surrogateescape")) - return semantic.Program.deserialize(retval[0].encode("utf-8", errors="surrogateescape")) - return list(retval[1:]) + serialized_ast_str = str(ret[0]) + serialized_ast_bytes = serialized_ast_str.encode(encoding='utf-8', errors="surrogateescape") + deserialized_ast = semantic.Root.deserialize(serialized_ast_bytes) + return deserialized_ast + return list(ret[1:]) def analyze_string(self, *args): - retval = super().analyze_string(*args) - if len(retval) == 1: + ret = super().analyze_string(*args) + if len(ret) == 1: import cqasm.v3x.semantic as semantic - return semantic.Program.deserialize(retval[0].encode("utf-8", errors="surrogateescape")) - return list(retval[1:]) + serialized_ast_str = str(ret[0]) + serialized_ast_bytes = serialized_ast_str.encode(encoding='utf-8', errors="surrogateescape") + deserialized_ast = semantic.Root.deserialize(serialized_ast_bytes) + return deserialized_ast + return list(ret[1:]) From 99080f61fb03083ffebb592d59872512e1541890 Mon Sep 17 00:00:00 2001 From: rturrado <68099809+rturrado@users.noreply.github.com> Date: Wed, 29 Nov 2023 13:13:12 +0100 Subject: [PATCH 23/31] Fixed python/module/cqasm/{v1x,v3x}/__init__.py. We also need to convert every error from a "libQasm string" to a "Python string" before returning. --- python/module/cqasm/v1x/__init__.py | 8 ++++---- python/module/cqasm/v3x/__init__.py | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/python/module/cqasm/v1x/__init__.py b/python/module/cqasm/v1x/__init__.py index 5bc19796..062b1ee8 100644 --- a/python/module/cqasm/v1x/__init__.py +++ b/python/module/cqasm/v1x/__init__.py @@ -12,7 +12,7 @@ def parse_file(*args): serialized_ast_bytes = serialized_ast_str.encode(encoding='utf-8', errors="surrogateescape") deserialized_ast = ast.Root.deserialize(serialized_ast_bytes) return deserialized_ast - return list(ret[1:]) + return [str(error) for error in ret[1:]] @staticmethod def parse_string(*args): @@ -23,7 +23,7 @@ def parse_string(*args): serialized_ast_bytes = serialized_ast_str.encode(encoding='utf-8', errors="surrogateescape") deserialized_ast = ast.Root.deserialize(serialized_ast_bytes) return deserialized_ast - return list(ret[1:]) + return [str(error) for error in ret[1:]] def analyze_file(self, *args): ret = super().analyze_file(*args) @@ -33,7 +33,7 @@ def analyze_file(self, *args): serialized_ast_bytes = serialized_ast_str.encode(encoding='utf-8', errors="surrogateescape") deserialized_ast = semantic.Root.deserialize(serialized_ast_bytes) return deserialized_ast - return list(ret[1:]) + return [str(error) for error in ret[1:]] def analyze_string(self, *args): ret = super().analyze_string(*args) @@ -43,4 +43,4 @@ def analyze_string(self, *args): serialized_ast_bytes = serialized_ast_str.encode(encoding='utf-8', errors="surrogateescape") deserialized_ast = semantic.Root.deserialize(serialized_ast_bytes) return deserialized_ast - return list(ret[1:]) + return [str(error) for error in ret[1:]] diff --git a/python/module/cqasm/v3x/__init__.py b/python/module/cqasm/v3x/__init__.py index f25bbb05..1330cc08 100644 --- a/python/module/cqasm/v3x/__init__.py +++ b/python/module/cqasm/v3x/__init__.py @@ -12,7 +12,7 @@ def parse_file(*args): serialized_ast_bytes = serialized_ast_str.encode(encoding='utf-8', errors="surrogateescape") deserialized_ast = ast.Root.deserialize(serialized_ast_bytes) return deserialized_ast - return list(ret[1:]) + return [str(error) for error in ret[1:]] @staticmethod def parse_string(*args): @@ -23,7 +23,7 @@ def parse_string(*args): serialized_ast_bytes = serialized_ast_str.encode(encoding='utf-8', errors="surrogateescape") deserialized_ast = ast.Root.deserialize(serialized_ast_bytes) return deserialized_ast - return list(ret[1:]) + return [str(error) for error in ret[1:]] def analyze_file(self, *args): ret = super().analyze_file(*args) @@ -33,7 +33,7 @@ def analyze_file(self, *args): serialized_ast_bytes = serialized_ast_str.encode(encoding='utf-8', errors="surrogateescape") deserialized_ast = semantic.Root.deserialize(serialized_ast_bytes) return deserialized_ast - return list(ret[1:]) + return [str(error) for error in ret[1:]] def analyze_string(self, *args): ret = super().analyze_string(*args) @@ -43,4 +43,4 @@ def analyze_string(self, *args): serialized_ast_bytes = serialized_ast_str.encode(encoding='utf-8', errors="surrogateescape") deserialized_ast = semantic.Root.deserialize(serialized_ast_bytes) return deserialized_ast - return list(ret[1:]) + return [str(error) for error in ret[1:]] From 858c6179cb1216ae3fc2d233dff01adf6f42e147 Mon Sep 17 00:00:00 2001 From: rturrado <68099809+rturrado@users.noreply.github.com> Date: Wed, 29 Nov 2023 13:14:36 +0100 Subject: [PATCH 24/31] Fixed src/{v1x,v3x}/cqasm-py.cpp. The analyzer functions always return a vector of strings. And, in this vector, the first string is reserved for the serialized AST. The next strings are filled with error messages, if any. --- src/v1x/cqasm-py.cpp | 42 ++++++++++++++++++++++++++---------------- src/v3x/cqasm-py.cpp | 42 ++++++++++++++++++++++++++---------------- 2 files changed, 52 insertions(+), 32 deletions(-) diff --git a/src/v1x/cqasm-py.cpp b/src/v1x/cqasm-py.cpp index 5ad2281b..312cda30 100644 --- a/src/v1x/cqasm-py.cpp +++ b/src/v1x/cqasm-py.cpp @@ -82,10 +82,12 @@ void V1xAnalyzer::register_error_model( std::vector V1xAnalyzer::parse_file( const std::string &filename ) { - auto result = v1x::parser::parse_file(filename); - return result.errors.empty() - ? std::vector{ tree::base::serialize(result.root) } - : result.errors; + if (auto parse_result = v1x::parser::parse_file(filename); parse_result.errors.empty()) { + return std::vector{ tree::base::serialize(parse_result.root) }; + } else { + parse_result.errors.insert(parse_result.errors.begin(), ""); + return parse_result.errors; + } } /** @@ -96,10 +98,12 @@ std::vector V1xAnalyzer::parse_string( const std::string &data, const std::string &filename ) { - auto result = v1x::parser::parse_string(data, filename); - return result.errors.empty() - ? std::vector{ tree::base::serialize(result.root) } - : result.errors; + if (auto parse_result = v1x::parser::parse_string(data, filename); parse_result.errors.empty()) { + return std::vector{ tree::base::serialize(parse_result.root) }; + } else { + parse_result.errors.insert(parse_result.errors.begin(), ""); + return parse_result.errors; + } } /** @@ -114,13 +118,16 @@ std::vector V1xAnalyzer::parse_string( [[nodiscard]] std::vector V1xAnalyzer::analyze_file( const std::string &filename ) const { - auto result = analyzer->analyze( + auto analysis_result = analyzer->analyze( [=](){ return cqasm::version::parse_file(filename); }, [=](){ return v1x::parser::parse_file(filename); } ); - return result.errors.empty() - ? std::vector{ tree::base::serialize(result.root) } - : result.errors; + if (analysis_result.errors.empty()) { + return std::vector{ tree::base::serialize(analysis_result.root) }; + } else { + analysis_result.errors.insert(analysis_result.errors.begin(), ""); + return analysis_result.errors; + } } /** @@ -131,11 +138,14 @@ std::vector V1xAnalyzer::parse_string( const std::string &data, const std::string &filename ) const { - auto result = analyzer->analyze( + auto analysis_result = analyzer->analyze( [=](){ return cqasm::version::parse_string(data, filename); }, [=](){ return v1x::parser::parse_string(data, filename); } ); - return result.errors.empty() - ? std::vector{ tree::base::serialize(result.root) } - : result.errors; + if (analysis_result.errors.empty()) { + return std::vector{ tree::base::serialize(analysis_result.root) }; + } else { + analysis_result.errors.insert(analysis_result.errors.begin(), ""); + return analysis_result.errors; + } } diff --git a/src/v3x/cqasm-py.cpp b/src/v3x/cqasm-py.cpp index a70b45ba..8dd9a51a 100644 --- a/src/v3x/cqasm-py.cpp +++ b/src/v3x/cqasm-py.cpp @@ -57,10 +57,12 @@ void V3xAnalyzer::register_instruction(const std::string &name, const std::strin std::vector V3xAnalyzer::parse_file( const std::string &filename ) { - auto result = v3x::parser::parse_file(filename); - return result.errors.empty() - ? std::vector{ tree::base::serialize(result.root) } - : result.errors; + if (auto parse_result = v3x::parser::parse_file(filename); parse_result.errors.empty()) { + return std::vector{ tree::base::serialize(parse_result.root) }; + } else { + parse_result.errors.insert(parse_result.errors.begin(), ""); + return parse_result.errors; + } } /** @@ -71,10 +73,12 @@ std::vector V3xAnalyzer::parse_string( const std::string &data, const std::string &filename ) { - auto result = v3x::parser::parse_string(data, filename); - return result.errors.empty() - ? std::vector{ tree::base::serialize(result.root) } - : result.errors; + if (auto parse_result = v3x::parser::parse_string(data, filename); parse_result.errors.empty()) { + return std::vector{ tree::base::serialize(parse_result.root) }; + } else { + parse_result.errors.insert(parse_result.errors.begin(), ""); + return parse_result.errors; + } } /** @@ -89,13 +93,16 @@ std::vector V3xAnalyzer::parse_string( std::vector V3xAnalyzer::analyze_file( const std::string &filename ) const { - auto result = analyzer->analyze( + auto analysis_result = analyzer->analyze( [=](){ return cqasm::version::parse_file(filename); }, [=](){ return v3x::parser::parse_file(filename); } ); - return result.errors.empty() - ? std::vector{ tree::base::serialize(result.root) } - : result.errors; + if (analysis_result.errors.empty()) { + return std::vector{ tree::base::serialize(analysis_result.root) }; + } else { + analysis_result.errors.insert(analysis_result.errors.begin(), ""); + return analysis_result.errors; + } } /** @@ -106,11 +113,14 @@ std::vector V3xAnalyzer::analyze_string( const std::string &data, const std::string &filename ) const { - auto result = analyzer->analyze( + auto analysis_result = analyzer->analyze( [=](){ return cqasm::version::parse_string(data, filename); }, [=](){ return v3x::parser::parse_string(data, filename); } ); - return result.errors.empty() - ? std::vector{ tree::base::serialize(result.root) } - : result.errors; + if (analysis_result.errors.empty()) { + return std::vector{ tree::base::serialize(analysis_result.root) }; + } else { + analysis_result.errors.insert(analysis_result.errors.begin(), ""); + return analysis_result.errors; + } } From 31ca6dbc90629505ec148f23d6b49925cfe0ce59 Mon Sep 17 00:00:00 2001 From: rturrado <68099809+rturrado@users.noreply.github.com> Date: Wed, 29 Nov 2023 14:31:36 +0100 Subject: [PATCH 25/31] Moved test_init.py back to test/v10/python. --- test/__init__.py | 0 test/v10/__init__.py | 0 test/v10/python/__init__.py | 0 test/v10/python/test_cqasm.py | 2 +- test/{ => v10/python}/test_init.py | 8 ++------ test/v10/python/test_interface.py | 2 +- 6 files changed, 4 insertions(+), 8 deletions(-) delete mode 100644 test/__init__.py delete mode 100644 test/v10/__init__.py delete mode 100644 test/v10/python/__init__.py rename test/{ => v10/python}/test_init.py (73%) diff --git a/test/__init__.py b/test/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/v10/__init__.py b/test/v10/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/v10/python/__init__.py b/test/v10/python/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/v10/python/test_cqasm.py b/test/v10/python/test_cqasm.py index 32b0c636..9c24a452 100644 --- a/test/v10/python/test_cqasm.py +++ b/test/v10/python/test_cqasm.py @@ -1,4 +1,4 @@ -from ...test_init import TestLibQasm +from test_init import TestLibQasm class TestQasm(TestLibQasm): diff --git a/test/test_init.py b/test/v10/python/test_init.py similarity index 73% rename from test/test_init.py rename to test/v10/python/test_init.py index 08b98220..87fc8f5d 100644 --- a/test/test_init.py +++ b/test/v10/python/test_init.py @@ -8,7 +8,7 @@ class TestLibQasm(unittest.TestCase): @staticmethod def _generic_test_steps(file_name): base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) - data_file = os.path.join(base_dir, 'res', 'v10', file_name + '.qasm') + data_file = os.path.join(base_dir, '..', '..', 'res', 'v10', file_name + '.qasm') lib_qasm = libQasm.libQasm() lib_qasm.parse_file(data_file) return lib_qasm @@ -16,13 +16,9 @@ def _generic_test_steps(file_name): @staticmethod def _generic_test_steps_as_string(file_name): base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) - data_file = os.path.join(base_dir, 'res', 'v10', file_name + '.qasm') + data_file = os.path.join(base_dir, '..', '..', 'res', 'v10', file_name + '.qasm') with open(data_file, 'r') as qasm_file: qasm_string = qasm_file.read() lib_qasm = libQasm.libQasm() lib_qasm.parse_string(qasm_string) return lib_qasm - - @staticmethod - def _get_v3x_analyzer(): - return libQasm.V3xAnalyzer() diff --git a/test/v10/python/test_interface.py b/test/v10/python/test_interface.py index e1407e64..1f5bf0f9 100644 --- a/test/v10/python/test_interface.py +++ b/test/v10/python/test_interface.py @@ -1,4 +1,4 @@ -from ...test_init import TestLibQasm +from test_init import TestLibQasm class TestInterface(TestLibQasm): From 0db9253298b14a5480a36d05c8b19a203e6095c9 Mon Sep 17 00:00:00 2001 From: rturrado <68099809+rturrado@users.noreply.github.com> Date: Wed, 29 Nov 2023 14:32:23 +0100 Subject: [PATCH 26/31] Fixed python/module/cqasm/v3x/__init__.py analyze_file and analyze_string functions. --- python/module/cqasm/v3x/__init__.py | 4 ++-- python/module/libQasm/__init__.py | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/python/module/cqasm/v3x/__init__.py b/python/module/cqasm/v3x/__init__.py index 1330cc08..38a271c8 100644 --- a/python/module/cqasm/v3x/__init__.py +++ b/python/module/cqasm/v3x/__init__.py @@ -31,7 +31,7 @@ def analyze_file(self, *args): import cqasm.v3x.semantic as semantic serialized_ast_str = str(ret[0]) serialized_ast_bytes = serialized_ast_str.encode(encoding='utf-8', errors="surrogateescape") - deserialized_ast = semantic.Root.deserialize(serialized_ast_bytes) + deserialized_ast = semantic.Program.deserialize(serialized_ast_bytes) return deserialized_ast return [str(error) for error in ret[1:]] @@ -41,6 +41,6 @@ def analyze_string(self, *args): import cqasm.v3x.semantic as semantic serialized_ast_str = str(ret[0]) serialized_ast_bytes = serialized_ast_str.encode(encoding='utf-8', errors="surrogateescape") - deserialized_ast = semantic.Root.deserialize(serialized_ast_bytes) + deserialized_ast = semantic.Program.deserialize(serialized_ast_bytes) return deserialized_ast return [str(error) for error in ret[1:]] diff --git a/python/module/libQasm/__init__.py b/python/module/libQasm/__init__.py index df8aca7b..0454f95b 100644 --- a/python/module/libQasm/__init__.py +++ b/python/module/libQasm/__init__.py @@ -1,17 +1,17 @@ # Author Imran Ashraf, Jeroen van Straten -# Before we can import the dynamic modules, we have to set the linker search -# path appropriately. import os +from sys import version_info + + +# Before we can import the dynamic modules, we have to set the linker search path appropriately. ld_lib_path = os.environ.get('LD_LIBRARY_PATH', '') if ld_lib_path: ld_lib_path += ':' os.environ['LD_LIBRARY_PATH'] = ld_lib_path + os.path.dirname(__file__) del ld_lib_path, os -# The import syntax changes slightly between python 2 and 3, so we -# need to detect which version is being used: -from sys import version_info +# The import syntax changes slightly between python 2 and 3, so we need to detect which version is being used: if version_info[0] == 3: PY3 = True elif version_info[0] == 2: From e363f681b9733bb2c5cc02682af00642daebbe93 Mon Sep 17 00:00:00 2001 From: rturrado <68099809+rturrado@users.noreply.github.com> Date: Wed, 29 Nov 2023 14:33:01 +0100 Subject: [PATCH 27/31] Fixed circular imports in python/module/cqasm/{v1x,v3x}/primitives.py. --- python/module/cqasm/v1x/primitives.py | 21 +++++++++++---------- python/module/cqasm/v3x/primitives.py | 10 +++++----- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/python/module/cqasm/v1x/primitives.py b/python/module/cqasm/v1x/primitives.py index 7b6687a7..0ed48e92 100644 --- a/python/module/cqasm/v1x/primitives.py +++ b/python/module/cqasm/v1x/primitives.py @@ -1,7 +1,8 @@ from enum import Enum import numpy as np -from cqasm.v1x.error_model import ErrorModel, ErrorModelRef -from cqasm.v1x.instruction import Instruction, InstructionRef + +import cqasm.v1x.error_model +import cqasm.v1x.instruction import cqasm.v1x.types Str = str @@ -100,7 +101,7 @@ def serialize(typ, val): return {'c': val.size_cols(), 'd': data} elif typ is Version: return {'x': list(val)} - elif typ is ErrorModelRef: + elif typ is cqasm.v1x.error_model.ErrorModelRef: if val.data is None: return {} else: @@ -108,7 +109,7 @@ def serialize(typ, val): 'n': val.data.name, 't': [x.serialize() for x in val.data.types] } - elif typ is InstructionRef: + elif typ is cqasm.v1x.instruction.InstructionRef: if val.data is None: return {} else: @@ -152,17 +153,17 @@ def deserialize(typ, val): return CMatrix(np.array(val['d'], dtype=complex).reshape([val['c'], len(val['d']) // val['c']])) elif typ is Version: return Version(val['x']) - elif typ is ErrorModelRef: + elif typ is cqasm.v1x.error_model.ErrorModelRef: if 'n' in val: - return ErrorModelRef( + return cqasm.v1x.error_model.ErrorModelRef( val['n'], [cqasm.v1x.types.Node.deserialize(x) for x in val['t']] ) else: - return ErrorModelRef() - elif typ is InstructionRef: + return cqasm.v1x.error_model.ErrorModelRef() + elif typ is cqasm.v1x.instruction.InstructionRef: if 'n' in val: - return InstructionRef( + return cqasm.v1x.instruction.InstructionRef( val['n'], [cqasm.v1x.types.Node.deserialize(x) for x in val['t']], val['c'], @@ -171,6 +172,6 @@ def deserialize(typ, val): val['d'] ) else: - return InstructionRef() + return cqasm.v1x.instruction.InstructionRef() else: assert False diff --git a/python/module/cqasm/v3x/primitives.py b/python/module/cqasm/v3x/primitives.py index dc85f5c9..d300c244 100644 --- a/python/module/cqasm/v3x/primitives.py +++ b/python/module/cqasm/v3x/primitives.py @@ -1,4 +1,4 @@ -from cqasm.v3x.instruction import Instruction, InstructionRef +import cqasm.v3x.instruction import cqasm.v3x.types Str = str @@ -32,7 +32,7 @@ def serialize(typ, val): return {'r': val.real, 'i': val.imag} elif typ is Version: return {'x': list(val)} - elif typ is InstructionRef: + elif typ is cqasm.v3x.instruction.InstructionRef: if val.data is None: return {} else: @@ -59,13 +59,13 @@ def deserialize(typ, val): return Complex(val['r'], val['i']) elif typ is Version: return Version(val['x']) - elif typ is InstructionRef: + elif typ is cqasm.v3x.instruction.InstructionRef: if 'n' in val: - return InstructionRef( + return cqasm.v3x.instruction.InstructionRef( val['n'], [cqasm.v3x.types.Node.deserialize(x) for x in val['t']] ) else: - return InstructionRef() + return cqasm.v3x.instruction.InstructionRef() else: assert False From cf1cec530cf79d00346efdde03437385ae9d804a Mon Sep 17 00:00:00 2001 From: rturrado <68099809+rturrado@users.noreply.github.com> Date: Wed, 29 Nov 2023 14:33:28 +0100 Subject: [PATCH 28/31] Fixed param types for measure instruction at src/v3x/cqasm.cpp default_analyzer. --- src/v3x/cqasm.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/v3x/cqasm.cpp b/src/v3x/cqasm.cpp index 188a950b..cb9e31c6 100644 --- a/src/v3x/cqasm.cpp +++ b/src/v3x/cqasm.cpp @@ -72,10 +72,10 @@ analyzer::Analyzer default_analyzer(const std::string &api_version) { analyzer.register_instruction("h", "Q"); analyzer.register_instruction("h", "V"); analyzer.register_instruction("i", "Q"); - analyzer.register_instruction("measure", "QB"); - analyzer.register_instruction("measure", "VW"); - analyzer.register_instruction("measure", "VB"); - analyzer.register_instruction("measure", "QW"); + analyzer.register_instruction("measure", "BQ"); + analyzer.register_instruction("measure", "WV"); + analyzer.register_instruction("measure", "BV"); + analyzer.register_instruction("measure", "WQ"); analyzer.register_instruction("mx90", "Q"); analyzer.register_instruction("mx90", "V"); analyzer.register_instruction("my90", "Q"); From 1328cf2af015f06c38a4120238933139f48c7361 Mon Sep 17 00:00:00 2001 From: rturrado <68099809+rturrado@users.noreply.github.com> Date: Wed, 29 Nov 2023 14:47:00 +0100 Subject: [PATCH 29/31] Implemented a few V3xAnalyzer tests. To exercise the parse_string and analyze_string APIs. Both when an AST or a list of errors is returned. --- test/v3x/python/test_v3x_analyzer.py | 88 ++++++++++++++++++++++++++-- 1 file changed, 82 insertions(+), 6 deletions(-) diff --git a/test/v3x/python/test_v3x_analyzer.py b/test/v3x/python/test_v3x_analyzer.py index fb308f1e..e20722a7 100644 --- a/test/v3x/python/test_v3x_analyzer.py +++ b/test/v3x/python/test_v3x_analyzer.py @@ -1,9 +1,85 @@ -from ...test_init import TestLibQasm +import unittest +import cqasm.v3x as cq -class TestV3xAnalyzer(TestLibQasm): - def test_parse_string(self): + +class TestV3xAnalyzer(unittest.TestCase): + def test_parse_string_returning_ast(self): + program_str = "version 3;qubit[5] q;bit[5] b;h q[0:4];b = measure q" + v3x_analyzer = cq.Analyzer() + ast = v3x_analyzer.parse_string(program_str) + + self.assertEqual(ast.version.items[0], 3) + + qubit_array = ast.statements.items[0] + self.assertEqual(qubit_array.names[0].name, "b'q'") + self.assertEqual(qubit_array.typ.name, "b'qubit'") + self.assertEqual(qubit_array.size.value, 5) + + bit_array = ast.statements.items[1] + self.assertEqual(bit_array.names[0].name, "b'b'") + self.assertEqual(bit_array.typ.name, "b'bit'") + self.assertEqual(bit_array.size.value, 5) + + h_instruction = ast.statements.items[2] + self.assertEqual(h_instruction.name.name, "b'h'") + h_operand = h_instruction.operands.items[0] + self.assertEqual(h_operand.expr.name, "b'q'") + self.assertEqual(h_operand.indices.items[0].first.value, 0) + self.assertEqual(h_operand.indices.items[0].last.value, 4) + + measure_instruction = ast.statements.items[3] + self.assertEqual(measure_instruction.name.name, "b'measure'") + self.assertEqual(measure_instruction.lhs.name, "b'b'") + self.assertEqual(measure_instruction.rhs.name, "b'q'") + + def test_parse_string_returning_errors(self): + program_str = "version 3;qubit[5] q;bit[5] b;h q[0:4];b = measure" + v3x_analyzer = cq.Analyzer() + errors = v3x_analyzer.parse_string(program_str) + expected_errors = [":1:51: mismatched input '' expecting {INTEGER_LITERAL, FLOAT_LITERAL, IDENTIFIER}"] + self.assertEqual(errors, expected_errors) + + def test_analyze_string_returning_ast(self): program_str = "version 3;qubit[5] q;bit[5] b;h q[0:4];b = measure q" - v3x_analyzer = self._get_v3x_analyzer() - ret = v3x_analyzer.parse_string(program_str) - self.assertEqual(ret, "") + v3x_analyzer = cq.Analyzer() + ast = v3x_analyzer.analyze_string(program_str) + + self.assertEqual(ast.version.items[0], 3) + + h_instruction = ast.statements[0] + self.assertEqual(h_instruction.name, "b'h'") + h_operand = h_instruction.operands[0] + self.assertEqual(h_operand.variable.name, "b'q'") + self.assertIsInstance(h_operand.variable.typ, cq.types.QubitArray) + self.assertEqual(h_operand.variable.typ.size, 5) + self.assertEqual(h_operand.indices[0].value, 0) + self.assertEqual(h_operand.indices[1].value, 1) + self.assertEqual(h_operand.indices[2].value, 2) + self.assertEqual(h_operand.indices[3].value, 3) + self.assertEqual(h_operand.indices[4].value, 4) + + measure_instruction = ast.statements[1] + self.assertEqual(measure_instruction.name, "b'measure'") + measure_bit_operand = measure_instruction.operands[0] + self.assertEqual(measure_bit_operand.variable.name, "b'b'") + self.assertIsInstance(measure_bit_operand.variable.typ, cq.types.BitArray) + self.assertEqual(measure_bit_operand.variable.typ.size, 5) + measure_qubit_operand = measure_instruction.operands[1] + self.assertEqual(measure_qubit_operand.variable.name, "b'q'") + self.assertIsInstance(measure_qubit_operand.variable.typ, cq.types.QubitArray) + self.assertEqual(measure_qubit_operand.variable.typ.size, 5) + + qubit_array = ast.variables[0] + self.assertEqual(qubit_array.name, "b'q'") + self.assertIsInstance(qubit_array.typ, cq.types.QubitArray) + bit_array = ast.variables[1] + self.assertEqual(bit_array.name, "b'b'") + self.assertIsInstance(bit_array.typ, cq.types.BitArray) + + def test_analyze_string_returning_errors(self): + program_str = "version 3;qubit[3] q;x q[3]" + v3x_analyzer = cq.Analyzer() + errors = v3x_analyzer.analyze_string(program_str) + expected_errors = ["Error at :1:24..25: index 3 out of range (size 3)"] + self.assertEqual(errors, expected_errors) From 07b5fc73c02864f3b8d0a08369da6db46e3fcca3 Mon Sep 17 00:00:00 2001 From: rturrado <68099809+rturrado@users.noreply.github.com> Date: Tue, 5 Dec 2023 12:06:01 +0100 Subject: [PATCH 30/31] Removed references to Python 2, as it is unsupported. --- python/module/libQasm/__init__.py | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/python/module/libQasm/__init__.py b/python/module/libQasm/__init__.py index 0454f95b..328c53af 100644 --- a/python/module/libQasm/__init__.py +++ b/python/module/libQasm/__init__.py @@ -11,23 +11,15 @@ os.environ['LD_LIBRARY_PATH'] = ld_lib_path + os.path.dirname(__file__) del ld_lib_path, os -# The import syntax changes slightly between python 2 and 3, so we need to detect which version is being used: -if version_info[0] == 3: - PY3 = True -elif version_info[0] == 2: - PY3 = False -else: +# We only support Python 3 +if version_info[0] != 3: raise EnvironmentError( - "sys.version_info refers to a version of Python neither 2 nor 3. " + "sys.version_info refers does not refer to a version of Python 3. " "This is not permitted. " "sys.version_info = {}".format(version_info)) del version_info # Import the SWIG-generated module. -if PY3: - from .libQasm import * -else: - from libQasm import * -del PY3 +from .libQasm import * # __all__ = [ init, schedule, compile ] From 8581bebd7544e383885f8f64d21f1681228f4539 Mon Sep 17 00:00:00 2001 From: rturrado Date: Tue, 5 Dec 2023 14:45:36 +0100 Subject: [PATCH 31/31] Updated parse_file and analyze_file comments. --- include/v1x/cqasm-py.hpp | 8 ++++---- include/v3x/cqasm-py.hpp | 8 ++++---- src/v1x/cqasm-py.cpp | 8 ++++---- src/v3x/cqasm-py.cpp | 8 ++++---- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/include/v1x/cqasm-py.hpp b/include/v1x/cqasm-py.hpp index 9299024f..1f0ffd8e 100644 --- a/include/v1x/cqasm-py.hpp +++ b/include/v1x/cqasm-py.hpp @@ -75,9 +75,9 @@ class V1xAnalyzer { * Only parses the given file. * The file must be in v1.x syntax. * No version check or conversion is performed. - * Returns a vector of strings, - * of which the first is always present and is the CBOR serialization of the v1.x AST. + * Returns a vector of strings, of which the first is reserved for the CBOR serialization of the v1.x AST. * Any additional strings represent error messages. + * Notice that the AST and error messages won't be available at the same time. */ static std::vector parse_file( const std::string &filename @@ -97,9 +97,9 @@ class V1xAnalyzer { * If the file is written in a later file version, * this function may try to reduce it to the maximum v1.x API version support advertised * using this object's constructor. - * Returns a vector of strings, - * of which the first is always present and is the CBOR serialization of the v1.x semantic tree. + * Returns a vector of strings, of which the first is reserved for the CBOR serialization of the v1.x semantic tree. * Any additional strings represent error messages. + * Notice that the AST and error messages won't be available at the same time. */ std::vector analyze_file( const std::string &filename diff --git a/include/v3x/cqasm-py.hpp b/include/v3x/cqasm-py.hpp index 24633bfb..3f774de1 100644 --- a/include/v3x/cqasm-py.hpp +++ b/include/v3x/cqasm-py.hpp @@ -59,9 +59,9 @@ class V3xAnalyzer { * Only parses the given file. * The file must be in v3.x syntax. * No version check or conversion is performed. - * Returns a vector of strings, - * of which the first is always present and is the CBOR serialization of the v3.x AST. + * Returns a vector of strings, of which the first is reserved for the CBOR serialization of the v3.x AST. * Any additional strings represent error messages. + * Notice that the AST and error messages won't be available at the same time. */ static std::vector parse_file( const std::string &filename @@ -81,9 +81,9 @@ class V3xAnalyzer { * If the file is written in a later file version, * this function may try to reduce it to the maximum v3.x API version support advertised * using this object's constructor. - * Returns a vector of strings, - * of which the first is always present and is the CBOR serialization of the v3.x semantic tree. + * Returns a vector of strings, of which the first is reserved for the CBOR serialization of the v3.x semantic tree. * Any additional strings represent error messages. + * Notice that the AST and error messages won't be available at the same time. */ std::vector analyze_file( const std::string &filename diff --git a/src/v1x/cqasm-py.cpp b/src/v1x/cqasm-py.cpp index 312cda30..a869d8cc 100644 --- a/src/v1x/cqasm-py.cpp +++ b/src/v1x/cqasm-py.cpp @@ -75,9 +75,9 @@ void V1xAnalyzer::register_error_model( * Only parses the given file. * The file must be in v1.x syntax. * No version check or conversion is performed. - * Returns a vector of strings, - * of which the first is always present and is the CBOR serialization of the v1.x AST. + * Returns a vector of strings, of which the first is reserved for the CBOR serialization of the v1.x AST. * Any additional strings represent error messages. + * Notice that the AST and error messages won't be available at the same time. */ std::vector V1xAnalyzer::parse_file( const std::string &filename @@ -111,9 +111,9 @@ std::vector V1xAnalyzer::parse_string( * If the file is written in a later file version, * this function may try to reduce it to the maximum v1.x API version support advertised * using this object's constructor. - * Returns a vector of strings, - * of which the first is always present and is the CBOR serialization of the v1x semantic tree. + * Returns a vector of strings, of which the first is reserved for the CBOR serialization of the v1.x semantic tree. * Any additional strings represent error messages. + * Notice that the AST and error messages won't be available at the same time. */ [[nodiscard]] std::vector V1xAnalyzer::analyze_file( const std::string &filename diff --git a/src/v3x/cqasm-py.cpp b/src/v3x/cqasm-py.cpp index 8dd9a51a..e13a4993 100644 --- a/src/v3x/cqasm-py.cpp +++ b/src/v3x/cqasm-py.cpp @@ -50,9 +50,9 @@ void V3xAnalyzer::register_instruction(const std::string &name, const std::strin * Only parses the given file. * The file must be in v3.x syntax. * No version check or conversion is performed. - * Returns a vector of strings, - * of which the first is always present and is the CBOR serialization of the v3.x AST. + * Returns a vector of strings, of which the first is reserved for the CBOR serialization of the v3.x AST. * Any additional strings represent error messages. + * Notice that the AST and error messages won't be available at the same time. */ std::vector V3xAnalyzer::parse_file( const std::string &filename @@ -86,9 +86,9 @@ std::vector V3xAnalyzer::parse_string( * If the file is written in a later file version, * this function may try to reduce it to the maximum v3.x API version support advertised * using this object's constructor. - * Returns a vector of strings, - * of which the first is always present and is the CBOR serialization of the v3x semantic tree. + * Returns a vector of strings, of which the first is reserved for the CBOR serialization of the v3.x semantic tree. * Any additional strings represent error messages. + * Notice that the AST and error messages won't be available at the same time. */ std::vector V3xAnalyzer::analyze_file( const std::string &filename