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.cc141
1 files changed, 47 insertions, 94 deletions
diff --git a/boot/type_check.cc b/boot/type_check.cc
index ad27337..8f7a30f 100644
--- a/boot/type_check.cc
+++ b/boot/type_check.cc
@@ -18,7 +18,6 @@ along with GCC; see the file COPYING3. If not see
#include "elna/boot/type_check.h"
#include "elna/boot/evaluator.h"
-#include <algorithm>
#include <utility>
namespace elna::boot
@@ -222,25 +221,6 @@ namespace elna::boot
}
}
- cyclic_declaration_error::cyclic_declaration_error(const source_position position,
- const std::vector<std::string>& cycle)
- : diagnostic(position), cycle(cycle)
- {
- }
-
- std::string cyclic_declaration_error::what() const
- {
- auto segment = std::cbegin(this->cycle);
- std::string message = "Type declaration forms a cycle: " + *segment;
-
- ++segment;
- for (; segment != std::cend(this->cycle); ++segment)
- {
- message += " -> " + *segment;
- }
- return message;
- }
-
argument_count_error::argument_count_error(const source_position position, kind kind,
std::string applicand, std::size_t expected, std::size_t actual)
: diagnostic(position), m_kind(kind), applicand(std::move(applicand)), expected(expected), actual(actual)
@@ -301,7 +281,9 @@ namespace elna::boot
/*
* Finds the first opaque type in a value position, following aliases,
- * qualifiers, arrays, slices, records and procedures but not pointers.
+ * qualifiers, arrays, records and procedures but not pointers or slices.
+ * Pointers and slices don't store their base type by value, so an opaque
+ * behind them is only reachable as a transient value.
*/
static std::optional<type> find_opaque_type(const type& checked)
{
@@ -326,10 +308,6 @@ namespace elna::boot
{
return find_opaque_type(array->base);
}
- else if (auto slice = referent.get<slice_type>())
- {
- return find_opaque_type(slice->base);
- }
else if (auto procedure = referent.get<procedure_type>())
{
for (const type& parameter : procedure->parameters)
@@ -387,22 +365,6 @@ namespace elna::boot
|| (resolved_left.get<record_type>() && resolved_right.get<record_type>());
}
- bool type_analysis_visitor::check_unresolved_symbol(const std::shared_ptr<alias_type>& alias,
- std::vector<std::string>& alias_path)
- {
- if (std::ranges::find(alias_path, alias->name) != std::cend(alias_path))
- {
- return false;
- }
- alias_path.push_back(alias->name);
-
- if (auto another_alias = alias->referent.get<alias_type>())
- {
- return check_unresolved_symbol(another_alias, alias_path);
- }
- return true;
- }
-
void type_analysis_visitor::visit_and_validate_condition(expression& condition)
{
condition.accept(this);
@@ -797,78 +759,69 @@ namespace elna::boot
void type_analysis_visitor::visit(type_declaration *declaration)
{
- std::vector<std::string> alias_path;
+ walking_visitor::visit(declaration);
auto unresolved_type = this->bag.lookup(declaration->identifier.name())->is_type()->symbol.get<alias_type>();
+ const type referent = resolve_aliases(unresolved_type->referent);
- if (!check_unresolved_symbol(unresolved_type, alias_path))
- {
- add_error<cyclic_declaration_error>(declaration->position(), alias_path);
- }
- else
+ if (auto record = referent.get<record_type>())
{
- walking_visitor::visit(declaration);
- const type referent = resolve_aliases(unresolved_type->referent);
-
- if (auto record = referent.get<record_type>())
+ for (const auto& [field_name, field_type] : record->fields)
{
- for (const auto& [field_name, field_type] : record->fields)
+ if (auto opaque = find_opaque_type(field_type))
{
- if (auto opaque = find_opaque_type(field_type))
- {
- add_error<type_requirement_error>(declaration->position(),
- opaque.value(), type_requirement_error::kind::opaque_field);
- }
- else if (has_zero_size(field_type, this->target))
- {
- add_error<type_requirement_error>(declaration->position(),
- field_type, type_requirement_error::kind::zero_sized);
- }
+ add_error<type_requirement_error>(declaration->position(),
+ opaque.value(), type_requirement_error::kind::opaque_field);
}
- }
- else if (auto array = referent.get<array_type>())
- {
- if (auto opaque = find_opaque_type(array->base))
+ else if (has_zero_size(field_type, this->target))
{
add_error<type_requirement_error>(declaration->position(),
- opaque.value(), type_requirement_error::kind::opaque_element);
+ field_type, type_requirement_error::kind::zero_sized);
}
}
- else if (auto slice = referent.get<slice_type>())
+ }
+ else if (auto array = referent.get<array_type>())
+ {
+ if (auto opaque = find_opaque_type(array->base))
+ {
+ add_error<type_requirement_error>(declaration->position(),
+ opaque.value(), type_requirement_error::kind::opaque_element);
+ }
+ }
+ else if (auto slice = referent.get<slice_type>())
+ {
+ if (auto opaque = find_opaque_type(slice->base))
{
- if (auto opaque = find_opaque_type(slice->base))
+ add_error<type_requirement_error>(declaration->position(),
+ opaque.value(), type_requirement_error::kind::opaque_element);
+ }
+ }
+ else if (auto procedure = referent.get<procedure_type>())
+ {
+ for (const type& parameter : procedure->parameters)
+ {
+ if (auto opaque = find_opaque_type(parameter))
+ {
+ add_error<type_requirement_error>(declaration->position(),
+ opaque.value(), type_requirement_error::kind::opaque_parameter);
+ }
+ else if (has_zero_size(parameter, this->target))
{
add_error<type_requirement_error>(declaration->position(),
- opaque.value(), type_requirement_error::kind::opaque_element);
+ parameter, type_requirement_error::kind::zero_sized);
}
}
- else if (auto procedure = referent.get<procedure_type>())
+ if (!procedure->return_type.proper_type.empty())
{
- for (const type& parameter : procedure->parameters)
+ if (auto opaque = find_opaque_type(procedure->return_type.proper_type))
{
- if (auto opaque = find_opaque_type(parameter))
- {
- add_error<type_requirement_error>(declaration->position(),
- opaque.value(), type_requirement_error::kind::opaque_parameter);
- }
- else if (has_zero_size(parameter, this->target))
- {
- add_error<type_requirement_error>(declaration->position(),
- parameter, type_requirement_error::kind::zero_sized);
- }
+ add_error<type_requirement_error>(declaration->position(),
+ opaque.value(), type_requirement_error::kind::opaque_return);
}
- if (!procedure->return_type.proper_type.empty())
+ else if (has_zero_size(procedure->return_type.proper_type, this->target))
{
- if (auto opaque = find_opaque_type(procedure->return_type.proper_type))
- {
- add_error<type_requirement_error>(declaration->position(),
- opaque.value(), type_requirement_error::kind::opaque_return);
- }
- else if (has_zero_size(procedure->return_type.proper_type, this->target))
- {
- add_error<type_requirement_error>(declaration->position(),
- procedure->return_type.proper_type,
- type_requirement_error::kind::zero_sized);
- }
+ add_error<type_requirement_error>(declaration->position(),
+ procedure->return_type.proper_type,
+ type_requirement_error::kind::zero_sized);
}
}
}