aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2026-09-07 22:02:15 +0200
committerEugen Wissner <belka@caraus.de>2026-09-07 23:39:53 +0200
commit72f5e82196d95008ed12c12de6bdccf24361e106 (patch)
tree8319324de8e2a5182dc3c1ddca00a837c2489ad2
parent47521ad6d85f9bd6caee39696ce40dff82cfa50d (diff)
downloadelna-72f5e82196d95008ed12c12de6bdccf24361e106.tar.gz
Make module entry point more procedure like
-rw-r--r--boot/ast.cc12
-rw-r--r--boot/dependency.cc18
-rw-r--r--boot/lexer.ll1
-rw-r--r--boot/name_analysis.cc15
-rw-r--r--boot/parser.yy18
-rw-r--r--boot/type_check.cc80
-rw-r--r--gcc/gcc/elna-builtins.cc5
-rw-r--r--gcc/gcc/elna-generic.cc73
-rw-r--r--include/elna/boot/ast.h7
-rw-r--r--include/elna/boot/dependency.h34
-rw-r--r--include/elna/boot/type_check.h5
-rw-r--r--source/main.elna4
-rw-r--r--testsuite/compilable/assign_record_to_base.elna2
-rw-r--r--testsuite/compilable/const_negation.elna2
-rw-r--r--testsuite/compilable/const_var_chain.elna2
-rw-r--r--testsuite/compilable/opaque_type.elna2
-rw-r--r--testsuite/compilable/pointer_cast.elna2
-rw-r--r--testsuite/compilable/pointer_const_conversion.elna2
-rw-r--r--testsuite/compilable/take_const_address.elna2
-rw-r--r--testsuite/compilable/traits_size.elna2
-rw-r--r--testsuite/fail_compilation/assign_array_length.elna2
-rw-r--r--testsuite/fail_compilation/assign_const_to_pointer.elna2
-rw-r--r--testsuite/fail_compilation/assign_from_const_pointer.elna2
-rw-r--r--testsuite/fail_compilation/assign_slice_ptr.elna2
-rw-r--r--testsuite/fail_compilation/assign_to_call_result_field.elna2
-rw-r--r--testsuite/fail_compilation/assign_to_slicing.elna2
-rw-r--r--testsuite/fail_compilation/assign_void_call.elna2
-rw-r--r--testsuite/fail_compilation/case_label_overflow.elna2
-rw-r--r--testsuite/fail_compilation/case_non_constant.elna2
-rw-r--r--testsuite/fail_compilation/case_type_mismatch.elna2
-rw-r--r--testsuite/fail_compilation/case_unique_label.elna2
-rw-r--r--testsuite/fail_compilation/compare_unrelated_records.elna2
-rw-r--r--testsuite/fail_compilation/constant_enum_to_int.elna2
-rw-r--r--testsuite/fail_compilation/import_local_collision/sut.elna1
-rw-r--r--testsuite/fail_compilation/non_constant_array_dimension.elna2
-rw-r--r--testsuite/fail_compilation/opaque_pointer_arithmetic.elna2
-rw-r--r--testsuite/fail_compilation/proc_type_without_parameters.elna2
-rw-r--r--testsuite/fail_compilation/program_arguments.elna4
-rw-r--r--testsuite/fail_compilation/record-base-cycle-indirect.elna2
-rw-r--r--testsuite/fail_compilation/record_base_constructor_type_mismatch.elna2
-rw-r--r--testsuite/fail_compilation/reference_call_result_field.elna2
-rw-r--r--testsuite/fail_compilation/reference_literal.elna2
-rw-r--r--testsuite/fail_compilation/reference_slicing.elna2
-rw-r--r--testsuite/fail_compilation/while_condition.elna2
-rw-r--r--testsuite/runnable/aggregate_argument.elna2
-rw-r--r--testsuite/runnable/aggregate_equality.elna2
-rw-r--r--testsuite/runnable/array_constructor.elna2
-rw-r--r--testsuite/runnable/binary_literal.elna2
-rw-r--r--testsuite/runnable/case_constant_label.elna2
-rw-r--r--testsuite/runnable/case_else.elna2
-rw-r--r--testsuite/runnable/case_int.elna2
-rw-r--r--testsuite/runnable/case_multilabel.elna2
-rw-r--r--testsuite/runnable/case_record.elna2
-rw-r--r--testsuite/runnable/compile_time_array_access.elna2
-rw-r--r--testsuite/runnable/const_copy.elna2
-rw-r--r--testsuite/runnable/const_initialization.elna2
-rw-r--r--testsuite/runnable/constant_string_initializer.elna2
-rw-r--r--testsuite/runnable/define_multiple_local_variables.elna2
-rw-r--r--testsuite/runnable/exported_variable/sut.elna2
-rw-r--r--testsuite/runnable/fixed_int_max.elna2
-rw-r--r--testsuite/runnable/fixed_int_min.elna2
-rw-r--r--testsuite/runnable/fixed_word_max.elna2
-rw-r--r--testsuite/runnable/float_arithmetic.elna2
-rw-r--r--testsuite/runnable/for_call.elna3
-rw-r--r--testsuite/runnable/for_defer.elna3
-rw-r--r--testsuite/runnable/for_each_array.elna2
-rw-r--r--testsuite/runnable/for_each_slice.elna2
-rw-r--r--testsuite/runnable/for_with.elna5
-rw-r--r--testsuite/runnable/generic_pointer_arithmetic.elna2
-rw-r--r--testsuite/runnable/hexadecimal_literal.elna2
-rw-r--r--testsuite/runnable/multi_module/sut.elna2
-rw-r--r--testsuite/runnable/procedure_cast.elna2
-rw-r--r--testsuite/runnable/record_base_assignment.elna2
-rw-r--r--testsuite/runnable/record_base_constructor.elna2
-rw-r--r--testsuite/runnable/record_construction.elna2
-rw-r--r--testsuite/runnable/record_extension.elna2
-rw-r--r--testsuite/runnable/record_layout.elna2
-rw-r--r--testsuite/runnable/recursive_record.elna2
-rw-r--r--testsuite/runnable/repeat_loop.elna2
-rw-r--r--testsuite/runnable/return_aggregate.elna2
-rw-r--r--testsuite/runnable/slice_array.elna2
-rw-r--r--testsuite/runnable/slice_cast.elna2
-rw-r--r--testsuite/runnable/slice_equality.elna2
-rw-r--r--testsuite/runnable/slice_pointer.elna2
-rw-r--r--testsuite/runnable/slice_slice.elna2
-rw-r--r--testsuite/runnable/two_fields_same_type.elna2
-rw-r--r--testsuite/runnable/two_parameters_same_type.elna2
-rw-r--r--testsuite/runnable/unary_plus.elna2
-rw-r--r--testsuite/runnable/unicode_escape_character.elna2
-rw-r--r--testsuite/runnable/unicode_escape_string.elna2
90 files changed, 351 insertions, 83 deletions
diff --git a/boot/ast.cc b/boot/ast.cc
index b8647f4..edf1237 100644
--- a/boot/ast.cc
+++ b/boot/ast.cc
@@ -367,10 +367,15 @@ namespace elna::boot
}
if (unit->entry_point.has_value())
{
- traverse_body(this, unit->entry_point.value());
+ visit_entry_point(unit);
}
}
+ void walking_visitor::visit_entry_point(unit *unit)
+ {
+ traverse_body(this, unit->entry_point.value());
+ }
+
void walking_visitor::visit(type_declaration *declaration)
{
declaration->underlying_type().accept(this);
@@ -1033,10 +1038,13 @@ namespace elna::boot
std::vector<type_declaration *>&& types,
std::vector<variable_declaration *>&& variables,
std::vector<procedure_declaration *>&& procedures,
+ std::vector<identifier>&& parameters,
+ const source_position entry_position,
std::optional<procedure_body>&& body)
: node(position),
imports(std::move(imports)), types(std::move(types)), procedures(std::move(procedures)),
- variables(std::move(variables)), entry_point(std::move(body))
+ variables(std::move(variables)), entry_point(std::move(body)),
+ parameters(std::move(parameters)), entry_position(entry_position)
{
}
diff --git a/boot/dependency.cc b/boot/dependency.cc
index 9b52ce9..1eb5953 100644
--- a/boot/dependency.cc
+++ b/boot/dependency.cc
@@ -26,15 +26,23 @@ along with GCC; see the file COPYING3. If not see
namespace elna::boot
{
- circular_import_error::circular_import_error(const source_position position,
- const std::string& module_name)
- : diagnostic(position), module_name(module_name)
+ import_error::import_error(const source_position position,
+ const std::string& module_name, const kind payload)
+ : diagnostic(position), module_name(module_name), m_payload(payload)
{
}
- std::string circular_import_error::what() const
+ std::string import_error::what() const
{
- return "Circular import of module '" + this->module_name + "'";
+ switch (this->m_payload)
+ {
+ case kind::circular:
+ return "Circular import of module '" + this->module_name + "'";
+ case kind::program:
+ return "Module '" + this->module_name + "' is a program and cannot be imported";
+ default:
+ __builtin_unreachable();
+ }
}
read_result read_source(std::istream& entry_point, const target_info& target)
diff --git a/boot/lexer.ll b/boot/lexer.ll
index bebfa67..5da70e5 100644
--- a/boot/lexer.ll
+++ b/boot/lexer.ll
@@ -71,6 +71,7 @@ EXPONENT [eE][+-]?[[:digit:]]+
this->location.step();
}
\n+ {
+ this->location.step();
}
if {
return yy::parser::make_IF(this->location);
diff --git a/boot/name_analysis.cc b/boot/name_analysis.cc
index 77335d1..37c7ced 100644
--- a/boot/name_analysis.cc
+++ b/boot/name_analysis.cc
@@ -1131,6 +1131,7 @@ namespace elna::boot
{
add_error<declaration_format_error>(unit->position(),
declaration_format_error::kind::module_entry);
+ return;
}
else if (unit->parameters.size() == 1)
{
@@ -1150,18 +1151,12 @@ namespace elna::boot
}
this->bag.leave();
- info->position.emplace(unit->position());
+ info->position = unit->entry_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);
- }
+ // A unit has at most one entry point and an imported program is
+ // rejected before its symbols are merged, so this cannot collide.
+ this->bag.enter("", info);
}
}
diff --git a/boot/parser.yy b/boot/parser.yy
index dc1d4e8..ba611b5 100644
--- a/boot/parser.yy
+++ b/boot/parser.yy
@@ -157,7 +157,7 @@ along with GCC; see the file COPYING3. If not see
%type <std::unique_ptr<elna::boot::identifier_definition>> identifier_definition;
%type <std::vector<elna::boot::identifier_definition>> identifier_definitions;
%type <std::vector<std::string>> import_declaration;
-%type <std::vector<elna::boot::identifier>> identifiers;
+%type <std::vector<elna::boot::identifier>> required_identifiers optional_identifiers;
%type <std::vector<elna::boot::import_declaration *>> import_declarations import_part;
%type <std::unique_ptr<elna::boot::array_type_expression>> array_type_expression;
%%
@@ -167,10 +167,11 @@ program:
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" "."
+ | import_part type_part variable_part procedure_part
+ "program" "(" optional_identifiers ")" procedure_body "end" "."
{
boot::unit *tree = new boot::unit(boot::make_position(@$), $1, $2, $3, $4,
- boot::procedure_body({}, std::move($8)));
+ std::move($7), boot::make_position(@5), std::move(*$9));
driver.tree.reset(tree);
}
procedure_body:
@@ -541,7 +542,7 @@ statements:
}
| statement { $$.push_back($1); }
field_declaration:
- identifiers ":" type_expression { $$ = std::make_pair($1, std::shared_ptr<boot::type_expression>($3)); }
+ required_identifiers ":" type_expression { $$ = std::make_pair($1, std::shared_ptr<boot::type_expression>($3)); }
required_fields:
field_declaration ";" required_fields
{
@@ -589,7 +590,7 @@ type_expression:
{
$$ = $2.release();
}
- | "(" identifiers ")"
+ | "(" required_identifiers ")"
{
$$ = new boot::enumeration_type_expression(boot::make_position(@$), $2);
}
@@ -597,13 +598,16 @@ type_expression:
{
$$ = new boot::named_expression(boot::make_position(@$), $1);
}
-identifiers:
- identifier "," identifiers
+required_identifiers:
+ identifier "," required_identifiers
{
$$ = $3;
$$.emplace($$.cbegin(), std::move(*$1));
}
| identifier { $$.emplace_back(std::move(*$1)); }
+optional_identifiers:
+ required_identifiers { $$ = $1; }
+ | %empty {}
variable_declaration:
identifier_definitions ":" type_expression
{
diff --git a/boot/type_check.cc b/boot/type_check.cc
index da60a21..cdc78df 100644
--- a/boot/type_check.cc
+++ b/boot/type_check.cc
@@ -114,6 +114,12 @@ namespace elna::boot
}, this->payload);
}
+ /// The program body is the only callable without a name.
+ static std::string describe_callable(const std::string& identifier)
+ {
+ return identifier.empty() ? "Program body" : "Procedure '" + identifier + "'";
+ }
+
type_mismatch_error::type_mismatch_error(const source_position position,
type actual, payload_type payload)
: diagnostic(position), actual(std::move(actual)), payload(std::move(payload))
@@ -140,12 +146,12 @@ namespace elna::boot
{
if (!this->actual.empty())
{
- return "Procedure '" + payload.identifier
- + "' does not return a value, but return expression has type '"
+ return describe_callable(payload.identifier)
+ + " does not return a value, but return expression has type '"
+ this->actual.to_string() + "'";
}
- return "Procedure '" + payload.identifier
- + "' is expected to return, but does not have a return statement";
+ return describe_callable(payload.identifier)
+ + " is expected to return, but does not have a return statement";
}
else if constexpr (std::is_same_v<T, unary>)
@@ -660,35 +666,41 @@ namespace elna::boot
}
if (declaration->body.has_value())
{
- if (declaration->body.value().return_expression != nullptr)
- {
- const expression *return_expr = declaration->body.value().return_expression;
- type const return_type = this->current_procedure->symbol.return_type.proper_type;
+ check_return(declaration->body.value(), declaration->position(),
+ declaration->identifier.name());
+ this->bag.leave();
+ }
+ this->current_procedure.reset();
+ }
- if (!return_type.empty())
- {
- if (!is_assignable_from(return_type, return_expr->type_decoration))
- {
- add_error<type_mismatch_error>(return_expr->position(),
- return_expr->type_decoration,
- type_mismatch_error::expected_type{ return_type });
- }
- }
- else
- {
- add_error<type_mismatch_error>(return_expr->position(),
- return_expr->type_decoration,
- type_mismatch_error::return_type{ .identifier = declaration->identifier.name() });
- }
- }
- else if (declaration->heading().return_type.proper_type != nullptr)
+ void type_analysis_visitor::check_return(const procedure_body& body,
+ const source_position position, const std::string& name)
+ {
+ const type return_type = this->current_procedure->symbol.return_type.proper_type;
+
+ if (body.return_expression == nullptr)
+ {
+ if (!return_type.empty())
{
- add_error<type_mismatch_error>(declaration->position(), type(),
- type_mismatch_error::return_type{ .identifier = declaration->identifier.name() });
+ add_error<type_mismatch_error>(position, type(),
+ type_mismatch_error::return_type{ .identifier = name });
}
- this->bag.leave();
+ return;
+ }
+ const expression *return_expr = body.return_expression;
+
+ if (return_type.empty())
+ {
+ add_error<type_mismatch_error>(return_expr->position(),
+ return_expr->type_decoration,
+ type_mismatch_error::return_type{ .identifier = name });
+ }
+ else if (!is_assignable_from(return_type, return_expr->type_decoration))
+ {
+ add_error<type_mismatch_error>(return_expr->position(),
+ return_expr->type_decoration,
+ type_mismatch_error::expected_type{ return_type });
}
- this->current_procedure.reset();
}
void type_analysis_visitor::visit(assign_statement *statement)
@@ -714,6 +726,16 @@ namespace elna::boot
}
}
+ void type_analysis_visitor::visit_entry_point(unit *unit)
+ {
+ this->current_procedure = this->bag.lookup("")->is_procedure();
+ this->bag.enter(this->current_procedure->scope);
+ walking_visitor::visit_entry_point(unit);
+ check_return(unit->entry_point.value(), unit->entry_position.value(), "");
+ this->bag.leave();
+ this->current_procedure.reset();
+ }
+
void type_analysis_visitor::visit(variable_declaration *declaration)
{
walking_visitor::visit(declaration);
diff --git a/gcc/gcc/elna-builtins.cc b/gcc/gcc/elna-builtins.cc
index 23315e5..637e37a 100644
--- a/gcc/gcc/elna-builtins.cc
+++ b/gcc/gcc/elna-builtins.cc
@@ -335,8 +335,9 @@ namespace elna::gcc
function_args_iter_next(&parameter_type);
}
DECL_ARGUMENTS(fndecl) = argument_chain;
- // Elna has no exceptions.
- TREE_NOTHROW(fndecl) = 1;
+ // Elna has no exceptions, but an extern procedure is defined elsewhere
+ // and may well be able to unwind.
+ TREE_NOTHROW(fndecl) = static_cast<unsigned>(!info.is_extern());
DECL_EXTERNAL(fndecl) = static_cast<unsigned>(info.is_extern());
// An extern procedure has C linkage whether or not Elna re-exports the name.
TREE_PUBLIC(fndecl) = static_cast<unsigned>(info.exported || info.is_extern());
diff --git a/gcc/gcc/elna-generic.cc b/gcc/gcc/elna-generic.cc
index b527280..9bb1e89 100644
--- a/gcc/gcc/elna-generic.cc
+++ b/gcc/gcc/elna-generic.cc
@@ -259,38 +259,71 @@ namespace elna::gcc
}
if (unit->entry_point.has_value())
{
- tree declaration_type = build_function_type_list(elna_int_type_node,
- elna_int_type_node,
- build_pointer_type(build_pointer_type(unsigned_intQI_type_node)),
- NULL_TREE);
- tree fndecl = build_fn_decl("main", declaration_type);
-
- tree resdecl = build_decl(UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE, integer_type_node);
+ const std::shared_ptr<boot::procedure_info> entry_point = this->bag.lookup("")->is_procedure();
+ const location_t location = get_location(&entry_point->position.value());
+ tree declaration_type = unit->parameters.empty()
+ ? build_function_type_list(integer_type_node, NULL_TREE)
+ : build_function_type_list(integer_type_node,
+ integer_type_node,
+ build_pointer_type(build_pointer_type(char_type_node)),
+ NULL_TREE);
+ // build_fn_decl would mark the declaration artificial, which drops the
+ // source coordinates from the debug information.
+ tree fndecl = build_decl(location, FUNCTION_DECL, get_identifier("main"), declaration_type);
+ TREE_PUBLIC(fndecl) = 1;
+ // Elna has no exceptions.
+ TREE_NOTHROW(fndecl) = 1;
+
+ tree resdecl = build_decl(location, RESULT_DECL, NULL_TREE, integer_type_node);
DECL_CONTEXT(resdecl) = fndecl;
DECL_RESULT(fndecl) = resdecl;
begin_function(fndecl);
+ this->bag.enter(entry_point->scope);
- tree parameter_type = TYPE_ARG_TYPES(declaration_type);
- for (const char *argument_name : std::array<const char *, 2>{ "count", "parameters" })
+ if (!unit->parameters.empty())
{
- tree declaration_tree = build_decl(UNKNOWN_LOCATION, PARM_DECL,
- get_identifier(argument_name), TREE_VALUE(parameter_type));
- DECL_CONTEXT(declaration_tree) = fndecl;
- DECL_ARG_TYPE(declaration_tree) = TREE_VALUE(parameter_type);
-
- this->symbols->enter(argument_name, declaration_tree);
- DECL_ARGUMENTS(fndecl) = chainon(DECL_ARGUMENTS(fndecl), declaration_tree);
- parameter_type = TREE_CHAIN(parameter_type);
+ constexpr std::array<const char *, 2> argument_names{ "$argc", "$argv" };
+ std::array<tree, argument_names.size()> argument_declarations{};
+ tree parameter_type = TYPE_ARG_TYPES(declaration_type);
+
+ for (std::size_t i = 0; i < argument_names.size(); ++i)
+ {
+ tree declaration_tree = build_decl(UNKNOWN_LOCATION, PARM_DECL,
+ get_identifier(argument_names.at(i)), TREE_VALUE(parameter_type));
+ DECL_CONTEXT(declaration_tree) = fndecl;
+ DECL_ARG_TYPE(declaration_tree) = TREE_VALUE(parameter_type);
+ DECL_ARTIFICIAL(declaration_tree) = 1;
+
+ DECL_ARGUMENTS(fndecl) = chainon(DECL_ARGUMENTS(fndecl), declaration_tree);
+ argument_declarations.at(i) = declaration_tree;
+ parameter_type = TREE_CHAIN(parameter_type);
+ }
+ const boot::type& argument_type = entry_point->symbol.parameters.front();
+ tree slice_type = get_inner_alias(argument_type, this->symbols);
+ tree ptr_field = TYPE_FIELDS(slice_type);
+ tree length_field = TREE_CHAIN(ptr_field);
+ tree slice_pointer = fold_convert(TREE_TYPE(ptr_field), argument_declarations.at(1));
+ tree slice_length = fold_convert(TREE_TYPE(length_field), argument_declarations.at(0));
+ tree slice = build_slice(slice_type, slice_pointer, slice_length);
+ const boot::variable_info argument_info(argument_type, false);
+
+ declare_local_variable(unit->parameters.front(), argument_info, slice);
+ }
+ for (boot::variable_declaration *const variable : unit->entry_point->variables)
+ {
+ variable->accept(this);
}
visit_statements(unit->entry_point->statements);
- tree set_result = build2(INIT_EXPR, void_type_node, DECL_RESULT(fndecl),
- integer_zero_node);
+
+ unit->entry_point->return_expression->accept(this);
+ tree return_value = fold_convert(integer_type_node, this->current_expression);
+ tree set_result = build2(INIT_EXPR, void_type_node, DECL_RESULT(fndecl), return_value);
tree return_stmt = build1(RETURN_EXPR, void_type_node, set_result);
append_statement(return_stmt);
this->current_expression = NULL_TREE;
- DECL_EXTERNAL(fndecl) = 0;
+ this->bag.leave();
finish_function(fndecl);
}
}
diff --git a/include/elna/boot/ast.h b/include/elna/boot/ast.h
index c485dc7..4919510 100644
--- a/include/elna/boot/ast.h
+++ b/include/elna/boot/ast.h
@@ -292,6 +292,10 @@ namespace elna::boot
void visit(literal<std::uint32_t> *) override;
void visit(literal<std::nullptr_t> *) override;
void visit(literal<std::string> *) override;
+
+ protected:
+ /// Passes needing the entry point's scope override this.
+ virtual void visit_entry_point(unit *unit);
};
/**
@@ -951,6 +955,7 @@ namespace elna::boot
const std::vector<variable_declaration *> variables;
const std::optional<procedure_body> entry_point;
const std::vector<identifier> parameters;
+ const std::optional<source_position> entry_position;
unit(const source_position position,
std::vector<import_declaration *>&& imports,
@@ -962,6 +967,8 @@ namespace elna::boot
std::vector<type_declaration *>&& types,
std::vector<variable_declaration *>&& variables,
std::vector<procedure_declaration *>&& procedures,
+ std::vector<identifier>&& parameters,
+ const source_position entry_position,
std::optional<procedure_body>&& body);
void accept(parser_visitor *visitor) override;
diff --git a/include/elna/boot/dependency.h b/include/elna/boot/dependency.h
index 9bc1adf..195d37a 100644
--- a/include/elna/boot/dependency.h
+++ b/include/elna/boot/dependency.h
@@ -104,16 +104,27 @@ namespace elna::boot
};
/**
- * An import that closes a cycle, e.g. a module importing itself.
+ * A module that cannot be imported.
*/
- class circular_import_error final : public diagnostic
+ class import_error final : public diagnostic
{
const std::string module_name;
public:
- circular_import_error(const source_position position, const std::string& module_name);
+ enum class kind
+ {
+ /// An import that closes a cycle, e.g. a module importing itself.
+ circular,
+ /// A program has an entry point and is not importable.
+ program
+ };
+
+ import_error(const source_position position, const std::string& module_name, kind payload);
std::string what() const override;
+
+ private:
+ const kind m_payload;
};
/**
@@ -249,6 +260,19 @@ namespace elna::boot
std::vector<std::shared_ptr<symbol_table>> imports;
diagnostic_list circular;
+ if (imported && tree->entry_point.has_value())
+ {
+ diagnostic_list entry_point;
+
+ entry_point.push_back(std::make_unique<import_error>(tree->entry_position.value(),
+ key.stem().string(), import_error::kind::program));
+ result.append(key, std::move(entry_point));
+ this->cache.insert({ key, symbol_bag({}, this->globals) });
+ this->in_progress.erase(key);
+
+ return result;
+ }
+
for (const import_declaration* sub_tree : tree->imports)
{
const std::filesystem::path module_path = loader.resolve(
@@ -256,8 +280,8 @@ namespace elna::boot
if (this->in_progress.contains(module_path))
{
- circular.push_back(std::make_unique<circular_import_error>(sub_tree->position(),
- module_path.stem().string()));
+ circular.push_back(std::make_unique<import_error>(sub_tree->position(),
+ module_path.stem().string(), import_error::kind::circular));
continue;
}
dependency sub = this->compile(module_path, loader, target, true);
diff --git a/include/elna/boot/type_check.h b/include/elna/boot/type_check.h
index 345ef9d..50b9225 100644
--- a/include/elna/boot/type_check.h
+++ b/include/elna/boot/type_check.h
@@ -214,6 +214,11 @@ namespace elna::boot
static bool is_equality_compatible(const type& left, const type& right);
void visit_and_validate_condition(expression& condition);
+ void check_return(const procedure_body& body, const source_position position,
+ const std::string& name);
+
+ protected:
+ void visit_entry_point(unit *unit) override;
public:
explicit type_analysis_visitor(symbol_bag bag, const target_info& target);
diff --git a/source/main.elna b/source/main.elna
index 23fdc97..955f313 100644
--- a/source/main.elna
+++ b/source/main.elna
@@ -825,8 +825,10 @@ begin
stderr := fdopen(2, "w\0".ptr)
return
+program(parameters)
begin
initialize_global_state();
- exit(process(count, parameters))
+return cast(process(cast(parameters.length: Int), parameters.ptr): Word8)
+
end.
diff --git a/testsuite/compilable/assign_record_to_base.elna b/testsuite/compilable/assign_record_to_base.elna
index 7601d06..303bde0 100644
--- a/testsuite/compilable/assign_record_to_base.elna
+++ b/testsuite/compilable/assign_record_to_base.elna
@@ -13,4 +13,6 @@ var
program()
begin
x := y;
+return 0u8
+
end.
diff --git a/testsuite/compilable/const_negation.elna b/testsuite/compilable/const_negation.elna
index cb76e58..82a4cb6 100644
--- a/testsuite/compilable/const_negation.elna
+++ b/testsuite/compilable/const_negation.elna
@@ -6,4 +6,6 @@ program()
begin
assert(x = -5);
assert(y = 5);
+return 0u8
+
end.
diff --git a/testsuite/compilable/const_var_chain.elna b/testsuite/compilable/const_var_chain.elna
index 5a3623f..ad85f48 100644
--- a/testsuite/compilable/const_var_chain.elna
+++ b/testsuite/compilable/const_var_chain.elna
@@ -5,4 +5,6 @@ var
program()
begin
assert(y = 42)
+return 0u8
+
end.
diff --git a/testsuite/compilable/opaque_type.elna b/testsuite/compilable/opaque_type.elna
index fdb2928..c570e0d 100644
--- a/testsuite/compilable/opaque_type.elna
+++ b/testsuite/compilable/opaque_type.elna
@@ -12,4 +12,6 @@ return h
program()
begin
alias := take(handle)
+return 0u8
+
end.
diff --git a/testsuite/compilable/pointer_cast.elna b/testsuite/compilable/pointer_cast.elna
index 3807d69..ad15432 100644
--- a/testsuite/compilable/pointer_cast.elna
+++ b/testsuite/compilable/pointer_cast.elna
@@ -6,4 +6,6 @@ program()
begin
p := c;
c := p
+return 0u8
+
end.
diff --git a/testsuite/compilable/pointer_const_conversion.elna b/testsuite/compilable/pointer_const_conversion.elna
index d2328ae..a5bd297 100644
--- a/testsuite/compilable/pointer_const_conversion.elna
+++ b/testsuite/compilable/pointer_const_conversion.elna
@@ -5,4 +5,6 @@ var
program()
begin
p := @x
+return 0u8
+
end.
diff --git a/testsuite/compilable/take_const_address.elna b/testsuite/compilable/take_const_address.elna
index 71c8e0b..4f82b2a 100644
--- a/testsuite/compilable/take_const_address.elna
+++ b/testsuite/compilable/take_const_address.elna
@@ -5,4 +5,6 @@ var
program()
begin
x := @y
+return 0u8
+
end.
diff --git a/testsuite/compilable/traits_size.elna b/testsuite/compilable/traits_size.elna
index 7ee46f1..f245637 100644
--- a/testsuite/compilable/traits_size.elna
+++ b/testsuite/compilable/traits_size.elna
@@ -10,4 +10,6 @@ begin
assert(s > 0);
assert(as = 10 * cast(#size(Int): Int));
assert(p > 0)
+return 0u8
+
end.
diff --git a/testsuite/fail_compilation/assign_array_length.elna b/testsuite/fail_compilation/assign_array_length.elna
index bf6f96c..92d6769 100644
--- a/testsuite/fail_compilation/assign_array_length.elna
+++ b/testsuite/fail_compilation/assign_array_length.elna
@@ -5,4 +5,6 @@ var
program()
begin
array.length := slice.length (* @Error Cannot assign to a value of type 'const Word', because it is constant or contains constant members *)
+return 0u8
+
end.
diff --git a/testsuite/fail_compilation/assign_const_to_pointer.elna b/testsuite/fail_compilation/assign_const_to_pointer.elna
index 7e26679..50e4a44 100644
--- a/testsuite/fail_compilation/assign_const_to_pointer.elna
+++ b/testsuite/fail_compilation/assign_const_to_pointer.elna
@@ -5,4 +5,6 @@ var
program()
begin
p := @c (* @Error Expected type 'Pointer', but got '\^const Int' *)
+return 0u8
+
end.
diff --git a/testsuite/fail_compilation/assign_from_const_pointer.elna b/testsuite/fail_compilation/assign_from_const_pointer.elna
index 5dc050d..4c383cc 100644
--- a/testsuite/fail_compilation/assign_from_const_pointer.elna
+++ b/testsuite/fail_compilation/assign_from_const_pointer.elna
@@ -5,4 +5,6 @@ var
program()
begin
p := cv (* @Error Expected type 'Pointer', but got 'const Pointer' *)
+return 0u8
+
end.
diff --git a/testsuite/fail_compilation/assign_slice_ptr.elna b/testsuite/fail_compilation/assign_slice_ptr.elna
index 6f09f00..fa3dd22 100644
--- a/testsuite/fail_compilation/assign_slice_ptr.elna
+++ b/testsuite/fail_compilation/assign_slice_ptr.elna
@@ -5,4 +5,6 @@ var
program()
begin
slice.ptr := array.ptr (* @Error Cannot assign to a value of type 'const \^Int', because it is constant or contains constant members *)
+return 0u8
+
end.
diff --git a/testsuite/fail_compilation/assign_to_call_result_field.elna b/testsuite/fail_compilation/assign_to_call_result_field.elna
index 25096ed..50cd135 100644
--- a/testsuite/fail_compilation/assign_to_call_result_field.elna
+++ b/testsuite/fail_compilation/assign_to_call_result_field.elna
@@ -13,4 +13,6 @@ return result
program()
begin
make().x := 5 (* @Error Expression of type 'Int' is not addressable *)
+return 0u8
+
end.
diff --git a/testsuite/fail_compilation/assign_to_slicing.elna b/testsuite/fail_compilation/assign_to_slicing.elna
index 6743e06..92d0dae 100644
--- a/testsuite/fail_compilation/assign_to_slicing.elna
+++ b/testsuite/fail_compilation/assign_to_slicing.elna
@@ -5,4 +5,6 @@ var
program()
begin
s[1 to 2] := t[1 to 2] (* @Error Expression of type '\[\]Int' is not addressable *)
+return 0u8
+
end.
diff --git a/testsuite/fail_compilation/assign_void_call.elna b/testsuite/fail_compilation/assign_void_call.elna
index 381bb06..75f7c6b 100644
--- a/testsuite/fail_compilation/assign_void_call.elna
+++ b/testsuite/fail_compilation/assign_void_call.elna
@@ -7,4 +7,6 @@ return
program()
begin
x := v() (* @Error Expected type 'Int', but the expression has no value *)
+return 0u8
+
end.
diff --git a/testsuite/fail_compilation/case_label_overflow.elna b/testsuite/fail_compilation/case_label_overflow.elna
index 787f043..def83e9 100644
--- a/testsuite/fail_compilation/case_label_overflow.elna
+++ b/testsuite/fail_compilation/case_label_overflow.elna
@@ -9,4 +9,6 @@ begin
else
assert(false)
end
+return 0u8
+
end.
diff --git a/testsuite/fail_compilation/case_non_constant.elna b/testsuite/fail_compilation/case_non_constant.elna
index a446c29..0345653 100644
--- a/testsuite/fail_compilation/case_non_constant.elna
+++ b/testsuite/fail_compilation/case_non_constant.elna
@@ -14,4 +14,6 @@ begin
case x of
r: (* @Error Case label must be a constant expression *)
end
+return 0u8
+
end.
diff --git a/testsuite/fail_compilation/case_type_mismatch.elna b/testsuite/fail_compilation/case_type_mismatch.elna
index 57afd1f..56be244 100644
--- a/testsuite/fail_compilation/case_type_mismatch.elna
+++ b/testsuite/fail_compilation/case_type_mismatch.elna
@@ -7,4 +7,6 @@ begin
1: (* ok *)
| true: (* @Error Invalid operands of type 'Int' and 'Bool' for operator = *)
end
+return 0u8
+
end.
diff --git a/testsuite/fail_compilation/case_unique_label.elna b/testsuite/fail_compilation/case_unique_label.elna
index 7ee8391..95d5f53 100644
--- a/testsuite/fail_compilation/case_unique_label.elna
+++ b/testsuite/fail_compilation/case_unique_label.elna
@@ -5,4 +5,6 @@ begin
| 3:
| 1 + 2: (* @Error Duplicate case label *)
end
+return 0u8
+
end.
diff --git a/testsuite/fail_compilation/compare_unrelated_records.elna b/testsuite/fail_compilation/compare_unrelated_records.elna
index 1699406..4b04aa7 100644
--- a/testsuite/fail_compilation/compare_unrelated_records.elna
+++ b/testsuite/fail_compilation/compare_unrelated_records.elna
@@ -15,4 +15,6 @@ var
program()
begin
ok := b = a (* @Error Invalid operands of type 'B' and 'A' for operator = *)
+return 0u8
+
end.
diff --git a/testsuite/fail_compilation/constant_enum_to_int.elna b/testsuite/fail_compilation/constant_enum_to_int.elna
index 52c31c3..85f6d4c 100644
--- a/testsuite/fail_compilation/constant_enum_to_int.elna
+++ b/testsuite/fail_compilation/constant_enum_to_int.elna
@@ -8,4 +8,6 @@ var
program()
begin
y := x[Enumeration.one to Enumeration.two] (* @Error Array index must be an integral type, but got 'Enumeration' *)
+return 0u8
+
end.
diff --git a/testsuite/fail_compilation/import_local_collision/sut.elna b/testsuite/fail_compilation/import_local_collision/sut.elna
index 8b52586..ecac1ca 100644
--- a/testsuite/fail_compilation/import_local_collision/sut.elna
+++ b/testsuite/fail_compilation/import_local_collision/sut.elna
@@ -4,5 +4,6 @@ var
X: Int (* @Error Symbol 'X' has been already defined *)
program()
+return 0u8
end.
diff --git a/testsuite/fail_compilation/non_constant_array_dimension.elna b/testsuite/fail_compilation/non_constant_array_dimension.elna
index e3661c7..8efb9e9 100644
--- a/testsuite/fail_compilation/non_constant_array_dimension.elna
+++ b/testsuite/fail_compilation/non_constant_array_dimension.elna
@@ -7,4 +7,6 @@ begin
program()
begin
f(5)
+return 0u8
+
end.
diff --git a/testsuite/fail_compilation/opaque_pointer_arithmetic.elna b/testsuite/fail_compilation/opaque_pointer_arithmetic.elna
index 0223cc8..cb3a20e 100644
--- a/testsuite/fail_compilation/opaque_pointer_arithmetic.elna
+++ b/testsuite/fail_compilation/opaque_pointer_arithmetic.elna
@@ -7,4 +7,6 @@ var
program()
begin
p := p + 1 (* @Error Opaque type 'Handle' cannot be used as an element type in pointer arithmetic *)
+return 0u8
+
end.
diff --git a/testsuite/fail_compilation/proc_type_without_parameters.elna b/testsuite/fail_compilation/proc_type_without_parameters.elna
index 3868e1b..f7cdffe 100644
--- a/testsuite/fail_compilation/proc_type_without_parameters.elna
+++ b/testsuite/fail_compilation/proc_type_without_parameters.elna
@@ -7,4 +7,6 @@ return
program()
begin
x := f (* @Error Expected type 'Int', but got 'proc\(\)' *)
+return 0u8
+
end.
diff --git a/testsuite/fail_compilation/program_arguments.elna b/testsuite/fail_compilation/program_arguments.elna
new file mode 100644
index 0000000..e614368
--- /dev/null
+++ b/testsuite/fail_compilation/program_arguments.elna
@@ -0,0 +1,4 @@
+program(first, second) (* @Error Program entry point should have no or one argument *)
+return 0u8
+
+end.
diff --git a/testsuite/fail_compilation/record-base-cycle-indirect.elna b/testsuite/fail_compilation/record-base-cycle-indirect.elna
index 1ea6ca5..f60b1aa 100644
--- a/testsuite/fail_compilation/record-base-cycle-indirect.elna
+++ b/testsuite/fail_compilation/record-base-cycle-indirect.elna
@@ -11,4 +11,6 @@ var
program()
begin
+return 0u8
+
end.
diff --git a/testsuite/fail_compilation/record_base_constructor_type_mismatch.elna b/testsuite/fail_compilation/record_base_constructor_type_mismatch.elna
index fbba47c..621a06c 100644
--- a/testsuite/fail_compilation/record_base_constructor_type_mismatch.elna
+++ b/testsuite/fail_compilation/record_base_constructor_type_mismatch.elna
@@ -12,4 +12,6 @@ var
program()
begin
c := Child{a: "wrong", b: 9} (* @Error Expected type 'Int', but got '\[\]const Word8' *)
+return 0u8
+
end.
diff --git a/testsuite/fail_compilation/reference_call_result_field.elna b/testsuite/fail_compilation/reference_call_result_field.elna
index 2a721f4..d339ed9 100644
--- a/testsuite/fail_compilation/reference_call_result_field.elna
+++ b/testsuite/fail_compilation/reference_call_result_field.elna
@@ -16,4 +16,6 @@ return result
program()
begin
p := @make().x (* @Error Expression of type 'Int' is not addressable *)
+return 0u8
+
end.
diff --git a/testsuite/fail_compilation/reference_literal.elna b/testsuite/fail_compilation/reference_literal.elna
index 1eef82f..26d5a22 100644
--- a/testsuite/fail_compilation/reference_literal.elna
+++ b/testsuite/fail_compilation/reference_literal.elna
@@ -4,4 +4,6 @@ var
program()
begin
p := @5 (* @Error Expression of type 'Int' is not addressable *)
+return 0u8
+
end.
diff --git a/testsuite/fail_compilation/reference_slicing.elna b/testsuite/fail_compilation/reference_slicing.elna
index 078b48a..3875a5d 100644
--- a/testsuite/fail_compilation/reference_slicing.elna
+++ b/testsuite/fail_compilation/reference_slicing.elna
@@ -5,4 +5,6 @@ var
program()
begin
p := @s[1 to 2] (* @Error Expression of type '\[\]Int' is not addressable *)
+return 0u8
+
end.
diff --git a/testsuite/fail_compilation/while_condition.elna b/testsuite/fail_compilation/while_condition.elna
index bd54796..0e4aa3c 100644
--- a/testsuite/fail_compilation/while_condition.elna
+++ b/testsuite/fail_compilation/while_condition.elna
@@ -2,4 +2,6 @@ program()
begin
while 1 do (* @Error Condition must be a boolean expression, but got 'Int' *)
end
+return 0u8
+
end.
diff --git a/testsuite/runnable/aggregate_argument.elna b/testsuite/runnable/aggregate_argument.elna
index 7aa6ea0..b36ccc3 100644
--- a/testsuite/runnable/aggregate_argument.elna
+++ b/testsuite/runnable/aggregate_argument.elna
@@ -10,4 +10,6 @@ return r.a = 1 & r.b = 2
program()
begin
assert(f(R{a: 1, b: 2}))
+return 0u8
+
end.
diff --git a/testsuite/runnable/aggregate_equality.elna b/testsuite/runnable/aggregate_equality.elna
index b8da9e9..be7b4f1 100644
--- a/testsuite/runnable/aggregate_equality.elna
+++ b/testsuite/runnable/aggregate_equality.elna
@@ -10,4 +10,6 @@ return R{a: 1, b: 2} = R{a: 1, b: 2}
program()
begin
assert(f())
+return 0u8
+
end.
diff --git a/testsuite/runnable/array_constructor.elna b/testsuite/runnable/array_constructor.elna
index aa1c43c..50d243a 100644
--- a/testsuite/runnable/array_constructor.elna
+++ b/testsuite/runnable/array_constructor.elna
@@ -9,4 +9,6 @@ begin
a := [5, 6, 7];
assert(a[1] = 5 & a[2] = 6 & a[3] = 7)
+return 0u8
+
end.
diff --git a/testsuite/runnable/binary_literal.elna b/testsuite/runnable/binary_literal.elna
index 6380f24..4f0fc97 100644
--- a/testsuite/runnable/binary_literal.elna
+++ b/testsuite/runnable/binary_literal.elna
@@ -2,4 +2,6 @@ program()
begin
assert(0b11 = 3u);
assert(0B011 = 3u)
+return 0u8
+
end.
diff --git a/testsuite/runnable/case_constant_label.elna b/testsuite/runnable/case_constant_label.elna
index 2402bf7..49fa2c2 100644
--- a/testsuite/runnable/case_constant_label.elna
+++ b/testsuite/runnable/case_constant_label.elna
@@ -11,4 +11,6 @@ begin
| limit: matched := true
end;
assert(matched)
+return 0u8
+
end.
diff --git a/testsuite/runnable/case_else.elna b/testsuite/runnable/case_else.elna
index b5ab3c0..68330da 100644
--- a/testsuite/runnable/case_else.elna
+++ b/testsuite/runnable/case_else.elna
@@ -12,4 +12,6 @@ begin
matched := true
end;
assert(matched)
+return 0u8
+
end.
diff --git a/testsuite/runnable/case_int.elna b/testsuite/runnable/case_int.elna
index ca36fc8..3a446d6 100644
--- a/testsuite/runnable/case_int.elna
+++ b/testsuite/runnable/case_int.elna
@@ -10,4 +10,6 @@ begin
else
assert(false)
end
+return 0u8
+
end.
diff --git a/testsuite/runnable/case_multilabel.elna b/testsuite/runnable/case_multilabel.elna
index 083bdb0..3a042d2 100644
--- a/testsuite/runnable/case_multilabel.elna
+++ b/testsuite/runnable/case_multilabel.elna
@@ -9,4 +9,6 @@ begin
else
assert(false)
end
+return 0u8
+
end.
diff --git a/testsuite/runnable/case_record.elna b/testsuite/runnable/case_record.elna
index 26436ea..25b3eb4 100644
--- a/testsuite/runnable/case_record.elna
+++ b/testsuite/runnable/case_record.elna
@@ -15,4 +15,6 @@ begin
else
assert(false)
end
+return 0u8
+
end.
diff --git a/testsuite/runnable/compile_time_array_access.elna b/testsuite/runnable/compile_time_array_access.elna
index b854635..825e8d5 100644
--- a/testsuite/runnable/compile_time_array_access.elna
+++ b/testsuite/runnable/compile_time_array_access.elna
@@ -5,4 +5,6 @@ var
program()
begin
assert(i = 2)
+return 0u8
+
end.
diff --git a/testsuite/runnable/const_copy.elna b/testsuite/runnable/const_copy.elna
index 32cee67..fde423b 100644
--- a/testsuite/runnable/const_copy.elna
+++ b/testsuite/runnable/const_copy.elna
@@ -10,4 +10,6 @@ return
program()
begin
f()
+return 0u8
+
end.
diff --git a/testsuite/runnable/const_initialization.elna b/testsuite/runnable/const_initialization.elna
index 56a6697..b388845 100644
--- a/testsuite/runnable/const_initialization.elna
+++ b/testsuite/runnable/const_initialization.elna
@@ -8,4 +8,6 @@ return
program()
begin
f()
+return 0u8
+
end.
diff --git a/testsuite/runnable/constant_string_initializer.elna b/testsuite/runnable/constant_string_initializer.elna
index 8fd3b78..0982373 100644
--- a/testsuite/runnable/constant_string_initializer.elna
+++ b/testsuite/runnable/constant_string_initializer.elna
@@ -4,4 +4,6 @@ var
program()
begin
assert(s = "String value")
+return 0u8
+
end.
diff --git a/testsuite/runnable/define_multiple_local_variables.elna b/testsuite/runnable/define_multiple_local_variables.elna
index 72f0874..bd4ba68 100644
--- a/testsuite/runnable/define_multiple_local_variables.elna
+++ b/testsuite/runnable/define_multiple_local_variables.elna
@@ -6,4 +6,6 @@ return a = 5 & b = 5
program()
begin
assert(f())
+return 0u8
+
end.
diff --git a/testsuite/runnable/exported_variable/sut.elna b/testsuite/runnable/exported_variable/sut.elna
index 1fbc6ee..753293d 100644
--- a/testsuite/runnable/exported_variable/sut.elna
+++ b/testsuite/runnable/exported_variable/sut.elna
@@ -3,4 +3,6 @@ import helper
program()
begin
assert(Shared = 42)
+return 0u8
+
end.
diff --git a/testsuite/runnable/fixed_int_max.elna b/testsuite/runnable/fixed_int_max.elna
index f00fd60..7ccf2fb 100644
--- a/testsuite/runnable/fixed_int_max.elna
+++ b/testsuite/runnable/fixed_int_max.elna
@@ -4,4 +4,6 @@ begin
assert(#max(Int16) = 32767i16);
assert(#max(Int32) = 2147483647i32);
assert(#max(Int64) = 9223372036854775807i64)
+return 0u8
+
end.
diff --git a/testsuite/runnable/fixed_int_min.elna b/testsuite/runnable/fixed_int_min.elna
index fd6b110..f9522fd 100644
--- a/testsuite/runnable/fixed_int_min.elna
+++ b/testsuite/runnable/fixed_int_min.elna
@@ -4,4 +4,6 @@ begin
assert(#min(Int16) = -32768i16);
assert(#min(Int32) = -2147483648i32);
assert(#min(Int64) = -9223372036854775808i64)
+return 0u8
+
end.
diff --git a/testsuite/runnable/fixed_word_max.elna b/testsuite/runnable/fixed_word_max.elna
index c657614..8fb8d27 100644
--- a/testsuite/runnable/fixed_word_max.elna
+++ b/testsuite/runnable/fixed_word_max.elna
@@ -4,4 +4,6 @@ begin
assert(#max(Word16) = 65535u16);
assert(#max(Word32) = 4294967295u32);
assert(#max(Word64) = 18446744073709551615u64)
+return 0u8
+
end.
diff --git a/testsuite/runnable/float_arithmetic.elna b/testsuite/runnable/float_arithmetic.elna
index f792b04..e98a26d 100644
--- a/testsuite/runnable/float_arithmetic.elna
+++ b/testsuite/runnable/float_arithmetic.elna
@@ -11,4 +11,6 @@ begin
assert(3.0f * 0.5f = 1.5f);
assert(1.0f / 4.0f = 0.25f);
assert(-3.14f < 0.0f)
+return 0u8
+
end.
diff --git a/testsuite/runnable/for_call.elna b/testsuite/runnable/for_call.elna
index a8401e6..a2fcd06 100644
--- a/testsuite/runnable/for_call.elna
+++ b/testsuite/runnable/for_call.elna
@@ -6,9 +6,12 @@ begin
element^ := 1
return
+program()
begin
for x of actual do
set_element(x)
end;
assert(actual = [1, 1])
+return 0u8
+
end.
diff --git a/testsuite/runnable/for_defer.elna b/testsuite/runnable/for_defer.elna
index 6c9291b..04f0404 100644
--- a/testsuite/runnable/for_defer.elna
+++ b/testsuite/runnable/for_defer.elna
@@ -1,6 +1,7 @@
var
array: [2]Int := [0, 0]
+program()
begin
for x of array do
defer
@@ -8,4 +9,6 @@ begin
end
end;
assert(array = [1, 1])
+return 0u8
+
end.
diff --git a/testsuite/runnable/for_each_array.elna b/testsuite/runnable/for_each_array.elna
index 806a84b..6eae577 100644
--- a/testsuite/runnable/for_each_array.elna
+++ b/testsuite/runnable/for_each_array.elna
@@ -10,4 +10,6 @@ begin
i := i + 1u
end;
assert(actual = [4u, 8u, 12u, 16u])
+return 0u8
+
end.
diff --git a/testsuite/runnable/for_each_slice.elna b/testsuite/runnable/for_each_slice.elna
index ecd3cc3..bfc8b44 100644
--- a/testsuite/runnable/for_each_slice.elna
+++ b/testsuite/runnable/for_each_slice.elna
@@ -13,4 +13,6 @@ begin
i := i + 1u
end;
assert(actual = [4u, 8u, 12u, 16u])
+return 0u8
+
end.
diff --git a/testsuite/runnable/for_with.elna b/testsuite/runnable/for_with.elna
index 582a641..0859ed0 100644
--- a/testsuite/runnable/for_with.elna
+++ b/testsuite/runnable/for_with.elna
@@ -1,10 +1,11 @@
+program()
var
actual: [3]Word := [0u, 0u, 0u]
-
-program()
begin
for element of [1u, 2u, 3u] with i do
actual[i] := i * element^
end;
assert(actual = [1u, 4u, 9u])
+return 0u8
+
end.
diff --git a/testsuite/runnable/generic_pointer_arithmetic.elna b/testsuite/runnable/generic_pointer_arithmetic.elna
index 9aad7d6..fe1e197 100644
--- a/testsuite/runnable/generic_pointer_arithmetic.elna
+++ b/testsuite/runnable/generic_pointer_arithmetic.elna
@@ -11,4 +11,6 @@ begin
second := first + 1;
assert(cast(second : Word) - cast(first : Word) = 1u);
assert(second - 1 = first)
+return 0u8
+
end.
diff --git a/testsuite/runnable/hexadecimal_literal.elna b/testsuite/runnable/hexadecimal_literal.elna
index a168bd2..02bc4c5 100644
--- a/testsuite/runnable/hexadecimal_literal.elna
+++ b/testsuite/runnable/hexadecimal_literal.elna
@@ -2,4 +2,6 @@ program()
begin
assert(0xff = 255u);
assert(0X0f = 15u)
+return 0u8
+
end.
diff --git a/testsuite/runnable/multi_module/sut.elna b/testsuite/runnable/multi_module/sut.elna
index 666f82a..5ad6860 100644
--- a/testsuite/runnable/multi_module/sut.elna
+++ b/testsuite/runnable/multi_module/sut.elna
@@ -3,4 +3,6 @@ import helper
program()
begin
assert(multiply(3, 4) = 12)
+return 0u8
+
end.
diff --git a/testsuite/runnable/procedure_cast.elna b/testsuite/runnable/procedure_cast.elna
index 11e0e72..724fadf 100644
--- a/testsuite/runnable/procedure_cast.elna
+++ b/testsuite/runnable/procedure_cast.elna
@@ -7,4 +7,6 @@ program()
begin
cb := cast(probe_int: proc(x: ^Char) -> Int);
assert(cb(nil) = 42)
+return 0u8
+
end.
diff --git a/testsuite/runnable/record_base_assignment.elna b/testsuite/runnable/record_base_assignment.elna
index 81ee7cf..5f84f20 100644
--- a/testsuite/runnable/record_base_assignment.elna
+++ b/testsuite/runnable/record_base_assignment.elna
@@ -19,4 +19,6 @@ return
program()
begin
f()
+return 0u8
+
end.
diff --git a/testsuite/runnable/record_base_constructor.elna b/testsuite/runnable/record_base_constructor.elna
index 1ca3214..52936e9 100644
--- a/testsuite/runnable/record_base_constructor.elna
+++ b/testsuite/runnable/record_base_constructor.elna
@@ -17,4 +17,6 @@ begin
assert(g.a = 3);
assert(g.b = 5);
assert(g.c = 7)
+return 0u8
+
end.
diff --git a/testsuite/runnable/record_construction.elna b/testsuite/runnable/record_construction.elna
index 31fc21f..ca99859 100644
--- a/testsuite/runnable/record_construction.elna
+++ b/testsuite/runnable/record_construction.elna
@@ -9,4 +9,6 @@ var
program()
begin
assert(r.x = 1 & r.y = 2)
+return 0u8
+
end.
diff --git a/testsuite/runnable/record_extension.elna b/testsuite/runnable/record_extension.elna
index b195759..5f61d60 100644
--- a/testsuite/runnable/record_extension.elna
+++ b/testsuite/runnable/record_extension.elna
@@ -16,4 +16,6 @@ begin
cast(current_token: ^ElnaLexerStringToken)^.value := "Some string";
assert(token_memory.value = "Some string")
+return 0u8
+
end.
diff --git a/testsuite/runnable/record_layout.elna b/testsuite/runnable/record_layout.elna
index b94f18a..6150a32 100644
--- a/testsuite/runnable/record_layout.elna
+++ b/testsuite/runnable/record_layout.elna
@@ -53,4 +53,6 @@ return
program()
begin
f()
+return 0u8
+
end.
diff --git a/testsuite/runnable/recursive_record.elna b/testsuite/runnable/recursive_record.elna
index c940da9..5c59e64 100644
--- a/testsuite/runnable/recursive_record.elna
+++ b/testsuite/runnable/recursive_record.elna
@@ -46,4 +46,6 @@ begin
free(first);
free(second);
free(third)
+return 0u8
+
end.
diff --git a/testsuite/runnable/repeat_loop.elna b/testsuite/runnable/repeat_loop.elna
index ea50884..084b801 100644
--- a/testsuite/runnable/repeat_loop.elna
+++ b/testsuite/runnable/repeat_loop.elna
@@ -9,4 +9,6 @@ begin
actual[i] := i
until i = 4u;
assert(actual = [1u, 2u, 3u, 4u])
+return 0u8
+
end.
diff --git a/testsuite/runnable/return_aggregate.elna b/testsuite/runnable/return_aggregate.elna
index ad3ec65..4377d94 100644
--- a/testsuite/runnable/return_aggregate.elna
+++ b/testsuite/runnable/return_aggregate.elna
@@ -10,4 +10,6 @@ return R{ a: 1, b: 2 }
program()
begin
assert(f() = R{ a: 1, b: 2 })
+return 0u8
+
end.
diff --git a/testsuite/runnable/slice_array.elna b/testsuite/runnable/slice_array.elna
index 2b747ea..7a889a3 100644
--- a/testsuite/runnable/slice_array.elna
+++ b/testsuite/runnable/slice_array.elna
@@ -9,4 +9,6 @@ begin
assert(slice.length = 3u);
assert(slice[1] = 2);
assert(slice[3] = 6)
+return 0u8
+
end.
diff --git a/testsuite/runnable/slice_cast.elna b/testsuite/runnable/slice_cast.elna
index d11f80a..0d4a861 100644
--- a/testsuite/runnable/slice_cast.elna
+++ b/testsuite/runnable/slice_cast.elna
@@ -4,4 +4,6 @@ var
program()
begin
assert(cast(ints[1u to 4u]: []Int8).length = #size(Int32) * ints.length)
+return 0u8
+
end.
diff --git a/testsuite/runnable/slice_equality.elna b/testsuite/runnable/slice_equality.elna
index 08eb4f2..1510f40 100644
--- a/testsuite/runnable/slice_equality.elna
+++ b/testsuite/runnable/slice_equality.elna
@@ -8,4 +8,6 @@ begin
rhs := rhs_payload[1 to 3];
assert(lhs = rhs)
+return 0u8
+
end.
diff --git a/testsuite/runnable/slice_pointer.elna b/testsuite/runnable/slice_pointer.elna
index 6ebcec9..c19e64a 100644
--- a/testsuite/runnable/slice_pointer.elna
+++ b/testsuite/runnable/slice_pointer.elna
@@ -9,4 +9,6 @@ begin
assert(slice.length = 3u);
assert(slice[1] = 2);
assert(slice[3] = 6)
+return 0u8
+
end.
diff --git a/testsuite/runnable/slice_slice.elna b/testsuite/runnable/slice_slice.elna
index 459cf51..fcfea8b 100644
--- a/testsuite/runnable/slice_slice.elna
+++ b/testsuite/runnable/slice_slice.elna
@@ -11,4 +11,6 @@ begin
assert(slice2[1] = 4);
assert(slice2[2] = 6);
assert(slice2[3] = 8)
+return 0u8
+
end.
diff --git a/testsuite/runnable/two_fields_same_type.elna b/testsuite/runnable/two_fields_same_type.elna
index 7d7292d..af591e4 100644
--- a/testsuite/runnable/two_fields_same_type.elna
+++ b/testsuite/runnable/two_fields_same_type.elna
@@ -11,4 +11,6 @@ return r.x + r.y
program()
begin
assert(f() = 5)
+return 0u8
+
end.
diff --git a/testsuite/runnable/two_parameters_same_type.elna b/testsuite/runnable/two_parameters_same_type.elna
index 41d688c..08a1b5a 100644
--- a/testsuite/runnable/two_parameters_same_type.elna
+++ b/testsuite/runnable/two_parameters_same_type.elna
@@ -4,4 +4,6 @@ return x + y
program()
begin
assert(f(2, 3) = 5)
+return 0u8
+
end.
diff --git a/testsuite/runnable/unary_plus.elna b/testsuite/runnable/unary_plus.elna
index e4b3762..7f331d4 100644
--- a/testsuite/runnable/unary_plus.elna
+++ b/testsuite/runnable/unary_plus.elna
@@ -6,4 +6,6 @@ begin
assert(+3 = 3);
assert(f(5) = 5);
assert(f(-7) = -7)
+return 0u8
+
end.
diff --git a/testsuite/runnable/unicode_escape_character.elna b/testsuite/runnable/unicode_escape_character.elna
index 0cfd3e2..f5a4b3f 100644
--- a/testsuite/runnable/unicode_escape_character.elna
+++ b/testsuite/runnable/unicode_escape_character.elna
@@ -2,4 +2,6 @@ program()
begin
assert(`\{U+E9}` = `é`);
assert(`\{U+1F600}` = `😀`)
+return 0u8
+
end.
diff --git a/testsuite/runnable/unicode_escape_string.elna b/testsuite/runnable/unicode_escape_string.elna
index bec794a..20be668 100644
--- a/testsuite/runnable/unicode_escape_string.elna
+++ b/testsuite/runnable/unicode_escape_string.elna
@@ -2,4 +2,6 @@ program()
begin
assert("caf\{U+E9}" = "café");
assert("Hi \{U+1F600}!" = "Hi 😀!")
+return 0u8
+
end.