diff options
| author | Eugen Wissner <belka@caraus.de> | 2026-09-02 13:31:04 +0200 |
|---|---|---|
| committer | Eugen Wissner <belka@caraus.de> | 2026-09-07 10:53:02 +0200 |
| commit | 47521ad6d85f9bd6caee39696ce40dff82cfa50d (patch) | |
| tree | cf5813033a440c6ac374948894d5dd70e0712cdb | |
| parent | 0fada11e99da430e9a056e46da9f0e110df6c45c (diff) | |
| download | elna-47521ad6d85f9bd6caee39696ce40dff82cfa50d.tar.gz | |
Implement program entry point
99 files changed, 292 insertions, 161 deletions
diff --git a/boot/ast.cc b/boot/ast.cc index d4f015b..b8647f4 100644 --- a/boot/ast.cc +++ b/boot/ast.cc @@ -232,18 +232,7 @@ namespace elna::boot } if (declaration->body.has_value()) { - for (variable_declaration *variable : declaration->body.value().variables) - { - variable->accept(this); - } - for (auto *statement : declaration->body.value().entry_point) - { - statement->accept(this); - } - if (declaration->body.value().return_expression != nullptr) - { - declaration->body.value().return_expression->accept(this); - } + traverse_body(this, declaration->body.value()); } } @@ -376,9 +365,9 @@ namespace elna::boot { procedure->accept(this); } - for (auto *entry_statement : unit->entry_point) + if (unit->entry_point.has_value()) { - entry_statement->accept(this); + traverse_body(this, unit->entry_point.value()); } } @@ -989,20 +978,20 @@ namespace elna::boot procedure_body::procedure_body(std::vector<variable_declaration *>&& variables, std::vector<statement *>&& entry_point, expression *return_expression) : variables(std::move(variables)), - entry_point(std::move(entry_point)), return_expression(return_expression) + statements(std::move(entry_point)), return_expression(return_expression) { } procedure_body::procedure_body(procedure_body&& that) noexcept : variables(std::move(const_cast<std::vector<variable_declaration *>&>(that.variables))), - entry_point(std::move(const_cast<std::vector<statement *>&>(that.entry_point))), + statements(std::move(const_cast<std::vector<statement *>&>(that.statements))), return_expression(that.return_expression) { } procedure_body::~procedure_body() { - for (const statement *body_statement : this->entry_point) + for (const statement *body_statement : this->statements) { delete body_statement; } @@ -1012,9 +1001,30 @@ namespace elna::boot } } - unit::unit(const source_position position) + void traverse_body(parser_visitor *visitor, const procedure_body& body) + { + for (variable_declaration *variable : body.variables) + { + variable->accept(visitor); + } + for (statement *body_statement : body.statements) + { + body_statement->accept(visitor); + } + if (body.return_expression != nullptr) + { + body.return_expression->accept(visitor); + } + } + + unit::unit(const source_position position, + std::vector<import_declaration *>&& imports, + std::vector<type_declaration *>&& types, + std::vector<variable_declaration *>&& variables, + std::vector<procedure_declaration *>&& procedures) : node(position), - procedure_body(std::vector<variable_declaration *>{}, std::vector<statement *>{}, nullptr) + imports(std::move(imports)), types(std::move(types)), procedures(std::move(procedures)), + variables(std::move(variables)) { } @@ -1023,10 +1033,10 @@ namespace elna::boot std::vector<type_declaration *>&& types, std::vector<variable_declaration *>&& variables, std::vector<procedure_declaration *>&& procedures, - std::vector<statement *>&& entry_point) + std::optional<procedure_body>&& body) : node(position), - procedure_body(std::move(variables), std::move(entry_point)), - imports(std::move(imports)), types(std::move(types)), procedures(std::move(procedures)) + imports(std::move(imports)), types(std::move(types)), procedures(std::move(procedures)), + variables(std::move(variables)), entry_point(std::move(body)) { } @@ -1035,11 +1045,6 @@ namespace elna::boot visitor->visit(this); } - bool unit::has_body() const - { - return !this->entry_point.empty(); - } - unit::~unit() { for (const procedure_declaration *procedure : this->procedures) diff --git a/boot/lexer.ll b/boot/lexer.ll index d0493c1..bebfa67 100644 --- a/boot/lexer.ll +++ b/boot/lexer.ll @@ -171,6 +171,9 @@ of { to { return yy::parser::make_TO(this->location); } +program { + return yy::parser::make_PROGRAM(this->location); +} {ID1}{ID2}* { return yy::parser::make_IDENTIFIER(yytext, this->location); } diff --git a/boot/name_analysis.cc b/boot/name_analysis.cc index 3c4c6f8..77335d1 100644 --- a/boot/name_analysis.cc +++ b/boot/name_analysis.cc @@ -23,12 +23,12 @@ along with GCC; see the file COPYING3. If not see namespace elna::boot { - declaration_error::declaration_error(const source_position position, const std::string& name, payload_type payload) + symbol_declaration_error::symbol_declaration_error(const source_position position, const std::string& name, payload_type payload) : diagnostic(position), name(name), payload(std::move(payload)) { } - std::string declaration_error::what() const + std::string symbol_declaration_error::what() const { return std::visit([this](const auto& payload) -> std::string { using T = std::decay_t<decltype(payload)>; @@ -57,7 +57,7 @@ namespace elna::boot }, this->payload); } - std::optional<diagnostic_note> declaration_error::note() const + std::optional<diagnostic_note> symbol_declaration_error::note() const { if (std::holds_alternative<redefinition>(this->payload)) { @@ -89,12 +89,12 @@ namespace elna::boot return message + " -> " + this->cycle.front(); } - const_qualifier_error::const_qualifier_error(const source_position position, payload_type payload) + declaration_format_error::declaration_format_error(const source_position position, payload_type payload) : diagnostic(position), payload(std::move(payload)) { } - std::string const_qualifier_error::what() const + std::string declaration_format_error::what() const { return std::visit([](const auto& payload) -> std::string { using T = std::decay_t<decltype(payload)>; @@ -112,6 +112,8 @@ namespace elna::boot return "const must be written before the array size, not after"; case duplicate: return "Duplicate 'const' qualifier is not allowed"; + case module_entry: + return "Program entry point should have no or one argument"; default: __builtin_unreachable(); } @@ -119,7 +121,7 @@ namespace elna::boot }, this->payload); } - std::optional<diagnostic_note> const_qualifier_error::note() const + std::optional<diagnostic_note> declaration_format_error::note() const { if (std::holds_alternative<not_initialized>(this->payload)) { @@ -256,9 +258,9 @@ namespace elna::boot if (!this->unresolved.insert({ type_identifier, std::make_shared<alias_type>(type_identifier) }).second) { - add_error<declaration_error>(declaration->identifier.id().position(), + add_error<symbol_declaration_error>(declaration->identifier.id().position(), declaration->identifier.id().name(), - declaration_error::redefinition{ .original = declaration->position(), .file = {} }); + symbol_declaration_error::redefinition{ .original = declaration->position(), .file = {} }); } } @@ -272,24 +274,28 @@ namespace elna::boot { } - std::pair<procedure_type, std::vector<std::string>> resolving_visitor::build_procedure( - procedure_type_expression& expression) + procedure_type::return_t resolving_visitor::build_return_type( + const procedure_type_expression::return_t& return_type) { - procedure_type::return_t result_return; - - if (expression.return_type.no_return) + if (return_type.no_return) { - result_return = procedure_type::return_t(std::monostate{}); + return procedure_type::return_t(std::monostate{}); } - else if (expression.return_type.proper_type != nullptr) + else if (return_type.proper_type != nullptr) { - expression.return_type.proper_type->accept(this); - result_return = procedure_type::return_t(this->current_type); + return_type.proper_type->accept(this); + return procedure_type::return_t(this->current_type); } else { - result_return = procedure_type::return_t(); + return procedure_type::return_t(); } + } + + std::pair<procedure_type, std::vector<std::string>> resolving_visitor::build_procedure( + procedure_type_expression& expression) + { + const procedure_type::return_t result_return = build_return_type(expression.return_type); std::pair<procedure_type, std::vector<std::string>> result_type{ procedure_type(result_return), std::vector<std::string>() }; @@ -361,9 +367,11 @@ namespace elna::boot if (!this->bag.enter(name, variable_symbol)) { auto original = this->bag.lookup(name); - add_error<declaration_error>(position, name, - declaration_error::redefinition{ .original = original->position, - .file = this->redefinition_file(original) }); + symbol_declaration_error::redefinition original_definition{ + .original = original->position, + .file = this->redefinition_file(original) + }; + add_error<symbol_declaration_error>(position, name, original_definition); } return variable_symbol; } @@ -424,8 +432,8 @@ namespace elna::boot { auto position_span = source_position(declaration->identifiers.front().id().position().start(), declaration->identifiers.back().id().position().end()); - add_error<const_qualifier_error>(position_span, - const_qualifier_error::not_initialized{ extract_identifiers(declaration->identifiers) }); + add_error<declaration_format_error>(position_span, + declaration_format_error::not_initialized{ extract_identifiers(declaration->identifiers) }); } for (const identifier_definition& variable_identifier : declaration->identifiers) { @@ -443,8 +451,8 @@ namespace elna::boot if (array_base.get<constant_type>() != nullptr) { - add_error<const_qualifier_error>(expression->position(), - const_qualifier_error::kind::array_position); + add_error<declaration_format_error>(expression->position(), + declaration_format_error::kind::array_position); } expression->dimensions().accept(this); if (expression->dimensions().type_decoration.empty()) @@ -483,8 +491,8 @@ namespace elna::boot expression->base().accept(this); if (this->current_type.get<constant_type>() != nullptr) { - add_error<const_qualifier_error>(expression->position(), - const_qualifier_error::kind::duplicate); + add_error<declaration_format_error>(expression->position(), + declaration_format_error::kind::duplicate); } this->current_type = type(std::make_shared<constant_type>(this->current_type)); } @@ -512,8 +520,8 @@ namespace elna::boot } else { - add_error<declaration_error>(expression->base.value().position(), - expression->base.value().name(), declaration_error::kind::undeclared_type); + add_error<symbol_declaration_error>(expression->base.value().position(), + expression->base.value().name(), symbol_declaration_error::kind::undeclared_type); this->current_type = type(); return; } @@ -698,8 +706,8 @@ namespace elna::boot } else { - add_error<declaration_error>(expression->type_name.position(), - expression->type_name.name(), declaration_error::kind::undeclared_type); + add_error<symbol_declaration_error>(expression->type_name.position(), + expression->type_name.name(), symbol_declaration_error::kind::undeclared_type); } for (const field_initializer& initializer : expression->field_initializers) { @@ -766,8 +774,8 @@ namespace elna::boot } else { - add_error<declaration_error>(trait->name.position(), - trait->name.name(), declaration_error::kind::undeclared_trait); + add_error<symbol_declaration_error>(trait->name.position(), + trait->name.name(), symbol_declaration_error::kind::undeclared_trait); } this->current_type = type(); } @@ -847,8 +855,8 @@ namespace elna::boot } else { - add_error<declaration_error>(expression->position(), - expression->name, declaration_error::kind::undeclared_symbol); + add_error<symbol_declaration_error>(expression->position(), + expression->name, symbol_declaration_error::kind::undeclared_symbol); } } @@ -1112,6 +1120,49 @@ namespace elna::boot { procedure->accept(this); } + if (unit->entry_point.has_value()) + { + auto word8_primitive = lookup_primitive_type("Word8"); + const procedure_type::return_t result_return = procedure_type::return_t(word8_primitive); + auto heading = procedure_type(result_return); + std::shared_ptr<procedure_info> info; + + if (unit->parameters.size() > 1) + { + add_error<declaration_format_error>(unit->position(), + declaration_format_error::kind::module_entry); + } + else if (unit->parameters.size() == 1) + { + auto variable_type = type(std::make_shared<pointer_type>(word8_primitive)); + variable_type = type(std::make_shared<slice_type>(variable_type)); + + heading.parameters.push_back(variable_type); + + info = std::make_shared<procedure_info>(heading, + std::vector<std::string>({ unit->parameters.at(0).name() }), this->bag.enter()); + + register_variable(info->names.at(0), variable_type, unit->parameters.at(0).position()); + } + else + { + info = std::make_shared<procedure_info>(heading, std::vector<std::string>{}, this->bag.enter()); + } + this->bag.leave(); + + info->position.emplace(unit->position()); + info->file = this->module_file; + + if (!this->bag.enter("", info)) + { + auto original = this->bag.lookup(""); + symbol_declaration_error::redefinition original_definition{ + .original = original->position, + .file = this->redefinition_file(original) + }; + add_error<symbol_declaration_error>(unit->position(), "program", original_definition); + } + } } void declaration_visitor::visit(type_declaration *declaration) @@ -1138,9 +1189,12 @@ namespace elna::boot if (!this->bag.enter(declaration->identifier.name(), info)) { auto original = this->bag.lookup(declaration->identifier.name()); - add_error<declaration_error>(declaration->identifier.id().position(), declaration->identifier.name(), - declaration_error::redefinition{ .original = original->position, - .file = this->redefinition_file(original) }); + symbol_declaration_error::redefinition original_definition{ + .original = original->position, + .file = this->redefinition_file(original) + }; + add_error<symbol_declaration_error>(declaration->identifier.id().position(), + declaration->identifier.name(), original_definition); } } @@ -1159,7 +1213,6 @@ namespace elna::boot { auto variable_symbol = register_variable(*name_iterator, *type_iterator, declaration->heading().position()); - variable_symbol->exported = false; ++name_iterator; ++type_iterator; @@ -1176,9 +1229,12 @@ namespace elna::boot if (!this->bag.enter(declaration->identifier.name(), info)) { auto original = this->bag.lookup(declaration->identifier.name()); - add_error<declaration_error>(declaration->identifier.id().position(), declaration->identifier.name(), - declaration_error::redefinition{ .original = original->position, - .file = this->redefinition_file(original) }); + symbol_declaration_error::redefinition original_definition{ + .original = original->position, + .file = this->redefinition_file(original) + }; + add_error<symbol_declaration_error>(declaration->identifier.id().position(), + declaration->identifier.name(), original_definition); } } @@ -1199,25 +1255,12 @@ namespace elna::boot { procedure->accept(this); } - if (unit->has_body()) + if (unit->entry_point.has_value()) { - this->bag.enter(); - auto variable_type = lookup_primitive_type("Int"); - auto count_symbol = std::make_shared<variable_info>(variable_type, false); - count_symbol->file = this->module_file; - this->bag.enter("count", count_symbol); - - variable_type = lookup_primitive_type("Word8"); - variable_type = type(std::make_shared<pointer_type>(variable_type)); - variable_type = type(std::make_shared<pointer_type>(variable_type)); - auto parameters_symbol = std::make_shared<variable_info>(variable_type, false); - parameters_symbol->file = this->module_file; - this->bag.enter("parameters", parameters_symbol); + const std::shared_ptr<procedure_info> info = this->bag.lookup("")->is_procedure(); - for (statement *const statement : unit->entry_point) - { - statement->accept(this); - } + this->bag.enter(info->scope); + traverse_body(this, unit->entry_point.value()); this->bag.leave(); } } @@ -1234,31 +1277,21 @@ namespace elna::boot { if (variable_identifier.exported()) { - add_error<declaration_error>(variable_identifier.id().position(), - variable_identifier.id().name(), declaration_error::kind::local_export); + add_error<symbol_declaration_error>(variable_identifier.id().position(), + variable_identifier.id().name(), symbol_declaration_error::kind::local_export); } } } void name_analysis_visitor::visit(procedure_declaration *declaration) { - const std::shared_ptr<procedure_info> info = this->bag.lookup(declaration->identifier.name())->is_procedure(); - if (declaration->body.has_value()) { + const std::shared_ptr<procedure_info> info = + this->bag.lookup(declaration->identifier.name())->is_procedure(); + this->bag.enter(info->scope); - for (variable_declaration *const variable : declaration->body.value().variables) - { - variable->accept(this); - } - for (statement *const statement : declaration->body.value().entry_point) - { - statement->accept(this); - } - if (declaration->body.value().return_expression != nullptr) - { - declaration->body.value().return_expression->accept(this); - } + traverse_body(this, declaration->body.value()); this->bag.leave(); } } diff --git a/boot/parser.yy b/boot/parser.yy index b53a94c..dc1d4e8 100644 --- a/boot/parser.yy +++ b/boot/parser.yy @@ -93,7 +93,7 @@ along with GCC; see the file COPYING3. If not see EXCLAMATION "!" ARROW "->" AT "@" HAT "^" COLON ":" SEMICOLON ";" DOT "." COMMA "," -%token NOT "~" +%token PROGRAM "program" CAST "cast" NIL "nil" CONST "const" @@ -113,7 +113,7 @@ along with GCC; see the file COPYING3. If not see OF "of" TO "to" PIPE "|" -%token OR "or" AND "&" XOR "xor" +%token NOT "~" OR "or" AND "&" XOR "xor" EQUALS "=" NOT_EQUAL "<>" LESS_THAN "<" GREATER_THAN ">" LESS_EQUAL "<=" GREATER_EQUAL ">=" SHIFT_LEFT "<<" SHIFT_RIGHT ">>" PLUS "+" MINUS "-" @@ -125,7 +125,7 @@ along with GCC; see the file COPYING3. If not see %left "+" "-" %left "*" "/" "%" -%type <elna::boot::literal_expression *> literal; +%type <std::unique_ptr<elna::boot::literal_expression>> literal; %type <std::vector<elna::boot::expression *>> case_labels; %type <elna::boot::switch_case> switch_case; %type <std::vector<elna::boot::switch_case>> switch_cases; @@ -162,9 +162,15 @@ along with GCC; see the file COPYING3. If not see %type <std::unique_ptr<elna::boot::array_type_expression>> array_type_expression; %% program: - import_part type_part variable_part procedure_part statement_part "end" "." + import_part type_part variable_part procedure_part "end" "." { - boot::unit *tree = new boot::unit(boot::make_position(@$), $1, $2, $3, $4, $5); + boot::unit *tree = new boot::unit(boot::make_position(@$), $1, $2, $3, $4); + driver.tree.reset(tree); + } + | import_part type_part variable_part procedure_part "program" "(" ")" statement_part "end" "." + { + boot::unit *tree = new boot::unit(boot::make_position(@$), $1, $2, $3, $4, + boot::procedure_body({}, std::move($8))); driver.tree.reset(tree); } procedure_body: @@ -242,91 +248,94 @@ literal: INTEGER { auto [magnitude, wants_signed] = $1; - $$ = new boot::literal<boot::integer_literal>(boot::make_position(@$), + $$ = std::make_unique<boot::literal<boot::integer_literal>>(boot::make_position(@$), boot::integer_literal::from(magnitude), wants_signed, false); } | INTEGER8 { auto [magnitude, wants_signed] = $1; - $$ = new boot::literal<boot::integer_literal>(boot::make_position(@$), + $$ = std::make_unique<boot::literal<boot::integer_literal>>(boot::make_position(@$), boot::integer_literal::from(magnitude), wants_signed); } | INTEGER16 { auto [magnitude, wants_signed] = $1; - $$ = new boot::literal<boot::integer_literal>(boot::make_position(@$), + $$ = std::make_unique<boot::literal<boot::integer_literal>>(boot::make_position(@$), boot::integer_literal::from(magnitude), wants_signed); } | INTEGER32 { auto [magnitude, wants_signed] = $1; - $$ = new boot::literal<boot::integer_literal>(boot::make_position(@$), + $$ = std::make_unique<boot::literal<boot::integer_literal>>(boot::make_position(@$), boot::integer_literal::from(magnitude), wants_signed); } | INTEGER64 { auto [magnitude, wants_signed] = $1; - $$ = new boot::literal<boot::integer_literal>(boot::make_position(@$), + $$ = std::make_unique<boot::literal<boot::integer_literal>>(boot::make_position(@$), boot::integer_literal::from(magnitude), wants_signed); } | WORD { auto [magnitude, wants_signed] = $1; - $$ = new boot::literal<boot::integer_literal>(boot::make_position(@$), + $$ = std::make_unique<boot::literal<boot::integer_literal>>(boot::make_position(@$), boot::integer_literal::from(magnitude), wants_signed, false); } | WORD8 { auto [magnitude, wants_signed] = $1; - $$ = new boot::literal<boot::integer_literal>(boot::make_position(@$), + $$ = std::make_unique<boot::literal<boot::integer_literal>>(boot::make_position(@$), boot::integer_literal::from(magnitude), wants_signed); } | WORD16 { auto [magnitude, wants_signed] = $1; - $$ = new boot::literal<boot::integer_literal>(boot::make_position(@$), + $$ = std::make_unique<boot::literal<boot::integer_literal>>(boot::make_position(@$), boot::integer_literal::from(magnitude), wants_signed); } | WORD32 { auto [magnitude, wants_signed] = $1; - $$ = new boot::literal<boot::integer_literal>(boot::make_position(@$), + $$ = std::make_unique<boot::literal<boot::integer_literal>>(boot::make_position(@$), boot::integer_literal::from(magnitude), wants_signed); } | WORD64 { auto [magnitude, wants_signed] = $1; - $$ = new boot::literal<boot::integer_literal>(boot::make_position(@$), + $$ = std::make_unique<boot::literal<boot::integer_literal>>(boot::make_position(@$), boot::integer_literal::from(magnitude), wants_signed); } | SINGLE { - $$ = new boot::literal<boot::float_literal>(boot::make_position(@$), + $$ = std::make_unique<boot::literal<boot::float_literal>>(boot::make_position(@$), boot::float_literal::from($1), boot::integer_sign::unmarked); } | DOUBLE { - $$ = new boot::literal<boot::float_literal>(boot::make_position(@$), + $$ = std::make_unique<boot::literal<boot::float_literal>>(boot::make_position(@$), boot::float_literal::from($1), boot::integer_sign::unmarked); } | BOOLEAN { - $$ = new boot::literal<bool>(boot::make_position(@$), $1, boot::integer_sign::_unsigned); + $$ = std::make_unique<boot::literal<bool>>(boot::make_position(@$), $1, boot::integer_sign::_unsigned); } | CHARACTER { - $$ = new boot::literal<std::uint32_t>(boot::make_position(@$), $1, boot::integer_sign::_unsigned); + $$ = std::make_unique<boot::literal<std::uint32_t>>(boot::make_position(@$), + $1, boot::integer_sign::_unsigned); } | "nil" { - $$ = new boot::literal<std::nullptr_t>(boot::make_position(@$), nullptr, boot::integer_sign::_unsigned); + $$ = std::make_unique<boot::literal<std::nullptr_t>>(boot::make_position(@$), + nullptr, boot::integer_sign::_unsigned); } | STRING { - $$ = new boot::literal<std::string>(boot::make_position(@$), $1, boot::integer_sign::_unsigned); + $$ = std::make_unique<boot::literal<std::string>>(boot::make_position(@$), + $1, boot::integer_sign::_unsigned); } simple_expression: - literal { $$ = $1; } + literal { $$ = $1.release(); } | designator_expression { $$ = $1; } | TRAIT "(" type_expressions ")" { diff --git a/boot/type_check.cc b/boot/type_check.cc index fd47998..da60a21 100644 --- a/boot/type_check.cc +++ b/boot/type_check.cc @@ -691,11 +691,6 @@ namespace elna::boot this->current_procedure.reset(); } - void type_analysis_visitor::visit(unit *unit) - { - walking_visitor::visit(unit); - } - void type_analysis_visitor::visit(assign_statement *statement) { walking_visitor::visit(statement); diff --git a/boot/validation.cc b/boot/validation.cc index b046b4e..91dc064 100644 --- a/boot/validation.cc +++ b/boot/validation.cc @@ -79,9 +79,12 @@ namespace elna::boot { procedure->accept(this); } - for (auto *entry_statement : unit->entry_point) + if (unit->entry_point.has_value()) { - entry_statement->accept(this); + for (auto *entry_statement : unit->entry_point->statements) + { + entry_statement->accept(this); + } } } @@ -91,7 +94,7 @@ namespace elna::boot { auto procedure = this->bag.lookup(declaration->identifier.name())->is_procedure(); this->bag.enter(procedure->scope); - for (auto *statement : declaration->body.value().entry_point) + for (auto *statement : declaration->body.value().statements) { statement->accept(this); } diff --git a/gcc/gcc/elna-generic.cc b/gcc/gcc/elna-generic.cc index 34ae5ee..b527280 100644 --- a/gcc/gcc/elna-generic.cc +++ b/gcc/gcc/elna-generic.cc @@ -257,7 +257,7 @@ namespace elna::gcc { procedure->accept(this); } - if (unit->has_body()) + if (unit->entry_point.has_value()) { tree declaration_type = build_function_type_list(elna_int_type_node, elna_int_type_node, @@ -283,7 +283,7 @@ namespace elna::gcc DECL_ARGUMENTS(fndecl) = chainon(DECL_ARGUMENTS(fndecl), declaration_tree); parameter_type = TREE_CHAIN(parameter_type); } - visit_statements(unit->entry_point); + visit_statements(unit->entry_point->statements); tree set_result = build2(INIT_EXPR, void_type_node, DECL_RESULT(fndecl), integer_zero_node); tree return_stmt = build1(RETURN_EXPR, void_type_node, set_result); @@ -315,7 +315,7 @@ namespace elna::gcc { variable->accept(this); } - visit_statements(declaration->body.value().entry_point); + visit_statements(declaration->body.value().statements); if (declaration->body.value().return_expression != nullptr) { diff --git a/include/elna/boot/ast.h b/include/elna/boot/ast.h index f959936..c485dc7 100644 --- a/include/elna/boot/ast.h +++ b/include/elna/boot/ast.h @@ -579,7 +579,7 @@ namespace elna::boot struct procedure_body { const std::vector<variable_declaration *> variables; - const std::vector<statement *> entry_point; + const std::vector<statement *> statements; expression *const return_expression{ nullptr }; procedure_body(std::vector<variable_declaration *>&& variables, @@ -593,6 +593,8 @@ namespace elna::boot virtual ~procedure_body(); }; + void traverse_body(parser_visitor *visitor, const procedure_body& body); + /** * Procedure definition. */ @@ -940,21 +942,28 @@ namespace elna::boot /** * Stores module-level definitions. */ - class unit : public node, public procedure_body + class unit : public node { public: const std::vector<import_declaration *> imports; const std::vector<type_declaration *> types; const std::vector<procedure_declaration *> procedures; + const std::vector<variable_declaration *> variables; + const std::optional<procedure_body> entry_point; + const std::vector<identifier> parameters; - unit(const source_position position); + unit(const source_position position, + std::vector<import_declaration *>&& imports, + std::vector<type_declaration *>&& types, + std::vector<variable_declaration *>&& variables, + std::vector<procedure_declaration *>&& procedures); unit(const source_position position, std::vector<import_declaration *>&& imports, std::vector<type_declaration *>&& types, std::vector<variable_declaration *>&& variables, std::vector<procedure_declaration *>&& procedures, - std::vector<statement *>&& entry_point); - bool has_body() const; + std::optional<procedure_body>&& body); + void accept(parser_visitor *visitor) override; ~unit() override; diff --git a/include/elna/boot/name_analysis.h b/include/elna/boot/name_analysis.h index 8e945b2..cf35ab6 100644 --- a/include/elna/boot/name_analysis.h +++ b/include/elna/boot/name_analysis.h @@ -35,7 +35,7 @@ namespace elna::boot * Error declaring or using a symbol (undeclared, redefinition, * local export). */ - class declaration_error final : public diagnostic + class symbol_declaration_error final : public diagnostic { public: enum class kind @@ -56,7 +56,7 @@ namespace elna::boot }; using payload_type = std::variant<redefinition, kind>; - declaration_error(const source_position position, const std::string& name, payload_type payload); + symbol_declaration_error(const source_position position, const std::string& name, payload_type payload); std::string what() const override; std::optional<diagnostic_note> note() const override; @@ -80,15 +80,16 @@ namespace elna::boot }; /** - * \c const qualifier used incorrectly — wrong position or duplicate. + * Invalid declaration format. */ - class const_qualifier_error final : public diagnostic + class declaration_format_error final : public diagnostic { public: enum class kind { array_position, - duplicate + duplicate, + module_entry }; struct not_initialized { @@ -96,7 +97,7 @@ namespace elna::boot }; using payload_type = std::variant<not_initialized, kind>; - const_qualifier_error(const source_position position, payload_type payload); + declaration_format_error(const source_position position, payload_type payload); std::optional<diagnostic_note> note() const override; std::string what() const override; @@ -173,6 +174,8 @@ namespace elna::boot resolving_visitor(symbol_bag& bag, const target_info& target, const std::filesystem::path& module_path); + procedure_type::return_t build_return_type( + const procedure_type_expression::return_t& return_type); std::pair<procedure_type, std::vector<std::string>> build_procedure( procedure_type_expression& expression); ordered_map<type> build_composite_type(const std::vector<field_declaration>& fields, diff --git a/include/elna/boot/type_check.h b/include/elna/boot/type_check.h index fea7e49..345ef9d 100644 --- a/include/elna/boot/type_check.h +++ b/include/elna/boot/type_check.h @@ -219,7 +219,6 @@ namespace elna::boot explicit type_analysis_visitor(symbol_bag bag, const target_info& target); void visit(procedure_declaration *declaration) override; - void visit(unit *unit) override; void visit(assign_statement *statement) override; void visit(variable_declaration *declaration) override; void visit(type_declaration *declaration) override; diff --git a/testsuite/compilable/assign_record_to_base.elna b/testsuite/compilable/assign_record_to_base.elna index fb28e7b..7601d06 100644 --- a/testsuite/compilable/assign_record_to_base.elna +++ b/testsuite/compilable/assign_record_to_base.elna @@ -10,6 +10,7 @@ var x: ^B := nil y: ^R := nil +program() begin x := y; end. diff --git a/testsuite/compilable/const_alias.elna b/testsuite/compilable/const_alias.elna index e17c55f..3a6b365 100644 --- a/testsuite/compilable/const_alias.elna +++ b/testsuite/compilable/const_alias.elna @@ -6,5 +6,4 @@ var x: CCI := 8 y: const CI := 9 -begin end. diff --git a/testsuite/compilable/const_element_array.elna b/testsuite/compilable/const_element_array.elna index a812d23..2d68ff5 100644 --- a/testsuite/compilable/const_element_array.elna +++ b/testsuite/compilable/const_element_array.elna @@ -5,5 +5,4 @@ var a: [3]CI := [1, 2, 3] b: [3]CI -begin end. diff --git a/testsuite/compilable/const_extern.elna b/testsuite/compilable/const_extern.elna index 8df801e..9e8fbb0 100644 --- a/testsuite/compilable/const_extern.elna +++ b/testsuite/compilable/const_extern.elna @@ -1,5 +1,4 @@ var errno_like: const Int := extern -begin end. diff --git a/testsuite/compilable/const_negation.elna b/testsuite/compilable/const_negation.elna index a62cc1e..cb76e58 100644 --- a/testsuite/compilable/const_negation.elna +++ b/testsuite/compilable/const_negation.elna @@ -2,6 +2,7 @@ var x: const Int := -5 y: const Int := -x +program() begin assert(x = -5); assert(y = 5); diff --git a/testsuite/compilable/const_var_chain.elna b/testsuite/compilable/const_var_chain.elna index a6db8c8..5a3623f 100644 --- a/testsuite/compilable/const_var_chain.elna +++ b/testsuite/compilable/const_var_chain.elna @@ -2,6 +2,7 @@ var x: const Int := 42 y: Int := x +program() begin assert(y = 42) end. diff --git a/testsuite/compilable/empty_proc_type_expression.elna b/testsuite/compilable/empty_proc_type_expression.elna index ad959f3..7738cae 100644 --- a/testsuite/compilable/empty_proc_type_expression.elna +++ b/testsuite/compilable/empty_proc_type_expression.elna @@ -1,2 +1,4 @@ -type P = proc() +type + P = proc() + end. diff --git a/testsuite/compilable/opaque_type.elna b/testsuite/compilable/opaque_type.elna index bdbf0d6..fdb2928 100644 --- a/testsuite/compilable/opaque_type.elna +++ b/testsuite/compilable/opaque_type.elna @@ -9,6 +9,7 @@ var proc take(h: ^Handle) -> ^Handle return h +program() begin alias := take(handle) end. diff --git a/testsuite/compilable/pointer_cast.elna b/testsuite/compilable/pointer_cast.elna index ab4b071..3807d69 100644 --- a/testsuite/compilable/pointer_cast.elna +++ b/testsuite/compilable/pointer_cast.elna @@ -2,7 +2,8 @@ var c: ^Char := nil p: Pointer := nil +program() begin p := c; - c := p; + c := p end. diff --git a/testsuite/compilable/pointer_const_conversion.elna b/testsuite/compilable/pointer_const_conversion.elna index fd8e097..d2328ae 100644 --- a/testsuite/compilable/pointer_const_conversion.elna +++ b/testsuite/compilable/pointer_const_conversion.elna @@ -2,6 +2,7 @@ var x: Int p: ^const Int +program() begin p := @x end. diff --git a/testsuite/compilable/self-referencing-record.elna b/testsuite/compilable/self-referencing-record.elna index cc98f86..311f148 100644 --- a/testsuite/compilable/self-referencing-record.elna +++ b/testsuite/compilable/self-referencing-record.elna @@ -2,4 +2,5 @@ type R = record field: ^R end + end. diff --git a/testsuite/compilable/take_const_address.elna b/testsuite/compilable/take_const_address.elna index f8c9e5c..71c8e0b 100644 --- a/testsuite/compilable/take_const_address.elna +++ b/testsuite/compilable/take_const_address.elna @@ -2,6 +2,7 @@ var x: ^const Int y: const Int := 1 +program() begin x := @y end. diff --git a/testsuite/compilable/traits_size.elna b/testsuite/compilable/traits_size.elna index 523045f..7ee46f1 100644 --- a/testsuite/compilable/traits_size.elna +++ b/testsuite/compilable/traits_size.elna @@ -5,6 +5,7 @@ var as: Int := cast(#size([10]Int): Int) p: Int := cast(#size(Pointer): Int) +program() begin assert(s > 0); assert(as = 10 * cast(#size(Int): Int)); diff --git a/testsuite/fail_compilation/assign_array_length.elna b/testsuite/fail_compilation/assign_array_length.elna index ac8f9df..bf6f96c 100644 --- a/testsuite/fail_compilation/assign_array_length.elna +++ b/testsuite/fail_compilation/assign_array_length.elna @@ -2,6 +2,7 @@ var slice: []Int array: [2]Int +program() begin array.length := slice.length (* @Error Cannot assign to a value of type 'const Word', because it is constant or contains constant members *) end. diff --git a/testsuite/fail_compilation/assign_const_to_pointer.elna b/testsuite/fail_compilation/assign_const_to_pointer.elna index 87047e5..7e26679 100644 --- a/testsuite/fail_compilation/assign_const_to_pointer.elna +++ b/testsuite/fail_compilation/assign_const_to_pointer.elna @@ -2,6 +2,7 @@ var c: const Int := 2 p: Pointer +program() begin p := @c (* @Error Expected type 'Pointer', but got '\^const Int' *) end. diff --git a/testsuite/fail_compilation/assign_from_const_pointer.elna b/testsuite/fail_compilation/assign_from_const_pointer.elna index c39d5cd..5dc050d 100644 --- a/testsuite/fail_compilation/assign_from_const_pointer.elna +++ b/testsuite/fail_compilation/assign_from_const_pointer.elna @@ -2,6 +2,7 @@ var cv: const Pointer := nil p: Pointer +program() begin p := cv (* @Error Expected type 'Pointer', but got 'const Pointer' *) end. diff --git a/testsuite/fail_compilation/assign_slice_ptr.elna b/testsuite/fail_compilation/assign_slice_ptr.elna index aa7a379..6f09f00 100644 --- a/testsuite/fail_compilation/assign_slice_ptr.elna +++ b/testsuite/fail_compilation/assign_slice_ptr.elna @@ -2,6 +2,7 @@ var slice: []Int array: [2]Int +program() begin slice.ptr := array.ptr (* @Error Cannot assign to a value of type 'const \^Int', because it is constant or contains constant members *) end. diff --git a/testsuite/fail_compilation/assign_to_call_result_field.elna b/testsuite/fail_compilation/assign_to_call_result_field.elna index 509b2dd..25096ed 100644 --- a/testsuite/fail_compilation/assign_to_call_result_field.elna +++ b/testsuite/fail_compilation/assign_to_call_result_field.elna @@ -10,6 +10,7 @@ begin result.x := 1 return result +program() begin make().x := 5 (* @Error Expression of type 'Int' is not addressable *) end. diff --git a/testsuite/fail_compilation/assign_to_slicing.elna b/testsuite/fail_compilation/assign_to_slicing.elna index 2266431..6743e06 100644 --- a/testsuite/fail_compilation/assign_to_slicing.elna +++ b/testsuite/fail_compilation/assign_to_slicing.elna @@ -2,6 +2,7 @@ var s: [3]Int t: [2]Int +program() begin s[1 to 2] := t[1 to 2] (* @Error Expression of type '\[\]Int' is not addressable *) end. diff --git a/testsuite/fail_compilation/assign_void_call.elna b/testsuite/fail_compilation/assign_void_call.elna index d18b1c8..381bb06 100644 --- a/testsuite/fail_compilation/assign_void_call.elna +++ b/testsuite/fail_compilation/assign_void_call.elna @@ -4,6 +4,7 @@ var proc v() return +program() begin x := v() (* @Error Expected type 'Int', but the expression has no value *) end. diff --git a/testsuite/fail_compilation/case_label_overflow.elna b/testsuite/fail_compilation/case_label_overflow.elna index ab6dbfd..787f043 100644 --- a/testsuite/fail_compilation/case_label_overflow.elna +++ b/testsuite/fail_compilation/case_label_overflow.elna @@ -1,6 +1,7 @@ var x: Int8 := 100i8 +program() begin case x of 100i8: assert(true) diff --git a/testsuite/fail_compilation/case_non_constant.elna b/testsuite/fail_compilation/case_non_constant.elna index dc69703..a446c29 100644 --- a/testsuite/fail_compilation/case_non_constant.elna +++ b/testsuite/fail_compilation/case_non_constant.elna @@ -8,6 +8,7 @@ var r: R x: R +program() begin x := r; case x of diff --git a/testsuite/fail_compilation/case_type_mismatch.elna b/testsuite/fail_compilation/case_type_mismatch.elna index 9cdae38..57afd1f 100644 --- a/testsuite/fail_compilation/case_type_mismatch.elna +++ b/testsuite/fail_compilation/case_type_mismatch.elna @@ -1,6 +1,7 @@ var x: Int +program() begin case x of 1: (* ok *) diff --git a/testsuite/fail_compilation/case_unique_label.elna b/testsuite/fail_compilation/case_unique_label.elna index a97fb37..7ee8391 100644 --- a/testsuite/fail_compilation/case_unique_label.elna +++ b/testsuite/fail_compilation/case_unique_label.elna @@ -1,3 +1,4 @@ +program() begin case 3 of 1: diff --git a/testsuite/fail_compilation/compare_unrelated_records.elna b/testsuite/fail_compilation/compare_unrelated_records.elna index 71eaeda..1699406 100644 --- a/testsuite/fail_compilation/compare_unrelated_records.elna +++ b/testsuite/fail_compilation/compare_unrelated_records.elna @@ -12,6 +12,7 @@ var b: B ok: Bool +program() begin ok := b = a (* @Error Invalid operands of type 'B' and 'A' for operator = *) end. diff --git a/testsuite/fail_compilation/constant_enum_to_int.elna b/testsuite/fail_compilation/constant_enum_to_int.elna index 4be6131..52c31c3 100644 --- a/testsuite/fail_compilation/constant_enum_to_int.elna +++ b/testsuite/fail_compilation/constant_enum_to_int.elna @@ -5,6 +5,7 @@ var x: [3]Int := [1, 2, 3] y: []Int +program() begin y := x[Enumeration.one to Enumeration.two] (* @Error Array index must be an integral type, but got 'Enumeration' *) end. diff --git a/testsuite/fail_compilation/import_local_collision/helper.elna b/testsuite/fail_compilation/import_local_collision/helper.elna index d6e3712..e60ca8e 100644 --- a/testsuite/fail_compilation/import_local_collision/helper.elna +++ b/testsuite/fail_compilation/import_local_collision/helper.elna @@ -1,6 +1,4 @@ var - X*: Int + X*: Int := 1 -begin - X := 1 end. diff --git a/testsuite/fail_compilation/import_local_collision/sut.elna b/testsuite/fail_compilation/import_local_collision/sut.elna index a9de9c9..8b52586 100644 --- a/testsuite/fail_compilation/import_local_collision/sut.elna +++ b/testsuite/fail_compilation/import_local_collision/sut.elna @@ -3,5 +3,6 @@ import helper var X: Int (* @Error Symbol 'X' has been already defined *) -begin +program() + end. diff --git a/testsuite/fail_compilation/non_constant_array_dimension.elna b/testsuite/fail_compilation/non_constant_array_dimension.elna index 4ab0d34..e3661c7 100644 --- a/testsuite/fail_compilation/non_constant_array_dimension.elna +++ b/testsuite/fail_compilation/non_constant_array_dimension.elna @@ -4,6 +4,7 @@ var begin return +program() begin f(5) end. diff --git a/testsuite/fail_compilation/opaque_pointer_arithmetic.elna b/testsuite/fail_compilation/opaque_pointer_arithmetic.elna index 307aed8..0223cc8 100644 --- a/testsuite/fail_compilation/opaque_pointer_arithmetic.elna +++ b/testsuite/fail_compilation/opaque_pointer_arithmetic.elna @@ -4,6 +4,7 @@ type var p: ^Handle +program() begin p := p + 1 (* @Error Opaque type 'Handle' cannot be used as an element type in pointer arithmetic *) end. diff --git a/testsuite/fail_compilation/opaque_slice_element.elna b/testsuite/fail_compilation/opaque_slice_element.elna index 0f28dae..f50be8a 100644 --- a/testsuite/fail_compilation/opaque_slice_element.elna +++ b/testsuite/fail_compilation/opaque_slice_element.elna @@ -4,5 +4,4 @@ type var s: []Handle (* @Error Opaque type 'Handle' cannot be used to declare a variable *) -begin end. diff --git a/testsuite/fail_compilation/pointer-cycle.elna b/testsuite/fail_compilation/pointer-cycle.elna index f9ee649..fe0258a 100644 --- a/testsuite/fail_compilation/pointer-cycle.elna +++ b/testsuite/fail_compilation/pointer-cycle.elna @@ -1,3 +1,4 @@ type A = ^A (* @Error Type declaration forms a cycle: A -> A *) + end. diff --git a/testsuite/fail_compilation/proc_type_without_parameters.elna b/testsuite/fail_compilation/proc_type_without_parameters.elna index 92514f6..3868e1b 100644 --- a/testsuite/fail_compilation/proc_type_without_parameters.elna +++ b/testsuite/fail_compilation/proc_type_without_parameters.elna @@ -4,6 +4,7 @@ var proc f() return +program() begin x := f (* @Error Expected type 'Int', but got 'proc\(\)' *) end. diff --git a/testsuite/fail_compilation/procedure-cycle.elna b/testsuite/fail_compilation/procedure-cycle.elna index 796cccf..2284605 100644 --- a/testsuite/fail_compilation/procedure-cycle.elna +++ b/testsuite/fail_compilation/procedure-cycle.elna @@ -1,3 +1,4 @@ type A = proc() -> A (* @Error Type declaration forms a cycle: A -> A *) + end. diff --git a/testsuite/fail_compilation/record-base-cycle-indirect.elna b/testsuite/fail_compilation/record-base-cycle-indirect.elna index 412e6ea..1ea6ca5 100644 --- a/testsuite/fail_compilation/record-base-cycle-indirect.elna +++ b/testsuite/fail_compilation/record-base-cycle-indirect.elna @@ -9,5 +9,6 @@ type var v: A +program() begin end. diff --git a/testsuite/fail_compilation/record-base-cycle.elna b/testsuite/fail_compilation/record-base-cycle.elna index f3bcb20..8af254d 100644 --- a/testsuite/fail_compilation/record-base-cycle.elna +++ b/testsuite/fail_compilation/record-base-cycle.elna @@ -1,4 +1,5 @@ type R = record(R) (* @Error Type declaration forms a cycle: R -> R *) end + end. diff --git a/testsuite/fail_compilation/record_base_constructor_type_mismatch.elna b/testsuite/fail_compilation/record_base_constructor_type_mismatch.elna index 85c93c1..fbba47c 100644 --- a/testsuite/fail_compilation/record_base_constructor_type_mismatch.elna +++ b/testsuite/fail_compilation/record_base_constructor_type_mismatch.elna @@ -9,6 +9,7 @@ type var c: Child +program() begin c := Child{a: "wrong", b: 9} (* @Error Expected type 'Int', but got '\[\]const Word8' *) end. diff --git a/testsuite/fail_compilation/record_duplicate_field.elna b/testsuite/fail_compilation/record_duplicate_field.elna index b98f990..5cf69a9 100644 --- a/testsuite/fail_compilation/record_duplicate_field.elna +++ b/testsuite/fail_compilation/record_duplicate_field.elna @@ -4,5 +4,4 @@ type x: Int (* @Error Record already has a field named 'x' *) end -begin end. diff --git a/testsuite/fail_compilation/record_duplicate_field_import_base/sut.elna b/testsuite/fail_compilation/record_duplicate_field_import_base/sut.elna index 7530017..58f2f3d 100644 --- a/testsuite/fail_compilation/record_duplicate_field_import_base/sut.elna +++ b/testsuite/fail_compilation/record_duplicate_field_import_base/sut.elna @@ -6,5 +6,4 @@ type z: Int end -begin end. diff --git a/testsuite/fail_compilation/redefined_variable.elna b/testsuite/fail_compilation/redefined_variable.elna index 9cf8c24..905f6ed 100644 --- a/testsuite/fail_compilation/redefined_variable.elna +++ b/testsuite/fail_compilation/redefined_variable.elna @@ -2,5 +2,4 @@ var x: Int x: Int (* @Error Symbol 'x' has been already defined *) -begin end. diff --git a/testsuite/fail_compilation/reference_call_result_field.elna b/testsuite/fail_compilation/reference_call_result_field.elna index 5051cc8..2a721f4 100644 --- a/testsuite/fail_compilation/reference_call_result_field.elna +++ b/testsuite/fail_compilation/reference_call_result_field.elna @@ -13,6 +13,7 @@ begin result.x := 1 return result +program() begin p := @make().x (* @Error Expression of type 'Int' is not addressable *) end. diff --git a/testsuite/fail_compilation/reference_literal.elna b/testsuite/fail_compilation/reference_literal.elna index 1967243..1eef82f 100644 --- a/testsuite/fail_compilation/reference_literal.elna +++ b/testsuite/fail_compilation/reference_literal.elna @@ -1,6 +1,7 @@ var p: ^Int +program() begin p := @5 (* @Error Expression of type 'Int' is not addressable *) end. diff --git a/testsuite/fail_compilation/reference_slicing.elna b/testsuite/fail_compilation/reference_slicing.elna index fac8ec6..078b48a 100644 --- a/testsuite/fail_compilation/reference_slicing.elna +++ b/testsuite/fail_compilation/reference_slicing.elna @@ -2,6 +2,7 @@ var s: [3]Int p: ^Int +program() begin p := @s[1 to 2] (* @Error Expression of type '\[\]Int' is not addressable *) end. diff --git a/testsuite/fail_compilation/slice-cycle.elna b/testsuite/fail_compilation/slice-cycle.elna index 39eb7db..fe0a3e1 100644 --- a/testsuite/fail_compilation/slice-cycle.elna +++ b/testsuite/fail_compilation/slice-cycle.elna @@ -1,3 +1,4 @@ type A = []A (* @Error Type declaration forms a cycle: A -> A *) + end. diff --git a/testsuite/fail_compilation/while_condition.elna b/testsuite/fail_compilation/while_condition.elna index 1e17489..bd54796 100644 --- a/testsuite/fail_compilation/while_condition.elna +++ b/testsuite/fail_compilation/while_condition.elna @@ -1,3 +1,4 @@ +program() begin while 1 do (* @Error Condition must be a boolean expression, but got 'Int' *) end diff --git a/testsuite/runnable/aggregate_argument.elna b/testsuite/runnable/aggregate_argument.elna index 875265e..7aa6ea0 100644 --- a/testsuite/runnable/aggregate_argument.elna +++ b/testsuite/runnable/aggregate_argument.elna @@ -7,6 +7,7 @@ type proc f(r: R) -> Bool return r.a = 1 & r.b = 2 +program() begin assert(f(R{a: 1, b: 2})) end. diff --git a/testsuite/runnable/aggregate_equality.elna b/testsuite/runnable/aggregate_equality.elna index bfe2174..b8da9e9 100644 --- a/testsuite/runnable/aggregate_equality.elna +++ b/testsuite/runnable/aggregate_equality.elna @@ -7,6 +7,7 @@ type proc f() -> Bool return R{a: 1, b: 2} = R{a: 1, b: 2} +program() begin assert(f()) end. diff --git a/testsuite/runnable/array_constructor.elna b/testsuite/runnable/array_constructor.elna index 0e7b08b..aa1c43c 100644 --- a/testsuite/runnable/array_constructor.elna +++ b/testsuite/runnable/array_constructor.elna @@ -2,6 +2,7 @@ var a: [3]Int := [1, 2, 3] b: [2]Int := [4, 0] +program() begin assert(a[1] = 1 & a[2] = 2 & a[3] = 3); assert(b[1] = 4 & b[2] = 0); diff --git a/testsuite/runnable/binary_literal.elna b/testsuite/runnable/binary_literal.elna index 0c2cbd9..6380f24 100644 --- a/testsuite/runnable/binary_literal.elna +++ b/testsuite/runnable/binary_literal.elna @@ -1,3 +1,4 @@ +program() begin assert(0b11 = 3u); assert(0B011 = 3u) diff --git a/testsuite/runnable/case_constant_label.elna b/testsuite/runnable/case_constant_label.elna index 5d55e9f..2402bf7 100644 --- a/testsuite/runnable/case_constant_label.elna +++ b/testsuite/runnable/case_constant_label.elna @@ -4,6 +4,7 @@ var x: Int := 2 matched: Bool := false +program() begin case x of 1: assert(false) diff --git a/testsuite/runnable/case_else.elna b/testsuite/runnable/case_else.elna index dbec6df..b5ab3c0 100644 --- a/testsuite/runnable/case_else.elna +++ b/testsuite/runnable/case_else.elna @@ -2,6 +2,7 @@ var x: Int := 5 matched: Bool := false +program() begin case x of 1: assert(false) diff --git a/testsuite/runnable/case_int.elna b/testsuite/runnable/case_int.elna index 3b770a7..ca36fc8 100644 --- a/testsuite/runnable/case_int.elna +++ b/testsuite/runnable/case_int.elna @@ -1,6 +1,7 @@ var x: Int := 2 +program() begin case x of 1: assert(false) diff --git a/testsuite/runnable/case_multilabel.elna b/testsuite/runnable/case_multilabel.elna index be647d4..083bdb0 100644 --- a/testsuite/runnable/case_multilabel.elna +++ b/testsuite/runnable/case_multilabel.elna @@ -1,6 +1,7 @@ var x: Int := 3 +program() begin case x of 1, 2, 3: assert(true) diff --git a/testsuite/runnable/case_record.elna b/testsuite/runnable/case_record.elna index 4f65a5b..26436ea 100644 --- a/testsuite/runnable/case_record.elna +++ b/testsuite/runnable/case_record.elna @@ -7,6 +7,7 @@ type var r: R := R{a: 1, b: 2} +program() begin case r of R{a: 0, b: 0}: assert(false) diff --git a/testsuite/runnable/compile_time_array_access.elna b/testsuite/runnable/compile_time_array_access.elna index 4d59215..b854635 100644 --- a/testsuite/runnable/compile_time_array_access.elna +++ b/testsuite/runnable/compile_time_array_access.elna @@ -2,6 +2,7 @@ var array: const [3]Int := [1, 2, 3] i: const Int := array[2] +program() begin assert(i = 2) end. diff --git a/testsuite/runnable/const_copy.elna b/testsuite/runnable/const_copy.elna index 5982149..32cee67 100644 --- a/testsuite/runnable/const_copy.elna +++ b/testsuite/runnable/const_copy.elna @@ -7,6 +7,7 @@ begin assert(y = 5) return +program() begin f() end. diff --git a/testsuite/runnable/const_initialization.elna b/testsuite/runnable/const_initialization.elna index 7f922ff..56a6697 100644 --- a/testsuite/runnable/const_initialization.elna +++ b/testsuite/runnable/const_initialization.elna @@ -5,6 +5,7 @@ begin assert(x = 5) return +program() begin f() end. diff --git a/testsuite/runnable/constant_string_initializer.elna b/testsuite/runnable/constant_string_initializer.elna index 52ca429..8fd3b78 100644 --- a/testsuite/runnable/constant_string_initializer.elna +++ b/testsuite/runnable/constant_string_initializer.elna @@ -1,6 +1,7 @@ var s: []const Word8 := "String value" +program() begin assert(s = "String value") end. diff --git a/testsuite/runnable/define_multiple_local_variables.elna b/testsuite/runnable/define_multiple_local_variables.elna index 8e44da4..72f0874 100644 --- a/testsuite/runnable/define_multiple_local_variables.elna +++ b/testsuite/runnable/define_multiple_local_variables.elna @@ -3,6 +3,7 @@ var a, b: Int := 5 return a = 5 & b = 5 +program() begin assert(f()) end. diff --git a/testsuite/runnable/exported_variable/sut.elna b/testsuite/runnable/exported_variable/sut.elna index 52fb291..1fbc6ee 100644 --- a/testsuite/runnable/exported_variable/sut.elna +++ b/testsuite/runnable/exported_variable/sut.elna @@ -1,5 +1,6 @@ import helper +program() begin assert(Shared = 42) end. diff --git a/testsuite/runnable/fixed_int_max.elna b/testsuite/runnable/fixed_int_max.elna index 0564dd6..f00fd60 100644 --- a/testsuite/runnable/fixed_int_max.elna +++ b/testsuite/runnable/fixed_int_max.elna @@ -1,3 +1,4 @@ +program() begin assert(#max(Int8) = 127i8); assert(#max(Int16) = 32767i16); diff --git a/testsuite/runnable/fixed_int_min.elna b/testsuite/runnable/fixed_int_min.elna index de83d1a..fd6b110 100644 --- a/testsuite/runnable/fixed_int_min.elna +++ b/testsuite/runnable/fixed_int_min.elna @@ -1,3 +1,4 @@ +program() begin assert(#min(Int8) = -128i8); assert(#min(Int16) = -32768i16); diff --git a/testsuite/runnable/fixed_word_max.elna b/testsuite/runnable/fixed_word_max.elna index 76026a2..c657614 100644 --- a/testsuite/runnable/fixed_word_max.elna +++ b/testsuite/runnable/fixed_word_max.elna @@ -1,3 +1,4 @@ +program() begin assert(#max(Word8) = 255u8); assert(#max(Word16) = 65535u16); diff --git a/testsuite/runnable/float_arithmetic.elna b/testsuite/runnable/float_arithmetic.elna index 73072f2..f792b04 100644 --- a/testsuite/runnable/float_arithmetic.elna +++ b/testsuite/runnable/float_arithmetic.elna @@ -1,3 +1,4 @@ +program() begin assert(6.0 / 2.0 = 3.0); assert(5.0 / 2.0 = 2.5); diff --git a/testsuite/runnable/for_each_array.elna b/testsuite/runnable/for_each_array.elna index c6cba41..806a84b 100644 --- a/testsuite/runnable/for_each_array.elna +++ b/testsuite/runnable/for_each_array.elna @@ -3,6 +3,7 @@ var input: [4]Word := [2u, 4u, 6u, 8u] i: Word := 1u +program() begin for element of input do actual[i] := element^ * 2u; diff --git a/testsuite/runnable/for_each_slice.elna b/testsuite/runnable/for_each_slice.elna index 5356bc8..ecd3cc3 100644 --- a/testsuite/runnable/for_each_slice.elna +++ b/testsuite/runnable/for_each_slice.elna @@ -4,6 +4,7 @@ var slice: []Word i: Word := 1u +program() begin slice := input[1u to input.length]; diff --git a/testsuite/runnable/for_with.elna b/testsuite/runnable/for_with.elna index 22ccb13..582a641 100644 --- a/testsuite/runnable/for_with.elna +++ b/testsuite/runnable/for_with.elna @@ -1,6 +1,7 @@ var actual: [3]Word := [0u, 0u, 0u] +program() begin for element of [1u, 2u, 3u] with i do actual[i] := i * element^ diff --git a/testsuite/runnable/generic_pointer_arithmetic.elna b/testsuite/runnable/generic_pointer_arithmetic.elna index c737c7d..9aad7d6 100644 --- a/testsuite/runnable/generic_pointer_arithmetic.elna +++ b/testsuite/runnable/generic_pointer_arithmetic.elna @@ -4,6 +4,7 @@ var first: Pointer second: Pointer +program() begin element := base.ptr; first := element; diff --git a/testsuite/runnable/hexadecimal_literal.elna b/testsuite/runnable/hexadecimal_literal.elna index 71fd2da..a168bd2 100644 --- a/testsuite/runnable/hexadecimal_literal.elna +++ b/testsuite/runnable/hexadecimal_literal.elna @@ -1,3 +1,4 @@ +program() begin assert(0xff = 255u); assert(0X0f = 15u) diff --git a/testsuite/runnable/multi_module/sut.elna b/testsuite/runnable/multi_module/sut.elna index fb26a26..666f82a 100644 --- a/testsuite/runnable/multi_module/sut.elna +++ b/testsuite/runnable/multi_module/sut.elna @@ -1,5 +1,6 @@ import helper +program() begin assert(multiply(3, 4) = 12) end. diff --git a/testsuite/runnable/procedure_cast.elna b/testsuite/runnable/procedure_cast.elna index ee97a6b..11e0e72 100644 --- a/testsuite/runnable/procedure_cast.elna +++ b/testsuite/runnable/procedure_cast.elna @@ -3,6 +3,7 @@ var cb: proc(x: ^Char) -> Int proc probe_int(x: ^Int) -> Int return 42 +program() begin cb := cast(probe_int: proc(x: ^Char) -> Int); assert(cb(nil) = 42) diff --git a/testsuite/runnable/record_base_assignment.elna b/testsuite/runnable/record_base_assignment.elna index 2a15d0f..81ee7cf 100644 --- a/testsuite/runnable/record_base_assignment.elna +++ b/testsuite/runnable/record_base_assignment.elna @@ -16,6 +16,7 @@ begin assert(r.x = 3u & r.y = 2u) return +program() begin f() end. diff --git a/testsuite/runnable/record_base_constructor.elna b/testsuite/runnable/record_base_constructor.elna index 86da08a..1ca3214 100644 --- a/testsuite/runnable/record_base_constructor.elna +++ b/testsuite/runnable/record_base_constructor.elna @@ -12,6 +12,7 @@ type var g: Grandchild := Grandchild{a: 3, b: 5, c: 7} +program() begin assert(g.a = 3); assert(g.b = 5); diff --git a/testsuite/runnable/record_construction.elna b/testsuite/runnable/record_construction.elna index 2bbc493..31fc21f 100644 --- a/testsuite/runnable/record_construction.elna +++ b/testsuite/runnable/record_construction.elna @@ -6,6 +6,7 @@ type var r: R := R{x: 1, y: 2} +program() begin assert(r.x = 1 & r.y = 2) end. diff --git a/testsuite/runnable/record_extension.elna b/testsuite/runnable/record_extension.elna index 7d8dc61..b195759 100644 --- a/testsuite/runnable/record_extension.elna +++ b/testsuite/runnable/record_extension.elna @@ -10,6 +10,7 @@ var token_memory: ElnaLexerStringToken current_token: ^ElnaLexerToken +program() begin current_token := @token_memory; cast(current_token: ^ElnaLexerStringToken)^.value := "Some string"; diff --git a/testsuite/runnable/record_layout.elna b/testsuite/runnable/record_layout.elna index 180d7bc..b94f18a 100644 --- a/testsuite/runnable/record_layout.elna +++ b/testsuite/runnable/record_layout.elna @@ -50,6 +50,7 @@ begin assert(array_record_c_offset = 3u * int_size) return +program() begin f() end. diff --git a/testsuite/runnable/recursive_record.elna b/testsuite/runnable/recursive_record.elna index 237eece..c940da9 100644 --- a/testsuite/runnable/recursive_record.elna +++ b/testsuite/runnable/recursive_record.elna @@ -27,6 +27,7 @@ begin end; return result +program() begin first := malloc(#size(Node)); second := malloc(#size(Node)); diff --git a/testsuite/runnable/repeat_loop.elna b/testsuite/runnable/repeat_loop.elna index 71554f0..ea50884 100644 --- a/testsuite/runnable/repeat_loop.elna +++ b/testsuite/runnable/repeat_loop.elna @@ -2,6 +2,7 @@ var actual: [4]Word := [0u, 0u, 0u, 0u] i: Word := 0u +program() begin repeat i := i + 1u; diff --git a/testsuite/runnable/return_aggregate.elna b/testsuite/runnable/return_aggregate.elna index fbc1a08..ad3ec65 100644 --- a/testsuite/runnable/return_aggregate.elna +++ b/testsuite/runnable/return_aggregate.elna @@ -7,6 +7,7 @@ type proc f() -> R return R{ a: 1, b: 2 } +program() begin assert(f() = R{ a: 1, b: 2 }) end. diff --git a/testsuite/runnable/slice_array.elna b/testsuite/runnable/slice_array.elna index 8baaff3..2b747ea 100644 --- a/testsuite/runnable/slice_array.elna +++ b/testsuite/runnable/slice_array.elna @@ -2,6 +2,7 @@ var array: [3]Int := [2, 4, 6] slice: []Int +program() begin slice := array[1 to 3]; diff --git a/testsuite/runnable/slice_cast.elna b/testsuite/runnable/slice_cast.elna index ca093db..d11f80a 100644 --- a/testsuite/runnable/slice_cast.elna +++ b/testsuite/runnable/slice_cast.elna @@ -1,6 +1,7 @@ var ints: [4]Int32 := [1i32, 2i32, 3i32, 4i32] +program() begin assert(cast(ints[1u to 4u]: []Int8).length = #size(Int32) * ints.length) end. diff --git a/testsuite/runnable/slice_equality.elna b/testsuite/runnable/slice_equality.elna index e34981a..08eb4f2 100644 --- a/testsuite/runnable/slice_equality.elna +++ b/testsuite/runnable/slice_equality.elna @@ -2,6 +2,7 @@ var lhs_payload, rhs_payload: [3]Int := [2, 4, 6] lhs, rhs: []Int +program() begin lhs := lhs_payload[1 to 3]; rhs := rhs_payload[1 to 3]; diff --git a/testsuite/runnable/slice_pointer.elna b/testsuite/runnable/slice_pointer.elna index 1ab367e..6ebcec9 100644 --- a/testsuite/runnable/slice_pointer.elna +++ b/testsuite/runnable/slice_pointer.elna @@ -2,6 +2,7 @@ var array: [3]Int := [2, 4, 6] slice: []Int +program() begin slice := array.ptr[1 to 3]; diff --git a/testsuite/runnable/slice_slice.elna b/testsuite/runnable/slice_slice.elna index f5e0eba..459cf51 100644 --- a/testsuite/runnable/slice_slice.elna +++ b/testsuite/runnable/slice_slice.elna @@ -2,6 +2,7 @@ var array: [5]Int := [2, 4, 6, 8, 10] slice1, slice2: []Int +program() begin slice1 := array[1 to array.length]; slice2 := slice1[2 to 4]; diff --git a/testsuite/runnable/two_fields_same_type.elna b/testsuite/runnable/two_fields_same_type.elna index 71dcbee..7d7292d 100644 --- a/testsuite/runnable/two_fields_same_type.elna +++ b/testsuite/runnable/two_fields_same_type.elna @@ -8,7 +8,7 @@ var r: R := R{x: 3, y: 2} return r.x + r.y - +program() begin assert(f() = 5) end. diff --git a/testsuite/runnable/two_parameters_same_type.elna b/testsuite/runnable/two_parameters_same_type.elna index 105a40c..41d688c 100644 --- a/testsuite/runnable/two_parameters_same_type.elna +++ b/testsuite/runnable/two_parameters_same_type.elna @@ -1,6 +1,7 @@ proc f(x, y: Int) -> Int return x + y +program() begin assert(f(2, 3) = 5) end. diff --git a/testsuite/runnable/unary_plus.elna b/testsuite/runnable/unary_plus.elna index bfd59d6..e4b3762 100644 --- a/testsuite/runnable/unary_plus.elna +++ b/testsuite/runnable/unary_plus.elna @@ -1,6 +1,7 @@ proc f(x: Int) -> Int return +x +program() begin assert(+3 = 3); assert(f(5) = 5); diff --git a/testsuite/runnable/unicode_escape_character.elna b/testsuite/runnable/unicode_escape_character.elna index d49910c..0cfd3e2 100644 --- a/testsuite/runnable/unicode_escape_character.elna +++ b/testsuite/runnable/unicode_escape_character.elna @@ -1,3 +1,4 @@ +program() begin assert(`\{U+E9}` = `é`); assert(`\{U+1F600}` = `😀`) diff --git a/testsuite/runnable/unicode_escape_string.elna b/testsuite/runnable/unicode_escape_string.elna index 5905eda..bec794a 100644 --- a/testsuite/runnable/unicode_escape_string.elna +++ b/testsuite/runnable/unicode_escape_string.elna @@ -1,3 +1,4 @@ +program() begin assert("caf\{U+E9}" = "café"); assert("Hi \{U+1F600}!" = "Hi 😀!") |
