From f7b035a505e86ad916a43ab1dc1a662a6066b011 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Thu, 24 Sep 2026 00:39:51 +0200 Subject: Move module heading to the top --- .clang-tidy | 5 +- boot/ast.cc | 12 +- boot/driver.cc | 25 +-- boot/evaluator.cc | 58 +++--- boot/lexer.ll | 5 +- boot/name_analysis.cc | 166 ++++++++--------- boot/parser.yy | 81 +++++---- boot/result.cc | 10 +- boot/symbol.cc | 112 ++++++------ boot/type_check.cc | 197 +++++++++++---------- boot/validation.cc | 8 +- gcc/gcc/elna-builtins.cc | 34 ++-- gcc/gcc/elna-generic.cc | 35 ++-- gcc/gcc/elna-tree.cc | 5 +- include/elna/boot/ast.h | 8 +- include/elna/boot/dependency.h | 5 +- include/elna/boot/driver.h | 8 +- include/elna/boot/result.h | 24 +-- include/elna/boot/symbol.h | 4 +- include/elna/boot/type_check.h | 6 + source/cctype.elna | 1 + source/command_line_interface.elna | 2 +- source/common.elna | 2 +- source/cstdio.elna | 1 + source/cstdlib.elna | 1 + source/cstring.elna | 1 + source/lexer.elna | 2 +- source/main.elna | 8 +- testsuite/compilable/aliased_type_constant.elna | 2 + testsuite/compilable/assign_record_to_base.elna | 6 +- .../compilable/compile_time_array_length.elna | 2 + testsuite/compilable/const_alias.elna | 2 + testsuite/compilable/const_element_array.elna | 2 + testsuite/compilable/const_extern.elna | 2 + testsuite/compilable/const_negation.elna | 4 +- testsuite/compilable/const_var_chain.elna | 4 +- testsuite/compilable/double_literals.elna | 2 + testsuite/compilable/empty_proc.elna | 2 + .../compilable/empty_proc_type_expression.elna | 2 + .../compilable/empty_statements_in_a_row.elna | 2 + testsuite/compilable/generic_alias.elna | 4 +- testsuite/compilable/generic_arguments.elna | 8 +- testsuite/compilable/generic_base_chain.elna | 4 +- testsuite/compilable/generic_inference.elna | 4 +- testsuite/compilable/opaque_type.elna | 4 +- testsuite/compilable/pointer_cast.elna | 4 +- testsuite/compilable/pointer_const_conversion.elna | 4 +- testsuite/compilable/pointer_subtraction.elna | 2 + .../compilable/procedure_forward_reference.elna | 2 + testsuite/compilable/record_const_base.elna | 2 + testsuite/compilable/self-referencing-record.elna | 2 + .../compilable/semicolon_parameter_separator.elna | 2 + testsuite/compilable/single_literals.elna | 2 + testsuite/compilable/slice_index.elna | 2 + testsuite/compilable/take_const_address.elna | 4 +- testsuite/compilable/trailing_text.elna | 2 + testsuite/compilable/traits_size.elna | 4 +- .../fail_compilation/access_record_type_field.elna | 2 + .../fail_compilation/alias-cycle-behind-const.elna | 3 + testsuite/fail_compilation/alias-cycle.elna | 3 + testsuite/fail_compilation/alias-field-cycle.elna | 3 + testsuite/fail_compilation/aligned_attribute.elna | 6 +- testsuite/fail_compilation/array-cycle.elna | 3 + .../fail_compilation/assign_array_length.elna | 4 +- .../assign_const_array_pointer.elna | 2 + .../fail_compilation/assign_const_element.elna | 2 + .../fail_compilation/assign_const_member.elna | 2 + .../fail_compilation/assign_const_primitive.elna | 2 + .../assign_const_record_pointer.elna | 2 + .../fail_compilation/assign_const_to_pointer.elna | 4 +- .../assign_deep_const_pointer.elna | 2 + .../fail_compilation/assign_element_of_const.elna | 2 + .../assign_from_const_pointer.elna | 4 +- .../fail_compilation/assign_member_of_const.elna | 2 + testsuite/fail_compilation/assign_slice_ptr.elna | 4 +- .../assign_to_call_result_field.elna | 4 +- testsuite/fail_compilation/assign_to_slicing.elna | 4 +- testsuite/fail_compilation/assign_void_call.elna | 4 +- .../fail_compilation/case_label_overflow.elna | 4 +- testsuite/fail_compilation/case_non_constant.elna | 4 +- testsuite/fail_compilation/case_type_mismatch.elna | 4 +- testsuite/fail_compilation/case_unique_label.elna | 2 - .../fail_compilation/circular_import/sut.elna | 2 + .../compare_unrelated_records.elna | 4 +- .../fail_compilation/compile_time_array_ptr.elna | 2 + testsuite/fail_compilation/const_array.elna | 3 +- .../fail_compilation/const_uninitialized.elna | 2 + .../fail_compilation/constant_enum_to_int.elna | 4 +- testsuite/fail_compilation/double_const.elna | 3 +- .../enumeration_member_missing.elna | 2 + testsuite/fail_compilation/float_remainder.elna | 2 + testsuite/fail_compilation/generic_arity.elna | 6 +- .../fail_compilation/generic_base_mismatch.elna | 4 +- .../generic_parameter_arithmetic.elna | 6 +- .../fail_compilation/generic_uninferrable.elna | 8 +- .../import_import_collision/first.elna | 2 + .../import_import_collision/second.elna | 2 + .../import_import_collision/sut.elna | 2 + .../import_local_collision/helper.elna | 2 + .../import_local_collision/sut.elna | 5 +- testsuite/fail_compilation/local_var_exported.elna | 2 + testsuite/fail_compilation/local_var_extern.elna | 2 + .../negative_integer_literal_overflow.elna | 2 + .../non_constant_array_dimension.elna | 8 +- testsuite/fail_compilation/offset_not_record.elna | 4 +- .../opaque_pointer_arithmetic.elna | 4 +- .../fail_compilation/opaque_slice_element.elna | 2 + testsuite/fail_compilation/pointer-cycle.elna | 2 + .../proc_type_without_parameters.elna | 4 +- testsuite/fail_compilation/procedure-cycle.elna | 2 + testsuite/fail_compilation/program_arguments.elna | 2 - .../record-base-cycle-indirect.elna | 6 +- testsuite/fail_compilation/record-base-cycle.elna | 2 + .../record_base_constructor_type_mismatch.elna | 4 +- .../fail_compilation/record_duplicate_field.elna | 2 + .../record_duplicate_field_import_base/helper.elna | 2 + .../record_duplicate_field_import_base/sut.elna | 2 + testsuite/fail_compilation/redefined_variable.elna | 2 + .../reference_call_result_field.elna | 4 +- testsuite/fail_compilation/reference_literal.elna | 4 +- testsuite/fail_compilation/reference_slicing.elna | 4 +- testsuite/fail_compilation/slice-cycle.elna | 2 + .../fail_compilation/unary_minus_on_record.elna | 2 + .../fail_compilation/unary_negation_on_record.elna | 2 + .../fail_compilation/unary_plus_on_record.elna | 2 + testsuite/fail_compilation/varargs_argument.elna | 4 +- testsuite/fail_compilation/varargs_attribute.elna | 3 +- testsuite/fail_compilation/while_condition.elna | 2 - testsuite/runnable/aggregate_argument.elna | 4 +- testsuite/runnable/aggregate_equality.elna | 4 +- testsuite/runnable/aligned_attribute.elna | 4 +- testsuite/runnable/array_constructor.elna | 4 +- testsuite/runnable/binary_literal.elna | 2 - testsuite/runnable/block_local_variable.elna | 3 +- testsuite/runnable/case_constant_label.elna | 4 +- testsuite/runnable/case_else.elna | 4 +- testsuite/runnable/case_int.elna | 4 +- testsuite/runnable/case_multilabel.elna | 4 +- testsuite/runnable/case_record.elna | 4 +- testsuite/runnable/compile_time_array_access.elna | 4 +- testsuite/runnable/const_copy.elna | 4 +- testsuite/runnable/const_initialization.elna | 4 +- .../runnable/constant_string_initializer.elna | 4 +- .../runnable/define_multiple_local_variables.elna | 4 +- testsuite/runnable/exported_variable/helper.elna | 2 + testsuite/runnable/exported_variable/sut.elna | 4 +- testsuite/runnable/fixed_int_max.elna | 2 - testsuite/runnable/fixed_int_min.elna | 2 - testsuite/runnable/fixed_word_max.elna | 2 - testsuite/runnable/float_arithmetic.elna | 2 - testsuite/runnable/float_cast.elna | 4 +- testsuite/runnable/for_call.elna | 4 +- testsuite/runnable/for_defer.elna | 4 +- testsuite/runnable/for_each_array.elna | 4 +- testsuite/runnable/for_each_slice.elna | 4 +- testsuite/runnable/for_with.elna | 3 +- testsuite/runnable/generic_base.elna | 4 +- testsuite/runnable/generic_constructor.elna | 4 +- testsuite/runnable/generic_erasure.elna | 4 +- testsuite/runnable/generic_pointer_arithmetic.elna | 4 +- testsuite/runnable/generic_record.elna | 4 +- testsuite/runnable/hexadecimal_literal.elna | 2 - testsuite/runnable/multi_module/helper.elna | 2 + testsuite/runnable/multi_module/sut.elna | 4 +- testsuite/runnable/named_block.elna | 4 +- testsuite/runnable/procedure_cast.elna | 7 +- testsuite/runnable/record_base_assignment.elna | 4 +- testsuite/runnable/record_base_constructor.elna | 4 +- testsuite/runnable/record_construction.elna | 4 +- testsuite/runnable/record_extension.elna | 4 +- testsuite/runnable/record_layout.elna | 4 +- testsuite/runnable/recursive_record.elna | 4 +- testsuite/runnable/repeat_loop.elna | 4 +- testsuite/runnable/return_aggregate.elna | 4 +- testsuite/runnable/slice_array.elna | 4 +- testsuite/runnable/slice_cast.elna | 4 +- testsuite/runnable/slice_equality.elna | 4 +- testsuite/runnable/slice_pointer.elna | 4 +- testsuite/runnable/slice_slice.elna | 4 +- testsuite/runnable/two_fields_same_type.elna | 4 +- testsuite/runnable/two_parameters_same_type.elna | 5 +- testsuite/runnable/unary_plus.elna | 5 +- testsuite/runnable/unicode_escape_character.elna | 2 - testsuite/runnable/unicode_escape_string.elna | 2 - testsuite/runnable/varargs.elna | 4 +- 185 files changed, 661 insertions(+), 686 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index c5d99db..e447482 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -9,6 +9,7 @@ Checks: | concurrency-*, cert-*, -bugprone-easily-swappable-parameters, + -bugprone-unchecked-optional-access, -misc-include-cleaner, -misc-multiple-inheritance, -misc-non-private-member-variables-in-classes, @@ -18,15 +19,13 @@ Checks: | -readability-else-after-return, -readability-function-cognitive-complexity, -readability-named-parameter, - -bugprone-unchecked-optional-access, + -readability-trailing-comma, -performance-enum-size, -modernize-use-trailing-return-type, -modernize-use-nodiscard, -modernize-pass-by-value, -modernize-use-auto, -modernize-return-braced-init-list, - # False positives: does not see delete inside loop bodies of destructors. - -modernize-use-equals-default, # llvm/llvm-project#213560: fires on every assert() with glibc's variadic macro. -misc-static-assert, diff --git a/boot/ast.cc b/boot/ast.cc index b38e8d1..2d8e90d 100644 --- a/boot/ast.cc +++ b/boot/ast.cc @@ -367,7 +367,10 @@ namespace elna::boot void walking_visitor::visit_entry_point(unit *unit) { - traverse_body(this, unit->entry_point.value()); + for (statement *body_statement : unit->entry_point.value()) + { + body_statement->accept(this); + } } void walking_visitor::visit(type_declaration *declaration) @@ -1121,10 +1124,9 @@ namespace elna::boot std::vector&& declarations, std::vector&& parameters, const source_position entry_position, - std::optional&& body) - : node(position), - imports(std::move(imports)), declarations(std::move(declarations)), entry_point(std::move(body)), - parameters(std::move(parameters)), entry_position(entry_position) + std::vector&& body) + : node(position), imports(std::move(imports)), declarations(std::move(declarations)), + entry_point(std::move(body)), parameters(std::move(parameters)), entry_position(entry_position) { } diff --git a/boot/driver.cc b/boot/driver.cc index 2bcbcb1..14575f7 100644 --- a/boot/driver.cc +++ b/boot/driver.cc @@ -23,9 +23,9 @@ namespace elna::boot { source_position make_position(const yy::location& location) { - auto start_location = boot::location(static_cast(location.begin.line), + const boot::location start_location = boot::location(static_cast(location.begin.line), static_cast(location.begin.column)); - auto end_location = boot::location(static_cast(location.end.line), + const boot::location end_location = boot::location(static_cast(location.end.line), static_cast(location.end.column)); return source_position(start_location, end_location); @@ -41,6 +41,11 @@ namespace elna::boot return message; } + bool driver::has_finished() const + { + return this->tree != nullptr; + } + static char unescape_character(char escape) { switch (escape) @@ -79,19 +84,19 @@ namespace elna::boot constexpr unsigned char utf8_lead_tag_3byte = 0xE0; constexpr unsigned char utf8_lead_tag_4byte = 0xF0; - constexpr int utf8_continuation_bits = 6; - constexpr uint32_t utf8_continuation_mask = 0x3F; + constexpr std::uint32_t utf8_continuation_bits = 6; + constexpr std::uint32_t utf8_continuation_mask = 0x3F; constexpr unsigned char utf8_continuation_tag = 0x80; - constexpr uint32_t utf8_surrogate_range_start = 0xD800; - constexpr uint32_t utf8_surrogate_range_end = 0xDFFF; - constexpr uint32_t utf8_max_unicode_codepoint = 0x10FFFF; + constexpr std::uint32_t utf8_surrogate_range_start = 0xD800; + constexpr std::uint32_t utf8_surrogate_range_end = 0xDFFF; + constexpr std::uint32_t utf8_max_unicode_codepoint = 0x10FFFF; static std::optional encode_utf8(uint32_t codepoint) { - constexpr uint32_t utf8_1byte_max = 0x80; - constexpr uint32_t utf8_2byte_max = 0x800; - constexpr uint32_t utf8_3byte_max = 0x10000; + constexpr std::uint32_t utf8_1byte_max = 0x80; + constexpr std::uint32_t utf8_2byte_max = 0x800; + constexpr std::uint32_t utf8_3byte_max = 0x10000; std::string result; diff --git a/boot/evaluator.cc b/boot/evaluator.cc index 0085c62..6cf287c 100644 --- a/boot/evaluator.cc +++ b/boot/evaluator.cc @@ -66,7 +66,7 @@ namespace elna::boot std::optional get_type_properties(const type& subject, const target_info& target) { - auto resolved = resolve_underlying_type(subject); + const type resolved = resolve_underlying_type(subject); if (resolved.get() != nullptr) { @@ -78,7 +78,7 @@ namespace elna::boot return erased.empty() ? std::nullopt : get_type_properties(erased, target); } - else if (auto resolved_primitive = resolved.get()) + else if (const auto resolved_primitive = resolved.get()) { return resolved_primitive->properties; } @@ -93,7 +93,7 @@ namespace elna::boot { return target.pointer_properties; } - else if (auto array = resolved.get()) + else if (const auto array = resolved.get()) { if (auto element = get_type_properties(array->base, target)) { @@ -103,7 +103,7 @@ namespace elna::boot }; } } - else if (auto record = resolved.get()) + else if (const auto record = resolved.get()) { auto record_layout = layout_record(record, target); if (record_layout.has_value()) @@ -212,7 +212,7 @@ namespace elna::boot { return evaluate_traits(*traits); } - else if (auto *record_constructor = subject.is_record_constructor()) + else if (const auto *record_constructor = subject.is_record_constructor()) { ordered_map aggregate; @@ -227,7 +227,7 @@ namespace elna::boot } return constant_value{ constant_aggregate{ std::move(aggregate) } }; } - else if (auto *array_constructor = subject.is_array_constructor()) + else if (const auto *array_constructor = subject.is_array_constructor()) { std::vector elements; for (expression *element : array_constructor->elements) @@ -275,13 +275,13 @@ namespace elna::boot std::optional evaluator::evaluate_named(named_expression& subject) { - auto symbol = this->bag.lookup(subject.name); + const std::shared_ptr symbol = this->bag.lookup(subject.name); if (symbol == nullptr) { return std::nullopt; } - auto variable = symbol->is_variable(); + const std::shared_ptr variable = symbol->is_variable(); if (variable == nullptr || resolve_aliases(variable->symbol).get() == nullptr) @@ -315,17 +315,17 @@ namespace elna::boot // reading the type decoration set by name analysis. if (auto *base_designator = subject.base().is_designator()) { - if (auto *base_name = base_designator->is_named()) + if (const auto *base_name = base_designator->is_named()) { - auto symbol = this->bag.lookup(base_name->name); + const std::shared_ptr symbol = this->bag.lookup(base_name->name); if (symbol != nullptr) { - if (auto type_symbol = symbol->is_type()) + if (const auto type_symbol = symbol->is_type()) { - if (auto enumeration = resolve_underlying_type(type_symbol->symbol).get()) + if (const auto enumeration = resolve_underlying_type(type_symbol->symbol).get()) { - auto member_iterator = std::ranges::find(enumeration->members, subject.field().name()); + const auto member_iterator = std::ranges::find(enumeration->members, subject.field().name()); if (member_iterator == enumeration->members.end()) { @@ -344,7 +344,7 @@ namespace elna::boot { if (auto *record = std::get_if>(&base.value())) { - auto field_iterator = (*record)->find(subject.field().name()); + const auto field_iterator = (*record)->find(subject.field().name()); return field_iterator != std::cend(**record) ? std::make_optional(field_iterator->second) @@ -355,7 +355,7 @@ namespace elna::boot { return constant_value{ integer_literal::from((*vector)->size()) }; } - else if (auto *string_value = std::get_if(&base.value()); subject.field() == "length") + else if (const auto *string_value = std::get_if(&base.value()); subject.field() == "length") { return constant_value{ integer_literal::from(string_value->size()) }; } @@ -370,7 +370,7 @@ namespace elna::boot { return std::nullopt; } - auto& index_literal = std::get(evaluated_index.value()); + const integer_literal& index_literal = std::get(evaluated_index.value()); return index_literal < 0 ? std::nullopt : index_literal.try_to(); } @@ -389,8 +389,8 @@ namespace elna::boot { return std::nullopt; } - auto slice_begin = std::next((*array)->begin(), static_cast(start_index.value() - 1)); - auto slice_end = std::next((*array)->begin(), static_cast(end_index.value())); + const auto slice_begin = std::next((*array)->begin(), static_cast(start_index.value() - 1)); + const auto slice_end = std::next((*array)->begin(), static_cast(end_index.value())); return constant_value{ constant_aggregate{ std::vector(slice_begin, slice_end) } @@ -687,7 +687,7 @@ namespace elna::boot } return std::visit([&rhs, operation = subject.operation()](auto&& lhs_value) { using T = std::decay_t; - auto rhs_value = std::get(rhs.value()); + const T rhs_value = std::get(rhs.value()); return evaluate_operation(operation, lhs_value, rhs_value); }, lhs.value()); @@ -921,13 +921,11 @@ namespace elna::boot { return source_expression; } - if (const auto *address = std::get_if(&source_expression)) + // Only the null pointer has a constant representation. + else if (const auto *address = std::get_if(&source_expression); + *address == std::ptrdiff_t{ 0 }) { - // Only the null pointer has a constant representation. - if (*address == std::ptrdiff_t{ 0 }) - { - return constant_value{ nullptr }; - } + return constant_value{ nullptr }; } return std::nullopt; } @@ -1056,7 +1054,7 @@ namespace elna::boot { return constant_value{ float_literal::from(std::numeric_limits::min()) }; } - if (auto enumeration = resolved.get()) + if (const auto enumeration = resolved.get()) { return constant_value{ integer_literal::from(1) }; } @@ -1101,22 +1099,22 @@ namespace elna::boot { return constant_value{ float_literal::from(std::numeric_limits::max()) }; } - if (auto enumeration = resolved.get()) + if (const auto enumeration = resolved.get()) { return constant_value{ integer_literal::from(enumeration->members.size()) }; } } else if (subject.name.name() == "offset") { - auto *field = subject.arguments.at(1)->is_named(); - auto record = erase_generic(subject.types.front()).get(); + const named_expression *field = subject.arguments.at(1)->is_named(); + const std::shared_ptr record = erase_generic(subject.types.front()).get(); if (field == nullptr || record == nullptr) { return std::nullopt; } if (auto record_layout = layout_record(record, this->target)) { - auto field_search = record_layout.value().offset_map.find(field->name); + const auto field_search = record_layout.value().offset_map.find(field->name); if (field_search != std::cend(record_layout.value().offset_map)) { diff --git a/boot/lexer.ll b/boot/lexer.ll index 3d881e3..6fa1904 100644 --- a/boot/lexer.ll +++ b/boot/lexer.ll @@ -55,7 +55,7 @@ EXPONENT [eE][+-]?[[:digit:]]+ %% %{ - if (driver.finished) + if (driver.has_finished()) { return yy::parser::make_YYEOF(this->location); } @@ -197,6 +197,9 @@ to { program { return yy::parser::make_PROGRAM(this->location); } +module { + return yy::parser::make_MODULE(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 18aaca2..5d5bd34 100644 --- a/boot/name_analysis.cc +++ b/boot/name_analysis.cc @@ -195,7 +195,7 @@ namespace elna::boot if (is_enum || is_record) { std::string message = is_enum ? "Enumeration" : "Record"; - if (auto alias = this->composite.get()) + if (const auto alias = this->composite.get()) { message += " '" + alias->name + "'"; } @@ -220,7 +220,7 @@ namespace elna::boot const std::string kind = is_enum ? "member" : "field"; std::string message = is_enum ? "Enumeration" : "Record"; - if (auto alias = this->composite.get()) + if (const auto alias = this->composite.get()) { message += " '" + alias->name + "'"; } @@ -267,7 +267,7 @@ namespace elna::boot static void collect_field_names(const type& composite_type, ordered_map& names) { - auto record = erase_generic(composite_type).get(); + const std::shared_ptr record = erase_generic(composite_type).get(); if (record == nullptr) { return; @@ -276,7 +276,7 @@ namespace elna::boot { collect_field_names(record->base, names); } - for (auto& field : record->fields) + for (const auto& field : record->fields) { names.insert(field.first, field_origin{ .position = std::nullopt, .base_type = composite_type }); } @@ -435,7 +435,7 @@ namespace elna::boot if (!existing->second.position.has_value() && !existing->second.base_type.empty()) { - if (auto alias = existing->second.base_type.get()) + if (const auto alias = existing->second.base_type.get()) { base_name = alias->name; } @@ -471,7 +471,7 @@ namespace elna::boot if (!this->bag.enter(name, variable_symbol)) { - auto original = this->bag.lookup(name); + const std::shared_ptr original = this->bag.lookup(name); symbol_declaration_error::redefinition original_definition{ .original = original->position, .file = this->redefinition_file(original) @@ -490,7 +490,7 @@ namespace elna::boot } if (field_name == "ptr") { - auto pointer = type(std::make_shared(element_type)); + const type pointer = type(std::make_shared(element_type)); return type(std::make_shared(pointer)); } return std::nullopt; @@ -506,9 +506,9 @@ namespace elna::boot } const type resolved_type = resolve_underlying_type(composite_type); - if (auto range_base = get_range_base_type(resolved_type)) + if (const auto range_base = get_range_base_type(resolved_type)) { - if (auto field = lookup_pointer_like_field(field_name, range_base)) + if (const auto field = lookup_pointer_like_field(field_name, range_base)) { return field.value(); } @@ -524,18 +524,18 @@ namespace elna::boot for (const identifier& parameter : parameters) { const type parameter_symbol = type(std::make_shared(parameter.name())); - auto info = std::make_shared(parameter_symbol); + const std::shared_ptr info_object = std::make_shared(parameter_symbol); - info->position.emplace(parameter.position()); - info->file = this->module_file; + info_object->position.emplace(parameter.position()); + info_object->file = this->module_file; - if (this->bag.enter(parameter.name(), info)) + if (this->bag.enter(parameter.name(), info_object)) { result.push_back(parameter_symbol); } else { - auto original = this->bag.lookup(parameter.name()); + const std::shared_ptr original = this->bag.lookup(parameter.name()); add_error(parameter.position(), parameter.name(), symbol_declaration_error::redefinition{ @@ -556,7 +556,7 @@ namespace elna::boot // to something other than a type is left to report. if (this->current_type.empty()) { - if (auto *named = expression.is_named(); + if (const auto *named = expression.is_named(); named != nullptr && this->bag.lookup(named->name) != nullptr) { add_error(named->position(), @@ -639,13 +639,13 @@ namespace elna::boot { type base_type; - if (auto unresolved_alias = this->bag.declared(expression->base.value().name())) + if (const auto unresolved_alias = this->bag.declared(expression->base.value().name())) { base_type = type(unresolved_alias); } - else if (auto base_symbol = this->bag.lookup(expression->base.value().name())) + else if (const auto base_symbol = this->bag.lookup(expression->base.value().name())) { - if (auto base_type_info = base_symbol->is_type()) + if (const auto base_type_info = base_symbol->is_type()) { base_type = base_type_info->symbol; } @@ -708,7 +708,7 @@ namespace elna::boot for (const auto& member : expression->members) { - auto existing = seen.find(member.name()); + const std::map::const_iterator existing = seen.find(member.name()); if (existing != seen.end()) { add_error(member.position(), member.name(), aggregate, @@ -799,13 +799,13 @@ namespace elna::boot statement->body.symbols = this->bag.enter(); - auto label_symbol = std::make_shared(this->defer_depth); + const std::shared_ptr label_symbol = std::make_shared(this->defer_depth); label_symbol->position.emplace(statement->name.position()); label_symbol->file = this->module_file; if (!this->bag.enter(label_name, label_symbol)) { - auto original = this->bag.lookup(label_name); + const std::shared_ptr original = this->bag.lookup(label_name); symbol_declaration_error::redefinition original_definition{ .original = original->position, .file = this->redefinition_file(original) @@ -829,7 +829,7 @@ namespace elna::boot symbol_declaration_error::kind::undeclared_label); return; } - auto label_symbol = symbol->is_label(); + const std::shared_ptr label_symbol = symbol->is_label(); if (label_symbol == nullptr) { @@ -867,7 +867,7 @@ namespace elna::boot void resolving_visitor::visit(procedure_call *call) { call->callable().accept(this); - if (auto procedure = call->callable().type_decoration.get()) + if (const auto procedure = call->callable().type_decoration.get()) { call->type_decoration = procedure->return_type.proper_type; } @@ -888,9 +888,9 @@ namespace elna::boot void resolving_visitor::visit(record_constructor_expression *expression) { - if (auto type_symbol = this->bag.lookup(expression->type_name.name())) + if (const auto type_symbol = this->bag.lookup(expression->type_name.name())) { - if (auto type_info = type_symbol->is_type()) + if (const auto type_info = type_symbol->is_type()) { expression->type_decoration = expression->arguments.empty() ? type_info->symbol @@ -918,7 +918,7 @@ namespace elna::boot void resolving_visitor::visit(array_constructor_expression *expression) { - for (auto *element : expression->elements) + for (auto *const element : expression->elements) { element->accept(this); } @@ -931,17 +931,17 @@ namespace elna::boot void resolving_visitor::visit(slicing_expression *expression) { expression->base().accept(this); - auto resolved_base = resolve_underlying_type(expression->base().type_decoration); + const type resolved_base = resolve_underlying_type(expression->base().type_decoration); - if (auto pointer = resolved_base.get()) + if (const auto pointer = resolved_base.get()) { expression->type_decoration = type(std::make_shared(pointer->base)); } - else if (auto array = resolved_base.get()) + else if (const auto array = resolved_base.get()) { expression->type_decoration = type(std::make_shared(array->base)); } - else if (auto slice = resolved_base.get()) + else if (const auto slice = resolved_base.get()) { expression->type_decoration = type(slice); } @@ -1027,21 +1027,21 @@ namespace elna::boot { this->current_type = type(); - if (auto unresolved_alias = this->bag.declared(expression->name)) + if (const auto unresolved_alias = this->bag.declared(expression->name)) { this->current_type = type(unresolved_alias); } - else if (auto from_symbol_table = this->bag.lookup(expression->name)) + else if (const auto from_symbol_table = this->bag.lookup(expression->name)) { - if (auto type_symbol = from_symbol_table->is_type()) + if (const auto type_symbol = from_symbol_table->is_type()) { this->current_type = type_symbol->symbol; } - else if (auto variable_symbol = from_symbol_table->is_variable()) + else if (const auto variable_symbol = from_symbol_table->is_variable()) { expression->type_decoration = variable_symbol->symbol; } - else if (auto procedure_symbol = from_symbol_table->is_procedure()) + else if (const auto procedure_symbol = from_symbol_table->is_procedure()) { type procedure = type(std::make_shared(procedure_symbol->symbol)); @@ -1051,7 +1051,7 @@ namespace elna::boot procedure = substitute(procedure, procedure_symbol->parameters, expression->argument_types); } - expression->type_decoration = procedure; + std::swap(expression->type_decoration, procedure); return; } } @@ -1092,11 +1092,11 @@ namespace elna::boot { expression->base().accept(this); expression->index().accept(this); - auto resolved_base = resolve_underlying_type(expression->base().type_decoration); + const type resolved_base = resolve_underlying_type(expression->base().type_decoration); if (auto range_base = get_range_base_type(resolved_base)) { - expression->type_decoration = range_base; + std::swap(expression->type_decoration, range_base); // Elements of a constant array are constant themselves since a static // array is a holistic type. @@ -1113,11 +1113,11 @@ namespace elna::boot // Handling field access on a type (only valid for enumerations). if (!this->current_type.empty()) { - auto resolved_base = resolve_underlying_type(this->current_type); + const type resolved_base = resolve_underlying_type(this->current_type); - if (auto enumeration_base = resolved_base.get()) + if (const auto enumeration_base = resolved_base.get()) { - auto member_iterator = std::ranges::find(enumeration_base->members, expression->field().name()); + const auto member_iterator = std::ranges::find(enumeration_base->members, expression->field().name()); if (member_iterator == enumeration_base->members.cend()) { @@ -1158,7 +1158,7 @@ namespace elna::boot { expression->base().accept(this); - if (auto pointer = resolve_underlying_type(expression->base().type_decoration).get()) + if (const auto pointer = resolve_underlying_type(expression->base().type_decoration).get()) { expression->type_decoration = pointer->base; } @@ -1251,7 +1251,7 @@ namespace elna::boot * cycle is behind a pointer or a slice, so that the record layout * stays finite. All other cycles are rejected. */ - if (auto link = referent.get()) + if (const auto link = referent.get()) { if (std::ranges::find(alias_path, link->name) != std::cend(alias_path)) { @@ -1270,38 +1270,38 @@ namespace elna::boot } return acyclic; } - else if (auto link = referent.get()) + else if (const auto link = referent.get()) { return find_alias_cycle(being_resolved, link->unqualified, alias_path, state); } - else if (auto link = referent.get()) + else if (const auto link = referent.get()) { walk_state guarded_state = state; guarded_state.guarded = true; return find_alias_cycle(being_resolved, link->base, alias_path, guarded_state); } - else if (auto link = referent.get()) + else if (const auto link = referent.get()) { walk_state guarded_state = state; guarded_state.guarded = true; return find_alias_cycle(being_resolved, link->base, alias_path, guarded_state); } - else if (auto link = referent.get()) + else if (const auto link = referent.get()) { return find_alias_cycle(being_resolved, link->base, alias_path, state); } - else if (auto link = referent.get()) + else if (const auto link = referent.get()) { return find_alias_cycle(being_resolved, link->referent, alias_path, state); } - else if (auto link = referent.get()) + else if (const auto link = referent.get()) { // Erasure is argument blind, so the arguments cannot close a cycle // the generic does not close on its own. This is what lets // polymorphic recursion terminate. return find_alias_cycle(being_resolved, link->generic, alias_path, state); } - else if (auto link = referent.get()) + else if (const auto link = referent.get()) { const std::size_t saved_path = alias_path.size(); @@ -1320,7 +1320,7 @@ namespace elna::boot } return true; } - else if (auto link = referent.get()) + else if (const auto link = referent.get()) { const std::size_t saved_path = alias_path.size(); walk_state in_record = state; @@ -1353,7 +1353,7 @@ namespace elna::boot } if (unit->entry_point.has_value()) { - auto word8_primitive = lookup_primitive_type("Word8"); + const type 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 info; @@ -1385,8 +1385,6 @@ namespace elna::boot info->position = unit->entry_position; info->file = this->module_file; - // 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); } } @@ -1411,23 +1409,22 @@ namespace elna::boot // Reject the cycle and wire an empty referent: the declaration still // resolves and is entered, so its uses degrade silently. - if (auto cycle = find_alias_cycle( - this->bag.declared(declaration->identifier.name()), underlying)) + if (const auto cycle = find_alias_cycle(this->bag.declared(declaration->identifier.name()), underlying)) { add_error(declaration->position(), *cycle); underlying = type(); } const std::shared_ptr resolved = this->bag.resolve(declaration->identifier.name(), underlying); - auto info = std::make_shared(type(resolved)); + const std::shared_ptr info_object = std::make_shared(type(resolved)); - info->exported = declaration->identifier.exported(); - info->position.emplace(declaration->position()); - info->file = this->module_file; + info_object->exported = declaration->identifier.exported(); + info_object->position.emplace(declaration->position()); + info_object->file = this->module_file; - if (!this->bag.enter(declaration->identifier.name(), info)) + if (!this->bag.enter(declaration->identifier.name(), info_object)) { - auto original = this->bag.lookup(declaration->identifier.name()); + const std::shared_ptr original = this->bag.lookup(declaration->identifier.name()); symbol_declaration_error::redefinition original_definition{ .original = original->position, .file = this->redefinition_file(original) @@ -1455,7 +1452,7 @@ namespace elna::boot } else if (!declaration->is_extern && resolve_aliases(variable_type).get() != nullptr) { - auto position_span = source_position( + const source_position position_span = source_position( declaration->identifiers.front().id().position().start(), declaration->identifiers.back().id().position().end()); add_error(position_span, @@ -1463,7 +1460,7 @@ namespace elna::boot } for (const auto& variable_identifier : declaration->identifiers) { - auto variable_symbol = register_variable(variable_identifier.name(), + const std::shared_ptr variable_symbol = register_variable(variable_identifier.name(), variable_type, declaration->position(), declaration->is_extern); variable_symbol->exported = variable_identifier.exported(); variable_symbol->alignment = @@ -1482,18 +1479,19 @@ namespace elna::boot const std::vector type_parameters = enter_parameters(declaration->parameters); auto [heading, parameter_names] = build_procedure(declaration->heading(), !declaration->body.has_value()); - std::shared_ptr info; + std::shared_ptr info_object; if (declaration->body.has_value()) { - info = std::make_shared(heading, std::move(parameter_names), scope); - auto name_iterator = std::cbegin(info->names); - auto type_iterator = std::cbegin(info->symbol.parameters); + info_object = std::make_shared(heading, std::move(parameter_names), scope); + auto name_iterator = std::cbegin(info_object->names); + auto type_iterator = std::cbegin(info_object->symbol.parameters); - while (name_iterator != std::cend(info->names) && type_iterator != std::cend(info->symbol.parameters)) + while (name_iterator != std::cend(info_object->names) + && type_iterator != std::cend(info_object->symbol.parameters)) { - auto variable_symbol = register_variable(*name_iterator, *type_iterator, - declaration->heading().position()); + const std::shared_ptr variable_symbol = + register_variable(*name_iterator, *type_iterator, declaration->heading().position()); ++name_iterator; ++type_iterator; @@ -1501,16 +1499,16 @@ namespace elna::boot } else { - info = std::make_shared(heading, std::move(parameter_names)); + info_object = std::make_shared(heading, std::move(parameter_names)); } this->bag.leave(); - info->parameters = type_parameters; - info->exported = declaration->identifier.exported(); - info->position.emplace(declaration->position()); - info->file = this->module_file; - if (!this->bag.enter(declaration->identifier.name(), info)) + info_object->parameters = type_parameters; + info_object->exported = declaration->identifier.exported(); + info_object->position.emplace(declaration->position()); + info_object->file = this->module_file; + if (!this->bag.enter(declaration->identifier.name(), info_object)) { - auto original = this->bag.lookup(declaration->identifier.name()); + const std::shared_ptr original = this->bag.lookup(declaration->identifier.name()); symbol_declaration_error::redefinition original_definition{ .original = original->position, .file = this->redefinition_file(original) @@ -1541,9 +1539,11 @@ namespace elna::boot { const std::shared_ptr info = this->bag.lookup("")->is_procedure(); - unit->entry_point->symbols = info->scope; this->bag.enter(info->scope); - traverse_body(this, unit->entry_point.value()); + for (statement *body_statement : unit->entry_point.value()) + { + body_statement->accept(this); + } this->bag.leave(); } } @@ -1564,7 +1564,7 @@ namespace elna::boot } else if (resolve_aliases(variable_type).get() != nullptr) { - auto position_span = source_position( + const source_position position_span = source_position( declaration->identifiers.front().id().position().start(), declaration->identifiers.back().id().position().end()); add_error(position_span, @@ -1572,7 +1572,7 @@ namespace elna::boot } for (const auto& variable_identifier : declaration->identifiers) { - auto variable_symbol = register_variable(variable_identifier.name(), + const std::shared_ptr variable_symbol = register_variable(variable_identifier.name(), variable_type, declaration->position(), declaration->is_extern); variable_symbol->exported = variable_identifier.exported(); variable_symbol->alignment = @@ -1598,7 +1598,7 @@ namespace elna::boot void name_analysis_visitor::visit(for_statement *statement) { statement->range().accept(this); - auto resolved_range = resolve_underlying_type(statement->range().type_decoration); + const type resolved_range = resolve_underlying_type(statement->range().type_decoration); const type control_variable_base_type = get_range_base_type(resolved_range); const type control_variable_pointer_type = type(std::make_shared(control_variable_base_type)); const type control_variable_const_type = type(std::make_shared(control_variable_pointer_type)); diff --git a/boot/parser.yy b/boot/parser.yy index 01dfa80..1e732c6 100644 --- a/boot/parser.yy +++ b/boot/parser.yy @@ -95,12 +95,11 @@ along with GCC; see the file COPYING3. If not see EXCLAMATION "!" ARROW "->" AT "@" HAT "^" COLON ":" SEMICOLON ";" DOT "." COMMA "," -%token PROGRAM "program" +%token PROGRAM "program" MODULE "module" CAST "cast" NIL "nil" CONST "const" - VAR "var" - THREADVAR "threadvar" + VAR "var" THREADVAR "threadvar" PROCEDURE "proc" TYPE "type" RECORD "record" @@ -135,7 +134,7 @@ along with GCC; see the file COPYING3. If not see %type switch_case; %type > switch_cases; %type variable_declaration; -%type > variable_declarations variable_part; +%type > variable_declarations; %type type_expression; %type > type_expressions; %type expression operand simple_expression procedure_return unary_expression; @@ -144,14 +143,15 @@ along with GCC; see the file COPYING3. If not see %type designator_expression; %type > call_expression; %type statement; -%type > statements statement_part; +%type > statements statement_part optional_begin_statements; %type block; %type procedure_declaration; %type > procedure_heading; %type return_declaration; %type > type_declaration; -%type > type_declarations; -%type > module_declaration module_declarations; +%type > type_declarations sections section; +%type , std::vector>> + required_declarations optional_declarations; %type > procedure_body; %type field_declaration; %type > field_declarations; @@ -167,31 +167,38 @@ along with GCC; see the file COPYING3. If not see %type > import_declaration; %type > required_identifiers optional_identifiers generic_parameters; %type name_reference; -%type > import_declarations import_part; +%type > import_declarations; %type > array_type_expression; +%type > unit; %% -program: - import_part module_declarations "end" "." +program: unit { - driver.finished = true; + driver.tree = $1; + } +unit: + "module" optional_declarations "end" "." + { + auto [modules, sections] = $2; - boot::unit *tree = new boot::unit(boot::make_position(@$), $1, $2); - driver.tree.reset(tree); + $$ = std::make_unique(boot::make_position(@$), std::move(modules), std::move(sections)); } - | import_part module_declarations - "program" "(" optional_identifiers ")" procedure_body "end" "." + | "program" "(" optional_identifiers ")" required_declarations statement_part "end" "." { - driver.finished = true; + auto [modules, sections] = $5; - boot::unit *tree = new boot::unit(boot::make_position(@$), $1, $2, - std::move($5), boot::make_position(@3), std::move(*$7)); - driver.tree.reset(tree); + $$ = std::make_unique(boot::make_position(@$), std::move(modules), + std::move(sections), $3, boot::make_position(@1), $6); } -module_declaration: + | "program" "(" optional_identifiers ")" optional_begin_statements "end" "." + { + $$ = std::make_unique(boot::make_position(@$), std::vector{}, + std::vector{}, $3, boot::make_position(@1), $5); + } +section: "type" type_declarations { $$ = $2; } - | variable_part + | "var" variable_declarations { - std::vector variables = $1; + std::vector variables = $2; $$.insert($$.end(), variables.begin(), variables.end()); } @@ -206,33 +213,36 @@ module_declaration: $$.insert($$.end(), variables.begin(), variables.end()); } | procedure_declaration { $$.emplace_back($1); } -module_declarations: +required_declarations: + sections { $$ = { {}, $1 }; } + | "import" import_declarations { $$ = { $2, {} }; } + | "import" import_declarations sections { $$ = { $2, $3 }; } +optional_declarations: %empty {} - | module_declaration module_declarations + | required_declarations { $$ = $1; } +sections: + section sections { std::vector appendix = $2; $$ = $1; $$.insert($$.end(), appendix.begin(), appendix.end()); } + | section { $$ = $1; } procedure_body: block procedure_return { $$ = std::make_unique(std::move($1), $2); } - -variable_part: - "var" variable_declarations { $$ = $2; } - block: - variable_part statement_part - { $$ = boot::block(std::move($1), std::move($2)); } - | "begin" statements - { $$ = boot::block(std::vector(), std::move($2)); } - | statements + "var" variable_declarations statement_part + { $$ = boot::block(std::move($2), std::move($3)); } + | optional_begin_statements { $$ = boot::block(std::vector(), std::move($1)); } - statement_part: %empty {} | "begin" statements { $$ = $2; } +optional_begin_statements: + "begin" statements { $$ = $2; } + | statements { $$ = $1; } identifier: IDENTIFIER { $$ = std::make_unique($1, boot::make_position(@1)); } identifier_definition: @@ -739,9 +749,6 @@ import_declarations: { $$.emplace_back(new boot::import_declaration(boot::make_position(@$), $1)); } -import_part: - %empty {} - | "import" import_declarations { $$ = $2; } type_declaration: identifier_definition generic_parameters "=" type_expression { $$ = std::make_unique(boot::make_position(@$), std::move(*$1), $4); diff --git a/boot/result.cc b/boot/result.cc index c8ea267..71326c0 100644 --- a/boot/result.cc +++ b/boot/result.cc @@ -131,7 +131,7 @@ namespace elna::boot std::optional identifier_list_note( const std::vector& identifiers) { - auto position_span = source_position(identifiers.front().position().start(), + const source_position position_span = source_position(identifiers.front().position().start(), identifiers.back().position().end()); return diagnostic_note{ .message = join(identifiers), .position = position_span, .file = {} }; @@ -501,7 +501,7 @@ namespace elna::boot constexpr std::size_t shortest_round_trip = 24; std::array buffer; - auto float_chars = std::to_chars(buffer.begin(), buffer.end(), this->raw); + const std::to_chars_result float_chars = std::to_chars(buffer.begin(), buffer.end(), this->raw); return std::string(buffer.begin(), float_chars.ptr); } @@ -557,7 +557,8 @@ std::size_t std::hash>::operator()( const elna::boot::constant_aggregate& key) const noexcept { const elna::boot::constant_value_hash hasher{}; - auto hash = std::accumulate(key->begin(), key->end(), elna::boot::hash_accumulator{}, + const elna::boot::hash_accumulator hash = std::accumulate(key->begin(), key->end(), + elna::boot::hash_accumulator{}, [&hasher](const auto& accumulator, const auto& element) { return accumulator + hasher(element); }); @@ -569,7 +570,8 @@ std::size_t std::hash>:: const elna::boot::constant_aggregate& key) const noexcept { const elna::boot::constant_value_hash hasher{}; - auto hash = std::accumulate(key->begin(), key->end(), elna::boot::hash_accumulator{}, + const elna::boot::hash_accumulator hash = std::accumulate(key->begin(), key->end(), + elna::boot::hash_accumulator{}, [&hasher](const auto& accumulator, const auto& element) { return accumulator + std::hash{}(element.first) + hasher(element.second); }); diff --git a/boot/symbol.cc b/boot/symbol.cc index 962808a..54cb595 100644 --- a/boot/symbol.cc +++ b/boot/symbol.cc @@ -67,77 +67,80 @@ namespace elna::boot bool type::operator==(const type& other) const { - type const resolved_this = resolve_aliases(*this); - type const resolved_that = resolve_aliases(other); + const type resolved_this = resolve_aliases(*this); + const type resolved_that = resolve_aliases(other); - if (auto left_record = resolved_this.get()) + if (const auto left_record = resolved_this.get()) { return left_record == resolved_that.get(); } - if (auto left_primitive = resolved_this.get()) + else if (const auto left_primitive = resolved_this.get()) { - auto right_primitive = resolved_that.get(); + const std::shared_ptr right_primitive = resolved_that.get(); return right_primitive != nullptr && left_primitive->identifier == right_primitive->identifier; } - if (auto left_enumeration = resolved_this.get()) + else if (const auto left_enumeration = resolved_this.get()) { return left_enumeration == resolved_that.get(); } - if (auto left_extern = resolved_this.get()) + else if (const auto left_extern = resolved_this.get()) { return left_extern == resolved_that.get(); } - if (auto left_pointer = resolved_this.get()) + else if (const auto left_pointer = resolved_this.get()) { - auto right_pointer = resolved_that.get(); + const std::shared_ptr right_pointer = resolved_that.get(); return right_pointer != nullptr && left_pointer->base == right_pointer->base; } - if (auto left_const = resolved_this.get()) + else if (const auto left_const = resolved_this.get()) { - auto right_const = resolved_that.get(); + const std::shared_ptr right_const = resolved_that.get(); return right_const != nullptr && left_const->unqualified == right_const->unqualified; } - if (auto left_array = resolved_this.get()) + else if (const auto left_array = resolved_this.get()) { - auto right_array = resolved_that.get(); + const std::shared_ptr right_array = resolved_that.get(); return right_array != nullptr && left_array->size == right_array->size && left_array->base == right_array->base; } - if (auto left_slice = resolved_this.get()) + else if (const auto left_slice = resolved_this.get()) { - auto right_slice = resolved_that.get(); + const std::shared_ptr right_slice = resolved_that.get(); return right_slice != nullptr && left_slice->base == right_slice->base; } - if (auto left_procedure = resolved_this.get()) + else if (const auto left_procedure = resolved_this.get()) { - auto right_procedure = resolved_that.get(); + const std::shared_ptr right_procedure = resolved_that.get(); return right_procedure != nullptr && left_procedure->return_type == right_procedure->return_type && left_procedure->parameters == right_procedure->parameters && left_procedure->variadic == right_procedure->variadic; } - if (auto left_parameter = resolved_this.get()) + else if (const auto left_parameter = resolved_this.get()) { return left_parameter == resolved_that.get(); } - if (auto left_generic = resolved_this.get()) + else if (const auto left_generic = resolved_this.get()) { return left_generic == resolved_that.get(); } - if (auto left_instance = resolved_this.get()) + else if (const auto left_instance = resolved_this.get()) { - auto right_instance = resolved_that.get(); + const std::shared_ptr right_instance = resolved_that.get(); return right_instance != nullptr && left_instance->generic == right_instance->generic && left_instance->arguments == right_instance->arguments; } - return resolved_this.empty() && resolved_that.empty(); + else + { + return resolved_this.empty() && resolved_that.empty(); + } } type::operator bool() const @@ -378,14 +381,14 @@ namespace elna::boot // matching the machine word. if (bit_size == properties.front().size * CHAR_BIT) { - auto alias = std::make_shared(integer_name, variant_type); + const std::shared_ptr alias = std::make_shared(integer_name, variant_type); symbols->enter(integer_name, std::make_shared(type(alias))); } } if (!symbols->contains(integer_name)) { - auto variant_type = type(std::make_shared(integer_name, properties.front())); + const type variant_type = type(std::make_shared(integer_name, properties.front())); symbols->enter(integer_name, std::make_shared(variant_type)); } @@ -489,14 +492,14 @@ namespace elna::boot std::shared_ptr symbol_bag::declared(const std::string& symbol_name) { - auto unresolved_alias = this->unresolved.find(symbol_name); + const auto unresolved_alias = this->unresolved.find(symbol_name); return unresolved_alias == this->unresolved.end() ? std::shared_ptr() : unresolved_alias->second; } std::shared_ptr symbol_bag::resolve(const std::string& symbol_name, type& resolution) { - auto unresolved_node = this->unresolved.extract(symbol_name); + const auto unresolved_node = this->unresolved.extract(symbol_name); assert(!unresolved_node.empty()); auto unresolved_declaration = unresolved_node.mapped(); @@ -563,7 +566,7 @@ namespace elna::boot { type resolved_alias = resolve_aliases(alias); - if (auto qualified = resolved_alias.get()) + if (const auto qualified = resolved_alias.get()) { return resolve_underlying_type(qualified->unqualified); } @@ -575,7 +578,7 @@ namespace elna::boot type unwrap_aliases(const type& checked) { - if (auto alias = checked.get()) + if (const auto alias = checked.get()) { return unwrap_aliases(alias->referent); } @@ -590,7 +593,7 @@ namespace elna::boot type substitute(const type& subject, const std::vector& parameters, const std::vector& arguments) { - if (auto parameter = subject.get()) + if (const auto parameter = subject.get()) { for (std::size_t i = 0; i < parameters.size() && i < arguments.size(); ++i) { @@ -601,27 +604,27 @@ namespace elna::boot } return subject; } - if (auto pointer = subject.get()) + else if (const auto pointer = subject.get()) { return type(std::make_shared( substitute(pointer->base, parameters, arguments))); } - if (auto slice = subject.get()) + else if (const auto slice = subject.get()) { return type(std::make_shared( substitute(slice->base, parameters, arguments))); } - if (auto array = subject.get()) + else if (const auto array = subject.get()) { return type(std::make_shared( substitute(array->base, parameters, arguments), array->size)); } - if (auto qualified = subject.get()) + else if (const auto qualified = subject.get()) { return type(std::make_shared( substitute(qualified->unqualified, parameters, arguments))); } - if (auto procedure = subject.get()) + else if (const auto procedure = subject.get()) { procedure_type::return_t result_return = procedure->return_type; @@ -630,7 +633,7 @@ namespace elna::boot result_return = procedure_type::return_t( substitute(result_return.proper_type, parameters, arguments)); } - auto result = std::make_shared(std::move(result_return)); + const std::shared_ptr result = std::make_shared(std::move(result_return)); result->variadic = procedure->variadic; result->parameters.reserve(procedure->parameters.size()); @@ -640,7 +643,7 @@ namespace elna::boot } return type(result); } - if (auto instance = subject.get()) + else if (const auto instance = subject.get()) { std::vector substituted; @@ -667,17 +670,20 @@ namespace elna::boot { type resolved = resolve_underlying_type(checked); - if (auto instance = resolved.get()) + if (const auto instance = resolved.get()) { std::shared_ptr const generic = unwrap_generic(instance->generic); return generic == nullptr ? type() : resolve_underlying_type(generic->referent); } - if (auto generic = resolved.get()) + else if (const auto generic = resolved.get()) { return resolve_underlying_type(generic->referent); } - return resolved; + else + { + return resolved; + } } /* @@ -686,13 +692,13 @@ namespace elna::boot */ static type substitute_from(const type& subject, const type& taken) { - auto instance = subject.get(); + const std::shared_ptr instance = subject.get(); if (instance == nullptr) { return taken; } - std::shared_ptr const generic = unwrap_generic(instance->generic); + const std::shared_ptr generic = unwrap_generic(instance->generic); return generic == nullptr ? type() @@ -702,7 +708,7 @@ namespace elna::boot type base_of(const type& derived) { const type resolved = resolve_underlying_type(derived); - auto record = erase_generic(resolved).get(); + const std::shared_ptr record = erase_generic(resolved).get(); return record == nullptr || record->base.empty() ? type() @@ -723,13 +729,13 @@ namespace elna::boot type resolve_aliases(const type& checked) { - if (auto alias = checked.get()) + if (const auto alias = checked.get()) { return resolve_aliases(alias->referent); } - if (auto instance = checked.get()) + else if (const auto instance = checked.get()) { - std::shared_ptr const generic = unwrap_generic(instance->generic); + const std::shared_ptr generic = unwrap_generic(instance->generic); // A record referent makes the instantiation nominal, so resolution // stops here and Stack#[^File] stays distinct from Stack#[^Socket]. @@ -744,7 +750,7 @@ namespace elna::boot bool is_primitive_type(const type& checked, const std::string& name) { - if (auto primitive_checked = checked.get()) + if (const auto primitive_checked = checked.get()) { return primitive_checked->identifier == name; } @@ -753,7 +759,7 @@ namespace elna::boot bool is_integer_type(const type& checked) { - if (auto primitive_checked = checked.get()) + if (const auto primitive_checked = checked.get()) { return primitive_checked->identifier.starts_with("Int"); } @@ -762,7 +768,7 @@ namespace elna::boot bool is_word_type(const type& checked) { - if (auto primitive_checked = checked.get()) + if (const auto primitive_checked = checked.get()) { return primitive_checked->identifier.starts_with("Word"); } @@ -811,9 +817,9 @@ namespace elna::boot bool is_string_type(const type& checked) { - if (auto slice = checked.get()) + if (const auto slice = checked.get()) { - if (auto base = resolve_aliases(slice->base).get()) + if (const auto base = resolve_aliases(slice->base).get()) { return is_primitive_type(resolve_aliases(base->unqualified), "Word8"); } @@ -823,11 +829,11 @@ namespace elna::boot type get_range_base_type(const type& range) { - if (auto array = range.get()) + if (const auto array = range.get()) { return array->base; } - else if (auto slice = range.get()) + else if (const auto slice = range.get()) { return slice->base; } @@ -838,7 +844,7 @@ namespace elna::boot { const type resolved_type = resolve_underlying_type(composite_type); - if (auto record = erase_generic(resolved_type).get()) + if (const auto record = erase_generic(resolved_type).get()) { for (const auto& [name, field] : record->fields) { diff --git a/boot/type_check.cc b/boot/type_check.cc index 5d5bc59..7be236d 100644 --- a/boot/type_check.cc +++ b/boot/type_check.cc @@ -44,7 +44,7 @@ namespace elna::boot __builtin_unreachable(); } - static std::string print_binary_operator(const binary_operator operation) + static std::string_view print_binary_operator(const binary_operator operation) { switch (operation) { @@ -215,7 +215,7 @@ namespace elna::boot { return "Invalid operands of type '" + this->actual.to_string() + "' and '" + payload.right.to_string() - + "' for operator " + print_binary_operator(payload.operation); + + "' for operator " + std::string(print_binary_operator(payload.operation)); } else if constexpr (std::is_same_v) { @@ -345,13 +345,13 @@ namespace elna::boot static bool contains_constant_member(const type& checked) { - auto referent = resolve_aliases(checked); + const type referent = resolve_aliases(checked); if (referent.get() != nullptr) { return true; } - else if (auto record = referent.get()) + else if (const auto record = referent.get()) { for (const auto& [field_name, field] : record->fields) { @@ -363,7 +363,7 @@ namespace elna::boot return !record->base.empty() && contains_constant_member(resolve_underlying_type(record->base)); } - else if (auto array = referent.get()) + else if (const auto array = referent.get()) { return contains_constant_member(array->base); } @@ -385,30 +385,30 @@ namespace elna::boot } const type referent = resolve_aliases(checked); - if (auto record = referent.get()) + if (const auto record = referent.get()) { for (const auto& [field_name, field] : record->fields) { - if (auto opaque = find_opaque_type(field.field_type)) + if (const auto opaque = find_opaque_type(field.field_type)) { return opaque; } } return !record->base.empty() ? find_opaque_type(record->base) : std::nullopt; } - else if (auto array = referent.get()) + else if (const auto array = referent.get()) { return find_opaque_type(array->base); } - else if (auto slice = referent.get()) + else if (const auto slice = referent.get()) { return find_opaque_type(slice->base); } - else if (auto procedure = referent.get()) + else if (const auto procedure = referent.get()) { for (const type& parameter : procedure->parameters) { - if (auto opaque = find_opaque_type(parameter)) + if (const auto opaque = find_opaque_type(parameter)) { return opaque; } @@ -446,7 +446,7 @@ namespace elna::boot { return std::nullopt; } - if (auto pointer = (lhs_integral ? rhs : lhs).get()) + if (const auto pointer = (lhs_integral ? rhs : lhs).get()) { return find_opaque_type(pointer->base); } @@ -456,7 +456,8 @@ namespace elna::boot // Checks whether the type has zero size. static bool has_zero_size(const type& checked, const target_info& target) { - auto properties = get_type_properties(resolve_underlying_type(checked), target); + const std::optional properties = + get_type_properties(resolve_underlying_type(checked), target); return properties.has_value() && properties->size == 0; } @@ -469,7 +470,7 @@ namespace elna::boot { return checked; } - if (auto record = resolve_aliases(checked).get()) + if (const auto record = resolve_aliases(checked).get()) { for (const auto& [field_name, field] : record->fields) { @@ -520,23 +521,18 @@ namespace elna::boot } } - /* - * Checks whether derived has base in its record parent chain. - * - * Base record type must not be null. Derived record type may be null. - */ assign_check::verdict assign_check::guard_const_laundering() const { if (!is_primitive_type(ctx.aliased_assignee, "Pointer")) { return verdict::pass; } - if (auto ptr = ctx.aliased_assignment.get(); + if (const auto ptr = ctx.aliased_assignment.get(); ptr != nullptr && resolve_aliases(ptr->base).get() != nullptr) { return verdict::reject; } - if (auto const_assign = ctx.aliased_assignment.get(); + if (const auto const_assign = ctx.aliased_assignment.get(); const_assign != nullptr && is_primitive_type(const_assign->unqualified, "Pointer")) { return verdict::reject; @@ -566,15 +562,16 @@ namespace elna::boot assign_check::verdict assign_check::check_pointer_conversion() const { - auto assignee_ptr = ctx.resolved_assignee.get(); - auto assignment_ptr = ctx.resolved_assignment.get(); + const std::shared_ptr assignee_ptr = ctx.resolved_assignee.get(); + const std::shared_ptr assignment_ptr = ctx.resolved_assignment.get(); if (assignee_ptr == nullptr || assignment_ptr == nullptr) { return verdict::pass; } - auto assignee_pointee_const = resolve_aliases(assignee_ptr->base).get(); - auto assignment_pointee_const = resolve_aliases(assignment_ptr->base).get(); + const std::shared_ptr assignee_pointee_const = + resolve_aliases(assignee_ptr->base).get(); + const std::shared_ptr assignment_pointee_const = resolve_aliases(assignment_ptr->base).get(); // Constness can be added at the first indirection level, but not removed. if (assignee_pointee_const != nullptr @@ -599,15 +596,17 @@ namespace elna::boot assign_check::verdict assign_check::check_slice_conversion() const { - auto assignee_slice = ctx.resolved_assignee.get(); - auto assignment_slice = ctx.resolved_assignment.get(); + const std::shared_ptr assignee_slice = ctx.resolved_assignee.get(); + const std::shared_ptr assignment_slice = ctx.resolved_assignment.get(); if (assignee_slice == nullptr || assignment_slice == nullptr) { return verdict::pass; } - auto assignee_element_const = resolve_aliases(assignee_slice->base).get(); - auto assignment_element_const = resolve_aliases(assignment_slice->base).get(); + const std::shared_ptr assignee_element_const = + resolve_aliases(assignee_slice->base).get(); + const std::shared_ptr assignment_element_const = + resolve_aliases(assignment_slice->base).get(); // Const can be added to the element type, but not removed. if (assignee_element_const != nullptr @@ -624,16 +623,18 @@ namespace elna::boot assign_check::verdict assign_check::check_array_conversion() const { - auto assignee_array = ctx.resolved_assignee.get(); - auto assignment_array = ctx.resolved_assignment.get(); + const std::shared_ptr assignee_array = ctx.resolved_assignee.get(); + const std::shared_ptr assignment_array = ctx.resolved_assignment.get(); if (assignee_array == nullptr || assignment_array == nullptr || assignee_array->size != assignment_array->size) { return verdict::pass; } - auto assignee_element_const = resolve_aliases(assignee_array->base).get(); - auto assignment_element_const = resolve_aliases(assignment_array->base).get(); + const std::shared_ptr assignee_element_const = + resolve_aliases(assignee_array->base).get(); + const std::shared_ptr assignment_element_const = + resolve_aliases(assignment_array->base).get(); // An array is copied by value, so const can be added to the element type, // but not removed. Writing to such an array is rejected on the lvalue. @@ -651,7 +652,7 @@ namespace elna::boot bool assign_check::run() { - auto const assign_handlers = { + const std::initializer_list assign_handlers = { &assign_check::guard_const_laundering, &assign_check::check_exact_match, &assign_check::check_slice_conversion, @@ -659,7 +660,7 @@ namespace elna::boot &assign_check::check_pointer_hatch, &assign_check::check_pointer_conversion }; - for (auto handler : assign_handlers) + for (const auto handler : assign_handlers) { switch ((this->*handler)()) { @@ -804,7 +805,6 @@ namespace elna::boot 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(); } @@ -815,14 +815,15 @@ namespace elna::boot for (const auto& variable_identifier : declaration->identifiers) { - auto variable_symbol = this->bag.lookup(variable_identifier.name())->is_variable(); + const std::shared_ptr variable_symbol = + this->bag.lookup(variable_identifier.name())->is_variable(); - if (auto opaque = find_opaque_type(variable_symbol->symbol)) + if (const auto opaque = find_opaque_type(variable_symbol->symbol)) { add_error(variable_identifier.id().position(), opaque.value(), type_requirement_error::kind::opaque_variable); } - else if (auto found = find_zero_sized(variable_symbol->symbol, this->target)) + else if (const auto found = find_zero_sized(variable_symbol->symbol, this->target)) { add_error(variable_identifier.id().position(), found.value(), type_requirement_error::kind::zero_sized); @@ -834,7 +835,9 @@ namespace elna::boot } for (const auto& variable_identifier : declaration->identifiers) { - auto variable_symbol = this->bag.lookup(variable_identifier.name())->is_variable(); + const std::shared_ptr variable_symbol = + this->bag.lookup(variable_identifier.name())->is_variable(); + if (!is_assignable_from(variable_symbol->symbol, declaration->initializer->type_decoration)) { add_error(declaration->initializer->position(), @@ -869,7 +872,7 @@ namespace elna::boot void type_analysis_visitor::visit(for_statement *statement) { statement->range().accept(this); - auto resolved_range = resolve_underlying_type(statement->range().type_decoration); + const type resolved_range = resolve_underlying_type(statement->range().type_decoration); if (!get_range_base_type(resolved_range)) { @@ -923,9 +926,10 @@ namespace elna::boot void type_analysis_visitor::visit(type_declaration *declaration) { walking_visitor::visit(declaration); - auto unresolved_type = this->bag.lookup(declaration->identifier.name())->is_type()->symbol.get(); + const std::shared_ptr unresolved_type = + this->bag.lookup(declaration->identifier.name())->is_type()->symbol.get(); - if (auto generic = unresolved_type->referent.get()) + if (const auto generic = unresolved_type->referent.get()) { check_parameters_used(declaration->position(), declaration->identifier.name(), generic->parameters, generic->referent); @@ -933,11 +937,11 @@ namespace elna::boot } const type referent = resolve_aliases(unresolved_type->referent); - if (auto record = referent.get()) + if (const auto record = referent.get()) { for (const auto& [field_name, field] : record->fields) { - if (auto opaque = find_opaque_type(field.field_type)) + if (const auto opaque = find_opaque_type(field.field_type)) { add_error(declaration->position(), opaque.value(), type_requirement_error::kind::opaque_field); @@ -949,27 +953,27 @@ namespace elna::boot } } } - else if (auto array = referent.get()) + else if (const auto array = referent.get()) { - if (auto opaque = find_opaque_type(array->base)) + if (const auto opaque = find_opaque_type(array->base)) { add_error(declaration->position(), opaque.value(), type_requirement_error::kind::opaque_element); } } - else if (auto slice = referent.get()) + else if (const auto slice = referent.get()) { - if (auto opaque = find_opaque_type(slice->base)) + if (const auto opaque = find_opaque_type(slice->base)) { add_error(declaration->position(), opaque.value(), type_requirement_error::kind::opaque_element); } } - else if (auto procedure = referent.get()) + else if (const auto procedure = referent.get()) { for (const type& parameter : procedure->parameters) { - if (auto opaque = find_opaque_type(parameter)) + if (const auto opaque = find_opaque_type(parameter)) { add_error(declaration->position(), opaque.value(), type_requirement_error::kind::opaque_parameter); @@ -982,7 +986,7 @@ namespace elna::boot } if (!procedure->return_type.proper_type.empty()) { - if (auto opaque = find_opaque_type(procedure->return_type.proper_type)) + if (const auto opaque = find_opaque_type(procedure->return_type.proper_type)) { add_error(declaration->position(), opaque.value(), type_requirement_error::kind::opaque_return); @@ -1001,7 +1005,8 @@ namespace elna::boot { if (expression->base.has_value()) { - auto const base_symbol = this->bag.lookup(expression->base.value().name()); + const std::shared_ptr base_symbol = this->bag.lookup(expression->base.value().name()); + if (base_symbol == nullptr || base_symbol->is_type() == nullptr) { add_error(expression->position(), @@ -1009,7 +1014,7 @@ namespace elna::boot } else { - type const base_type = erase_generic(base_symbol->is_type()->symbol); + const type base_type = erase_generic(base_symbol->is_type()->symbol); if (base_type.get() == nullptr) { add_error(expression->position(), @@ -1032,23 +1037,23 @@ namespace elna::boot { return true; } - if (auto pointer = subject.get()) + else if (const auto pointer = subject.get()) { return occurs_in(parameter, pointer->base); } - if (auto slice = subject.get()) + else if (const auto slice = subject.get()) { return occurs_in(parameter, slice->base); } - if (auto array = subject.get()) + else if (const auto array = subject.get()) { return occurs_in(parameter, array->base); } - if (auto qualified = subject.get()) + else if (const auto qualified = subject.get()) { return occurs_in(parameter, qualified->unqualified); } - if (auto record = subject.get()) + else if (const auto record = subject.get()) { for (const auto& [field_name, field] : record->fields) { @@ -1059,7 +1064,7 @@ namespace elna::boot } return !record->base.empty() && occurs_in(parameter, record->base); } - if (auto procedure = subject.get()) + else if (const auto procedure = subject.get()) { for (const type& parameter_type : procedure->parameters) { @@ -1071,7 +1076,7 @@ namespace elna::boot return !procedure->return_type.proper_type.empty() && occurs_in(parameter, procedure->return_type.proper_type); } - if (auto instance = subject.get()) + else if (const auto instance = subject.get()) { for (const type& argument : instance->arguments) { @@ -1112,7 +1117,7 @@ namespace elna::boot const type left = resolve_aliases(declared); const type right = resolve_aliases(actual); - if (auto parameter = left.get()) + if (const auto parameter = left.get()) { for (std::size_t i = 0; i < parameters.size(); ++i) { @@ -1125,40 +1130,40 @@ namespace elna::boot } return true; } - if (auto left_pointer = left.get()) + else if (const auto left_pointer = left.get()) { - auto right_pointer = right.get(); + const std::shared_ptr right_pointer = right.get(); return right_pointer != nullptr && bind_arguments(parameters, bindings, left_pointer->base, right_pointer->base); } - if (auto left_slice = left.get()) + else if (const auto left_slice = left.get()) { - auto right_slice = right.get(); + const std::shared_ptr right_slice = right.get(); return right_slice != nullptr && bind_arguments(parameters, bindings, left_slice->base, right_slice->base); } - if (auto left_array = left.get()) + else if (const auto left_array = left.get()) { - auto right_array = right.get(); + const std::shared_ptr right_array = right.get(); return right_array != nullptr && bind_arguments(parameters, bindings, left_array->base, right_array->base); } - if (auto left_constant = left.get()) + else if (const auto left_constant = left.get()) { - auto right_constant = right.get(); + const std::shared_ptr right_constant = right.get(); return right_constant != nullptr - && bind_arguments(parameters, bindings, - left_constant->unqualified, right_constant->unqualified); + && bind_arguments(parameters, bindings, left_constant->unqualified, right_constant->unqualified); } - if (auto left_instance = left.get()) + else if (const auto left_instance = left.get()) { for (type candidate = right; !candidate.empty(); candidate = base_of(candidate)) { - auto right_instance = resolve_aliases(candidate).get(); + const std::shared_ptr right_instance = + resolve_aliases(candidate).get(); if (right_instance == nullptr || !(left_instance->generic == right_instance->generic) @@ -1178,9 +1183,9 @@ namespace elna::boot } return false; } - if (auto left_procedure = left.get()) + else if (const auto left_procedure = left.get()) { - auto right_procedure = right.get(); + const std::shared_ptr right_procedure = right.get(); if (right_procedure == nullptr || left_procedure->parameters.size() != right_procedure->parameters.size()) @@ -1281,7 +1286,7 @@ namespace elna::boot } const type denoted = expression->type_decoration; - if (auto instance = denoted.get()) + if (const auto instance = denoted.get()) { std::shared_ptr const generic = unwrap_generic(instance->generic); @@ -1404,7 +1409,7 @@ namespace elna::boot { // Inference reads the argument types, so they are decorated // before the parameter types they will be checked against exist. - for (expression *argument : call->arguments) + for (expression *const argument : call->arguments) { argument->accept(this); } @@ -1414,13 +1419,13 @@ namespace elna::boot // Name analysis decorated the call with the declared return // type, which still mentions the parameters inference has // just bound. - if (auto substituted = callable_type.get()) + if (const auto substituted = callable_type.get()) { call->type_decoration = substituted->return_type.proper_type; } } } - if (auto procedure = callable_type.get()) + if (const auto procedure = callable_type.get()) { std::vector::const_iterator argument_iterator = std::cbegin(call->arguments); std::vector::const_iterator type_iterator = std::cbegin(procedure->parameters); @@ -1455,7 +1460,7 @@ namespace elna::boot if (call->arguments.size() < procedure->parameters.size() || (!procedure->variadic && call->arguments.size() > procedure->parameters.size())) { - if (auto *procedure_name = call->callable().is_named()) + if (const auto *procedure_name = call->callable().is_named()) { add_error(call->position(), argument_count_error::kind::call, procedure_name->name, @@ -1480,7 +1485,7 @@ namespace elna::boot void type_analysis_visitor::visit(record_constructor_expression *expression) { - auto record = erase_generic(expression->type_decoration).get(); + const std::shared_ptr record = erase_generic(expression->type_decoration).get(); if (record == nullptr) { @@ -1507,7 +1512,8 @@ namespace elna::boot void type_analysis_visitor::visit(array_constructor_expression *expression) { - auto array = resolve_underlying_type(expression->type_decoration).get(); + const std::shared_ptr array = + resolve_underlying_type(expression->type_decoration).get(); if (array == nullptr) { @@ -1518,7 +1524,7 @@ namespace elna::boot } // The first element of the array literal determines the array type and // does not have to be checked. - for (auto *element : expression->elements | std::views::drop(1)) + for (const auto *element : expression->elements | std::views::drop(1)) { if (!is_assignable_from(array->base, element->type_decoration)) { @@ -1548,7 +1554,7 @@ namespace elna::boot { walking_visitor::visit(expression); - auto resolved_base = resolve_underlying_type(expression->base().type_decoration); + const type resolved_base = resolve_underlying_type(expression->base().type_decoration); if (resolved_base.get() == nullptr && resolved_base.get() == nullptr) { @@ -1566,7 +1572,7 @@ namespace elna::boot { walking_visitor::visit(expression); - auto operation = expression->operation(); + const unary_operator operation = expression->operation(); type const resolved = resolve_underlying_type(expression->operand().type_decoration); if (operation == unary_operator::plus || operation == unary_operator::minus) @@ -1595,14 +1601,11 @@ namespace elna::boot type_mismatch_error::unary{ .operation = operation }); } } - else if (operation == unary_operator::reference) + else if (operation == unary_operator::reference && !is_addressable(expression->operand())) { - if (!is_addressable(expression->operand())) - { - add_error(expression->position(), - expression->operand().type_decoration, - type_requirement_error::kind::not_addressable); - } + add_error(expression->position(), + expression->operand().type_decoration, + type_requirement_error::kind::not_addressable); } } @@ -1634,8 +1637,8 @@ namespace elna::boot opaque.value(), type_requirement_error::kind::opaque_cast); return; } - auto source = resolve_underlying_type(expression->value().type_decoration); - auto target = resolve_underlying_type(expression->type_decoration); + const type source = resolve_underlying_type(expression->value().type_decoration); + const type target = resolve_underlying_type(expression->type_decoration); if (source != target // const cast. && (!is_scalar_type(source) || !is_scalar_type(target)) @@ -1651,7 +1654,7 @@ namespace elna::boot { walking_visitor::visit(expression); - auto operation = expression->operation(); + const binary_operator operation = expression->operation(); type const lhs_resolved = resolve_underlying_type(expression->lhs().type_decoration); type const rhs_resolved = resolve_underlying_type(expression->rhs().type_decoration); bool valid = false; @@ -1804,7 +1807,7 @@ namespace elna::boot add_error(trait->name.position(), trait->name.name(), trait_error::unsupported_type{ trait->types.front() }); } - else if (auto *field = trait->arguments.at(1)->is_named()) + else if (const auto *field = trait->arguments.at(1)->is_named()) { if (erase_generic(trait->types.front()).get() == nullptr) { diff --git a/boot/validation.cc b/boot/validation.cc index facef04..dda3af7 100644 --- a/boot/validation.cc +++ b/boot/validation.cc @@ -64,10 +64,10 @@ namespace elna::boot } if (unit->entry_point.has_value()) { - auto entry_point = this->bag.lookup("")->is_procedure(); + const std::shared_ptr entry_point = this->bag.lookup("")->is_procedure(); this->bag.enter(entry_point->scope); - visit_statements(unit->entry_point->statements); + visit_statements(unit->entry_point.value()); this->bag.leave(); } } @@ -84,7 +84,9 @@ namespace elna::boot { if (declaration->body.has_value()) { - auto procedure = this->bag.lookup(declaration->identifier.name())->is_procedure(); + const std::shared_ptr procedure = + this->bag.lookup(declaration->identifier.name())->is_procedure(); + this->bag.enter(procedure->scope); visit_statements(declaration->body.value().statements); this->bag.leave(); diff --git a/gcc/gcc/elna-builtins.cc b/gcc/gcc/elna-builtins.cc index 0da991a..ee6856d 100644 --- a/gcc/gcc/elna-builtins.cc +++ b/gcc/gcc/elna-builtins.cc @@ -31,6 +31,7 @@ namespace elna::gcc { return boot::type_properties{ .size = static_cast(TYPE_PRECISION(node) / BITS_PER_UNIT), + // NOLINTNEXTLINE(bugprone-signed-bitwise) .alignment = TYPE_ALIGN_UNIT(node) }; } @@ -59,6 +60,7 @@ namespace elna::gcc .bool_properties = { .size = static_cast( (TYPE_PRECISION(elna_bool_type_node) + BITS_PER_UNIT - 1) / BITS_PER_UNIT), + // NOLINTNEXTLINE(bugprone-signed-bitwise) .alignment = TYPE_ALIGN_UNIT(elna_bool_type_node) }, .c_int_properties = get_host_numeric_properties(integer_type_node) @@ -190,14 +192,14 @@ namespace elna::gcc tree get_inner_alias(const boot::type& type, const std::shared_ptr& symbols, tree placeholder) { - if (auto reference = type.get()) + if (const auto reference = type.get()) { tree looked_up = symbols->lookup(reference->identifier); gcc_assert(looked_up != NULL_TREE); return TREE_TYPE(looked_up); } - else if (auto reference = type.get()) + else if (const auto reference = type.get()) { tree composite_type_node = placeholder != NULL_TREE ? placeholder : make_node(RECORD_TYPE); @@ -220,11 +222,11 @@ namespace elna::gcc } return composite_type_node; } - else if (auto reference = type.get()) + else if (const auto reference = type.get()) { return build_enumeration_type(reference->members); } - else if (auto reference = type.get()) + else if (const auto reference = type.get()) { /* * An incomplete type: a record without fields and without layout, @@ -233,17 +235,17 @@ namespace elna::gcc */ return make_node(RECORD_TYPE); } - else if (auto reference = type.get()) + else if (const auto reference = type.get()) { return build_pointer_type(get_inner_alias(reference->base, symbols, placeholder)); } - else if (auto reference = type.get()) + else if (const auto reference = type.get()) { tree base = get_inner_alias(reference->base, symbols, placeholder); return build_static_array_type(base, reference->size); } - else if (auto reference = type.get()) + else if (const auto reference = type.get()) { tree base_type = get_inner_alias(reference->base, symbols, placeholder); tree slice_record = make_node(RECORD_TYPE); @@ -256,18 +258,18 @@ namespace elna::gcc layout_type(slice_record); return type_hash_canon(type_hash_canon_hash(slice_record), slice_record); } - else if (auto reference = type.get()) + else if (const auto reference = type.get()) { tree procedure = build_procedure_type(*reference, symbols); return build_pointer_type(procedure); } - else if (auto reference = type.get()) + else if (const auto reference = type.get()) { tree unqualified = get_inner_alias(reference->unqualified, symbols, placeholder); return build_qualified_type(unqualified, TYPE_QUAL_CONST); } - else if (auto reference = type.get()) + else if (const auto reference = type.get()) { return TREE_TYPE(handle_symbol(reference->name, reference, symbols)); } @@ -275,13 +277,13 @@ namespace elna::gcc { return elna_pointer_type_node; } - else if (auto reference = type.get()) + else if (const auto reference = type.get()) { // Erasure is argument blind, so every instantiation of one generic // shares the tree the generic's own name is bound to. return get_inner_alias(reference->generic, symbols, placeholder); } - else if (auto reference = type.get()) + else if (const auto reference = type.get()) { return get_inner_alias(reference->referent, symbols, placeholder); } @@ -391,7 +393,7 @@ namespace elna::gcc const boot::type_info& info, const std::shared_ptr& symbols) { // The top level symbol table has basic (builtin) types in it which are not aliases. - if (auto alias_type = info.symbol.get()) + if (const auto alias_type = info.symbol.get()) { tree type_declaration = handle_symbol(name, alias_type, symbols); @@ -404,11 +406,11 @@ namespace elna::gcc { for (auto& [symbol_name, symbol_info] : *info_table) { - if (auto type_info = symbol_info->is_type()) + if (const auto type_info = symbol_info->is_type()) { declare_type(symbol_name, *type_info, symbols); } - else if (auto variable_info = symbol_info->is_variable()) + else if (const auto variable_info = symbol_info->is_variable()) { tree declaration_tree = declare_variable(symbol_name, *variable_info, symbols); @@ -422,7 +424,7 @@ namespace elna::gcc set_decl_tls_model(declaration_tree, decl_default_tls_model(declaration_tree)); } } - else if (auto procedure_info = symbol_info->is_procedure()) + else if (const auto procedure_info = symbol_info->is_procedure()) { declare_procedure(symbol_name, *procedure_info, symbols); } diff --git a/gcc/gcc/elna-generic.cc b/gcc/gcc/elna-generic.cc index 46c8edc..034e4ae 100644 --- a/gcc/gcc/elna-generic.cc +++ b/gcc/gcc/elna-generic.cc @@ -106,6 +106,7 @@ namespace elna::gcc pointer.accept(this); tree pointee = get_inner_alias(accessed, this->symbols); + // NOLINTNEXTLINE(bugprone-signed-bitwise) tree qualified = build_qualified_type(pointee, TYPE_QUALS(pointee) | TYPE_QUAL_VOLATILE); tree address = fold_convert_loc(location, build_pointer_type(qualified), prepare_rvalue(this->current_expression)); @@ -200,10 +201,10 @@ namespace elna::gcc expression->value().accept(this); this->current_expression = prepare_rvalue(this->current_expression); const location_t cast_location = get_location(&expression->position()); - auto source_slice = resolve_underlying_type(expression->value().type_decoration) - .get(); - auto target_slice = resolve_underlying_type(expression->type_decoration) - .get(); + const std::shared_ptr source_slice = + resolve_underlying_type(expression->value().type_decoration).get(); + const std::shared_ptr target_slice = + resolve_underlying_type(expression->type_decoration).get(); if (source_slice != nullptr && target_slice != nullptr) { @@ -398,19 +399,13 @@ namespace elna::gcc 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); + visit_statements(unit->entry_point.value()); - 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 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); append_statement(return_stmt); - this->current_expression = NULL_TREE; + this->current_expression = NULL_TREE; this->bag.leave(); finish_function(fndecl); } @@ -428,7 +423,8 @@ namespace elna::gcc const std::string& variable_name = variable_identifier.name(); tree declaration_tree = this->symbols->lookup(variable_name); - auto variable_symbol = this->bag.lookup(variable_name)->is_variable(); + const std::shared_ptr variable_symbol = + this->bag.lookup(variable_name)->is_variable(); if (declaration_tree == NULL_TREE) { @@ -1080,9 +1076,11 @@ namespace elna::gcc tree end_pointer = do_pointer_arithmetic(boot::binary_operator::sum, start_pointer, length, location); enter_scope(); - // Declare control variable with the unqualified type. The constant_type wrapper - // is for semantic checking only, because GENERIC needs to modify the control variable. - auto control_variable_info = statement->body.symbols->lookup(statement->control_variable.name()); + // Declare control variable with the unqualified type. The constant_type + // wrapper is for semantic checking only, because GENERIC needs to modify + // the control variable. + const boot::symbol_table::symbol_ptr control_variable_info = + statement->body.symbols->lookup(statement->control_variable.name()); const boot::variable_info unqualified_info( boot::resolve_underlying_type(control_variable_info->is_variable()->symbol), control_variable_info->is_variable()->is_extern); @@ -1092,7 +1090,8 @@ namespace elna::gcc tree counter_declaration{ NULL_TREE }; if (statement->counter != nullptr) { - auto counter_info = statement->body.symbols->lookup(statement->counter->name()); + const boot::symbol_table::symbol_ptr counter_info = + statement->body.symbols->lookup(statement->counter->name()); counter_declaration = declare_local_variable(*statement->counter, *counter_info->is_variable(), elna_word_one_node); } diff --git a/gcc/gcc/elna-tree.cc b/gcc/gcc/elna-tree.cc index 690cf41..e762b8e 100644 --- a/gcc/gcc/elna-tree.cc +++ b/gcc/gcc/elna-tree.cc @@ -226,6 +226,7 @@ namespace elna::gcc } TYPE_MIN_VALUE(composite_type_node) = DECL_INITIAL(TREE_VALUE(TYPE_VALUES(composite_type_node))); TYPE_UNSIGNED(composite_type_node) = TYPE_UNSIGNED(base_type); + // NOLINTNEXTLINE(bugprone-signed-bitwise) SET_TYPE_ALIGN(composite_type_node, TYPE_ALIGN(base_type)); TYPE_SIZE(composite_type_node) = NULL_TREE; TYPE_PRECISION(composite_type_node) = TYPE_PRECISION(base_type); @@ -261,7 +262,7 @@ namespace elna::gcc if (std::holds_alternative(constant_value)) { - auto literal_value = std::get(constant_value); + const boot::integer_literal literal_value = std::get(constant_value); if (literal_value.is_signed()) { @@ -282,7 +283,7 @@ namespace elna::gcc } else if (std::holds_alternative(constant_value)) { - auto literal = std::get(constant_value); + const boot::float_literal literal = std::get(constant_value); mpfr_t number; mpfr_init2(number, SIGNIFICAND_BITS); diff --git a/include/elna/boot/ast.h b/include/elna/boot/ast.h index 52461e6..4a0cdb0 100644 --- a/include/elna/boot/ast.h +++ b/include/elna/boot/ast.h @@ -687,7 +687,7 @@ namespace elna::boot { expression *return_expression{ nullptr }; - procedure_body(block&& body, expression *return_expression = nullptr); + explicit procedure_body(block&& body, expression *return_expression = nullptr); procedure_body(procedure_body&& that) noexcept = default; virtual ~procedure_body() = default; @@ -1076,7 +1076,7 @@ namespace elna::boot public: const std::vector imports; const std::vector declarations; - std::optional entry_point; + std::optional> entry_point; const std::vector parameters; const std::optional entry_position; @@ -1088,7 +1088,7 @@ namespace elna::boot std::vector&& declarations, std::vector&& parameters, const source_position entry_position, - std::optional&& body); + std::vector&& body); void accept(parser_visitor *visitor) override; @@ -1157,7 +1157,7 @@ namespace elna::boot class empty_statement : public statement { public: - empty_statement(const source_position); + explicit empty_statement(const source_position); void accept(parser_visitor *visitor) override; }; diff --git a/include/elna/boot/dependency.h b/include/elna/boot/dependency.h index a87503e..7bd3de9 100644 --- a/include/elna/boot/dependency.h +++ b/include/elna/boot/dependency.h @@ -23,7 +23,7 @@ along with GCC; see the file COPYING3. If not see #include #include -#include +#include #include #include #include @@ -250,7 +250,8 @@ namespace elna::boot dependency compile(const std::filesystem::path& key, Loader& loader, const target_info& target, const bool imported = false) { - auto cached = this->cache.find(key); + const auto cached = this->cache.find(key); + if (cached != this->cache.cend()) { return {}; diff --git a/include/elna/boot/driver.h b/include/elna/boot/driver.h index e918954..6bcfa9e 100644 --- a/include/elna/boot/driver.h +++ b/include/elna/boot/driver.h @@ -38,10 +38,14 @@ namespace elna::boot class driver final : public diagnostic_container { public: - std::unique_ptr tree; /// Set once the module terminator has been parsed. The lexer stops /// scanning then, so whatever follows is not program text. - bool finished{ false }; + std::unique_ptr tree; + + /** + * \return Whenever module terminator has been parsed. + */ + bool has_finished() const; driver() = default; }; diff --git a/include/elna/boot/result.h b/include/elna/boot/result.h index a8ad73b..d0a550a 100644 --- a/include/elna/boot/result.h +++ b/include/elna/boot/result.h @@ -100,7 +100,7 @@ namespace elna::boot class diagnostic { protected: - diagnostic(const source_position position); + explicit diagnostic(const source_position position); public: virtual ~diagnostic() = default; @@ -716,7 +716,8 @@ namespace elna::boot */ iterator find(const key_type& key) { - auto search_result = this->index_map.find(key); + const auto search_result = this->index_map.find(key); + if (search_result == this->index_map.cend()) { return this->payload.end(); @@ -730,7 +731,8 @@ namespace elna::boot /// \overload const_iterator find(const key_type& key) const { - auto search_result = this->index_map.find(key); + const auto search_result = this->index_map.find(key); + if (search_result == this->index_map.cend()) { return this->payload.cend(); @@ -752,23 +754,23 @@ namespace elna::boot */ std::pair insert(const key_type& key, const mapped_type& value) { - auto insert_result = this->index_map.emplace(key, this->payload.size()); - if (insert_result.second) + const auto [at_position, inserted] = this->index_map.emplace(key, this->payload.size()); + if (inserted) { this->payload.emplace_back(key, value); } - return { this->payload.begin() + insert_result.first->second, insert_result.second }; + return { this->payload.begin() + at_position->second, inserted }; } /// \overload std::pair insert(const key_type& key, mapped_type&& value) { - auto insert_result = this->index_map.emplace(key, this->payload.size()); - if (insert_result.second) + const auto [at_position, inserted] = this->index_map.emplace(key, this->payload.size()); + if (inserted) { this->payload.emplace_back(key, std::move(value)); } - return { this->payload.begin() + insert_result.first->second, insert_result.second }; + return { this->payload.begin() + at_position->second, inserted }; } /** @@ -992,8 +994,8 @@ namespace elna::boot private: static constexpr std::size_t golden_ratio = 0x9e3779b9; - static constexpr int mix_shift_left = 6; - static constexpr int mix_shift_right = 2; + static constexpr unsigned int mix_shift_left = 6; + static constexpr unsigned int mix_shift_right = 2; std::size_t m_seed{ 0 }; }; diff --git a/include/elna/boot/symbol.h b/include/elna/boot/symbol.h index a5f7ca8..38aee08 100644 --- a/include/elna/boot/symbol.h +++ b/include/elna/boot/symbol.h @@ -182,7 +182,7 @@ namespace elna::boot /// type's own alignment. std::optional alignment; - field_info(type field_type = type(), std::optional alignment = std::nullopt); + explicit field_info(type field_type = type(), std::optional alignment = std::nullopt); }; struct record_type @@ -370,7 +370,7 @@ namespace elna::boot */ symbol_ptr lookup(const std::string& name) { - auto entry = entries.find(name); + const iterator entry = entries.find(name); if (entry != entries.cend()) { diff --git a/include/elna/boot/type_check.h b/include/elna/boot/type_check.h index 94f8961..620af74 100644 --- a/include/elna/boot/type_check.h +++ b/include/elna/boot/type_check.h @@ -253,7 +253,13 @@ namespace elna::boot }; context ctx; + /** + * Checks whether derived has base in its record parent chain. + * + * Base record type must not be null. Derived record type may be null. + */ verdict guard_const_laundering() const; + verdict check_exact_match() const; verdict check_pointer_hatch() const; verdict check_pointer_conversion() const; diff --git a/source/cctype.elna b/source/cctype.elna index 13dc50a..19c3491 100644 --- a/source/cctype.elna +++ b/source/cctype.elna @@ -1,6 +1,7 @@ (* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. *) +module proc isdigit*(c: Int ) -> Int extern diff --git a/source/command_line_interface.elna b/source/command_line_interface.elna index 0feb53b..511d6a0 100644 --- a/source/command_line_interface.elna +++ b/source/command_line_interface.elna @@ -1,10 +1,10 @@ (* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. *) - (* Command line handling. *) +module import cstdlib, cstring, common type diff --git a/source/common.elna b/source/common.elna index 0a50fe1..e31def8 100644 --- a/source/common.elna +++ b/source/common.elna @@ -1,7 +1,7 @@ (* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. *) - +module import cstring, cstdio, cstdlib type diff --git a/source/cstdio.elna b/source/cstdio.elna index bf74234..e69d81a 100644 --- a/source/cstdio.elna +++ b/source/cstdio.elna @@ -1,6 +1,7 @@ (* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. *) +module type FILE* = extern diff --git a/source/cstdlib.elna b/source/cstdlib.elna index 09b1ddf..9b858e7 100644 --- a/source/cstdlib.elna +++ b/source/cstdlib.elna @@ -1,6 +1,7 @@ (* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. *) +module proc malloc*(size: Word) -> Pointer extern diff --git a/source/cstring.elna b/source/cstring.elna index 70c468c..dcf9e6f 100644 --- a/source/cstring.elna +++ b/source/cstring.elna @@ -1,6 +1,7 @@ (* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. *) +module proc memset*(ptr: Pointer; c: Int; n: Word) -> ^Word8 extern diff --git a/source/lexer.elna b/source/lexer.elna index 1cfe097..bf1c449 100644 --- a/source/lexer.elna +++ b/source/lexer.elna @@ -1,7 +1,7 @@ (* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. *) - +module import cstdio, common, cstdlib type diff --git a/source/main.elna b/source/main.elna index 955f313..adac5ac 100644 --- a/source/main.elna +++ b/source/main.elna @@ -2,7 +2,9 @@ v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. *) -import cstdio, cstdlib, cstring, cctype, common, command_line_interface, lexer +program(parameters) +import + cstdio, cstdlib, cstring, cctype, common, command_line_interface, lexer type SourceFile* = record @@ -825,10 +827,8 @@ begin stderr := fdopen(2, "w\0".ptr) return -program(parameters) begin initialize_global_state(); -return cast(process(cast(parameters.length: Int), parameters.ptr): Word8) - + exit(process(cast(parameters.length: Int), parameters.ptr)) end. diff --git a/testsuite/compilable/aliased_type_constant.elna b/testsuite/compilable/aliased_type_constant.elna index 16a52c2..e4054c7 100644 --- a/testsuite/compilable/aliased_type_constant.elna +++ b/testsuite/compilable/aliased_type_constant.elna @@ -1,3 +1,5 @@ +module + type Handle = Int diff --git a/testsuite/compilable/assign_record_to_base.elna b/testsuite/compilable/assign_record_to_base.elna index 303bde0..14bc3f5 100644 --- a/testsuite/compilable/assign_record_to_base.elna +++ b/testsuite/compilable/assign_record_to_base.elna @@ -1,3 +1,4 @@ +program() type B = record x: Int @@ -10,9 +11,6 @@ var x: ^B := nil y: ^R := nil -program() begin - x := y; -return 0u8 - + x := y end. diff --git a/testsuite/compilable/compile_time_array_length.elna b/testsuite/compilable/compile_time_array_length.elna index e38919e..9e2c896 100644 --- a/testsuite/compilable/compile_time_array_length.elna +++ b/testsuite/compilable/compile_time_array_length.elna @@ -1,3 +1,5 @@ +module + var source: const [3]Int := [1, 2, 3] target: Word := source.length diff --git a/testsuite/compilable/const_alias.elna b/testsuite/compilable/const_alias.elna index 3a6b365..e4b6434 100644 --- a/testsuite/compilable/const_alias.elna +++ b/testsuite/compilable/const_alias.elna @@ -1,3 +1,5 @@ +module + type CI = const Int CCI = const CI diff --git a/testsuite/compilable/const_element_array.elna b/testsuite/compilable/const_element_array.elna index 2d68ff5..d6419fa 100644 --- a/testsuite/compilable/const_element_array.elna +++ b/testsuite/compilable/const_element_array.elna @@ -1,3 +1,5 @@ +module + type CI = const Int diff --git a/testsuite/compilable/const_extern.elna b/testsuite/compilable/const_extern.elna index 9e8fbb0..6f4b058 100644 --- a/testsuite/compilable/const_extern.elna +++ b/testsuite/compilable/const_extern.elna @@ -1,3 +1,5 @@ +module + var errno_like: const Int := extern diff --git a/testsuite/compilable/const_negation.elna b/testsuite/compilable/const_negation.elna index 82a4cb6..1dd45f4 100644 --- a/testsuite/compilable/const_negation.elna +++ b/testsuite/compilable/const_negation.elna @@ -1,11 +1,9 @@ +program() var x: const Int := -5 y: const Int := -x -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 ad85f48..438b79a 100644 --- a/testsuite/compilable/const_var_chain.elna +++ b/testsuite/compilable/const_var_chain.elna @@ -1,10 +1,8 @@ +program() var x: const Int := 42 y: Int := x -program() begin assert(y = 42) -return 0u8 - end. diff --git a/testsuite/compilable/double_literals.elna b/testsuite/compilable/double_literals.elna index 9e8a73d..2f2bcdd 100644 --- a/testsuite/compilable/double_literals.elna +++ b/testsuite/compilable/double_literals.elna @@ -1,3 +1,5 @@ +module + proc f() var x: const Double := 3.14 diff --git a/testsuite/compilable/empty_proc.elna b/testsuite/compilable/empty_proc.elna index bf3bd84..d08593b 100644 --- a/testsuite/compilable/empty_proc.elna +++ b/testsuite/compilable/empty_proc.elna @@ -1,3 +1,5 @@ +module + proc f() return diff --git a/testsuite/compilable/empty_proc_type_expression.elna b/testsuite/compilable/empty_proc_type_expression.elna index 7738cae..f9c0819 100644 --- a/testsuite/compilable/empty_proc_type_expression.elna +++ b/testsuite/compilable/empty_proc_type_expression.elna @@ -1,3 +1,5 @@ +module + type P = proc() diff --git a/testsuite/compilable/empty_statements_in_a_row.elna b/testsuite/compilable/empty_statements_in_a_row.elna index 7cf723c..465ab19 100644 --- a/testsuite/compilable/empty_statements_in_a_row.elna +++ b/testsuite/compilable/empty_statements_in_a_row.elna @@ -1,3 +1,5 @@ +module + proc f() begin ; diff --git a/testsuite/compilable/generic_alias.elna b/testsuite/compilable/generic_alias.elna index 3b431be..47ac638 100644 --- a/testsuite/compilable/generic_alias.elna +++ b/testsuite/compilable/generic_alias.elna @@ -1,3 +1,4 @@ +program() type File = record fd: Int @@ -20,12 +21,9 @@ var raw: ^^File boxed: Boxed#[^File] -program() begin chain.next := nil; aliased := raw; raw := aliased; boxed.inner := @chain -return 0u8 - end. diff --git a/testsuite/compilable/generic_arguments.elna b/testsuite/compilable/generic_arguments.elna index 6bc5242..4d33db5 100644 --- a/testsuite/compilable/generic_arguments.elna +++ b/testsuite/compilable/generic_arguments.elna @@ -1,3 +1,4 @@ +program() type File = record fd: Int @@ -11,18 +12,15 @@ type var entry: Pair#[^File, ^Word8] -proc allocate#[T](size: Word) -> T extern +proc allocate#[T](size: Word) -> T +extern proc first#[K, V](entry_ptr: ^Pair#[K, V]) -> K -begin return entry_ptr^.key -program() begin entry.key := allocate#[^File](#size(File)); assert(#size(Pair#[^File, ^Word8]) = #size(Pointer) * 2u); assert(#offset(Pair#[^File, ^Word8], value) = #size(Pointer)); assert(first#[^File, ^Word8](@entry) = entry.key) -return 0u8 - end. diff --git a/testsuite/compilable/generic_base_chain.elna b/testsuite/compilable/generic_base_chain.elna index 736042b..c303e6d 100644 --- a/testsuite/compilable/generic_base_chain.elna +++ b/testsuite/compilable/generic_base_chain.elna @@ -1,3 +1,4 @@ +program() type File = record fd: Int @@ -22,10 +23,7 @@ begin target^.key := key return -program() begin upcast := @store; put(@store, byte_key) -return 0u8 - end. diff --git a/testsuite/compilable/generic_inference.elna b/testsuite/compilable/generic_inference.elna index 25faca4..ab1ff3a 100644 --- a/testsuite/compilable/generic_inference.elna +++ b/testsuite/compilable/generic_inference.elna @@ -1,3 +1,4 @@ +program() type File = record fd: Int @@ -23,11 +24,8 @@ begin store(target, value) return -program() begin store(@files, @f); relay(@bytes, @b); store(@files, nil) -return 0u8 - end. diff --git a/testsuite/compilable/opaque_type.elna b/testsuite/compilable/opaque_type.elna index c570e0d..6474337 100644 --- a/testsuite/compilable/opaque_type.elna +++ b/testsuite/compilable/opaque_type.elna @@ -1,3 +1,4 @@ +program() type Handle = extern Alias = Handle @@ -9,9 +10,6 @@ var proc take(h: ^Handle) -> ^Handle 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 ad15432..2b986c0 100644 --- a/testsuite/compilable/pointer_cast.elna +++ b/testsuite/compilable/pointer_cast.elna @@ -1,11 +1,9 @@ +program() var c: ^Char := nil p: Pointer := nil -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 a5bd297..c08862b 100644 --- a/testsuite/compilable/pointer_const_conversion.elna +++ b/testsuite/compilable/pointer_const_conversion.elna @@ -1,10 +1,8 @@ +program() var x: Int p: ^const Int -program() begin p := @x -return 0u8 - end. diff --git a/testsuite/compilable/pointer_subtraction.elna b/testsuite/compilable/pointer_subtraction.elna index 8dd1ff6..738845d 100644 --- a/testsuite/compilable/pointer_subtraction.elna +++ b/testsuite/compilable/pointer_subtraction.elna @@ -1,3 +1,5 @@ +module + proc test(a, b: ^Char) -> Int return a - b diff --git a/testsuite/compilable/procedure_forward_reference.elna b/testsuite/compilable/procedure_forward_reference.elna index cdf3008..0e6f93c 100644 --- a/testsuite/compilable/procedure_forward_reference.elna +++ b/testsuite/compilable/procedure_forward_reference.elna @@ -1,3 +1,5 @@ +module + proc first() -> Int return second() + 1 diff --git a/testsuite/compilable/record_const_base.elna b/testsuite/compilable/record_const_base.elna index f24d27b..a4c6b7b 100644 --- a/testsuite/compilable/record_const_base.elna +++ b/testsuite/compilable/record_const_base.elna @@ -1,3 +1,5 @@ +module + type B = record x: Int diff --git a/testsuite/compilable/self-referencing-record.elna b/testsuite/compilable/self-referencing-record.elna index 311f148..d340492 100644 --- a/testsuite/compilable/self-referencing-record.elna +++ b/testsuite/compilable/self-referencing-record.elna @@ -1,3 +1,5 @@ +module + type R = record field: ^R diff --git a/testsuite/compilable/semicolon_parameter_separator.elna b/testsuite/compilable/semicolon_parameter_separator.elna index 229fde0..c998606 100644 --- a/testsuite/compilable/semicolon_parameter_separator.elna +++ b/testsuite/compilable/semicolon_parameter_separator.elna @@ -1,3 +1,5 @@ +module + proc f(a: Int; b: Word) return diff --git a/testsuite/compilable/single_literals.elna b/testsuite/compilable/single_literals.elna index ac03623..a18d2ca 100644 --- a/testsuite/compilable/single_literals.elna +++ b/testsuite/compilable/single_literals.elna @@ -1,3 +1,5 @@ +module + proc f() var x: const Single := 3.14f diff --git a/testsuite/compilable/slice_index.elna b/testsuite/compilable/slice_index.elna index 70d26ae..13121eb 100644 --- a/testsuite/compilable/slice_index.elna +++ b/testsuite/compilable/slice_index.elna @@ -1,3 +1,5 @@ +module + proc f() var a: []Int diff --git a/testsuite/compilable/take_const_address.elna b/testsuite/compilable/take_const_address.elna index 4f82b2a..a60b1c2 100644 --- a/testsuite/compilable/take_const_address.elna +++ b/testsuite/compilable/take_const_address.elna @@ -1,10 +1,8 @@ +program() var x: ^const Int y: const Int := 1 -program() begin x := @y -return 0u8 - end. diff --git a/testsuite/compilable/trailing_text.elna b/testsuite/compilable/trailing_text.elna index 1eb3595..0a95516 100644 --- a/testsuite/compilable/trailing_text.elna +++ b/testsuite/compilable/trailing_text.elna @@ -1,3 +1,5 @@ +module + end. Everything after the module terminator is ignored and is never scanned, so it diff --git a/testsuite/compilable/traits_size.elna b/testsuite/compilable/traits_size.elna index f245637..ad49b61 100644 --- a/testsuite/compilable/traits_size.elna +++ b/testsuite/compilable/traits_size.elna @@ -1,3 +1,4 @@ +program() var i: Int := 1 s: Int := cast(#size(Int): Int) @@ -5,11 +6,8 @@ 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)); assert(p > 0) -return 0u8 - end. diff --git a/testsuite/fail_compilation/access_record_type_field.elna b/testsuite/fail_compilation/access_record_type_field.elna index 4378404..4dcdceb 100644 --- a/testsuite/fail_compilation/access_record_type_field.elna +++ b/testsuite/fail_compilation/access_record_type_field.elna @@ -1,3 +1,5 @@ +module + type R = record field1, field2: Int diff --git a/testsuite/fail_compilation/alias-cycle-behind-const.elna b/testsuite/fail_compilation/alias-cycle-behind-const.elna index 0c3b626..a05240b 100644 --- a/testsuite/fail_compilation/alias-cycle-behind-const.elna +++ b/testsuite/fail_compilation/alias-cycle-behind-const.elna @@ -1,4 +1,7 @@ +module + type A = B B = const A (* @Error Type declaration forms a cycle: A -> B -> A *) + end. diff --git a/testsuite/fail_compilation/alias-cycle.elna b/testsuite/fail_compilation/alias-cycle.elna index e6c822b..ba05947 100644 --- a/testsuite/fail_compilation/alias-cycle.elna +++ b/testsuite/fail_compilation/alias-cycle.elna @@ -1,4 +1,7 @@ +module + type A = B B = A (* @Error Type declaration forms a cycle: A -> B -> A *) + end. diff --git a/testsuite/fail_compilation/alias-field-cycle.elna b/testsuite/fail_compilation/alias-field-cycle.elna index f4a554a..8296c69 100644 --- a/testsuite/fail_compilation/alias-field-cycle.elna +++ b/testsuite/fail_compilation/alias-field-cycle.elna @@ -1,5 +1,8 @@ +module + type A = record (* @Error Type declaration forms a cycle: A -> A *) field: A end + end. diff --git a/testsuite/fail_compilation/aligned_attribute.elna b/testsuite/fail_compilation/aligned_attribute.elna index aab5513..46a9b94 100644 --- a/testsuite/fail_compilation/aligned_attribute.elna +++ b/testsuite/fail_compilation/aligned_attribute.elna @@ -1,3 +1,4 @@ +module type Uneven = record x #{aligned 3}: Word8 (* @Error Alignment must be a power of two *) @@ -10,11 +11,6 @@ type end proc takes(p #{aligned 8}: Int) (* @Error Attribute 'aligned' is not supported in this position *) -begin return -program() -begin -return 0u8 - end. diff --git a/testsuite/fail_compilation/array-cycle.elna b/testsuite/fail_compilation/array-cycle.elna index 617e23d..a5b79c2 100644 --- a/testsuite/fail_compilation/array-cycle.elna +++ b/testsuite/fail_compilation/array-cycle.elna @@ -1,3 +1,6 @@ +module + type A = [2]A (* @Error Type declaration forms a cycle: A -> A *) + end. diff --git a/testsuite/fail_compilation/assign_array_length.elna b/testsuite/fail_compilation/assign_array_length.elna index 92d6769..c794b11 100644 --- a/testsuite/fail_compilation/assign_array_length.elna +++ b/testsuite/fail_compilation/assign_array_length.elna @@ -1,10 +1,8 @@ +program() 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 *) -return 0u8 - end. diff --git a/testsuite/fail_compilation/assign_const_array_pointer.elna b/testsuite/fail_compilation/assign_const_array_pointer.elna index 32dc66d..d8ecb72 100644 --- a/testsuite/fail_compilation/assign_const_array_pointer.elna +++ b/testsuite/fail_compilation/assign_const_array_pointer.elna @@ -1,3 +1,5 @@ +module + proc f() var p: ^[2]Int diff --git a/testsuite/fail_compilation/assign_const_element.elna b/testsuite/fail_compilation/assign_const_element.elna index 9b9c341..721d337 100644 --- a/testsuite/fail_compilation/assign_const_element.elna +++ b/testsuite/fail_compilation/assign_const_element.elna @@ -1,3 +1,5 @@ +module + type CI = const Int diff --git a/testsuite/fail_compilation/assign_const_member.elna b/testsuite/fail_compilation/assign_const_member.elna index 8aecb01..a603729 100644 --- a/testsuite/fail_compilation/assign_const_member.elna +++ b/testsuite/fail_compilation/assign_const_member.elna @@ -1,3 +1,5 @@ +module + type R = record x: const Int diff --git a/testsuite/fail_compilation/assign_const_primitive.elna b/testsuite/fail_compilation/assign_const_primitive.elna index 22fef25..2db9c85 100644 --- a/testsuite/fail_compilation/assign_const_primitive.elna +++ b/testsuite/fail_compilation/assign_const_primitive.elna @@ -1,3 +1,5 @@ +module + proc f() var x: const Int := 4 diff --git a/testsuite/fail_compilation/assign_const_record_pointer.elna b/testsuite/fail_compilation/assign_const_record_pointer.elna index 5e6f3df..adf3d91 100644 --- a/testsuite/fail_compilation/assign_const_record_pointer.elna +++ b/testsuite/fail_compilation/assign_const_record_pointer.elna @@ -1,3 +1,5 @@ +module + type B = record x: Int diff --git a/testsuite/fail_compilation/assign_const_to_pointer.elna b/testsuite/fail_compilation/assign_const_to_pointer.elna index 50e4a44..796b60c 100644 --- a/testsuite/fail_compilation/assign_const_to_pointer.elna +++ b/testsuite/fail_compilation/assign_const_to_pointer.elna @@ -1,10 +1,8 @@ +program() var c: const Int := 2 p: Pointer -program() begin p := @c (* @Error Expected type 'Pointer', but got '\^const Int' *) -return 0u8 - end. diff --git a/testsuite/fail_compilation/assign_deep_const_pointer.elna b/testsuite/fail_compilation/assign_deep_const_pointer.elna index 7ed3840..7c977d4 100644 --- a/testsuite/fail_compilation/assign_deep_const_pointer.elna +++ b/testsuite/fail_compilation/assign_deep_const_pointer.elna @@ -1,3 +1,5 @@ +module + proc f() var p: ^^const Int diff --git a/testsuite/fail_compilation/assign_element_of_const.elna b/testsuite/fail_compilation/assign_element_of_const.elna index 8235448..a51822b 100644 --- a/testsuite/fail_compilation/assign_element_of_const.elna +++ b/testsuite/fail_compilation/assign_element_of_const.elna @@ -1,3 +1,5 @@ +module + proc f() var a: const [2]Int := [1, 3] diff --git a/testsuite/fail_compilation/assign_from_const_pointer.elna b/testsuite/fail_compilation/assign_from_const_pointer.elna index 4c383cc..64f7f5d 100644 --- a/testsuite/fail_compilation/assign_from_const_pointer.elna +++ b/testsuite/fail_compilation/assign_from_const_pointer.elna @@ -1,10 +1,8 @@ +program() var cv: const Pointer := nil p: Pointer -program() begin p := cv (* @Error Expected type 'Pointer', but got 'const Pointer' *) -return 0u8 - end. diff --git a/testsuite/fail_compilation/assign_member_of_const.elna b/testsuite/fail_compilation/assign_member_of_const.elna index fc945bb..efdf67b 100644 --- a/testsuite/fail_compilation/assign_member_of_const.elna +++ b/testsuite/fail_compilation/assign_member_of_const.elna @@ -1,3 +1,5 @@ +module + type R = record x: Int diff --git a/testsuite/fail_compilation/assign_slice_ptr.elna b/testsuite/fail_compilation/assign_slice_ptr.elna index fa3dd22..b4e72f1 100644 --- a/testsuite/fail_compilation/assign_slice_ptr.elna +++ b/testsuite/fail_compilation/assign_slice_ptr.elna @@ -1,10 +1,8 @@ +program() 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 *) -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 50cd135..e4995e5 100644 --- a/testsuite/fail_compilation/assign_to_call_result_field.elna +++ b/testsuite/fail_compilation/assign_to_call_result_field.elna @@ -1,3 +1,4 @@ +program() type R = record x: Int @@ -10,9 +11,6 @@ begin result.x := 1 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 92d0dae..da369b3 100644 --- a/testsuite/fail_compilation/assign_to_slicing.elna +++ b/testsuite/fail_compilation/assign_to_slicing.elna @@ -1,10 +1,8 @@ +program() 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 *) -return 0u8 - end. diff --git a/testsuite/fail_compilation/assign_void_call.elna b/testsuite/fail_compilation/assign_void_call.elna index 75f7c6b..ecdba8d 100644 --- a/testsuite/fail_compilation/assign_void_call.elna +++ b/testsuite/fail_compilation/assign_void_call.elna @@ -1,12 +1,10 @@ +program() var x: Int proc v() 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 def83e9..cfed88a 100644 --- a/testsuite/fail_compilation/case_label_overflow.elna +++ b/testsuite/fail_compilation/case_label_overflow.elna @@ -1,7 +1,7 @@ +program() var x: Int8 := 100i8 -program() begin case x of 100i8: assert(true) @@ -9,6 +9,4 @@ 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 0345653..9f7ba9a 100644 --- a/testsuite/fail_compilation/case_non_constant.elna +++ b/testsuite/fail_compilation/case_non_constant.elna @@ -1,3 +1,4 @@ +program() type R = record a: Int; @@ -8,12 +9,9 @@ var r: R x: R -program() begin x := r; 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 56be244..f2db7e7 100644 --- a/testsuite/fail_compilation/case_type_mismatch.elna +++ b/testsuite/fail_compilation/case_type_mismatch.elna @@ -1,12 +1,10 @@ +program() var x: Int -program() begin case x of 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 95d5f53..7ee8391 100644 --- a/testsuite/fail_compilation/case_unique_label.elna +++ b/testsuite/fail_compilation/case_unique_label.elna @@ -5,6 +5,4 @@ begin | 3: | 1 + 2: (* @Error Duplicate case label *) end -return 0u8 - end. diff --git a/testsuite/fail_compilation/circular_import/sut.elna b/testsuite/fail_compilation/circular_import/sut.elna index f6452fb..7641a73 100644 --- a/testsuite/fail_compilation/circular_import/sut.elna +++ b/testsuite/fail_compilation/circular_import/sut.elna @@ -1,3 +1,5 @@ +module + import sut (* @Error Circular import of module 'sut' *) end. diff --git a/testsuite/fail_compilation/compare_unrelated_records.elna b/testsuite/fail_compilation/compare_unrelated_records.elna index 4b04aa7..a113809 100644 --- a/testsuite/fail_compilation/compare_unrelated_records.elna +++ b/testsuite/fail_compilation/compare_unrelated_records.elna @@ -1,3 +1,4 @@ +program() type A = record x: Int @@ -12,9 +13,6 @@ var b: B ok: Bool -program() begin ok := b = a (* @Error Invalid operands of type 'B' and 'A' for operator = *) -return 0u8 - end. diff --git a/testsuite/fail_compilation/compile_time_array_ptr.elna b/testsuite/fail_compilation/compile_time_array_ptr.elna index bd630ac..f11f2f2 100644 --- a/testsuite/fail_compilation/compile_time_array_ptr.elna +++ b/testsuite/fail_compilation/compile_time_array_ptr.elna @@ -1,3 +1,5 @@ +module + var source: [3]Int := [1, 2, 3] target: ^Int := source.ptr (* @Error Variable initializers must be constant expressions *) diff --git a/testsuite/fail_compilation/const_array.elna b/testsuite/fail_compilation/const_array.elna index 7a1a6f5..d42f0b4 100644 --- a/testsuite/fail_compilation/const_array.elna +++ b/testsuite/fail_compilation/const_array.elna @@ -1,7 +1,8 @@ +module + proc f() var a: [10]const Int (* @Error const must be written before the array size, not after *) -begin return end. diff --git a/testsuite/fail_compilation/const_uninitialized.elna b/testsuite/fail_compilation/const_uninitialized.elna index 06db3d7..a3be5d3 100644 --- a/testsuite/fail_compilation/const_uninitialized.elna +++ b/testsuite/fail_compilation/const_uninitialized.elna @@ -1,3 +1,5 @@ +module + var x: const Int (* @Error All constants should be initialized *) diff --git a/testsuite/fail_compilation/constant_enum_to_int.elna b/testsuite/fail_compilation/constant_enum_to_int.elna index 85f6d4c..194109b 100644 --- a/testsuite/fail_compilation/constant_enum_to_int.elna +++ b/testsuite/fail_compilation/constant_enum_to_int.elna @@ -1,3 +1,4 @@ +program() type Enumeration = (one, two, three) @@ -5,9 +6,6 @@ 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' *) -return 0u8 - end. diff --git a/testsuite/fail_compilation/double_const.elna b/testsuite/fail_compilation/double_const.elna index 204a7f7..fe1b134 100644 --- a/testsuite/fail_compilation/double_const.elna +++ b/testsuite/fail_compilation/double_const.elna @@ -1,7 +1,8 @@ +module + proc f() var x: const const Int (* @Error Duplicate 'const' qualifier is not allowed *) -begin return end. diff --git a/testsuite/fail_compilation/enumeration_member_missing.elna b/testsuite/fail_compilation/enumeration_member_missing.elna index 6f82131..69f1eed 100644 --- a/testsuite/fail_compilation/enumeration_member_missing.elna +++ b/testsuite/fail_compilation/enumeration_member_missing.elna @@ -1,3 +1,5 @@ +module + type Enumeration = (one, two, three) diff --git a/testsuite/fail_compilation/float_remainder.elna b/testsuite/fail_compilation/float_remainder.elna index ec6c9e2..f2eba60 100644 --- a/testsuite/fail_compilation/float_remainder.elna +++ b/testsuite/fail_compilation/float_remainder.elna @@ -1,3 +1,5 @@ +module + proc f() var x: Double diff --git a/testsuite/fail_compilation/generic_arity.elna b/testsuite/fail_compilation/generic_arity.elna index bb234af..645aded 100644 --- a/testsuite/fail_compilation/generic_arity.elna +++ b/testsuite/fail_compilation/generic_arity.elna @@ -1,3 +1,5 @@ +module + type Stack#[T] = record items: T @@ -6,8 +8,4 @@ type var broken: Stack (* @Error Too few type arguments for generic 'Stack', expected 1, got 0 *) -program() -begin -return 0u8 - end. diff --git a/testsuite/fail_compilation/generic_base_mismatch.elna b/testsuite/fail_compilation/generic_base_mismatch.elna index 64e0c40..e361052 100644 --- a/testsuite/fail_compilation/generic_base_mismatch.elna +++ b/testsuite/fail_compilation/generic_base_mismatch.elna @@ -1,3 +1,4 @@ +program() type File = record fd: Int @@ -18,9 +19,6 @@ var jobs: Queue#[^File] wrong: ^List#[^Socket] -program() begin wrong := @jobs (* @Error Expected type '\^List#\[\^Socket\]', but got '\^Queue#\[\^File\]' *) -return 0u8 - end. diff --git a/testsuite/fail_compilation/generic_parameter_arithmetic.elna b/testsuite/fail_compilation/generic_parameter_arithmetic.elna index 969c5c7..e05b1ee 100644 --- a/testsuite/fail_compilation/generic_parameter_arithmetic.elna +++ b/testsuite/fail_compilation/generic_parameter_arithmetic.elna @@ -1,11 +1,9 @@ +module + proc walk#[T](value: T; step: ^T) begin step := step + 1; value := value + 1 (* @Error Type parameter 'T' cannot be used in pointer arithmetic *) return -program() -begin -return 0u8 - end. diff --git a/testsuite/fail_compilation/generic_uninferrable.elna b/testsuite/fail_compilation/generic_uninferrable.elna index 20d3d25..b3556d6 100644 --- a/testsuite/fail_compilation/generic_uninferrable.elna +++ b/testsuite/fail_compilation/generic_uninferrable.elna @@ -1,10 +1,10 @@ -proc allocate#[R](size: Word) -> R extern - program() var got: ^Word8 + +proc allocate#[R](size: Word) -> R +extern + begin got := allocate(8u) (* @Error Type parameter 'R' of 'allocate' cannot be inferred *) -return 0u8 - end. diff --git a/testsuite/fail_compilation/import_import_collision/first.elna b/testsuite/fail_compilation/import_import_collision/first.elna index e60ca8e..251eaee 100644 --- a/testsuite/fail_compilation/import_import_collision/first.elna +++ b/testsuite/fail_compilation/import_import_collision/first.elna @@ -1,3 +1,5 @@ +module + var X*: Int := 1 diff --git a/testsuite/fail_compilation/import_import_collision/second.elna b/testsuite/fail_compilation/import_import_collision/second.elna index 0a3d8e0..65f1ed3 100644 --- a/testsuite/fail_compilation/import_import_collision/second.elna +++ b/testsuite/fail_compilation/import_import_collision/second.elna @@ -1,3 +1,5 @@ +module + var X*: Int := 2 diff --git a/testsuite/fail_compilation/import_import_collision/sut.elna b/testsuite/fail_compilation/import_import_collision/sut.elna index 208aa21..657113d 100644 --- a/testsuite/fail_compilation/import_import_collision/sut.elna +++ b/testsuite/fail_compilation/import_import_collision/sut.elna @@ -1,3 +1,5 @@ +module + import first, second (* @Error Symbol 'X' has been already defined *) end. diff --git a/testsuite/fail_compilation/import_local_collision/helper.elna b/testsuite/fail_compilation/import_local_collision/helper.elna index e60ca8e..251eaee 100644 --- a/testsuite/fail_compilation/import_local_collision/helper.elna +++ b/testsuite/fail_compilation/import_local_collision/helper.elna @@ -1,3 +1,5 @@ +module + var X*: Int := 1 diff --git a/testsuite/fail_compilation/import_local_collision/sut.elna b/testsuite/fail_compilation/import_local_collision/sut.elna index ecac1ca..c628941 100644 --- a/testsuite/fail_compilation/import_local_collision/sut.elna +++ b/testsuite/fail_compilation/import_local_collision/sut.elna @@ -1,9 +1,8 @@ +program() + import helper var X: Int (* @Error Symbol 'X' has been already defined *) -program() -return 0u8 - end. diff --git a/testsuite/fail_compilation/local_var_exported.elna b/testsuite/fail_compilation/local_var_exported.elna index 307d34f..be0183d 100644 --- a/testsuite/fail_compilation/local_var_exported.elna +++ b/testsuite/fail_compilation/local_var_exported.elna @@ -1,3 +1,5 @@ +module + proc test_local_export() var v* : Int (* @Error Local symbols cannot be exported *) diff --git a/testsuite/fail_compilation/local_var_extern.elna b/testsuite/fail_compilation/local_var_extern.elna index d0eb22f..948689c 100644 --- a/testsuite/fail_compilation/local_var_extern.elna +++ b/testsuite/fail_compilation/local_var_extern.elna @@ -1,3 +1,5 @@ +module + proc test_local_extern() var v : Int := extern (* @Error Local symbols cannot be extern *) diff --git a/testsuite/fail_compilation/negative_integer_literal_overflow.elna b/testsuite/fail_compilation/negative_integer_literal_overflow.elna index 7db4888..fa90009 100644 --- a/testsuite/fail_compilation/negative_integer_literal_overflow.elna +++ b/testsuite/fail_compilation/negative_integer_literal_overflow.elna @@ -1,3 +1,5 @@ +module + var a: Int8 := -200i8 (* @Error Integer literal overflows *) diff --git a/testsuite/fail_compilation/non_constant_array_dimension.elna b/testsuite/fail_compilation/non_constant_array_dimension.elna index 8efb9e9..3c69b7e 100644 --- a/testsuite/fail_compilation/non_constant_array_dimension.elna +++ b/testsuite/fail_compilation/non_constant_array_dimension.elna @@ -1,12 +1,10 @@ +program() + proc f(len: Int) var array: [len]Int (* @Error Array dimensions for type 'Int' should be constant *) -begin - return +return -program() begin f(5) -return 0u8 - end. diff --git a/testsuite/fail_compilation/offset_not_record.elna b/testsuite/fail_compilation/offset_not_record.elna index d19e608..93459e4 100644 --- a/testsuite/fail_compilation/offset_not_record.elna +++ b/testsuite/fail_compilation/offset_not_record.elna @@ -1,9 +1,7 @@ +program() var n: Word -program() begin n := #offset(Int, top) (* @Error Type 'Int' does not support trait '#offset' *) -return 0u8 - end. diff --git a/testsuite/fail_compilation/opaque_pointer_arithmetic.elna b/testsuite/fail_compilation/opaque_pointer_arithmetic.elna index cb3a20e..117994a 100644 --- a/testsuite/fail_compilation/opaque_pointer_arithmetic.elna +++ b/testsuite/fail_compilation/opaque_pointer_arithmetic.elna @@ -1,12 +1,10 @@ +program() type Handle = extern var p: ^Handle -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/opaque_slice_element.elna b/testsuite/fail_compilation/opaque_slice_element.elna index f50be8a..1dc341d 100644 --- a/testsuite/fail_compilation/opaque_slice_element.elna +++ b/testsuite/fail_compilation/opaque_slice_element.elna @@ -1,3 +1,5 @@ +module + type Handle = extern diff --git a/testsuite/fail_compilation/pointer-cycle.elna b/testsuite/fail_compilation/pointer-cycle.elna index fe0258a..f2ed05c 100644 --- a/testsuite/fail_compilation/pointer-cycle.elna +++ b/testsuite/fail_compilation/pointer-cycle.elna @@ -1,3 +1,5 @@ +module + type A = ^A (* @Error Type declaration forms a cycle: A -> A *) diff --git a/testsuite/fail_compilation/proc_type_without_parameters.elna b/testsuite/fail_compilation/proc_type_without_parameters.elna index f7cdffe..d15b7f5 100644 --- a/testsuite/fail_compilation/proc_type_without_parameters.elna +++ b/testsuite/fail_compilation/proc_type_without_parameters.elna @@ -1,12 +1,10 @@ +program() var x: Int proc f() return -program() begin x := f (* @Error Expected type 'Int', but got 'proc\(\)' *) -return 0u8 - end. diff --git a/testsuite/fail_compilation/procedure-cycle.elna b/testsuite/fail_compilation/procedure-cycle.elna index 2284605..f9a128d 100644 --- a/testsuite/fail_compilation/procedure-cycle.elna +++ b/testsuite/fail_compilation/procedure-cycle.elna @@ -1,3 +1,5 @@ +module + type A = proc() -> A (* @Error Type declaration forms a cycle: A -> A *) diff --git a/testsuite/fail_compilation/program_arguments.elna b/testsuite/fail_compilation/program_arguments.elna index e614368..73c38df 100644 --- a/testsuite/fail_compilation/program_arguments.elna +++ b/testsuite/fail_compilation/program_arguments.elna @@ -1,4 +1,2 @@ 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 f60b1aa..75c9805 100644 --- a/testsuite/fail_compilation/record-base-cycle-indirect.elna +++ b/testsuite/fail_compilation/record-base-cycle-indirect.elna @@ -1,3 +1,5 @@ +module + type A = record(B) x: Int @@ -9,8 +11,4 @@ type var v: A -program() -begin -return 0u8 - end. diff --git a/testsuite/fail_compilation/record-base-cycle.elna b/testsuite/fail_compilation/record-base-cycle.elna index 8af254d..ea3d888 100644 --- a/testsuite/fail_compilation/record-base-cycle.elna +++ b/testsuite/fail_compilation/record-base-cycle.elna @@ -1,3 +1,5 @@ +module + type R = record(R) (* @Error Type declaration forms a cycle: R -> R *) end diff --git a/testsuite/fail_compilation/record_base_constructor_type_mismatch.elna b/testsuite/fail_compilation/record_base_constructor_type_mismatch.elna index 621a06c..d7a8419 100644 --- a/testsuite/fail_compilation/record_base_constructor_type_mismatch.elna +++ b/testsuite/fail_compilation/record_base_constructor_type_mismatch.elna @@ -1,3 +1,4 @@ +program() type Base = record a: Int @@ -9,9 +10,6 @@ type var c: Child -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/record_duplicate_field.elna b/testsuite/fail_compilation/record_duplicate_field.elna index 5cf69a9..0cdfbaa 100644 --- a/testsuite/fail_compilation/record_duplicate_field.elna +++ b/testsuite/fail_compilation/record_duplicate_field.elna @@ -1,3 +1,5 @@ +module + type R = record x: Int; diff --git a/testsuite/fail_compilation/record_duplicate_field_import_base/helper.elna b/testsuite/fail_compilation/record_duplicate_field_import_base/helper.elna index 0edb965..7865a3f 100644 --- a/testsuite/fail_compilation/record_duplicate_field_import_base/helper.elna +++ b/testsuite/fail_compilation/record_duplicate_field_import_base/helper.elna @@ -1,3 +1,5 @@ +module + type Parent* = record x: Int; 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 58f2f3d..97d9a2f 100644 --- a/testsuite/fail_compilation/record_duplicate_field_import_base/sut.elna +++ b/testsuite/fail_compilation/record_duplicate_field_import_base/sut.elna @@ -1,3 +1,5 @@ +module + import helper type diff --git a/testsuite/fail_compilation/redefined_variable.elna b/testsuite/fail_compilation/redefined_variable.elna index 905f6ed..1856807 100644 --- a/testsuite/fail_compilation/redefined_variable.elna +++ b/testsuite/fail_compilation/redefined_variable.elna @@ -1,3 +1,5 @@ +module + var x: Int x: Int (* @Error Symbol 'x' has been already defined *) diff --git a/testsuite/fail_compilation/reference_call_result_field.elna b/testsuite/fail_compilation/reference_call_result_field.elna index d339ed9..b10d324 100644 --- a/testsuite/fail_compilation/reference_call_result_field.elna +++ b/testsuite/fail_compilation/reference_call_result_field.elna @@ -1,3 +1,4 @@ +program() type R = record x: Int @@ -13,9 +14,6 @@ begin result.x := 1 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 26d5a22..72eb986 100644 --- a/testsuite/fail_compilation/reference_literal.elna +++ b/testsuite/fail_compilation/reference_literal.elna @@ -1,9 +1,7 @@ +program() var p: ^Int -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 3875a5d..838e101 100644 --- a/testsuite/fail_compilation/reference_slicing.elna +++ b/testsuite/fail_compilation/reference_slicing.elna @@ -1,10 +1,8 @@ +program() var s: [3]Int p: ^Int -program() begin p := @s[1 to 2] (* @Error Expression of type '\[\]Int' is not addressable *) -return 0u8 - end. diff --git a/testsuite/fail_compilation/slice-cycle.elna b/testsuite/fail_compilation/slice-cycle.elna index fe0a3e1..0ee44a9 100644 --- a/testsuite/fail_compilation/slice-cycle.elna +++ b/testsuite/fail_compilation/slice-cycle.elna @@ -1,3 +1,5 @@ +module + type A = []A (* @Error Type declaration forms a cycle: A -> A *) diff --git a/testsuite/fail_compilation/unary_minus_on_record.elna b/testsuite/fail_compilation/unary_minus_on_record.elna index d86995b..30da92c 100644 --- a/testsuite/fail_compilation/unary_minus_on_record.elna +++ b/testsuite/fail_compilation/unary_minus_on_record.elna @@ -1,3 +1,5 @@ +module + type R = record x: Int diff --git a/testsuite/fail_compilation/unary_negation_on_record.elna b/testsuite/fail_compilation/unary_negation_on_record.elna index d08d2e3..750f828 100644 --- a/testsuite/fail_compilation/unary_negation_on_record.elna +++ b/testsuite/fail_compilation/unary_negation_on_record.elna @@ -1,3 +1,5 @@ +module + type R = record x: Int diff --git a/testsuite/fail_compilation/unary_plus_on_record.elna b/testsuite/fail_compilation/unary_plus_on_record.elna index e1f6f4c..59485e3 100644 --- a/testsuite/fail_compilation/unary_plus_on_record.elna +++ b/testsuite/fail_compilation/unary_plus_on_record.elna @@ -1,3 +1,5 @@ +module + type R = record x: Int diff --git a/testsuite/fail_compilation/varargs_argument.elna b/testsuite/fail_compilation/varargs_argument.elna index 1325c29..b3b3459 100644 --- a/testsuite/fail_compilation/varargs_argument.elna +++ b/testsuite/fail_compilation/varargs_argument.elna @@ -1,12 +1,10 @@ +program() var written: Int32 proc printf(format: ^const Word8) #{varargs} -> Int32 extern -program() begin written := printf("%s".ptr, "text") (* @Error Type '\[\]const Word8' cannot be passed as a variadic argument *) -return 0u8 - end. diff --git a/testsuite/fail_compilation/varargs_attribute.elna b/testsuite/fail_compilation/varargs_attribute.elna index 1c6d3e0..ec42710 100644 --- a/testsuite/fail_compilation/varargs_attribute.elna +++ b/testsuite/fail_compilation/varargs_attribute.elna @@ -1,5 +1,6 @@ +module + proc with_body(x: Int) #{varargs} (* @Error Attribute 'varargs' is not supported in this position *) -begin return proc no_parameters() #{varargs} -> Int32 (* @Error Attribute 'varargs' requires at least one parameter *) diff --git a/testsuite/fail_compilation/while_condition.elna b/testsuite/fail_compilation/while_condition.elna index 0e4aa3c..bd54796 100644 --- a/testsuite/fail_compilation/while_condition.elna +++ b/testsuite/fail_compilation/while_condition.elna @@ -2,6 +2,4 @@ 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 b36ccc3..7ae4947 100644 --- a/testsuite/runnable/aggregate_argument.elna +++ b/testsuite/runnable/aggregate_argument.elna @@ -1,3 +1,4 @@ +program() type R = record a: Int; @@ -7,9 +8,6 @@ type proc f(r: R) -> Bool 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 be7b4f1..c9601f9 100644 --- a/testsuite/runnable/aggregate_equality.elna +++ b/testsuite/runnable/aggregate_equality.elna @@ -1,3 +1,4 @@ +program() type R = record a: Int; @@ -7,9 +8,6 @@ type proc f() -> Bool return R{a: 1, b: 2} = R{a: 1, b: 2} -program() begin assert(f()) -return 0u8 - end. diff --git a/testsuite/runnable/aligned_attribute.elna b/testsuite/runnable/aligned_attribute.elna index 45c0c37..e339faf 100644 --- a/testsuite/runnable/aligned_attribute.elna +++ b/testsuite/runnable/aligned_attribute.elna @@ -1,3 +1,4 @@ +program() type Plain = record a: Word8; @@ -23,7 +24,6 @@ var first: ^Word8 second: ^Word8 -program() begin assert(#size(Plain) = 2u); assert(#size(Spread) = 16u); @@ -36,6 +36,4 @@ begin first := @spread.a; second := @spread.b; assert(cast(second: Word) - cast(first: Word) = 8u) -return 0u8 - end. diff --git a/testsuite/runnable/array_constructor.elna b/testsuite/runnable/array_constructor.elna index 50d243a..fd22235 100644 --- a/testsuite/runnable/array_constructor.elna +++ b/testsuite/runnable/array_constructor.elna @@ -1,14 +1,12 @@ +program() 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); 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 4f0fc97..6380f24 100644 --- a/testsuite/runnable/binary_literal.elna +++ b/testsuite/runnable/binary_literal.elna @@ -2,6 +2,4 @@ program() begin assert(0b11 = 3u); assert(0B011 = 3u) -return 0u8 - end. diff --git a/testsuite/runnable/block_local_variable.elna b/testsuite/runnable/block_local_variable.elna index 6287eec..8d52b1c 100644 --- a/testsuite/runnable/block_local_variable.elna +++ b/testsuite/runnable/block_local_variable.elna @@ -1,6 +1,7 @@ program() var total: Int := 0 + begin if total = 0 then var @@ -9,6 +10,4 @@ begin total := total + inner end; assert(total = 7) -return 0u8 - end. diff --git a/testsuite/runnable/case_constant_label.elna b/testsuite/runnable/case_constant_label.elna index 49fa2c2..1b01736 100644 --- a/testsuite/runnable/case_constant_label.elna +++ b/testsuite/runnable/case_constant_label.elna @@ -1,16 +1,14 @@ +program() var base: const Int := 2 limit: const Int := base x: Int := 2 matched: Bool := false -program() begin case x of 1: assert(false) | limit: matched := true end; assert(matched) -return 0u8 - end. diff --git a/testsuite/runnable/case_else.elna b/testsuite/runnable/case_else.elna index 68330da..bc84069 100644 --- a/testsuite/runnable/case_else.elna +++ b/testsuite/runnable/case_else.elna @@ -1,8 +1,8 @@ +program() var x: Int := 5 matched: Bool := false -program() begin case x of 1: assert(false) @@ -12,6 +12,4 @@ begin matched := true end; assert(matched) -return 0u8 - end. diff --git a/testsuite/runnable/case_int.elna b/testsuite/runnable/case_int.elna index 3a446d6..018018c 100644 --- a/testsuite/runnable/case_int.elna +++ b/testsuite/runnable/case_int.elna @@ -1,7 +1,7 @@ +program() var x: Int := 2 -program() begin case x of 1: assert(false) @@ -10,6 +10,4 @@ begin else assert(false) end -return 0u8 - end. diff --git a/testsuite/runnable/case_multilabel.elna b/testsuite/runnable/case_multilabel.elna index 3a042d2..44bb150 100644 --- a/testsuite/runnable/case_multilabel.elna +++ b/testsuite/runnable/case_multilabel.elna @@ -1,7 +1,7 @@ +program() var x: Int := 3 -program() begin case x of 1, 2, 3: assert(true) @@ -9,6 +9,4 @@ begin else assert(false) end -return 0u8 - end. diff --git a/testsuite/runnable/case_record.elna b/testsuite/runnable/case_record.elna index 25b3eb4..db8a6ff 100644 --- a/testsuite/runnable/case_record.elna +++ b/testsuite/runnable/case_record.elna @@ -1,3 +1,4 @@ +program() type R = record a: Int; @@ -7,7 +8,6 @@ type var r: R := R{a: 1, b: 2} -program() begin case r of R{a: 0, b: 0}: assert(false) @@ -15,6 +15,4 @@ 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 825e8d5..5ce10a0 100644 --- a/testsuite/runnable/compile_time_array_access.elna +++ b/testsuite/runnable/compile_time_array_access.elna @@ -1,10 +1,8 @@ +program() var array: const [3]Int := [1, 2, 3] i: const Int := array[2] -program() begin assert(i = 2) -return 0u8 - end. diff --git a/testsuite/runnable/const_copy.elna b/testsuite/runnable/const_copy.elna index fde423b..3b7cd1b 100644 --- a/testsuite/runnable/const_copy.elna +++ b/testsuite/runnable/const_copy.elna @@ -1,3 +1,4 @@ +program() proc f() var x: const Int := 5 @@ -7,9 +8,6 @@ begin assert(y = 5) return -program() begin f() -return 0u8 - end. diff --git a/testsuite/runnable/const_initialization.elna b/testsuite/runnable/const_initialization.elna index b388845..b4272f4 100644 --- a/testsuite/runnable/const_initialization.elna +++ b/testsuite/runnable/const_initialization.elna @@ -1,3 +1,4 @@ +program() proc f() var x: const Int := 5 @@ -5,9 +6,6 @@ begin assert(x = 5) return -program() begin f() -return 0u8 - end. diff --git a/testsuite/runnable/constant_string_initializer.elna b/testsuite/runnable/constant_string_initializer.elna index 0982373..b33b255 100644 --- a/testsuite/runnable/constant_string_initializer.elna +++ b/testsuite/runnable/constant_string_initializer.elna @@ -1,9 +1,7 @@ +program() var s: []const Word8 := "String value" -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 bd4ba68..13bb357 100644 --- a/testsuite/runnable/define_multiple_local_variables.elna +++ b/testsuite/runnable/define_multiple_local_variables.elna @@ -1,11 +1,9 @@ +program() proc f() -> Bool var a, b: Int := 5 return a = 5 & b = 5 -program() begin assert(f()) -return 0u8 - end. diff --git a/testsuite/runnable/exported_variable/helper.elna b/testsuite/runnable/exported_variable/helper.elna index 23924be..4b2c9ba 100644 --- a/testsuite/runnable/exported_variable/helper.elna +++ b/testsuite/runnable/exported_variable/helper.elna @@ -1,3 +1,5 @@ +module + var Shared*: Int := 42 diff --git a/testsuite/runnable/exported_variable/sut.elna b/testsuite/runnable/exported_variable/sut.elna index 753293d..1d0449e 100644 --- a/testsuite/runnable/exported_variable/sut.elna +++ b/testsuite/runnable/exported_variable/sut.elna @@ -1,8 +1,6 @@ +program() 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 7ccf2fb..f00fd60 100644 --- a/testsuite/runnable/fixed_int_max.elna +++ b/testsuite/runnable/fixed_int_max.elna @@ -4,6 +4,4 @@ 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 f9522fd..fd6b110 100644 --- a/testsuite/runnable/fixed_int_min.elna +++ b/testsuite/runnable/fixed_int_min.elna @@ -4,6 +4,4 @@ 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 8fb8d27..c657614 100644 --- a/testsuite/runnable/fixed_word_max.elna +++ b/testsuite/runnable/fixed_word_max.elna @@ -4,6 +4,4 @@ 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 e98a26d..f792b04 100644 --- a/testsuite/runnable/float_arithmetic.elna +++ b/testsuite/runnable/float_arithmetic.elna @@ -11,6 +11,4 @@ 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/float_cast.elna b/testsuite/runnable/float_cast.elna index 08d14c5..26cb0d2 100644 --- a/testsuite/runnable/float_cast.elna +++ b/testsuite/runnable/float_cast.elna @@ -1,12 +1,10 @@ +program() var folded: Int := cast(2.9: Int) measure: Double := -2.9 -program() begin assert(folded = 2); assert(cast(measure: Int) = -2); assert(cast(folded: Double) = 2.0) -return 0u8 - end. diff --git a/testsuite/runnable/for_call.elna b/testsuite/runnable/for_call.elna index a2fcd06..6c72b38 100644 --- a/testsuite/runnable/for_call.elna +++ b/testsuite/runnable/for_call.elna @@ -1,3 +1,4 @@ +program() var actual: [2]Int := [0, 0] @@ -6,12 +7,9 @@ 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 04f0404..7a350a0 100644 --- a/testsuite/runnable/for_defer.elna +++ b/testsuite/runnable/for_defer.elna @@ -1,7 +1,7 @@ +program() var array: [2]Int := [0, 0] -program() begin for x of array do defer @@ -9,6 +9,4 @@ 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 6eae577..5a754da 100644 --- a/testsuite/runnable/for_each_array.elna +++ b/testsuite/runnable/for_each_array.elna @@ -1,15 +1,13 @@ +program() var actual: [4]Word := [0u, 0u, 0u, 0u] input: [4]Word := [2u, 4u, 6u, 8u] i: Word := 1u -program() begin for element of input do actual[i] := element^ * 2u; 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 bfc8b44..31bc65a 100644 --- a/testsuite/runnable/for_each_slice.elna +++ b/testsuite/runnable/for_each_slice.elna @@ -1,10 +1,10 @@ +program() var actual: [4]Word := [0u, 0u, 0u, 0u] input: [4]Word := [2u, 4u, 6u, 8u] slice: []Word i: Word := 1u -program() begin slice := input[1u to input.length]; @@ -13,6 +13,4 @@ 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 0859ed0..b3727f6 100644 --- a/testsuite/runnable/for_with.elna +++ b/testsuite/runnable/for_with.elna @@ -1,11 +1,10 @@ program() var actual: [3]Word := [0u, 0u, 0u] + 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_base.elna b/testsuite/runnable/generic_base.elna index c36eccf..63737e0 100644 --- a/testsuite/runnable/generic_base.elna +++ b/testsuite/runnable/generic_base.elna @@ -1,3 +1,4 @@ +program() type File = record fd: Int @@ -29,7 +30,6 @@ begin target^.tail := value return -program() begin seen := @jobs; enqueue(@jobs, @f); @@ -37,6 +37,4 @@ begin assert(jobs.head = @f); assert(jobs.tail = @f); assert(#size(Queue#[^File]) = #size(Pointer) * 3u) -return 0u8 - end. diff --git a/testsuite/runnable/generic_constructor.elna b/testsuite/runnable/generic_constructor.elna index 201e1b1..d0a3f78 100644 --- a/testsuite/runnable/generic_constructor.elna +++ b/testsuite/runnable/generic_constructor.elna @@ -1,3 +1,4 @@ +program() type File = record fd: Int @@ -12,11 +13,8 @@ var s: Stack#[^File] f: File -program() begin s := Stack#[^File]{ top: 1u, items: @f }; assert(s.top = 1u); assert(s.items = @f) -return 0u8 - end. diff --git a/testsuite/runnable/generic_erasure.elna b/testsuite/runnable/generic_erasure.elna index eccc1d2..20862fa 100644 --- a/testsuite/runnable/generic_erasure.elna +++ b/testsuite/runnable/generic_erasure.elna @@ -1,3 +1,4 @@ +program() type File = record fd: Int @@ -18,7 +19,6 @@ begin target^.held := value return -program() begin f.fd := 7; b := 3u8; @@ -26,6 +26,4 @@ begin store#[^Word8](@bytes, @b); assert(files.held^.fd = 7); assert(bytes.held^ = 3u8) -return 0u8 - end. diff --git a/testsuite/runnable/generic_pointer_arithmetic.elna b/testsuite/runnable/generic_pointer_arithmetic.elna index fe1e197..209287d 100644 --- a/testsuite/runnable/generic_pointer_arithmetic.elna +++ b/testsuite/runnable/generic_pointer_arithmetic.elna @@ -1,16 +1,14 @@ +program() var base: [4]Int element: ^Int first: Pointer second: Pointer -program() begin element := base.ptr; first := element; second := first + 1; assert(cast(second : Word) - cast(first : Word) = 1u); assert(second - 1 = first) -return 0u8 - end. diff --git a/testsuite/runnable/generic_record.elna b/testsuite/runnable/generic_record.elna index 8a334ce..4164c3d 100644 --- a/testsuite/runnable/generic_record.elna +++ b/testsuite/runnable/generic_record.elna @@ -1,3 +1,4 @@ +program() type File = record fd: Int @@ -18,12 +19,9 @@ begin target^.top := target^.top + 1u return -program() begin s.top := 0u; push#[^File](@s, @f); assert(s.top = 1u); assert(s.items = @f) -return 0u8 - end. diff --git a/testsuite/runnable/hexadecimal_literal.elna b/testsuite/runnable/hexadecimal_literal.elna index 02bc4c5..a168bd2 100644 --- a/testsuite/runnable/hexadecimal_literal.elna +++ b/testsuite/runnable/hexadecimal_literal.elna @@ -2,6 +2,4 @@ program() begin assert(0xff = 255u); assert(0X0f = 15u) -return 0u8 - end. diff --git a/testsuite/runnable/multi_module/helper.elna b/testsuite/runnable/multi_module/helper.elna index 5fd68af..c3c0bfd 100644 --- a/testsuite/runnable/multi_module/helper.elna +++ b/testsuite/runnable/multi_module/helper.elna @@ -1,3 +1,5 @@ +module + proc multiply*(x, y: Int) -> Int return x * y diff --git a/testsuite/runnable/multi_module/sut.elna b/testsuite/runnable/multi_module/sut.elna index 5ad6860..4b6e176 100644 --- a/testsuite/runnable/multi_module/sut.elna +++ b/testsuite/runnable/multi_module/sut.elna @@ -1,8 +1,6 @@ +program() import helper -program() begin assert(multiply(3, 4) = 12) -return 0u8 - end. diff --git a/testsuite/runnable/named_block.elna b/testsuite/runnable/named_block.elna index a9c44ed..0ba7eff 100644 --- a/testsuite/runnable/named_block.elna +++ b/testsuite/runnable/named_block.elna @@ -1,7 +1,7 @@ +program() var counter: Int := 0 -program() begin block outer while true do @@ -13,6 +13,4 @@ begin end end; assert(counter = 11) -return 0u8 - end. diff --git a/testsuite/runnable/procedure_cast.elna b/testsuite/runnable/procedure_cast.elna index 724fadf..191afbf 100644 --- a/testsuite/runnable/procedure_cast.elna +++ b/testsuite/runnable/procedure_cast.elna @@ -1,12 +1,11 @@ -var cb: proc(x: ^Char) -> Int +program() +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) -return 0u8 - end. diff --git a/testsuite/runnable/record_base_assignment.elna b/testsuite/runnable/record_base_assignment.elna index 5f84f20..7ad17e0 100644 --- a/testsuite/runnable/record_base_assignment.elna +++ b/testsuite/runnable/record_base_assignment.elna @@ -1,3 +1,4 @@ +program() type B = record x: Word @@ -16,9 +17,6 @@ begin assert(r.x = 3u & r.y = 2u) return -program() begin f() -return 0u8 - end. diff --git a/testsuite/runnable/record_base_constructor.elna b/testsuite/runnable/record_base_constructor.elna index 52936e9..80b6802 100644 --- a/testsuite/runnable/record_base_constructor.elna +++ b/testsuite/runnable/record_base_constructor.elna @@ -1,3 +1,4 @@ +program() type Base = record a: Int @@ -12,11 +13,8 @@ type var g: Grandchild := Grandchild{a: 3, b: 5, c: 7} -program() 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 ca99859..5a3a254 100644 --- a/testsuite/runnable/record_construction.elna +++ b/testsuite/runnable/record_construction.elna @@ -1,3 +1,4 @@ +program() type R = record x, y: Int @@ -6,9 +7,6 @@ type var r: R := R{x: 1, y: 2} -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 5f61d60..95165f4 100644 --- a/testsuite/runnable/record_extension.elna +++ b/testsuite/runnable/record_extension.elna @@ -1,3 +1,4 @@ +program() type ElnaLexerToken = record kind: Word @@ -10,12 +11,9 @@ var token_memory: ElnaLexerStringToken current_token: ^ElnaLexerToken -program() begin current_token := @token_memory; 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 6150a32..a3e64c4 100644 --- a/testsuite/runnable/record_layout.elna +++ b/testsuite/runnable/record_layout.elna @@ -1,3 +1,4 @@ +program() type IntChar = record x: Int; @@ -50,9 +51,6 @@ begin assert(array_record_c_offset = 3u * int_size) return -program() begin f() -return 0u8 - end. diff --git a/testsuite/runnable/recursive_record.elna b/testsuite/runnable/recursive_record.elna index 5c59e64..48fb873 100644 --- a/testsuite/runnable/recursive_record.elna +++ b/testsuite/runnable/recursive_record.elna @@ -1,3 +1,4 @@ +program() type Node = record value: Int; @@ -27,7 +28,6 @@ begin end; return result -program() begin first := malloc(#size(Node)); second := malloc(#size(Node)); @@ -46,6 +46,4 @@ 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 084b801..ff09735 100644 --- a/testsuite/runnable/repeat_loop.elna +++ b/testsuite/runnable/repeat_loop.elna @@ -1,14 +1,12 @@ +program() var actual: [4]Word := [0u, 0u, 0u, 0u] i: Word := 0u -program() begin repeat i := i + 1u; 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 4377d94..6959b60 100644 --- a/testsuite/runnable/return_aggregate.elna +++ b/testsuite/runnable/return_aggregate.elna @@ -1,3 +1,4 @@ +program() type R = record a: Int; @@ -7,9 +8,6 @@ type proc f() -> R 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 7a889a3..4d7ad7e 100644 --- a/testsuite/runnable/slice_array.elna +++ b/testsuite/runnable/slice_array.elna @@ -1,14 +1,12 @@ +program() var array: [3]Int := [2, 4, 6] slice: []Int -program() begin slice := array[1 to 3]; 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 0d4a861..d3309f9 100644 --- a/testsuite/runnable/slice_cast.elna +++ b/testsuite/runnable/slice_cast.elna @@ -1,9 +1,7 @@ +program() var ints: [4]Int32 := [1i32, 2i32, 3i32, 4i32] -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 1510f40..534afec 100644 --- a/testsuite/runnable/slice_equality.elna +++ b/testsuite/runnable/slice_equality.elna @@ -1,13 +1,11 @@ +program() 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]; assert(lhs = rhs) -return 0u8 - end. diff --git a/testsuite/runnable/slice_pointer.elna b/testsuite/runnable/slice_pointer.elna index c19e64a..150bda8 100644 --- a/testsuite/runnable/slice_pointer.elna +++ b/testsuite/runnable/slice_pointer.elna @@ -1,14 +1,12 @@ +program() var array: [3]Int := [2, 4, 6] slice: []Int -program() begin slice := array.ptr[1 to 3]; 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 fcfea8b..6395cea 100644 --- a/testsuite/runnable/slice_slice.elna +++ b/testsuite/runnable/slice_slice.elna @@ -1,8 +1,8 @@ +program() 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]; @@ -11,6 +11,4 @@ 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 af591e4..2b905b6 100644 --- a/testsuite/runnable/two_fields_same_type.elna +++ b/testsuite/runnable/two_fields_same_type.elna @@ -1,3 +1,4 @@ +program() type R = record x, y: Int @@ -8,9 +9,6 @@ var r: R := R{x: 3, y: 2} 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 08a1b5a..18e3d63 100644 --- a/testsuite/runnable/two_parameters_same_type.elna +++ b/testsuite/runnable/two_parameters_same_type.elna @@ -1,9 +1,8 @@ +program() + proc f(x, y: Int) -> Int 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 7f331d4..4df6922 100644 --- a/testsuite/runnable/unary_plus.elna +++ b/testsuite/runnable/unary_plus.elna @@ -1,11 +1,10 @@ +program() + proc f(x: Int) -> Int return +x -program() 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 f5a4b3f..0cfd3e2 100644 --- a/testsuite/runnable/unicode_escape_character.elna +++ b/testsuite/runnable/unicode_escape_character.elna @@ -2,6 +2,4 @@ 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 20be668..bec794a 100644 --- a/testsuite/runnable/unicode_escape_string.elna +++ b/testsuite/runnable/unicode_escape_string.elna @@ -2,6 +2,4 @@ program() begin assert("caf\{U+E9}" = "café"); assert("Hi \{U+1F600}!" = "Hi 😀!") -return 0u8 - end. diff --git a/testsuite/runnable/varargs.elna b/testsuite/runnable/varargs.elna index feeb94b..1bf16e9 100644 --- a/testsuite/runnable/varargs.elna +++ b/testsuite/runnable/varargs.elna @@ -1,3 +1,4 @@ +program() var buffer: [8]Word8 written: Int32 @@ -5,12 +6,9 @@ var proc snprintf(buffer: ^Word8; size: Word; format: ^const Word8) #{varargs} -> Int32 extern -program() begin written := snprintf(@buffer[1], 8u, "%d %.1f".ptr, 200u8, 1.5f); assert(written = 7i32); assert(buffer[1] = '2'); assert(buffer[7] = '5') -return 0u8 - end. -- cgit v1.2.3