diff options
| author | Eugen Wissner <belka@caraus.de> | 2026-07-23 01:01:03 +0200 |
|---|---|---|
| committer | Eugen Wissner <belka@caraus.de> | 2026-07-23 01:01:03 +0200 |
| commit | 275fa4bff6d153019b6914fed7127a7d919ca177 (patch) | |
| tree | 37f8ef0d49c304fe0fde47ce7d4b3ea32ffce707 /boot/name_analysis.cc | |
| parent | bd9fe800349dc139cc5841980bcae96e0d18e2db (diff) | |
| download | elna-275fa4bff6d153019b6914fed7127a7d919ca177.tar.gz | |
Implement for loop
Diffstat (limited to 'boot/name_analysis.cc')
| -rw-r--r-- | boot/name_analysis.cc | 259 |
1 files changed, 143 insertions, 116 deletions
diff --git a/boot/name_analysis.cc b/boot/name_analysis.cc index 907f318..f932a5d 100644 --- a/boot/name_analysis.cc +++ b/boot/name_analysis.cc @@ -21,127 +21,120 @@ along with GCC; see the file COPYING3. If not see namespace elna::boot { - declaration_error::declaration_error(const kind error_kind, - const boot::identifier& identifier) - : error(identifier.position()), identifier(identifier.name()), error_kind(error_kind) + symbol_error::symbol_error(const source_position position, payload_type payload) + : error(position), payload(std::move(payload)) { } - std::string declaration_error::what() const + std::string symbol_error::what() const { - switch (this->error_kind) - { - case kind::undeclared: - return "Type '" + identifier + "' not declared"; - case kind::local_export: - return "Local symbol '" + this->identifier + "' cannot be exported"; - default: - __builtin_unreachable(); - } - } - - redefinition_error::redefinition_error(const boot::identifier& identifier, - std::optional<source_position> original) - : error(identifier.position()), identifier(identifier.name()), original(original) - { - } - - std::string redefinition_error::what() const - { - return "Symbol '" + identifier + "' has been already defined"; + return std::visit([](const auto& pay) -> std::string { + using T = std::decay_t<decltype(pay)>; + if constexpr (std::is_same_v<T, undeclared>) + { + return "Type '" + pay.name + "' not declared"; + } + else if constexpr (std::is_same_v<T, local_export>) + { + return "Local symbol '" + pay.name + "' cannot be exported"; + } + else if constexpr (std::is_same_v<T, redefinition>) + { + return "Symbol '" + pay.name + "' has been already defined"; + } + }, payload); } - std::optional<std::pair<std::string, source_position>> redefinition_error::note() const + std::optional<std::pair<std::string, source_position>> symbol_error::note() const { - if (original.has_value() && original->start().available()) + if (const auto *redef = std::get_if<redefinition>(&payload)) { - return std::make_pair("previously declared here", *original); + if (redef->original.has_value() && redef->original->start().available()) + { + return std::make_pair("previously declared here", *redef->original); + } } return std::nullopt; } - const_array_error::const_array_error(const source_position position) - : error(position) - { - } - - std::string const_array_error::what() const - { - return "const must be written before the array size, not after"; - } - - double_const_error::double_const_error(const source_position position) - : error(position) - { - } - - std::string double_const_error::what() const - { - return "Duplicate 'const' qualifier is not allowed"; - } - - field_not_found_error::field_not_found_error(const identifier& field_name, - type composite_type) - : error(field_name.position()), field_name(field_name.name()), composite_type(std::move(composite_type)) + const_qualifier_error::const_qualifier_error(const source_position position, kind error_kind) + : error(position), error_kind(error_kind) { } - std::string field_not_found_error::what() const + std::string const_qualifier_error::what() const { - type const resolved = resolve_underlying_type(composite_type); - bool const is_enum = resolved.get<enumeration_type>() != nullptr; - bool const is_record = resolved.get<record_type>() != nullptr; - - if (is_enum || is_record) + switch (error_kind) { - std::string message = is_enum ? "Enumeration" : "Record"; - - if (auto alias = composite_type.get<alias_type>()) - { - message += " '" + alias->name + "'"; - } - message += " does not have a "; - message += is_enum ? "member" : "field"; - message += " named '" + field_name + "'"; - return message; + case kind::array_position: + return "const must be written before the array size, not after"; + case kind::duplicate: + return "Duplicate 'const' qualifier is not allowed"; + default: + __builtin_unreachable(); } - return "Type '" + composite_type.to_string() - + "' does not have a field named '" + field_name + "'"; } - duplicate_member_error::duplicate_member_error(const boot::identifier& member_name, - type aggregate, std::optional<source_position> original, - std::optional<std::string> base_name) - : error(member_name.position()), member_name(member_name.name()), aggregate(std::move(aggregate)), - original(original), base_name(std::move(base_name)) + member_error::member_error(const source_position position, payload_type payload) + : error(position), payload(std::move(payload)) { } - std::string duplicate_member_error::what() const + std::string member_error::what() const { - type const resolved = resolve_underlying_type(aggregate); - bool const is_enum = resolved.get<enumeration_type>() != nullptr; - std::string const kind = is_enum ? "member" : "field"; - std::string message = is_enum ? "Enumeration" : "Record"; + return std::visit([](const auto& pay) -> std::string { + using T = std::decay_t<decltype(pay)>; + if constexpr (std::is_same_v<T, not_found>) + { + const type resolved = resolve_underlying_type(pay.composite); + const bool is_enum = resolved.get<enumeration_type>() != nullptr; + const bool is_record = resolved.get<record_type>() != nullptr; - if (auto alias = aggregate.get<alias_type>()) - { - message += " '" + alias->name + "'"; - } - message += " already has a " + kind + " named '" + member_name + "'"; + if (is_enum || is_record) + { + std::string message = is_enum ? "Enumeration" : "Record"; + if (auto alias = pay.composite.template get<alias_type>()) + { + message += " '" + alias->name + "'"; + } + message += " does not have a "; + message += is_enum ? "member" : "field"; + message += " named '" + pay.name + "'"; + return message; + } + return "Type '" + pay.composite.to_string() + + "' does not have a field named '" + pay.name + "'"; + } + else if constexpr (std::is_same_v<T, duplicate>) + { + const type resolved = resolve_underlying_type(pay.aggregate); + const bool is_enum = resolved.get<enumeration_type>() != nullptr; + const std::string kind = is_enum ? "member" : "field"; + std::string message = is_enum ? "Enumeration" : "Record"; - if (base_name.has_value()) - { - message += " (defined in base type '" + *base_name + "')"; - } - return message; + if (auto alias = pay.aggregate.template get<alias_type>()) + { + message += " '" + alias->name + "'"; + } + message += " already has a " + kind + " named '" + pay.name + "'"; + + if (pay.base.has_value()) + { + message += " (defined in base type '" + *pay.base + "')"; + } + return message; + } + }, payload); } - std::optional<std::pair<std::string, source_position>> duplicate_member_error::note() const + std::optional<std::pair<std::string, source_position>> member_error::note() const { - if (original.has_value() && original->start().available()) + if (const auto *dup = std::get_if<duplicate>(&payload)) { - return std::make_pair("previously declared here", *original); + if (dup->original.has_value() && dup->original->start().available()) + { + return std::make_pair("previously declared here", *dup->original); + } } return std::nullopt; } @@ -231,7 +224,7 @@ namespace elna::boot type name_analysis_visitor::lookup_field(const type& composite_type, const std::string& field_name) { - type const resolved_type = resolve_underlying_type(composite_type); + const type resolved_type = resolve_underlying_type(composite_type); if (auto record = resolved_type.get<record_type>()) { @@ -287,7 +280,8 @@ namespace elna::boot if (this->current_type.get<constant_type>() != nullptr) { - add_error<double_const_error>(expression->position()); + add_error<const_qualifier_error>(expression->position(), + const_qualifier_error::kind::duplicate); } this->current_type = type(std::make_shared<constant_type>(this->current_type)); } @@ -298,7 +292,8 @@ namespace elna::boot if (this->current_type.get<constant_type>() != nullptr) { - add_error<const_array_error>(expression->position()); + add_error<const_qualifier_error>(expression->position(), + const_qualifier_error::kind::array_position); } this->current_type = type(std::make_shared<array_type>(this->current_type, expression->size)); } @@ -355,8 +350,9 @@ namespace elna::boot base_name = alias->name; } } - add_error<duplicate_member_error>(field_name, aggregate, - existing->second.declaration, base_name); + add_error<member_error>(field_name.position(), + member_error::duplicate{.name = field_name.name(), .aggregate = aggregate, + .original = existing->second.declaration, .base = base_name}); } else { @@ -392,8 +388,8 @@ namespace elna::boot } else { - add_error<declaration_error>(declaration_error::kind::undeclared, - expression->base.value()); + add_error<symbol_error>(expression->base.value().position(), + symbol_error::undeclared{.name = expression->base.value().name()}); this->current_type = type(); return; } @@ -421,8 +417,8 @@ namespace elna::boot } else { - add_error<declaration_error>(declaration_error::kind::undeclared, - expression->type_name); + add_error<symbol_error>(expression->type_name.position(), + symbol_error::undeclared{.name = expression->type_name.name()}); } for (const field_initializer& initializer : expression->field_initializers) { @@ -430,8 +426,8 @@ namespace elna::boot if (!expression->type_decoration.empty() && lookup_field(expression->type_decoration, initializer.name()).empty()) { - add_error<declaration_error>(declaration_error::kind::undeclared, - initializer.id()); + add_error<symbol_error>(initializer.id().position(), + symbol_error::undeclared{.name = initializer.id().name()}); } } } @@ -485,14 +481,16 @@ for (const auto& member : expression->members) std::shared_ptr<enumeration_type> const result_type = std::make_shared<enumeration_type>( member_names); std::map<std::string, source_position> seen; - type const aggregate(result_type); + const type aggregate(result_type); for (const auto& member : expression->members) { auto existing = seen.find(member.name()); if (existing != seen.end()) { - add_error<duplicate_member_error>(member, aggregate, existing->second); + add_error<member_error>(member.position(), + member_error::duplicate{.name = member.name(), .aggregate = aggregate, + .original = existing->second, .base = std::nullopt}); } else { @@ -511,8 +509,8 @@ for (const auto& member : expression->members) if (!this->bag.enter(name, variable_symbol)) { auto original = this->bag.lookup(name); - add_error<redefinition_error>(boot::identifier(name, position), - original->position); + add_error<symbol_error>(position, + symbol_error::redefinition{.name = name, .original = original->position}); } return variable_symbol; } @@ -642,7 +640,7 @@ for (const auto& member : expression->members) if (!trait->type_decoration.empty()) { - type const resolved = resolve_underlying_type(trait->type_decoration); + const type resolved = resolve_underlying_type(trait->type_decoration); if (resolved.get<enumeration_type>() == nullptr && !is_primitive_type(resolved, "Float") @@ -656,8 +654,8 @@ for (const auto& member : expression->members) } else { - add_error<declaration_error>(declaration_error::kind::undeclared, - trait->name); + add_error<symbol_error>(trait->name.position(), + symbol_error::undeclared{.name = trait->name.name()}); } } @@ -742,7 +740,9 @@ for (const auto& member : expression->members) } if (expression->type_decoration.empty()) { - add_error<field_not_found_error>(expression->field(), expression->base().type_decoration); + add_error<member_error>(expression->field().position(), + member_error::not_found{.name = expression->field().name(), + .composite = expression->base().type_decoration}); } else { @@ -761,6 +761,27 @@ for (const auto& member : expression->members) } } + void name_analysis_visitor::visit(for_statement *statement) + { + statement->initial_value().accept(this); + const type control_variable_type = type(std::make_shared<constant_type>(this->current_type)); + auto initial_value_info = std::make_shared<variable_info>(control_variable_type, false); + + statement->final_value().accept(this); + if (statement->step != nullptr) + { + statement->step->accept(this); + } + statement->symbols = this->bag.enter(); + + this->bag.enter(statement->control_variable.name(), initial_value_info); + for (auto *body_statement : statement->body) + { + body_statement->accept(this); + } + this->bag.leave(); + } + void name_analysis_visitor::visit(cast_expression *expression) { walking_visitor::visit(expression); @@ -792,29 +813,33 @@ for (const auto& member : expression->members) } else { - add_error<declaration_error>(declaration_error::kind::undeclared, - boot::identifier(expression->name, expression->position())); + add_error<symbol_error>(expression->position(), + symbol_error::undeclared{.name = expression->name}); } } void name_analysis_visitor::visit(literal<std::int32_t> *literal) { literal->type_decoration = lookup_primitive_type("Int"); + this->current_type = literal->type_decoration; } void name_analysis_visitor::visit(literal<std::uint32_t> *literal) { literal->type_decoration = lookup_primitive_type("Word"); + this->current_type = literal->type_decoration; } void name_analysis_visitor::visit(literal<double> *literal) { literal->type_decoration = lookup_primitive_type("Float"); + this->current_type = literal->type_decoration; } void name_analysis_visitor::visit(literal<bool> *literal) { literal->type_decoration = lookup_primitive_type("Bool"); + this->current_type = literal->type_decoration; } void name_analysis_visitor::visit(literal<unsigned char> *literal) @@ -831,6 +856,7 @@ for (const auto& member : expression->members) { literal->type_decoration = type(std::make_shared<slice_type>( type(std::make_shared<constant_type>(lookup_primitive_type("Char"))))); + this->current_type = literal->type_decoration; } declaration_visitor::declaration_visitor() @@ -864,8 +890,9 @@ for (const auto& member : expression->members) if (!this->unresolved.insert({ type_identifier, std::make_shared<alias_type>(type_identifier) }).second) { - add_error<redefinition_error>(declaration->identifier.id(), - declaration->position()); + add_error<symbol_error>(declaration->identifier.id().position(), + symbol_error::redefinition{.name = declaration->identifier.id().name(), + .original = declaration->position()}); } } @@ -887,8 +914,8 @@ for (const auto& member : expression->members) { if (variable_identifier.exported()) { - add_error<declaration_error>(declaration_error::kind::local_export, - variable_identifier.id()); + add_error<symbol_error>(variable_identifier.id().position(), + symbol_error::local_export{.name = variable_identifier.id().name()}); } } } |
