aboutsummaryrefslogtreecommitdiff
path: root/boot/type_check.cc
diff options
context:
space:
mode:
Diffstat (limited to 'boot/type_check.cc')
-rw-r--r--boot/type_check.cc63
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)