diff options
Diffstat (limited to 'boot/type_check.cc')
| -rw-r--r-- | boot/type_check.cc | 63 |
1 files changed, 22 insertions, 41 deletions
diff --git a/boot/type_check.cc b/boot/type_check.cc index 1689e65..761c4b2 100644 --- a/boot/type_check.cc +++ b/boot/type_check.cc @@ -93,14 +93,23 @@ namespace elna::boot + "' is expected to return, but does not have a return statement"; } - base_type_error::base_type_error(type actual, const source_position position) - : error(position), actual(std::move(actual)) + type_kind_error::type_kind_error(const source_position position, kind type_kind, const type& actual) + : error(position), type_kind(type_kind), actual(actual) { } - std::string base_type_error::what() const + std::string type_kind_error::what() const { - return "'" + actual.to_string() + "' is not a record type"; + switch (this->type_kind) + { + case kind::record_base: + return "'" + this->actual.to_string() + "' is not a record type"; + case kind::for_loop: + return "for-loop variable must be an array or a slice, got '" + + this->actual.to_string() + "'"; + default: + __builtin_unreachable(); + } } argument_count_error::argument_count_error(std::size_t expected, std::size_t actual, @@ -467,31 +476,13 @@ namespace elna::boot void type_analysis_visitor::visit(for_statement *statement) { - statement->initial_value().accept(this); - type const initial_type = resolve_underlying_type(statement->initial_value().type_decoration); + statement->range().accept(this); + auto resolved_range = resolve_underlying_type(statement->range().type_decoration); - if (!is_integral_type(initial_type)) - { - add_error<for_loop_type_error>( - statement->initial_value().position(), - statement->initial_value().type_decoration); - } - statement->final_value().accept(this); - if (!is_assignable_from(initial_type, statement->final_value().type_decoration)) - { - add_error<type_mismatch_error>( - statement->final_value().position(), - initial_type, statement->final_value().type_decoration); - } - if (statement->step != nullptr) + if (!get_range_base_type(resolved_range)) { - statement->step->accept(this); - if (!is_assignable_from(initial_type, statement->step->type_decoration)) - { - add_error<type_mismatch_error>( - statement->step->position(), - initial_type, statement->step->type_decoration); - } + add_error<type_kind_error>(statement->range().position(), type_kind_error::kind::for_loop, + statement->range().type_decoration); } this->bag.enter(statement->symbols); for (auto *body_statement : statement->body) @@ -523,14 +514,16 @@ namespace elna::boot auto const base_symbol = this->bag.lookup(expression->base.value().name()); if (base_symbol == nullptr || base_symbol->is_type() == nullptr) { - add_error<base_type_error>(type(), expression->position()); + add_error<type_kind_error>(expression->position(), + type_kind_error::kind::record_base, type()); } else { type const base_type = resolve_underlying_type(base_symbol->is_type()->symbol); if (base_type.get<record_type>() == nullptr) { - add_error<base_type_error>(base_type, expression->position()); + add_error<type_kind_error>(expression->position(), + type_kind_error::kind::record_base, base_type); } } } @@ -685,18 +678,6 @@ namespace elna::boot } } - for_loop_type_error::for_loop_type_error(const source_position position, - type actual) - : error(position), actual(std::move(actual)) - { - } - - std::string for_loop_type_error::what() const - { - return "for-loop variable must be Int or Word, but got '" - + actual.to_string() + "'"; - } - binary_operation_error::binary_operation_error(const source_position position, type left, type right, binary_operator operation) : error(position), left(std::move(left)), right(std::move(right)), op(operation) |
