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

V3 Extended: Functions #198

Merged
merged 33 commits into from
Mar 5, 2024
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
5306db7
Add function declarations to the grammar.
rturrado Feb 13, 2024
6a0c326
Update res/v3x/parsing files. Because:
rturrado Feb 13, 2024
d88c213
Add return type to function declarations.
rturrado Feb 13, 2024
d69c214
Changes to the v3 lexer:
rturrado Feb 14, 2024
ef52166
Update res/v3x/parsing files:
rturrado Feb 14, 2024
43c8fe7
Changes to the syntactic AST:
rturrado Feb 15, 2024
1378db4
Take v1x/{Scope and AnalyzerHelper} classes out of cqasm-analyzer.
rturrado Feb 15, 2024
b9d3561
Change param_types default parameter to an optional at Instruction co…
rturrado Feb 16, 2024
ab6a8db
Changes to the v3x/parser:
rturrado Feb 20, 2024
6976d4d
Temporarily adding a FunctionTable apart from the FunctionImplTable.
rturrado Feb 21, 2024
1bf49b6
Add assignment statement to the parser and to BuildTreeGenAstVisitor.
rturrado Feb 22, 2024
934f1fd
Changes to the parser:
rturrado Feb 22, 2024
9c9e4e6
Changes to AnalyzeTreeGenAstVisitor:
rturrado Feb 22, 2024
7fcdf51
Update res/v3x/parsing/function files.
rturrado Feb 22, 2024
9442003
Update res/v3x/parsing/function files.
rturrado Feb 23, 2024
3b32a1d
Changes to the parser:
rturrado Feb 23, 2024
d30408b
Fix Python tests.
rturrado Feb 24, 2024
0787e1c
Fix Python tests.
rturrado Feb 24, 2024
2fb83b4
Merge remote-tracking branch 'origin/v3-extended-functions' into v3-e…
rturrado Feb 24, 2024
c368e2e
Fix C++ tests.
rturrado Feb 26, 2024
3f026df
Fix C++ tests.
rturrado Feb 26, 2024
5ba0277
Merge remote-tracking branch 'origin/v3-extended-functions' into v3-e…
rturrado Feb 26, 2024
13f2181
Fix expand_to_include.
rturrado Feb 26, 2024
19e3332
Change filename to file_name.
rturrado Feb 26, 2024
2e74787
Add some Analyzer unit tests.
rturrado Feb 26, 2024
11d53f1
Add some AnalyzeTreeGenAstVisitor::visit_function unit tests.
rturrado Feb 27, 2024
1adbb3b
Added some v3x::values unit tests.
rturrado Feb 27, 2024
c391be0
Addressed some of the comments from Pablo's code review.
rturrado Mar 4, 2024
1fb1e56
Trying to fix clang compilation.
rturrado Mar 5, 2024
6295a85
Trying to fix clang compilation.
rturrado Mar 5, 2024
0c86f00
Merge remote-tracking branch 'origin/v3-extended-functions' into v3-e…
rturrado Mar 5, 2024
20db914
Trying to fix clang compilation.
rturrado Mar 5, 2024
0ae2b1a
Trying to fix clang compilation.
rturrado Mar 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
24 changes: 18 additions & 6 deletions include/cqasm-overload.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ namespace cqasm::overload {
struct NameResolutionFailure : public std::exception {};
struct OverloadResolutionFailure : public std::exception {};


//----------//
// Overload //
//----------//

/**
* Represents a possible overload for the parameter types of a function, gate, or error model.
* T is some tag type identifying the overload.
Expand Down Expand Up @@ -60,6 +65,11 @@ class Overload {
}
};


//------------------//
// OverloadResolver //
//------------------//

/**
* Represents a set of possible overloads for the parameter types of a function, gate, or error model.
* T is some tag type identifying the overload.
Expand Down Expand Up @@ -116,6 +126,11 @@ class OverloadResolver {
}
};


//----------------------//
// OverloadNameResolver //
//----------------------//

/**
* Table of overloaded callables with case-sensitive identifier matching.
* T is the tag type of the callable/overload pair.
Expand All @@ -141,8 +156,7 @@ class OverloadedNameResolver {
* so more specific overloads should always be added last.
*/
virtual void add_overload(const std::string &name, const T &tag, const Types &param_types) {
auto entry = table.find(name);
if (entry == table.end()) {
if (auto entry = table.find(name); entry == table.end()) {
auto resolver = OverloadResolver<T, TypeBase, Node>();
resolver.add_overload(tag, param_types);
table.insert(std::pair<std::string, OverloadResolver<T, TypeBase, Node>>(name, std::move(resolver)));
Expand All @@ -159,12 +173,10 @@ class OverloadedNameResolver {
* the appropriately promoted vector of value pointers.
*/
[[nodiscard]] virtual std::pair<T, Values> resolve(const std::string &name, const Values &args) {
auto entry = table.find(name);
if (entry == table.end()) {
throw NameResolutionFailure{};
} else {
if (auto entry = table.find(name); entry != table.end()) {
return entry->second.resolve(args);
}
throw NameResolutionFailure{};
}
};

Expand Down
6 changes: 2 additions & 4 deletions include/cqasm-tree.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,11 @@
#include "tree-annotatable.hpp"
#include "tree-base.hpp"

namespace cqasm {

/**
* Namespace for wrapping tree-gen's support library.
*/
namespace tree {
namespace cqasm::tree {

using signed_size_t = ::tree::signed_size_t;

Expand Down Expand Up @@ -45,5 +44,4 @@ One<T> make(Args... args) {
return One<T>(std::make_shared<T>(args...));
}

} // namespace tree
} // namespace cqasm
} // namespace cqasm::tree
287 changes: 287 additions & 0 deletions include/v1x/cqasm-analyzer-helper.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,287 @@
#pragma once

#include "v1x/cqasm-analysis-result.hpp"
#include "v1x/cqasm-analyzer.hpp"
#include "v1x/cqasm-scope.hpp"

#include <list>
#include <string>
#include <utility> // pair


namespace cqasm::v1x::analyzer {

/**
* Helper class for analyzing a single AST.
* This contains the stateful information that Analyzer can't have (to allow Analyzer to be reused).
*/
class AnalyzerHelper {
public:
/**
* The analyzer associated with this helper.
*/
const Analyzer &analyzer;

/**
* The analysis result being constructed.
*/
AnalysisResult result;

/**
* Scope stack. back() is the global scope, front() is the current scope.
*/
std::list<Scope> scope_stack;

/**
* List of all goto instructions in the program, for name resolution when all other analysis completes.
*/
std::list<std::pair<tree::Maybe<semantic::GotoInstruction>, std::string>> gotos;

/**
* Analyzes the given AST using the given analyzer.
*/
AnalyzerHelper(const Analyzer &analyzer, const ast::Program &ast);

/**
* Parses the version tag.
* Any semantic errors encountered are pushed into the result error vector.
*/
void analyze_version(const ast::Version &ast);

/**
* Checks the qubits statement and updates the scope accordingly.
* Any semantic errors encountered are pushed into the result error vector.
*/
void analyze_qubits(const ast::Expression &count);

/**
* Returns a reference to the subcircuit that's currently being built.
* If there is no subcircuit yet, a default one is created, using the source location annotation on the source node.
*/
tree::Maybe<semantic::Subcircuit> get_current_subcircuit(const tree::Annotatable &source);

/**
* Returns a reference to the current scope.
*/
Scope &get_current_scope();

/**
* Returns a reference to the global scope.
*/
Scope &get_global_scope();

/**
* Returns a reference to the block that's currently being built (1.2+).
*/
tree::Maybe<semantic::Block> get_current_block(const tree::Annotatable &source);

/**
* Adds an analyzed statement to the current block (1.2+).
*/
void add_to_current_block(const tree::Maybe<semantic::Statement> &stmt);

/**
* Analyzes the given statement list,
* adding the analyzed statements to the current subcircuit (API 1.0/1.1) or block (API 1.2+).
*/
void analyze_statements(const ast::StatementList &statements);

/**
* Analyzes a statement list corresponding to a structured control-flow subblock (1.2+).
* Handles the requisite scoping, then defers to analyze_statements().
*/
tree::Maybe<semantic::Block> analyze_subblock(const ast::StatementList &statements, bool is_loop);

/**
* Analyzes the given bundle and, if valid, adds it to the current subcircuit using API version 1.0/1.1.
* If an error occurs, the message is added to the result error vector, and nothing is added to the subcircuit.
*/
void analyze_bundle(const ast::Bundle &bundle);

/**
* Analyzes the given bundle and, if valid, adds it to the current scope/block using API version 1.2+.
* If an error occurs, the message is added to the result error vector, and nothing is added to the block.
*/
void analyze_bundle_ext(const ast::Bundle &bundle);

/**
* Analyzes the given instruction.
* If an error occurs, the message is added to the result error vector, and an empty Maybe is returned.
*/
tree::Maybe<semantic::Instruction> analyze_instruction(const ast::Instruction &insn);

/**
* Analyzes the given cQASM 1.2+ set instruction.
* If an error occurs, the message is added to the result error vector, and an empty Maybe is returned.
*/
tree::Maybe<semantic::SetInstruction> analyze_set_instruction(const ast::Instruction &insn);

/**
* Analyzes the given two operands as lhs and rhs of a set instruction.
* Used for the actual set instruction as well as the assignments in the header of a C-style for loop.
*/
tree::Maybe<semantic::SetInstruction> analyze_set_instruction_operands(
const ast::Expression &lhs_expr,
const ast::Expression &rhs_expr
);

/**
* Analyzes the given cQASM 1.2+ goto instruction.
* If an error occurs, the message is added to the result error vector, and an empty Maybe is returned.
*/
tree::Maybe<semantic::GotoInstruction> analyze_goto_instruction(const ast::Instruction &insn);

/**
* Analyzes the error model meta-instruction and, if valid, adds it to the analysis result.
* If an error occurs, the message is added to the result error vector, and nothing is added.
*/
void analyze_error_model(const ast::Instruction &insn);

/**
* Analyzes the given mapping and, if valid, adds it to the current scope.
* If an error occurs, the message is added to the result error vector, and nothing is added to the scope.
*/
void analyze_mapping(const ast::Mapping &mapping);

/**
* Analyzes the given declaration of one or more variables and, if valid, adds them to the current scope.
* If an error occurs, the message is added to the result error vector, and nothing is added to the scope.
*/
void analyze_variables(const ast::Variables &variables);

/**
* Analyzes the given subcircuit header and, if valid, adds it to the subcircuit list.
* If an error occurs, the message is added to the result error vector, and nothing is added to the result.
*/
void analyze_subcircuit(const ast::Subcircuit &subcircuit);

/**
* Analyzes the given structured control-flow statement and,
* if valid, adds it to the current scope/block using API version 1.2+.
* If an error occurs, the message is added to the result error vector, and nothing is added to the block.
*/
void analyze_structured(const ast::Structured &structured);

/**
* Analyzes the given if-else chain.
* Only intended for use as a helper function within analyze_structured().
*/
tree::Maybe<semantic::IfElse> analyze_if_else(const ast::IfElse &if_else);

/**
* Analyzes the given C-style for loop.
* Only intended for use as a helper function within analyze_structured().
*/
tree::Maybe<semantic::ForLoop> analyze_for_loop(const ast::ForLoop &for_loop);

/**
* Analyzes the given static for loop.
* Only intended for use as a helper function within analyze_structured().
*/
tree::Maybe<semantic::ForeachLoop> analyze_foreach_loop(const ast::ForeachLoop &foreach_loop);

/**
* Analyzes the given while loop.
* Only intended for use as a helper function within analyze_structured().
*/
tree::Maybe<semantic::WhileLoop> analyze_while_loop(const ast::WhileLoop &while_loop);

/**
* Analyzes the given repeat-until loop.
* Only intended for use as a helper function within analyze_structured().
*/
tree::Maybe<semantic::RepeatUntilLoop> analyze_repeat_until_loop(const ast::RepeatUntilLoop &repeat_until_loop);

/**
* Analyzes the given list of annotations.
* Any errors found result in the annotation being skipped and an error being appended to the result error vector.
*/
tree::Any<semantic::AnnotationData> analyze_annotations(
const tree::Any<ast::AnnotationData> &annotations);

/**
* Parses any kind of expression.
* Always returns a filled value or throws an exception.
*/
values::Value analyze_expression(const ast::Expression &expression);

/**
* Shorthand for parsing an expression and promoting it to the given type,
* constructed in-place with the type_args parameter pack.
* Returns empty when the cast fails.
*/
template <class Type, class... TypeArgs>
values::Value analyze_as(const ast::Expression &expression, TypeArgs... type_args) {
return values::promote(analyze_expression(expression), tree::make<Type>(type_args...));
}

/**
* Shorthand for parsing an expression to a constant integer.
*/
primitives::Int analyze_as_const_int(const ast::Expression &expression);

/**
* Parses a matrix. Always returns a filled value or throws an exception.
*/
values::Value analyze_matrix(const ast::MatrixLiteral &matrix_lit);

/**
* Helper for parsing a matrix.
* Highly templated to avoid repeating the same code for different kinds of matrices,
* but bear in mind that the template parameters are codependent.
* Returns empty on failure.
*/
template <class ElType, class ElVal, class MatLit, class MatVal>
values::Value analyze_matrix_helper(
size_t num_rows, size_t num_cols,
const std::vector<values::Value> &vals
) {
auto matrix = MatLit(num_rows, num_cols);
for (size_t row = 0; row < num_rows; row++) {
for (size_t col = 0; col < num_cols; col++) {
auto val = values::promote(vals[row * num_cols + col], tree::make<ElType>());
if (val.empty()) {
return {};
} else {
auto val_real = val.template as<ElVal>();
if (val_real.empty()) {
return {};
} else {
matrix.at(row + 1, col + 1) = val_real->value;
}
}
}
}
return tree::make<MatVal>(matrix);
}

/**
* Parses an index operator. Always returns a filled value or throws an
* error.
*/
values::Value analyze_index(const ast::Index &index);

/**
* Parses an index list.
*/
tree::Many<values::ConstInt> analyze_index_list(
const ast::IndexList &index_list, size_t size);

/**
* Parses a function. Always returns a filled value or throws an exception.
*/
values::Value analyze_function(
const ast::Identifier &name,
const ast::ExpressionList &args);

/**
* Parses an operator. Always returns a filled value or throws an exception.
*/
values::Value analyze_operator(
const std::string &name,
const tree::One<ast::Expression> &a,
const tree::One<ast::Expression> &b = tree::One<ast::Expression>(),
const tree::One<ast::Expression> &c = tree::One<ast::Expression>());
};

} // namespace cqasm::v1x::analyzer
Loading
Loading