aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2026-09-02 13:31:04 +0200
committerEugen Wissner <belka@caraus.de>2026-09-07 10:53:02 +0200
commit47521ad6d85f9bd6caee39696ce40dff82cfa50d (patch)
treecf5813033a440c6ac374948894d5dd70e0712cdb
parent0fada11e99da430e9a056e46da9f0e110df6c45c (diff)
downloadelna-47521ad6d85f9bd6caee39696ce40dff82cfa50d.tar.gz
Implement program entry point
-rw-r--r--boot/ast.cc59
-rw-r--r--boot/lexer.ll3
-rw-r--r--boot/name_analysis.cc183
-rw-r--r--boot/parser.yy53
-rw-r--r--boot/type_check.cc5
-rw-r--r--boot/validation.cc9
-rw-r--r--gcc/gcc/elna-generic.cc6
-rw-r--r--include/elna/boot/ast.h19
-rw-r--r--include/elna/boot/name_analysis.h15
-rw-r--r--include/elna/boot/type_check.h1
-rw-r--r--testsuite/compilable/assign_record_to_base.elna1
-rw-r--r--testsuite/compilable/const_alias.elna1
-rw-r--r--testsuite/compilable/const_element_array.elna1
-rw-r--r--testsuite/compilable/const_extern.elna1
-rw-r--r--testsuite/compilable/const_negation.elna1
-rw-r--r--testsuite/compilable/const_var_chain.elna1
-rw-r--r--testsuite/compilable/empty_proc_type_expression.elna4
-rw-r--r--testsuite/compilable/opaque_type.elna1
-rw-r--r--testsuite/compilable/pointer_cast.elna3
-rw-r--r--testsuite/compilable/pointer_const_conversion.elna1
-rw-r--r--testsuite/compilable/self-referencing-record.elna1
-rw-r--r--testsuite/compilable/take_const_address.elna1
-rw-r--r--testsuite/compilable/traits_size.elna1
-rw-r--r--testsuite/fail_compilation/assign_array_length.elna1
-rw-r--r--testsuite/fail_compilation/assign_const_to_pointer.elna1
-rw-r--r--testsuite/fail_compilation/assign_from_const_pointer.elna1
-rw-r--r--testsuite/fail_compilation/assign_slice_ptr.elna1
-rw-r--r--testsuite/fail_compilation/assign_to_call_result_field.elna1
-rw-r--r--testsuite/fail_compilation/assign_to_slicing.elna1
-rw-r--r--testsuite/fail_compilation/assign_void_call.elna1
-rw-r--r--testsuite/fail_compilation/case_label_overflow.elna1
-rw-r--r--testsuite/fail_compilation/case_non_constant.elna1
-rw-r--r--testsuite/fail_compilation/case_type_mismatch.elna1
-rw-r--r--testsuite/fail_compilation/case_unique_label.elna1
-rw-r--r--testsuite/fail_compilation/compare_unrelated_records.elna1
-rw-r--r--testsuite/fail_compilation/constant_enum_to_int.elna1
-rw-r--r--testsuite/fail_compilation/import_local_collision/helper.elna4
-rw-r--r--testsuite/fail_compilation/import_local_collision/sut.elna3
-rw-r--r--testsuite/fail_compilation/non_constant_array_dimension.elna1
-rw-r--r--testsuite/fail_compilation/opaque_pointer_arithmetic.elna1
-rw-r--r--testsuite/fail_compilation/opaque_slice_element.elna1
-rw-r--r--testsuite/fail_compilation/pointer-cycle.elna1
-rw-r--r--testsuite/fail_compilation/proc_type_without_parameters.elna1
-rw-r--r--testsuite/fail_compilation/procedure-cycle.elna1
-rw-r--r--testsuite/fail_compilation/record-base-cycle-indirect.elna1
-rw-r--r--testsuite/fail_compilation/record-base-cycle.elna1
-rw-r--r--testsuite/fail_compilation/record_base_constructor_type_mismatch.elna1
-rw-r--r--testsuite/fail_compilation/record_duplicate_field.elna1
-rw-r--r--testsuite/fail_compilation/record_duplicate_field_import_base/sut.elna1
-rw-r--r--testsuite/fail_compilation/redefined_variable.elna1
-rw-r--r--testsuite/fail_compilation/reference_call_result_field.elna1
-rw-r--r--testsuite/fail_compilation/reference_literal.elna1
-rw-r--r--testsuite/fail_compilation/reference_slicing.elna1
-rw-r--r--testsuite/fail_compilation/slice-cycle.elna1
-rw-r--r--testsuite/fail_compilation/while_condition.elna1
-rw-r--r--testsuite/runnable/aggregate_argument.elna1
-rw-r--r--testsuite/runnable/aggregate_equality.elna1
-rw-r--r--testsuite/runnable/array_constructor.elna1
-rw-r--r--testsuite/runnable/binary_literal.elna1
-rw-r--r--testsuite/runnable/case_constant_label.elna1
-rw-r--r--testsuite/runnable/case_else.elna1
-rw-r--r--testsuite/runnable/case_int.elna1
-rw-r--r--testsuite/runnable/case_multilabel.elna1
-rw-r--r--testsuite/runnable/case_record.elna1
-rw-r--r--testsuite/runnable/compile_time_array_access.elna1
-rw-r--r--testsuite/runnable/const_copy.elna1
-rw-r--r--testsuite/runnable/const_initialization.elna1
-rw-r--r--testsuite/runnable/constant_string_initializer.elna1
-rw-r--r--testsuite/runnable/define_multiple_local_variables.elna1
-rw-r--r--testsuite/runnable/exported_variable/sut.elna1
-rw-r--r--testsuite/runnable/fixed_int_max.elna1
-rw-r--r--testsuite/runnable/fixed_int_min.elna1
-rw-r--r--testsuite/runnable/fixed_word_max.elna1
-rw-r--r--testsuite/runnable/float_arithmetic.elna1
-rw-r--r--testsuite/runnable/for_each_array.elna1
-rw-r--r--testsuite/runnable/for_each_slice.elna1
-rw-r--r--testsuite/runnable/for_with.elna1
-rw-r--r--testsuite/runnable/generic_pointer_arithmetic.elna1
-rw-r--r--testsuite/runnable/hexadecimal_literal.elna1
-rw-r--r--testsuite/runnable/multi_module/sut.elna1
-rw-r--r--testsuite/runnable/procedure_cast.elna1
-rw-r--r--testsuite/runnable/record_base_assignment.elna1
-rw-r--r--testsuite/runnable/record_base_constructor.elna1
-rw-r--r--testsuite/runnable/record_construction.elna1
-rw-r--r--testsuite/runnable/record_extension.elna1
-rw-r--r--testsuite/runnable/record_layout.elna1
-rw-r--r--testsuite/runnable/recursive_record.elna1
-rw-r--r--testsuite/runnable/repeat_loop.elna1
-rw-r--r--testsuite/runnable/return_aggregate.elna1
-rw-r--r--testsuite/runnable/slice_array.elna1
-rw-r--r--testsuite/runnable/slice_cast.elna1
-rw-r--r--testsuite/runnable/slice_equality.elna1
-rw-r--r--testsuite/runnable/slice_pointer.elna1
-rw-r--r--testsuite/runnable/slice_slice.elna1
-rw-r--r--testsuite/runnable/two_fields_same_type.elna2
-rw-r--r--testsuite/runnable/two_parameters_same_type.elna1
-rw-r--r--testsuite/runnable/unary_plus.elna1
-rw-r--r--testsuite/runnable/unicode_escape_character.elna1
-rw-r--r--testsuite/runnable/unicode_escape_string.elna1
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 😀!")