aboutsummaryrefslogtreecommitdiff
path: root/boot
diff options
context:
space:
mode:
Diffstat (limited to 'boot')
-rw-r--r--boot/name_analysis.cc20
-rw-r--r--boot/symbol.cc25
-rw-r--r--boot/type_check.cc19
3 files changed, 38 insertions, 26 deletions
diff --git a/boot/name_analysis.cc b/boot/name_analysis.cc
index 620a32f..70b9031 100644
--- a/boot/name_analysis.cc
+++ b/boot/name_analysis.cc
@@ -385,23 +385,15 @@ namespace elna::boot
type resolving_visitor::lookup_field(const type& composite_type, const std::string& field_name)
{
- const type resolved_type = resolve_underlying_type(composite_type);
+ type record_field = elna::boot::lookup_field(composite_type, field_name);
- if (auto record = resolved_type.get<record_type>())
+ if (!record_field.empty())
{
- for (auto& field : record->fields)
- {
- if (field.first == field_name)
- {
- return field.second;
- }
- }
- if (!record->base.empty())
- {
- return lookup_field(record->base, field_name);
- }
+ return record_field;
}
- else if (auto range_base = get_range_base_type(resolved_type))
+ const type resolved_type = resolve_underlying_type(composite_type);
+
+ if (auto range_base = get_range_base_type(resolved_type))
{
if (auto field = lookup_pointer_like_field(field_name, range_base))
{
diff --git a/boot/symbol.cc b/boot/symbol.cc
index 4d6832d..0d847e1 100644
--- a/boot/symbol.cc
+++ b/boot/symbol.cc
@@ -176,11 +176,11 @@ namespace elna::boot
if (payload->return_type.no_return)
{
- result += ": !";
+ result += " -> !";
}
else if (!payload->return_type.proper_type.empty())
{
- result += ": " + payload->return_type.proper_type.to_string();
+ result += " -> " + payload->return_type.proper_type.to_string();
}
return result;
}
@@ -570,4 +570,25 @@ namespace elna::boot
}
return type();
}
+
+ type lookup_field(const type& composite_type, const std::string& field_name)
+ {
+ const type resolved_type = resolve_underlying_type(composite_type);
+
+ if (auto record = resolved_type.get<record_type>())
+ {
+ for (const auto& [name, field_type] : record->fields)
+ {
+ if (name == field_name)
+ {
+ return field_type;
+ }
+ }
+ if (!record->base.empty())
+ {
+ return lookup_field(record->base, field_name);
+ }
+ }
+ return type();
+ }
}
diff --git a/boot/type_check.cc b/boot/type_check.cc
index 8f7a30f..abee91f 100644
--- a/boot/type_check.cc
+++ b/boot/type_check.cc
@@ -911,17 +911,16 @@ namespace elna::boot
}
for (const field_initializer& initializer : expression->field_initializers)
{
- for (const auto& [field_name, field_type]: record->fields)
+ // An initializer for an unknown field is already reported in name
+ // analysis; only check the value type when the field was found.
+ const type field_type = lookup_field(expression->type_decoration, initializer.name());
+
+ if (!field_type.empty()
+ && !is_assignable_from(field_type, initializer.value().type_decoration))
{
- if (field_name == initializer.name())
- {
- if (!is_assignable_from(field_type, initializer.value().type_decoration))
- {
- add_error<type_mismatch_error>(
- initializer.value().position(), initializer.value().type_decoration, type_mismatch_error::expected_type{field_type});
- }
- break;
- }
+ add_error<type_mismatch_error>(
+ initializer.value().position(), initializer.value().type_decoration,
+ type_mismatch_error::expected_type{field_type});
}
}
}