aboutsummaryrefslogtreecommitdiff
path: root/boot/name_analysis.cc
diff options
context:
space:
mode:
Diffstat (limited to 'boot/name_analysis.cc')
-rw-r--r--boot/name_analysis.cc50
1 files changed, 47 insertions, 3 deletions
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<T, array_dimension_type>)
+ {
+ return "Array dimension must be of type 'Word' or 'Int', but got '"
+ + payload.actual.to_string() + "'";
+ }
else if constexpr (std::is_same_v<T, kind>)
{
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<declaration_format_error>(expression->dimensions().position(),
+ declaration_format_error::array_dimension_type{ expression->dimensions().type_decoration });
+ this->current_type = type();
+ return;
+ }
+
+ const std::optional<constant_value> evaluated =
+ this->constant_evaluator.evaluate(expression->dimensions());
+
+ if (!evaluated.has_value())
+ {
+ add_error<non_constant_expression_error>(expression->position(),
+ non_constant_expression_error::array_dimensions{ array_base });
+ this->current_type = type();
+ return;
+ }
+
+ const auto *literal = std::get_if<integer_literal>(&evaluated.value());
+
+ if (literal == nullptr)
{
add_error<non_constant_expression_error>(expression->position(),
non_constant_expression_error::array_dimensions{ array_base });
this->current_type = type();
return;
}
+ if (*literal <= 0)
+ {
+ add_error<declaration_format_error>(expression->dimensions().position(),
+ declaration_format_error::kind::array_dimension_size);
+ this->current_type = type();
+ return;
+ }
+
+ const std::optional<std::uint64_t> size_constant = literal->try_to<std::uint64_t>();
+
+ if (!size_constant.has_value())
+ {
+ add_error<declaration_format_error>(expression->dimensions().position(),
+ declaration_format_error::kind::array_dimension_size);
+ this->current_type = type();
+ return;
+ }
this->current_type = type(std::make_shared<array_type>(array_base, size_constant.value()));
}