From 56a1244380133ab400f98d2da15353e080ffb360 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Thu, 15 Oct 2026 14:46:38 +0200 Subject: Restrict index types to Int and Word --- boot/driver.cc | 2 ++ boot/name_analysis.cc | 50 +++++++++++++++++++++++++++++++++++++++++++++++--- boot/symbol.cc | 15 +++++++++++++++ boot/type_check.cc | 8 ++++---- 4 files changed, 68 insertions(+), 7 deletions(-) (limited to 'boot') diff --git a/boot/driver.cc b/boot/driver.cc index 14575f7..be52f23 100644 --- a/boot/driver.cc +++ b/boot/driver.cc @@ -66,6 +66,8 @@ namespace elna::boot return '\''; case '"': return '"'; + case '`': + return '`'; case '0': return '\0'; default: diff --git a/boot/name_analysis.cc b/boot/name_analysis.cc index 36faee1..9305cd2 100644 --- a/boot/name_analysis.cc +++ b/boot/name_analysis.cc @@ -144,6 +144,11 @@ namespace elna::boot { return "All constants should be initialized"; } + else if constexpr (std::is_same_v) + { + return "Array dimension must be of type 'Word' or 'Int', but got '" + + payload.actual.to_string() + "'"; + } else if constexpr (std::is_same_v) { switch (payload) @@ -162,6 +167,8 @@ namespace elna::boot case enumeration_values: return "Enumeration values should be omitted, given for the first member only," " or given for all members"; + case array_dimension_size: + return "Array dimension must be greater than zero"; default: __builtin_unreachable(); } @@ -327,7 +334,7 @@ namespace elna::boot resolving_visitor::resolving_visitor(symbol_bag& bag, const target_info& target, const std::filesystem::path& module_path) - : bag(bag), constant_evaluator(this->bag, target), module_file(module_path) + : bag(bag), target(target), constant_evaluator(this->bag, target), module_file(module_path) { } @@ -580,15 +587,52 @@ namespace elna::boot this->current_type = type(); return; } - const auto size_constant = this->constant_evaluator.evaluate_index(expression->dimensions()); - if (!size_constant.has_value()) + if (!is_index_type(expression->dimensions().type_decoration, this->target)) + { + add_error(expression->dimensions().position(), + declaration_format_error::array_dimension_type{ expression->dimensions().type_decoration }); + this->current_type = type(); + return; + } + + const std::optional evaluated = + this->constant_evaluator.evaluate(expression->dimensions()); + + if (!evaluated.has_value()) + { + add_error(expression->position(), + non_constant_expression_error::array_dimensions{ array_base }); + this->current_type = type(); + return; + } + + const auto *literal = std::get_if(&evaluated.value()); + + if (literal == nullptr) { add_error(expression->position(), non_constant_expression_error::array_dimensions{ array_base }); this->current_type = type(); return; } + if (*literal <= 0) + { + add_error(expression->dimensions().position(), + declaration_format_error::kind::array_dimension_size); + this->current_type = type(); + return; + } + + const std::optional size_constant = literal->try_to(); + + if (!size_constant.has_value()) + { + add_error(expression->dimensions().position(), + declaration_format_error::kind::array_dimension_size); + this->current_type = type(); + return; + } this->current_type = type(std::make_shared(array_base, size_constant.value())); } diff --git a/boot/symbol.cc b/boot/symbol.cc index 8feba4a..310ae8a 100644 --- a/boot/symbol.cc +++ b/boot/symbol.cc @@ -830,6 +830,21 @@ namespace elna::boot || is_float_type(checked); } + bool is_index_type(const type& checked, const target_info& target) + { + const type unaliased = resolve_underlying_type(checked); + if (const auto primitive = unaliased.get()) + { + const bool is_int = primitive->identifier.starts_with("Int") + && primitive->properties.size == target.int_properties.front().size; + const bool is_word = primitive->identifier.starts_with("Word") + && primitive->properties.size == target.word_properties.front().size; + + return is_int || is_word; + } + return false; + } + bool is_integral_type(const type& checked) { return is_integer_type(checked) || is_word_type(checked); diff --git a/boot/type_check.cc b/boot/type_check.cc index 797282c..5a8170a 100644 --- a/boot/type_check.cc +++ b/boot/type_check.cc @@ -250,7 +250,7 @@ namespace elna::boot return "Condition must be a boolean expression, but got '" + this->actual.to_string() + "'"; case array_index: - return "Array index must be an integral type, but got '" + return "Array index must be of type 'Word' or 'Int', but got '" + this->actual.to_string() + "'"; case non_indexable: return "Indexing is not allowed on type '" @@ -1528,12 +1528,12 @@ namespace elna::boot { walking_visitor::visit(expression); - if (!is_integral_type(resolve_underlying_type(expression->start().type_decoration))) + if (!is_index_type(expression->start().type_decoration, this->target)) { add_error(expression->start().position(), expression->start().type_decoration, type_requirement_error::kind::array_index); } - if (!is_integral_type(resolve_underlying_type(expression->end().type_decoration))) + if (!is_index_type(expression->end().type_decoration, this->target)) { add_error(expression->end().position(), expression->end().type_decoration, type_requirement_error::kind::array_index); @@ -1551,7 +1551,7 @@ namespace elna::boot add_error(expression->position(), expression->base().type_decoration, type_requirement_error::kind::non_indexable); } - if (!is_integral_type(resolve_underlying_type(expression->index().type_decoration))) + if (!is_index_type(expression->index().type_decoration, this->target)) { add_error(expression->index().position(), expression->index().type_decoration, type_requirement_error::kind::array_index); -- cgit v1.2.3