diff --git a/include/utap/AbstractBuilder.hpp b/include/utap/AbstractBuilder.hpp index 1b43870a..26080064 100644 --- a/include/utap/AbstractBuilder.hpp +++ b/include/utap/AbstractBuilder.hpp @@ -103,6 +103,7 @@ class AbstractBuilder : public ParserBuilder * Function declarations */ void decl_parameter(const char* name, bool) override; + void func_type() override; void decl_func_begin(const char* name) override; // n paramaters void decl_func_end() override; // 1 block void dynamic_load_lib(const char* name) override; @@ -297,6 +298,10 @@ class AbstractBuilder : public ParserBuilder void query_results_begin() override; void query_results_end() override; void query_end() override; + + void builtin_decl_end() override {} + void system_decl_begin() override {} + void system_decl_end() override {} }; } // namespace UTAP #endif diff --git a/include/utap/DocumentBuilder.hpp b/include/utap/DocumentBuilder.hpp index d2439b8a..2261cacf 100644 --- a/include/utap/DocumentBuilder.hpp +++ b/include/utap/DocumentBuilder.hpp @@ -99,6 +99,8 @@ class DocumentBuilder : public StatementBuilder // Method for handling types // + std::stack declarations; + declarations_t* getCurrentDeclarationBlock(); variable_t* addVariable(type_t type, const std::string& name, expression_t init, position_t pos) override; @@ -170,6 +172,9 @@ class DocumentBuilder : public StatementBuilder void query_results_begin() override; void query_results_end() override; void query_end() override; + + void system_decl_begin() override; + void system_decl_end() override; }; } // namespace UTAP #endif diff --git a/include/utap/ExpressionBuilder.hpp b/include/utap/ExpressionBuilder.hpp index 88d469ec..b3c59f07 100644 --- a/include/utap/ExpressionBuilder.hpp +++ b/include/utap/ExpressionBuilder.hpp @@ -220,6 +220,8 @@ class ExpressionBuilder : public AbstractBuilder void expr_foreach_dynamic_end(const char* name) override; void push_dynamic_frame_of(template_t* t, std::string name); // no override void pop_dynamic_frame_of(std::string name); + + void builtin_decl_end() override; }; } // namespace UTAP diff --git a/include/utap/StatementBuilder.hpp b/include/utap/StatementBuilder.hpp index 4a0e03ba..865a6fb5 100644 --- a/include/utap/StatementBuilder.hpp +++ b/include/utap/StatementBuilder.hpp @@ -55,6 +55,9 @@ class StatementBuilder : public ExpressionBuilder /** The labels of a struct. */ std::vector labels; + /** The positions of a struct. */ + std::vector positions; + /** path to libraries*/ std::vector libpaths; @@ -65,7 +68,7 @@ class StatementBuilder : public ExpressionBuilder static void collectDependencies(std::set&, type_t); public: - explicit StatementBuilder(Document&, std::vector libpaths = {}); + StatementBuilder(Document&, std::vector libpaths = {}); StatementBuilder(const StatementBuilder&) = delete; BlockStatement& get_block(); @@ -79,6 +82,7 @@ class StatementBuilder : public ExpressionBuilder void decl_init_list(uint32_t num) override; void decl_field_init(const char* name) override; void decl_parameter(const char* name, bool) override; + void func_type() override; void decl_func_begin(const char* name) override; void decl_func_end() override; void dynamic_load_lib(const char* name) override; diff --git a/include/utap/builder.h b/include/utap/builder.h index 32f903bf..b4906605 100644 --- a/include/utap/builder.h +++ b/include/utap/builder.h @@ -232,6 +232,7 @@ class ParserBuilder * Function declarations */ virtual void decl_parameter(const char* name, bool ref) = 0; + virtual void func_type() = 0; virtual void decl_func_begin(const char* name) = 0; virtual void decl_func_end() = 0; // 1 block virtual void dynamic_load_lib(const char* name) = 0; @@ -443,6 +444,13 @@ class ParserBuilder virtual void query_results_begin() = 0; virtual void query_results_end() = 0; virtual void query_end() = 0; + + // Called after built in declarations have been parsed + virtual void builtin_decl_end() = 0; + + // Before and after system declarations are parsed + virtual void system_decl_begin() = 0; + virtual void system_decl_end() = 0; }; /** Error/warning messages with some arguments */ diff --git a/include/utap/document.h b/include/utap/document.h index 06ad2fcb..7823809b 100644 --- a/include/utap/document.h +++ b/include/utap/document.h @@ -135,6 +135,7 @@ struct function_t : stringify_t std::unique_ptr body{nullptr}; /**< Pointer to the block. */ function_t() = default; std::ostream& print(std::ostream& os) const; /**< textual representation, used to write the XML file */ + position_t body_position; }; struct progress_t @@ -511,6 +512,8 @@ class Document /** Returns the global declarations of the document. */ declarations_t& get_globals() { return global; } + frame_t get_builtin_decls() { return global.frame.get_parent(); } + declarations_t& get_system_declarations() { return system_declarations; } /** Returns the templates of the document. */ std::list& get_templates() { return templates; } @@ -521,6 +524,9 @@ class Document /** Returns the processes of the document. */ std::list& get_processes() { return processes; } + /** Returns the instances of the document. */ + const std::list& get_instances() const { return instances; } + options_t& get_options(); void set_options(const options_t& options); @@ -529,10 +535,12 @@ class Document void add_position(uint32_t position, uint32_t offset, uint32_t line, std::shared_ptr path); const position_index_t::line_t& find_position(uint32_t position) const; + const position_index_t::line_t& find_first_position(uint32_t position) const; variable_t* add_variable_to_function(function_t*, frame_t, type_t, const std::string&, expression_t initital, position_t); - variable_t* add_variable(declarations_t*, type_t type, const std::string&, expression_t initial, position_t); + variable_t* add_variable(declarations_t*, frame_t, type_t type, const std::string&, expression_t initial, + position_t); void add_progress_measure(declarations_t*, expression_t guard, expression_t measure); template_t& add_template(const std::string& name, frame_t params, position_t, bool isTA = true, @@ -640,6 +648,7 @@ class Document // Global declarations declarations_t global; + declarations_t system_declarations; expression_t before_update; expression_t after_update; diff --git a/include/utap/position.h b/include/utap/position.h index 381f8cc4..a81a2ce4 100644 --- a/include/utap/position.h +++ b/include/utap/position.h @@ -78,7 +78,7 @@ class position_index_t private: std::vector lines; - const line_t& find(uint32_t position, uint32_t first, uint32_t last) const; + uint32_t find_index(uint32_t position) const; public: /** Add information about a line to the container. */ @@ -91,6 +91,12 @@ class position_index_t */ const line_t& find(uint32_t position) const; + /** + * Retrieves information about the first line in the document node + * that the position argument is pointing to + */ + const position_index_t::line_t& find_first_line(uint32_t position) const; + /** Dump table to stdout. */ std::ostream& print(std::ostream&) const; }; diff --git a/include/utap/statement.h b/include/utap/statement.h index cabd5173..71ed914d 100644 --- a/include/utap/statement.h +++ b/include/utap/statement.h @@ -135,10 +135,9 @@ class BlockStatement : public Statement, public declarations_t protected: std::vector> stats; - frame_t frame; public: - explicit BlockStatement(frame_t frame): frame{std::move(frame)} {} + explicit BlockStatement(frame_t frame) { this->frame = std::move(frame); } int32_t accept(StatementVisitor* visitor) override; bool returns() override; diff --git a/include/utap/type.h b/include/utap/type.h index 505bc3c6..f560e437 100644 --- a/include/utap/type.h +++ b/include/utap/type.h @@ -136,6 +136,9 @@ class type_t /** Returns the \a i'th label. */ const std::string& get_label(uint32_t) const; + /** Returns the position of i'th field in struct */ + const position_t& get_field_position(uint32_t) const; + /** Returns the expression associated with the type. */ expression_t get_expression() const; @@ -376,7 +379,8 @@ class type_t static type_t create_process_set(type_t instance, position_t = position_t()); /** Creates a new record type */ - static type_t create_record(const std::vector&, const std::vector&, position_t = position_t()); + static type_t create_record(const std::vector&, const std::vector&, + const std::vector&, position_t = position_t()); /** Creates a new function type */ static type_t create_function(type_t, const std::vector&, const std::vector&, diff --git a/src/DocumentBuilder.cpp b/src/DocumentBuilder.cpp index 07611ec1..c17318b1 100644 --- a/src/DocumentBuilder.cpp +++ b/src/DocumentBuilder.cpp @@ -38,7 +38,9 @@ using std::string; DocumentBuilder::DocumentBuilder(Document& doc, std::vector paths): StatementBuilder{doc, std::move(paths)} -{} +{ + declarations.push(&doc.get_globals()); +} /************************************************************ * Variable and function declarations @@ -48,7 +50,7 @@ variable_t* DocumentBuilder::addVariable(type_t type, const std::string& name, e if (currentFun) { return document.add_variable_to_function(currentFun, frames.top(), type, name, init, pos); } else { - return document.add_variable(getCurrentDeclarationBlock(), type, name, init, pos); + return document.add_variable(getCurrentDeclarationBlock(), frames.top(), type, name, init, pos); } } @@ -57,9 +59,18 @@ bool DocumentBuilder::addFunction(type_t type, const std::string& name, position return getCurrentDeclarationBlock()->add_function(type, name, pos, currentFun); } -declarations_t* DocumentBuilder::getCurrentDeclarationBlock() +declarations_t* DocumentBuilder::getCurrentDeclarationBlock() { return declarations.top(); } + +void DocumentBuilder::system_decl_begin() { - return (currentTemplate ? currentTemplate : &document.get_globals()); + declarations.push(&document.get_system_declarations()); + push_frame(document.get_system_declarations().frame); +} + +void DocumentBuilder::system_decl_end() +{ + declarations.pop(); + popFrame(); } void DocumentBuilder::addSelectSymbolToFrame(const std::string& id, frame_t& frame, position_t pos) @@ -165,12 +176,14 @@ void DocumentBuilder::proc_begin(const char* name, const bool isTA, const string } } + declarations.push(currentTemplate); push_frame(currentTemplate->frame); params = frame_t::create(); } void DocumentBuilder::proc_end() // 1 ProcBody { + declarations.pop(); currentTemplate = nullptr; popFrame(); } @@ -642,7 +655,10 @@ void DocumentBuilder::prechart_set(const bool pch) { currentTemplate->has_precha void DocumentBuilder::decl_dynamic_template(const std::string& name) { // Should be null, but error recovery can result in proc_end not being called - currentTemplate = nullptr; + if (currentTemplate != nullptr) { + currentTemplate = nullptr; + declarations.pop(); + } /* check if name already exists */ if (frames.top().contains(name)) { handle_error(DuplicateDefinitionError(name)); diff --git a/src/ExpressionBuilder.cpp b/src/ExpressionBuilder.cpp index e07181a9..2417c9cf 100644 --- a/src/ExpressionBuilder.cpp +++ b/src/ExpressionBuilder.cpp @@ -65,7 +65,9 @@ void ExpressionBuilder::ExpressionFragments::pop(uint32_t n) ExpressionBuilder::ExpressionBuilder(Document& doc): document{doc} { - push_frame(document.get_globals().frame); + frame_t frame = doc.get_builtin_decls(); + assert(frame != frame_t{}); + push_frame(std::move(frame)); scalar_count = 0; } @@ -83,6 +85,8 @@ void ExpressionBuilder::push_frame(frame_t frame) { frames.push(std::move(frame) void ExpressionBuilder::popFrame() { frames.pop(); } +void ExpressionBuilder::builtin_decl_end() { push_frame(document.get_globals().frame); } + bool ExpressionBuilder::resolve(const std::string& name, symbol_t& uid) const { assert(!frames.empty()); diff --git a/src/StatementBuilder.cpp b/src/StatementBuilder.cpp index 87c80d91..1ffb8761 100644 --- a/src/StatementBuilder.cpp +++ b/src/StatementBuilder.cpp @@ -127,13 +127,15 @@ void StatementBuilder::type_array_of_type(size_t n) */ void StatementBuilder::type_struct(PREFIX prefix, uint32_t n) { - vector f(fields.end() - n, fields.end()); - vector l(labels.end() - n, labels.end()); + auto f = vector(fields.end() - n, fields.end()); + auto l = vector(labels.end() - n, labels.end()); + auto p = vector(positions.end() - n, positions.end()); fields.erase(fields.end() - n, fields.end()); labels.erase(labels.end() - n, labels.end()); + positions.erase(positions.end() - n, positions.end()); - typeFragments.push(apply_prefix(prefix, type_t::create_record(f, l, position))); + typeFragments.push(apply_prefix(prefix, type_t::create_record(f, l, p, position))); } /** @@ -152,6 +154,7 @@ void StatementBuilder::struct_field(const char* name) fields.push_back(type); labels.push_back(name); + positions.push_back(position); /* Check the base type. We should check this in the type * checker. The problem is that we do not maintain the position of @@ -259,7 +262,7 @@ void StatementBuilder::decl_var(const char* name, bool hasInit) } // Add variable to document - addVariable(type, name, init, position_t()); + addVariable(type, name, init, position); } // Array and struct initialisers are represented as expressions having @@ -308,15 +311,18 @@ void StatementBuilder::decl_init_list(uint32_t num) // Compute new type (each field has a label type, see decl_field_init()) vector types; vector labels; + vector positions; for (uint32_t i = 0; i < num; i++) { type_t type = fields[i].get_type(); types.push_back(type[0]); labels.push_back(type.get_label(0)); fields[i].set_type(type[0]); + positions.push_back(fields[i].get_position()); } // Create list expression - fragments.push(expression_t::create_nary(LIST, fields, position, type_t::create_record(types, labels, position))); + fragments.push( + expression_t::create_nary(LIST, fields, position, type_t::create_record(types, labels, positions, position))); } /******************************************************************** @@ -334,9 +340,8 @@ void StatementBuilder::decl_parameter(const char* name, bool ref) params.add_symbol(name, type, position); } -void StatementBuilder::decl_func_begin(const char* name) +void StatementBuilder::func_type() { - // assert(currentFun == nullptr); // the parser should recover cleanly, but it does not if (currentFun != nullptr) { /* If currentFun != nullptr, we are in an error state. This error * state arises when a parsing error happens in the middle of a @@ -351,7 +356,6 @@ void StatementBuilder::decl_func_begin(const char* name) } type_t return_type = typeFragments[0]; - typeFragments.pop(); vector types; vector labels; @@ -359,8 +363,16 @@ void StatementBuilder::decl_func_begin(const char* name) types.push_back(params[i].get_type()); labels.push_back(params[i].get_name()); } - type_t type = type_t::create_function(return_type, types, labels, position); - if (!addFunction(type, name, {})) { + + typeFragments[0] = type_t::create_function(return_type, types, labels, position); +} + +void StatementBuilder::decl_func_begin(const char* name) +{ + type_t type = typeFragments[0]; + typeFragments.pop(); + + if (!addFunction(type, name, position)) { handle_error(DuplicateDefinitionError(name)); } @@ -393,6 +405,8 @@ void StatementBuilder::decl_func_end() handle_error(TypeException{"$Return_statement_expected"}); } + currentFun->body_position = position; + /* Restore global frame. */ popFrame(); diff --git a/src/abstractbuilder.cpp b/src/abstractbuilder.cpp index 08621726..c76099f1 100644 --- a/src/abstractbuilder.cpp +++ b/src/abstractbuilder.cpp @@ -93,6 +93,9 @@ void AbstractBuilder::gantt_entry_end() { UNSUPPORTED; } void AbstractBuilder::decl_progress(bool) { UNSUPPORTED; } void AbstractBuilder::decl_parameter(const char* name, bool) { UNSUPPORTED; } + +void AbstractBuilder::func_type() { UNSUPPORTED; } + void AbstractBuilder::decl_func_begin(const char* name) { UNSUPPORTED; } void AbstractBuilder::decl_func_end() { UNSUPPORTED; } void AbstractBuilder::dynamic_load_lib(const char* name) { UNSUPPORTED; } diff --git a/src/document.cpp b/src/document.cpp index 6c048bac..b6acc3c9 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -758,7 +758,8 @@ std::ostream& chan_priority_t::print(std::ostream& os) const Document::Document() { - global.frame = frame_t::create(); + global.frame = frame_t::create(frame_t::create()); + system_declarations.frame = frame_t::create(global.frame); #ifdef ENABLE_CORA addVariable(&global, type_t::create_primitive(COST), "cost", expression_t()); #endif @@ -920,10 +921,10 @@ options_t& Document::get_options() { return model_options; } void Document::set_options(const options_t& options) { model_options = options; } // Add a regular variable -variable_t* Document::add_variable(declarations_t* context, type_t type, const string& name, expression_t initial, - position_t pos) +variable_t* Document::add_variable(declarations_t* context, frame_t frame, type_t type, const string& name, + expression_t initial, position_t pos) { - variable_t* var = add_variable(context->variables, context->frame, type, name, pos); + variable_t* var = add_variable(context->variables, frame, type, name, pos); var->init = initial; return var; } @@ -1020,7 +1021,9 @@ void visitTemplate(template_t& t, DocumentVisitor& visitor) void Document::accept(DocumentVisitor& visitor) { visitor.visitDocBefore(*this); + visit(visitor, global.frame.get_parent()); visit(visitor, global.frame); + visit(visitor, system_declarations.frame); for (auto& templ : templates) visitTemplate(templ, visitor); for (auto& templ : dyn_templates) @@ -1039,14 +1042,14 @@ void Document::accept(DocumentVisitor& visitor) } } - for (auto&& decl : global.iodecl) + for (auto&& decl : system_declarations.iodecl) visitor.visitIODecl(decl); // Maybe not ideal place for this: - for (auto&& progress : global.progress) + for (auto&& progress : system_declarations.progress) visitor.visitProgressMeasure(progress); - for (auto&& gantt : global.ganttChart) + for (auto&& gantt : system_declarations.ganttChart) visitor.visitGanttChart(gantt); visitor.visitDocAfter(*this); @@ -1097,6 +1100,11 @@ const position_index_t::line_t& Document::find_position(uint32_t position) const void Document::add_channel(bool is_broadcast) { hasNonBroadcastChan |= !is_broadcast; } +const position_index_t::line_t& Document::find_first_position(uint32_t position) const +{ + return positions.find_first_line(position); +} + void Document::add_error(position_t position, std::string msg, std::string context) { errors.emplace_back(positions.find(position.start), positions.find(position.end), position, std::move(msg), diff --git a/src/featurechecker.cpp b/src/featurechecker.cpp index ed37c75f..655b451d 100644 --- a/src/featurechecker.cpp +++ b/src/featurechecker.cpp @@ -35,7 +35,7 @@ FeatureChecker::FeatureChecker(Document& document) visitFrame(document.get_globals().frame); if (document.has_dynamic_templates()) supported_methods.symbolic = false; - if (document.has_priority_declaration()){ + if (document.has_priority_declaration()) { supported_methods.stochastic = false; supported_methods.concrete = false; } diff --git a/src/parser.y b/src/parser.y index 265b992e..b0027078 100644 --- a/src/parser.y +++ b/src/parser.y @@ -529,19 +529,20 @@ AfterUpdateDecl: T_AFTER '{' ExprList '}' { CALL(@3, @3, after_update()); }; FunctionDecl: /* Notice that StatementList will catch all errors. Hence we * should be able to guarantee, that once declFuncBegin() has - * been called, we will also call declFuncEnd(). + * been called, we will also call decl_func_end(). * Correction: No it won't. * int f() { if (cond) { return 0; } - * will generate an error, not call declFuncEnd, and the builder + * will generate an error, not call decl_func_end, and the builder * will be left in an inconsistent state. EndBlock fixes that. * * Correction^2: It did not fix it. Discussion continued at * StatementBuilder::declFuncBegin definition */ Type Id OptionalParameterList '{' { - CALL(@1, @2, decl_func_begin($2)); + CALL(@1, @2, func_type()); + CALL(@2, @2, decl_func_begin($2)); } BlockLocalDeclList StatementList EndBlock { - CALL(@8, @8, decl_func_end()); + CALL(@4, @8, decl_func_end()); } ; @@ -584,10 +585,10 @@ ParameterList: Parameter: Type '&' NonTypeId ArrayDecl { - CALL(@1, @4, decl_parameter($3, true)); + CALL(@1, @3, decl_parameter($3, true)); } | Type NonTypeId ArrayDecl { - CALL(@1, @3, decl_parameter($2, false)); + CALL(@1, @2, decl_parameter($2, false)); } ; @@ -607,7 +608,7 @@ DeclId: Id { CALL(@1, @1, type_duplicate()); } ArrayDecl VarInit { - CALL(@1, @4, decl_var($1, $4)); + CALL(@1, @1, decl_var($1, $4)); } ; @@ -781,7 +782,7 @@ FieldDeclId: Id { CALL(@1, @1, type_duplicate()); } ArrayDecl { - CALL(@1, @3, struct_field($1)); + CALL(@1, @1, struct_field($1)); } ; @@ -1519,7 +1520,7 @@ OldConstDeclId: NonTypeId { CALL(@1, @1, type_duplicate()); } ArrayDecl Initializer { - CALL(@1, @4, decl_var($1, true)); + CALL(@1, @1, decl_var($1, true)); } ; @@ -2151,17 +2152,25 @@ return ; } +#include + int32_t parse_XTA(const char *str, ParserBuilder *builder, bool newxta) { - if (newxta) + if (newxta){ parse_XTA(utap_builtin_declarations(), builder, newxta, S_DECLARATION, ""); + builder->builtin_decl_end(); + } + return parse_XTA(str, builder, newxta, S_XTA, ""); } int32_t parse_XTA(FILE *file, ParserBuilder *builder, bool newxta) { - if (newxta) + if (newxta){ parse_XTA(utap_builtin_declarations(), builder, newxta, S_DECLARATION, ""); + builder->builtin_decl_end(); + } + utap__switch_to_buffer(utap__create_buffer(file, YY_BUF_SIZE)); int res = parse_XTA(builder, newxta, S_XTA, ""); utap__delete_buffer(YY_CURRENT_BUFFER); diff --git a/src/position.cpp b/src/position.cpp index a9e5bdd1..7aa02c48 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -38,8 +38,11 @@ void position_index_t::add(uint32_t position, uint32_t offset, uint32_t line, st lines.emplace_back(position, offset, line, std::move(path)); } -const position_index_t::line_t& position_index_t::find(uint32_t position, uint32_t first, uint32_t last) const +uint32_t position_index_t::find_index(uint32_t position) const { + uint32_t first = 0; + uint32_t last = lines.size(); + while (first + 1 < last) { uint32_t i = (first + last) / 2; if (position < lines[i].position) { @@ -48,14 +51,26 @@ const position_index_t::line_t& position_index_t::find(uint32_t position, uint32 first = i; } } - return lines[first]; + return first; } const position_index_t::line_t& position_index_t::find(uint32_t position) const { if (lines.empty()) throw std::logic_error("No positions have been added"); - return find(position, 0, lines.size()); + return lines[find_index(position)]; +} + +const position_index_t::line_t& position_index_t::find_first_line(uint32_t position) const +{ + if (lines.size() == 0) { + throw std::logic_error("No positions have been added"); + } + int index = find_index(position); + while (lines[index].line > 1) + index--; + + return lines[index]; } /** Dump table to stdout. */ diff --git a/src/symbols.cpp b/src/symbols.cpp index 2ab2aed1..96a2dcd8 100644 --- a/src/symbols.cpp +++ b/src/symbols.cpp @@ -96,11 +96,10 @@ std::ostream& operator<<(std::ostream& o, const UTAP::symbol_t& t) { return o << struct frame_t::frame_data : public std::enable_shared_from_this { - // bool hasParent; // True if there is a parent - frame_data* parent; // The parent frame data - vector symbols; // The symbols in the frame - map mapping; // Mapping from names to indices - explicit frame_data(frame_data* p): parent{p} {} + std::shared_ptr parent; // The parent frame data + vector symbols; // The symbols in the frame + map mapping; // Mapping from names to indices + explicit frame_data(std::shared_ptr p): parent{p} {} bool has_parent() const { return parent != nullptr; } }; @@ -231,7 +230,7 @@ frame_t frame_t::get_parent() const { if (!data->has_parent()) throw NoParentException(); - return frame_t{data->parent}; + return frame_t{data->parent.get()}; } /* Returns true if this frame has a parent */ @@ -247,7 +246,7 @@ frame_t frame_t::create() /* Creates and returns new frame with the given parent */ frame_t frame_t::create(const frame_t& parent) { - auto data = std::make_shared(parent.data.get()); + auto data = std::make_shared(parent.data); return frame_t{data.get()}; } diff --git a/src/type.cpp b/src/type.cpp index def9be47..41e1d9c3 100644 --- a/src/type.cpp +++ b/src/type.cpp @@ -37,6 +37,7 @@ struct child_t { string label; type_t child; + position_t position; }; struct type_t::type_data @@ -84,6 +85,12 @@ const std::string& type_t::get_label(uint32_t i) const return data->children[i].label; } +const position_t& type_t::get_field_position(uint32_t i) const +{ + assert(i < size()); + return data->children[i].position; +} + std::optional type_t::find_index_of(const std::string& label) const { assert(is_record() || is_process()); @@ -332,13 +339,15 @@ type_t type_t::create_range(type_t type, expression_t lower, expression_t upper, return t; } -type_t type_t::create_record(const vector& types, const vector& labels, position_t pos) +type_t type_t::create_record(const vector& types, const vector& labels, + const std::vector& positions, position_t pos) { assert(types.size() == labels.size()); auto type = type_t{RECORD, pos, types.size()}; for (size_t i = 0; i < types.size(); i++) { type.data->children[i].child = types[i]; type.data->children[i].label = labels[i]; + type.data->children[i].position = positions[i]; } return type; } diff --git a/src/xmlreader.cpp b/src/xmlreader.cpp index 08bf03c7..c10d08e0 100644 --- a/src/xmlreader.cpp +++ b/src/xmlreader.cpp @@ -1187,6 +1187,8 @@ bool XMLReader::instantiation() void XMLReader::system() { if (begin(tag_t::SYSTEM, false)) { + parser->system_decl_begin(); + const auto* text = (const xmlChar*)""; read(); auto nodeType = getNodeType(); @@ -1203,6 +1205,7 @@ void XMLReader::system() return; } parse(text, S_SYSTEM); + parser->system_decl_end(); close(tag_t::SYSTEM); } else { std::string s = (nta) ? path.str(tag_t::NTA) : path.str(tag_t::PROJECT); @@ -1326,8 +1329,10 @@ void XMLReader::project() if (!begin(tag_t::NTA) && !begin(tag_t::PROJECT)) throw TypeException{"$Missing_nta_or_project_tag"}; nta = begin(tag_t::NTA); // "nta" or "project"? - if (newxta) + if (newxta) { parse((const xmlChar*)utap_builtin_declarations(), S_DECLARATION); + parser->builtin_decl_end(); + } read(); declaration(); while (templ()) diff --git a/test/document_fixture.h b/test/document_fixture.h index 7e528056..7bd54088 100644 --- a/test/document_fixture.h +++ b/test/document_fixture.h @@ -156,7 +156,7 @@ class QueryFixture public: QueryFixture(std::unique_ptr new_doc): doc{std::move(new_doc)}, query_builder{*doc} {} - auto get_errors() const { return doc->get_errors(); } + auto& get_errors() const { return doc->get_errors(); } const UTAP::PropInfo& parse_query(const char* query) { auto result = parseProperty(query, &query_builder); diff --git a/test/test_parser.cpp b/test/test_parser.cpp index 9d6a208e..08efb877 100644 --- a/test/test_parser.cpp +++ b/test/test_parser.cpp @@ -22,24 +22,26 @@ #include +using namespace std::string_literals; + TEST_CASE("Double Serialization Test") { auto doc = read_document("if_statement.xml"); REQUIRE(doc); - auto& errors = doc->get_errors(); - CHECK(errors.size() == 0); - auto& warnings = doc->get_warnings(); - CHECK(warnings.size() == 0); + auto& errs = doc->get_errors(); + CHECK_MESSAGE(errs.empty(), errs.front().msg); + auto& warns = doc->get_warnings(); + CHECK_MESSAGE(warns.empty(), warns.front().msg); } TEST_CASE("Power expressions") { auto doc = read_document("powers.xml"); REQUIRE(doc); - auto& errors = doc->get_errors(); - CHECK(errors.size() == 0); - auto& warnings = doc->get_warnings(); - CHECK(warnings.size() == 0); + auto& errs = doc->get_errors(); + CHECK_MESSAGE(errs.empty(), errs.front().msg); + auto& warns = doc->get_warnings(); + CHECK_MESSAGE(warns.empty(), warns.front().msg); } struct Contains @@ -74,12 +76,12 @@ TEST_CASE("External functions") REQUIRE_MESSAGE(false, "OS is not supported"); } auto& warns = doc->get_warnings(); - CHECK(warns.size() == 0); + CHECK_MESSAGE(warns.empty(), warns.front().msg); // TypeChecker is not run when errors are present, so we do it on our own: auto checker = UTAP::TypeChecker{*doc}; doc->accept(checker); REQUIRE(errs.size() == 3); // no new errors - CHECK(warns.size() == 0); + CHECK_MESSAGE(warns.empty(), warns.front().msg); } TEST_CASE("Error location") @@ -88,8 +90,8 @@ TEST_CASE("Error location") REQUIRE(doc); auto& errs = doc->get_errors(); auto& warns = doc->get_warnings(); - REQUIRE(errs.size() == 0); - CHECK(warns.size() == 0); + CHECK_MESSAGE(errs.empty(), errs.front().msg); + CHECK_MESSAGE(warns.empty(), warns.front().msg); const auto& templates = doc->get_templates(); REQUIRE(templates.size() > 0); const auto& edges = templates.front().edges; @@ -144,55 +146,61 @@ TEST_CASE("Parsing implicit goals for learning queries") { using UTAP::Constants::kind_t; auto doc = read_document("simpleSystem.xml"); + auto& errs = doc->get_errors(); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); auto builder = std::make_unique(*doc); SUBCASE("Implicit time goal time priced") { auto res = parseProperty("minPr[<=20]", builder.get()); CHECK(res == -1); + REQUIRE(errs.size() == 1); } SUBCASE("Implicit step goal time priced") { - REQUIRE(doc->get_errors().size() == 0); auto res = parseProperty("minE(c)[#<=20]", builder.get()); CHECK(res == -1); + REQUIRE(errs.size() == 1); } SUBCASE("Implicit constraint goal expr priced") { auto res = parseProperty("minE(c)[c<=25]", builder.get()); CHECK(res == -1); + REQUIRE(errs.size() == 1); } SUBCASE("Implicit time goal expr priced") { auto res = parseProperty("minE(c)[<=20]", builder.get()); CHECK(res == -1); + REQUIRE(errs.size() == 1); } SUBCASE("Implicit step goal expr priced") { auto res = parseProperty("minE(c)[#<=20]", builder.get()); CHECK(res == -1); + REQUIRE(errs.size() == 1); } SUBCASE("Explicit goal expr priced") { - REQUIRE(doc->get_errors().size() == 0); auto res = parseProperty("minE(c)[<=20] :<> true", builder.get()); REQUIRE(res == 0); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); builder->typecheck(); - REQUIRE(doc->get_errors().size() == 0); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); } SUBCASE("Explicit constraint goal expr priced") { - REQUIRE(doc->get_errors().size() == 0); auto res = parseProperty("minE(c)[<=20] :<> c>=5", builder.get()); REQUIRE(res == 0); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); builder->typecheck(); - REQUIRE(doc->get_errors().size() == 0); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); } } @@ -289,8 +297,8 @@ TEST_CASE("Sim region cleanup causes memory errors (run with ASAN)") { auto doc = read_document("lsc_example.xml"); REQUIRE(doc); - auto& errors = doc->get_errors(); - CHECK(errors.size() == 0); + auto& errs = doc->get_errors(); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); auto& templ = doc->get_templates().back(); auto sims = templ.get_simregions(); @@ -302,9 +310,10 @@ TEST_CASE("Struct int,int initialization") auto doc = document_fixture{}.add_default_process().add_global_decl("const struct { int x; int y; } s = {1, 1};").parse(); REQUIRE(doc); - auto& errors = doc->get_errors(); - CHECK(errors.size() == 0); - CHECK(doc->get_warnings().size() == 0); + auto& errs = doc->get_errors(); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); + auto& warns = doc->get_warnings(); + REQUIRE_MESSAGE(warns.empty(), warns.front().msg); } TEST_CASE("Struct int,double initialization") @@ -314,9 +323,10 @@ TEST_CASE("Struct int,double initialization") .add_global_decl("const struct { int x; double y; } s = {1, 1.0};") .parse(); REQUIRE(doc); - auto& errors = doc->get_errors(); - CHECK(errors.size() == 0); - CHECK(doc->get_warnings().size() == 0); + auto& errs = doc->get_errors(); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); + auto& warns = doc->get_warnings(); + REQUIRE_MESSAGE(warns.empty(), warns.front().msg); } TEST_CASE("Struct double,double initialization") @@ -326,9 +336,10 @@ TEST_CASE("Struct double,double initialization") .add_global_decl("const struct { double x; double y; } s = {1.0, 1};") .parse(); REQUIRE(doc); - auto& errors = doc->get_errors(); - CHECK(errors.size() == 0); - CHECK(doc->get_warnings().size() == 0); + auto& errs = doc->get_errors(); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); + auto& warns = doc->get_warnings(); + REQUIRE_MESSAGE(warns.empty(), warns.front().msg); } TEST_CASE("Nested struct int,double initialization") @@ -339,9 +350,10 @@ TEST_CASE("Nested struct int,double initialization") .add_global_decl("typedef struct { int x; double y; } S; struct { S s1; S s2; } s = {{5,5.5},{2,2.25}};") .parse(); REQUIRE(doc); - auto& errors = doc->get_errors(); - CHECK(errors.size() == 0); - CHECK(doc->get_warnings().size() == 0); + auto& errs = doc->get_errors(); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); + auto& warns = doc->get_warnings(); + REQUIRE_MESSAGE(warns.empty(), warns.front().msg); } TEST_CASE("Meta struct") @@ -351,9 +363,10 @@ TEST_CASE("Meta struct") .add_global_decl("meta struct { int x; double y; } s = {1, 1.0};") .parse(); REQUIRE(doc); - auto& errors = doc->get_errors(); - CHECK(errors.size() == 0); - CHECK(doc->get_warnings().size() == 0); + auto& errs = doc->get_errors(); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); + auto& warns = doc->get_warnings(); + REQUIRE_MESSAGE(warns.empty(), warns.front().msg); } TEST_CASE("Struct meta field") @@ -363,9 +376,10 @@ TEST_CASE("Struct meta field") .add_global_decl("meta struct { int x; meta double y; } s = {1, 1.0};") .parse(); REQUIRE(doc); - auto& errors = doc->get_errors(); - CHECK(errors.size() == 0); - CHECK(doc->get_warnings().size() == 0); + auto& errs = doc->get_errors(); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); + auto& warns = doc->get_warnings(); + REQUIRE_MESSAGE(warns.empty(), warns.front().msg); } TEST_CASE("Initializing doubles in struct with ints") @@ -375,9 +389,10 @@ TEST_CASE("Initializing doubles in struct with ints") .add_global_decl("meta struct { double x; meta double y; } s = {1, 1};") .parse(); REQUIRE(doc); - auto& errors = doc->get_errors(); - CHECK(errors.size() == 0); - CHECK(doc->get_warnings().size() == 0); + auto& errs = doc->get_errors(); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); + auto& warns = doc->get_warnings(); + REQUIRE_MESSAGE(warns.empty(), warns.front().msg); } TEST_CASE("Initializing ints with double value") @@ -385,9 +400,10 @@ TEST_CASE("Initializing ints with double value") auto doc = document_fixture{}.add_default_process().add_global_decl("struct { int x; int y; } s = {1.1, 1.2};").parse(); REQUIRE(doc); - auto& errors = doc->get_errors(); - CHECK(errors.size() == 2); - CHECK(doc->get_warnings().size() == 0); + auto& errs = doc->get_errors(); + REQUIRE(errs.size() == 2); + auto& warns = doc->get_warnings(); + REQUIRE_MESSAGE(warns.empty(), warns.front().msg); } TEST_CASE("Meta field in non meta struct") @@ -397,9 +413,10 @@ TEST_CASE("Meta field in non meta struct") .add_global_decl("struct { int x; meta double y; } s = {1, 1.0};") .parse(); REQUIRE(doc); - auto& errors = doc->get_errors(); - CHECK(errors.size() == 0); - CHECK(doc->get_warnings().size() == 0); + auto& errs = doc->get_errors(); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); + auto& warns = doc->get_warnings(); + REQUIRE_MESSAGE(warns.empty(), warns.front().msg); } TEST_CASE("Meta field in non meta struct") @@ -409,9 +426,10 @@ TEST_CASE("Meta field in non meta struct") .add_global_decl("struct { int x; meta double y; } s = {1, 1.0};") .parse(); REQUIRE(doc); - auto& errors = doc->get_errors(); - CHECK(errors.size() == 0); - CHECK(doc->get_warnings().size() == 0); + auto& errs = doc->get_errors(); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); + auto& warns = doc->get_warnings(); + REQUIRE_MESSAGE(warns.empty(), warns.front().msg); } TEST_CASE("Nested structs") @@ -421,9 +439,10 @@ TEST_CASE("Nested structs") .add_global_decl("struct { int x; struct { int y; double d;} data; } s = {1, {5, 5.0}};") .parse(); REQUIRE(doc); - auto& errors = doc->get_errors(); - CHECK(errors.size() == 0); - CHECK(doc->get_warnings().size() == 0); + auto& errs = doc->get_errors(); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); + auto& warns = doc->get_warnings(); + REQUIRE_MESSAGE(warns.empty(), warns.front().msg); } TEST_CASE("Structs with arrays") @@ -433,9 +452,10 @@ TEST_CASE("Structs with arrays") .add_global_decl("struct { int x[2]; double y[2]; } s = {{1,1}, {5.0, 5.0}};") .parse(); REQUIRE(doc); - auto& errors = doc->get_errors(); - CHECK(errors.size() == 0); - CHECK(doc->get_warnings().size() == 0); + auto& errs = doc->get_errors(); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); + auto& warns = doc->get_warnings(); + REQUIRE_MESSAGE(warns.empty(), warns.front().msg); } TEST_CASE("Array of structs") @@ -445,9 +465,10 @@ TEST_CASE("Array of structs") .add_global_decl("struct { int x; double y;} s[2] = {{1,5.0}, {1,2.5}};") .parse(); REQUIRE(doc); - auto& errors = doc->get_errors(); - CHECK_MESSAGE(errors.size() == 0, errors.at(0).msg); - CHECK(doc->get_warnings().size() == 0); + auto& errs = doc->get_errors(); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); + auto& warns = doc->get_warnings(); + REQUIRE_MESSAGE(warns.empty(), warns.front().msg); } TEST_CASE("Pre increment precedence bug") @@ -457,8 +478,8 @@ TEST_CASE("Pre increment precedence bug") .add_global_decl("void f(){ ++i[0]; }") .add_default_process() .parse(); - - CHECK_MESSAGE(doc->get_errors().size() == 0, doc->get_errors().at(0).msg); + auto& errs = doc->get_errors(); + CHECK_MESSAGE(errs.empty(), errs.front().msg); } TEST_CASE("Post increment precedence bug") @@ -469,7 +490,8 @@ TEST_CASE("Post increment precedence bug") .add_default_process() .parse(); - CHECK_MESSAGE(doc->get_errors().size() == 0, doc->get_errors().at(0).msg); + auto& errs = doc->get_errors(); + CHECK_MESSAGE(errs.empty(), errs.front().msg); } TEST_CASE("Double post increment precedence") @@ -480,7 +502,8 @@ TEST_CASE("Double post increment precedence") .add_default_process() .parse(); - CHECK(doc->get_errors().size() == 1); + auto& errs = doc->get_errors(); + CHECK_MESSAGE(errs.size() == 1, (errs.empty() ? "expecting 1 error"s : errs.front().msg)); } TEST_CASE("pre post increment precedence") @@ -502,7 +525,10 @@ TEST_CASE("Double pre increment with forced precedence") .add_default_process() .parse(); - CHECK_MESSAGE(doc->get_errors().size() == 0, doc->get_errors().at(0).msg); + auto& errs = doc->get_errors(); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); + auto& warns = doc->get_warnings(); + REQUIRE_MESSAGE(warns.empty(), warns.front().msg); } TEST_CASE("Double pre increment precedence") @@ -513,7 +539,10 @@ TEST_CASE("Double pre increment precedence") .add_default_process() .parse(); - CHECK_MESSAGE(doc->get_errors().size() == 0, doc->get_errors().at(0).msg); + auto& errs = doc->get_errors(); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); + auto& warns = doc->get_warnings(); + REQUIRE_MESSAGE(warns.empty(), warns.front().msg); } TEST_CASE("Increment with array subscripting and dot accessing") @@ -524,7 +553,10 @@ TEST_CASE("Increment with array subscripting and dot accessing") .add_default_process() .parse(); - CHECK_MESSAGE(doc->get_errors().size() == 0, doc->get_errors().at(0).msg); + auto& errs = doc->get_errors(); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); + auto& warns = doc->get_warnings(); + REQUIRE_MESSAGE(warns.empty(), warns.front().msg); } TEST_CASE("Increment with multiple array subscripting and dot accessing") @@ -535,5 +567,8 @@ TEST_CASE("Increment with multiple array subscripting and dot accessing") .add_default_process() .parse(); - CHECK_MESSAGE(doc->get_errors().size() == 0, doc->get_errors().at(0).msg); + auto& errs = doc->get_errors(); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); + auto& warns = doc->get_warnings(); + REQUIRE_MESSAGE(warns.empty(), warns.front().msg); } \ No newline at end of file diff --git a/test/test_prettyprint.cpp b/test/test_prettyprint.cpp index fb1f6c50..65811fad 100644 --- a/test/test_prettyprint.cpp +++ b/test/test_prettyprint.cpp @@ -11,7 +11,8 @@ using namespace UTAP; TEST_CASE("Symbolic queries") { auto doc = read_document("simpleSystem.xml"); - REQUIRE(doc->get_errors().empty()); + auto& errs = doc->get_errors(); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); auto builder = std::make_unique(*doc); auto* pb = builder.get(); auto os = std::stringstream{}; @@ -20,8 +21,9 @@ TEST_CASE("Symbolic queries") { auto res = parseProperty("E<> \t Process.L3", pb); REQUIRE(res == 0); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); pb->typecheck(); - REQUIRE(doc->get_errors().empty()); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); pb->getQuery().print(os); CHECK(os.str() == "E<> Process.L3"); } @@ -29,8 +31,9 @@ TEST_CASE("Symbolic queries") { auto res = parseProperty("A[] \t Process.L3", pb); REQUIRE(res == 0); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); pb->typecheck(); - REQUIRE(doc->get_errors().empty()); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); pb->getQuery().print(os); CHECK(os.str() == "A[] Process.L3"); } @@ -38,8 +41,9 @@ TEST_CASE("Symbolic queries") { auto res = parseProperty("Process.L2 \t --> \t Process.L3", pb); REQUIRE(res == 0); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); pb->typecheck(); - REQUIRE(doc->get_errors().empty()); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); pb->getQuery().print(os); CHECK(os.str() == "Process.L2 --> Process.L3"); } @@ -47,8 +51,9 @@ TEST_CASE("Symbolic queries") { auto res = parseProperty("inf { Process.L2 } : c", pb); REQUIRE(res == 0); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); pb->typecheck(); - REQUIRE(doc->get_errors().empty()); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); pb->getQuery().print(os); CHECK(os.str() == "inf{Process.L2}: c"); } @@ -56,8 +61,9 @@ TEST_CASE("Symbolic queries") { auto res = parseProperty("sup { Process.L2 } : c", pb); REQUIRE(res == 0); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); pb->typecheck(); - REQUIRE(doc->get_errors().empty()); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); pb->getQuery().print(os); CHECK(os.str() == "sup{Process.L2}: c"); } @@ -65,8 +71,9 @@ TEST_CASE("Symbolic queries") { auto res = parseProperty("bounds { Process.L2 } : c", pb); REQUIRE(res == 0); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); pb->typecheck(); - REQUIRE(doc->get_errors().empty()); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); pb->getQuery().print(os); CHECK(os.str() == "bounds{Process.L2}: c"); } @@ -75,7 +82,8 @@ TEST_CASE("Symbolic queries") TEST_CASE("Minimization pretty printing") { auto doc = read_document("simpleSystem.xml"); - REQUIRE(doc->get_errors().empty()); + auto& errs = doc->get_errors(); + REQUIRE(errs.empty()); auto builder = std::make_unique(*doc); auto* pb = builder.get(); auto os = std::ostringstream{}; @@ -83,8 +91,9 @@ TEST_CASE("Minimization pretty printing") { auto res = parseProperty("minE(c)[<=20] {} -> {} : <> c >= 20", pb); REQUIRE(res == 0); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); builder->typecheck(); - REQUIRE(doc->get_errors().empty()); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); builder->getQuery().print(os); CHECK(os.str() == "minE(c)[<=20] {} -> {} : <> c >= 20"); } @@ -92,8 +101,9 @@ TEST_CASE("Minimization pretty printing") { auto res = parseProperty("minE(c)[#<=20] {} -> {} : <> c >= 20", pb); REQUIRE(res == 0); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); builder->typecheck(); - REQUIRE(doc->get_errors().empty()); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); builder->getQuery().print(os); CHECK(os.str() == "minE(c)[#<=20] {} -> {} : <> c >= 20"); } @@ -101,8 +111,9 @@ TEST_CASE("Minimization pretty printing") { auto res = parseProperty("minE(c)[c<=20] : <> c >= 20", pb); REQUIRE(res == 0); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); builder->typecheck(); - REQUIRE(doc->get_errors().empty()); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); builder->getQuery().print(os); CHECK(os.str() == "minE(c)[c<=20] : <> c >= 20"); } @@ -110,8 +121,9 @@ TEST_CASE("Minimization pretty printing") { auto res = parseProperty("minE(c)[c<=20] {} -> {} : <> c >= 20", pb); REQUIRE(res == 0); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); builder->typecheck(); - REQUIRE(doc->get_errors().empty()); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); builder->getQuery().print(os); CHECK(os.str() == "minE(c)[c<=20] {} -> {} : <> c >= 20"); } @@ -119,8 +131,9 @@ TEST_CASE("Minimization pretty printing") { auto res = parseProperty("minE(c)[c<=20] { Process.location } -> {} : <> c >= 20", pb); REQUIRE(res == 0); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); builder->typecheck(); - REQUIRE(doc->get_errors().empty()); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); builder->getQuery().print(os); CHECK(os.str() == "minE(c)[c<=20] {Process.location} -> {} : <> c >= 20"); } @@ -128,8 +141,9 @@ TEST_CASE("Minimization pretty printing") { auto res = parseProperty("minE(c)[c<=20] {} -> { c } : <> c >= 20", pb); REQUIRE(res == 0); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); builder->typecheck(); - REQUIRE(doc->get_errors().empty()); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); builder->getQuery().print(os); CHECK(os.str() == "minE(c)[c<=20] {} -> {c} : <> c >= 20"); } @@ -137,8 +151,9 @@ TEST_CASE("Minimization pretty printing") { auto res = parseProperty("minE(c)[c<=20] { Process.location } -> { c } : <> c >= 20", pb); REQUIRE(res == 0); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); builder->typecheck(); - REQUIRE(doc->get_errors().empty()); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); builder->getQuery().print(os); CHECK(os.str() == "minE(c)[c<=20] {Process.location} -> {c} : <> c >= 20"); } @@ -147,7 +162,8 @@ TEST_CASE("Minimization pretty printing") TEST_CASE("Maximization pretty printing") { auto doc = read_document("simpleSystem.xml"); - REQUIRE(doc->get_errors().empty()); + auto& errs = doc->get_errors(); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); auto builder = std::make_unique(*doc); auto* pb = builder.get(); auto os = std::ostringstream{}; @@ -155,8 +171,9 @@ TEST_CASE("Maximization pretty printing") { auto res = parseProperty("maxE(c)[<=20] {} -> {} : <> c >= 20", pb); REQUIRE(res == 0); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); builder->typecheck(); - REQUIRE(doc->get_errors().empty()); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); builder->getQuery().print(os); CHECK(os.str() == "maxE(c)[<=20] {} -> {} : <> c >= 20"); } @@ -164,8 +181,9 @@ TEST_CASE("Maximization pretty printing") { auto res = parseProperty("maxE(c)[#<=20] {} -> {} : <> c >= 20", pb); REQUIRE(res == 0); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); builder->typecheck(); - REQUIRE(doc->get_errors().empty()); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); builder->getQuery().print(os); CHECK(os.str() == "maxE(c)[#<=20] {} -> {} : <> c >= 20"); } @@ -173,8 +191,9 @@ TEST_CASE("Maximization pretty printing") { auto res = parseProperty("maxE(c)[c<=20] : <> c >= 20", pb); REQUIRE(res == 0); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); builder->typecheck(); - REQUIRE(doc->get_errors().empty()); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); builder->getQuery().print(os); CHECK(os.str() == "maxE(c)[c<=20] : <> c >= 20"); } @@ -182,8 +201,9 @@ TEST_CASE("Maximization pretty printing") { auto res = parseProperty("maxE(c)[c<=20] {} -> {} : <> c >= 20", pb); REQUIRE(res == 0); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); builder->typecheck(); - REQUIRE(doc->get_errors().empty()); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); builder->getQuery().print(os); CHECK(os.str() == "maxE(c)[c<=20] {} -> {} : <> c >= 20"); } @@ -191,8 +211,9 @@ TEST_CASE("Maximization pretty printing") { auto res = parseProperty("maxE(c)[c<=20] { Process.location } -> {} : <> c >= 20", pb); REQUIRE(res == 0); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); builder->typecheck(); - REQUIRE(doc->get_errors().empty()); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); builder->getQuery().print(os); CHECK(os.str() == "maxE(c)[c<=20] {Process.location} -> {} : <> c >= 20"); } @@ -200,8 +221,9 @@ TEST_CASE("Maximization pretty printing") { auto res = parseProperty("maxE(c)[c<=20] {} -> { c } : <> c >= 20", pb); REQUIRE(res == 0); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); builder->typecheck(); - REQUIRE(doc->get_errors().empty()); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); builder->getQuery().print(os); CHECK(os.str() == "maxE(c)[c<=20] {} -> {c} : <> c >= 20"); } @@ -209,8 +231,9 @@ TEST_CASE("Maximization pretty printing") { auto res = parseProperty("maxE(c)[c<=20] { Process.location } -> { c } : <> c >= 20", pb); REQUIRE(res == 0); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); builder->typecheck(); - REQUIRE(doc->get_errors().empty()); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); builder->getQuery().print(os); CHECK(os.str() == "maxE(c)[c<=20] {Process.location} -> {c} : <> c >= 20"); } @@ -219,7 +242,8 @@ TEST_CASE("Maximization pretty printing") TEST_CASE("saveStrategy pretty printing") { auto f = document_fixture{}.add_default_process().build_query_fixture(); - REQUIRE(f.get_errors().empty()); + auto& errs = f.get_errors(); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); const auto& strat = f.parse_query("strategy Name = control: A[] true"); auto res = f.parse_query("saveStrategy(\"path\", Name)"); CHECK(res.subjections.at(0) == &strat); @@ -229,7 +253,8 @@ TEST_CASE("saveStrategy pretty printing") TEST_CASE("Probability compare pretty print") { auto f = document_fixture{}.add_default_process().build_query_fixture(); - REQUIRE(f.get_errors().empty()); + auto& errs = f.get_errors(); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); auto query = f.parse_query("Pr[<=20] (<> true) >= Pr[<=5]([] false)").intermediate; REQUIRE(query.get_kind() == UTAP::Constants::PROBA_CMP); @@ -239,7 +264,8 @@ TEST_CASE("Probability compare pretty print") TEST_CASE("Simulate pretty prints") { auto f = document_fixture{}.add_default_process().build_query_fixture(); - REQUIRE(f.get_errors().empty()); + auto& errs = f.get_errors(); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); auto query1 = f.parse_query("simulate[<=20;1000] {5, true} : 100 : true").intermediate; REQUIRE(query1.get_kind() == UTAP::Constants::SIMULATEREACH); @@ -253,13 +279,14 @@ TEST_CASE("Simulate pretty prints") TEST_CASE("loadStrategy pretty printing") { auto doc = read_document("simpleSystem.xml"); + auto& errs = doc->get_errors(); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); auto builder = std::make_unique(*doc); auto res = parseProperty("strategy Name = loadStrategy{Process.location}->{c}(\"path\")", builder.get()); CHECK(res == 0); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); builder->typecheck(); - for (auto&& err : doc->get_errors()) - std::cerr << err << std::endl; - CHECK(doc->get_errors().empty()); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); auto os = std::ostringstream{}; builder->getQuery().print(os); CHECK(os.str() == "loadStrategy{Process.location} -> {c}(\"path\")"); @@ -268,7 +295,8 @@ TEST_CASE("loadStrategy pretty printing") TEST_CASE("Array access pretty printing") { auto f = document_fixture{}.add_global_decl("int arr[5];").add_default_process().build_query_fixture(); - REQUIRE(f.get_errors().empty()); + auto& errs = f.get_errors(); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); auto query1 = f.parse_query("E<> arr[2] == 5").intermediate; CHECK(query1.str() == "E<> arr[2] == 5"); @@ -277,7 +305,8 @@ TEST_CASE("Array access pretty printing") TEST_CASE("Chaining conjunctions") { auto f = document_fixture{}.add_default_process().build_query_fixture(); - REQUIRE(f.get_errors().empty()); + auto& errs = f.get_errors(); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); auto query1 = f.parse_query("E<> true && true && true").intermediate; CHECK(query1.str() == "E<> true && true && true"); @@ -286,7 +315,8 @@ TEST_CASE("Chaining conjunctions") TEST_CASE("Chaining disjunctive conjunctions") { auto f = document_fixture{}.add_default_process().build_query_fixture(); - REQUIRE(f.get_errors().empty()); + auto& errs = f.get_errors(); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); auto query1 = f.parse_query("E<> true && true || true && true").intermediate; CHECK(query1.str() == "E<> true && true || true && true"); @@ -295,7 +325,8 @@ TEST_CASE("Chaining disjunctive conjunctions") TEST_CASE("Chaining disjunctive conjunctions") { auto f = document_fixture{}.add_default_process().build_query_fixture(); - REQUIRE(f.get_errors().empty()); + auto& errs = f.get_errors(); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); auto query1 = f.parse_query("E<> true || true && true || true").intermediate; CHECK(query1.str() == "E<> true || true && true || true"); @@ -304,7 +335,8 @@ TEST_CASE("Chaining disjunctive conjunctions") TEST_CASE("Chaining disjunctive conjunctions with outer conjunction") { auto f = document_fixture{}.add_default_process().build_query_fixture(); - REQUIRE(f.get_errors().empty()); + auto& errs = f.get_errors(); + REQUIRE_MESSAGE(errs.empty(), errs.front().msg); auto query1 = f.parse_query("E<> (true || true && true || true) && false").intermediate; CHECK(query1.str() == "E<> (true || true && true || true) && false"); @@ -321,4 +353,4 @@ TEST_CASE("Post incrementing an identifier should not require parenthesis") auto expr = expression_t::create_unary(Constants::POST_INCREMENT, id); CHECK(expr.str() == "foo++"); -} \ No newline at end of file +}