diff options
Diffstat (limited to 'boot')
| -rw-r--r-- | boot/symbol.cc | 289 | ||||
| -rw-r--r-- | boot/type_check.cc | 5 |
2 files changed, 68 insertions, 226 deletions
diff --git a/boot/symbol.cc b/boot/symbol.cc index bd6ec49..6ad89b7 100644 --- a/boot/symbol.cc +++ b/boot/symbol.cc @@ -19,224 +19,72 @@ along with GCC; see the file COPYING3. If not see namespace elna::boot { - type::type() - { - } - type::type(std::shared_ptr<alias_type> alias) - : tag(type_tag::alias), alias(alias) + : payload(alias) { } type::type(std::shared_ptr<primitive_type> primitive) - : tag(type_tag::primitive), primitive(primitive) + : payload(primitive) { } type::type(std::shared_ptr<record_type> record) - : tag(type_tag::record), record(record) + : payload(record) { } type::type(std::shared_ptr<pointer_type> pointer) - : tag(type_tag::pointer), pointer(pointer) + : payload(pointer) { } type::type(std::shared_ptr<constant_type> constant) - : tag(type_tag::constant), constant(constant) + : payload(constant) { } type::type(std::shared_ptr<array_type> array) - : tag(type_tag::array), array(array) + : payload(array) { } type::type(std::shared_ptr<procedure_type> procedure) - : tag(type_tag::procedure), procedure(procedure) + : payload(procedure) { } type::type(std::shared_ptr<enumeration_type> enumeration) - : tag(type_tag::enumeration), enumeration(enumeration) + : payload(enumeration) { } - void type::copy(const type& other) + template<typename T> + std::shared_ptr<T> type::get() const { - switch (other.tag) + if constexpr (std::is_same_v<T, alias_type>) { - case type_tag::empty: - break; - case type_tag::alias: - new (&alias) std::weak_ptr<alias_type>(other.alias); - break; - case type_tag::primitive: - new (&primitive) std::shared_ptr<primitive_type>(other.primitive); - break; - case type_tag::record: - new (&record) std::shared_ptr<record_type>(other.record); - break; - case type_tag::pointer: - new (&pointer) std::shared_ptr<pointer_type>(other.pointer); - break; - case type_tag::constant: - new (&constant) std::shared_ptr<constant_type>(other.constant); - break; - case type_tag::array: - new (&array) std::shared_ptr<array_type>(other.array); - break; - case type_tag::procedure: - new (&procedure) std::shared_ptr<procedure_type>(other.procedure); - break; - case type_tag::enumeration: - new (&enumeration) std::shared_ptr<enumeration_type>(other.enumeration); - break; + if (auto *wp = std::get_if<std::weak_ptr<alias_type>>(&payload)) + return wp->lock(); + return nullptr; } - } - - type::type(const type& other) - : tag(other.tag) - { - copy(other); - } - - void type::move(type&& other) - { - switch (other.tag) - { - case type_tag::empty: - break; - case type_tag::alias: - new (&alias) std::weak_ptr<alias_type>(std::move(other.alias)); - break; - case type_tag::primitive: - new (&primitive) std::shared_ptr<primitive_type>(std::move(other.primitive)); - break; - case type_tag::record: - new (&record) std::shared_ptr<record_type>(std::move(other.record)); - break; - case type_tag::pointer: - new (&pointer) std::shared_ptr<pointer_type>(std::move(other.pointer)); - break; - case type_tag::constant: - new (&constant) std::shared_ptr<constant_type>(std::move(other.constant)); - break; - case type_tag::array: - new (&array) std::shared_ptr<array_type>(std::move(other.array)); - break; - case type_tag::procedure: - new (&procedure) std::shared_ptr<procedure_type>(std::move(other.procedure)); - break; - case type_tag::enumeration: - new (&enumeration) std::shared_ptr<enumeration_type>(std::move(other.enumeration)); - break; - } - } - - type& type::operator=(const type& other) - { - this->~type(); - this->tag = other.tag; - copy(other); - return *this; - } - - type::type(type&& other) - : tag(other.tag) - { - move(std::move(other)); - } - - type& type::operator=(type&& other) - { - this->~type(); - this->tag = other.tag; - move(std::move(other)); - return *this; - } - - type::~type() - { - switch (tag) + else { - case type_tag::empty: - break; - case type_tag::alias: - this->alias.~weak_ptr<alias_type>(); - break; - case type_tag::primitive: - this->primitive.~shared_ptr<primitive_type>(); - break; - case type_tag::record: - this->record.~shared_ptr<record_type>(); - break; - case type_tag::pointer: - this->pointer.~shared_ptr<pointer_type>(); - break; - case type_tag::constant: - this->constant.~shared_ptr<constant_type>(); - break; - case type_tag::array: - this->array.~shared_ptr<array_type>(); - break; - case type_tag::procedure: - this->procedure.~shared_ptr<procedure_type>(); - break; - case type_tag::enumeration: - this->enumeration.~shared_ptr<enumeration_type>(); - break; + if (auto *sp = std::get_if<std::shared_ptr<T>>(&payload)) + return *sp; + return nullptr; } } - template<> - std::shared_ptr<alias_type> type::get<alias_type>() const - { - return tag == type_tag::alias ? this->alias.lock() : nullptr; - } - - template<> - std::shared_ptr<primitive_type> type::get<primitive_type>() const - { - return tag == type_tag::primitive ? this->primitive : nullptr; - } - - template<> - std::shared_ptr<record_type> type::get<record_type>() const - { - return tag == type_tag::record ? this->record : nullptr; - } - - template<> - std::shared_ptr<pointer_type> type::get<pointer_type>() const - { - return tag == type_tag::pointer ? this->pointer : nullptr; - } - - template<> - std::shared_ptr<array_type> type::get<array_type>() const - { - return tag == type_tag::array ? this->array : nullptr; - } - - template<> - std::shared_ptr<constant_type> type::get<constant_type>() const - { - return tag == type_tag::constant ? this->constant : nullptr; - } - - template<> - std::shared_ptr<procedure_type> type::get<procedure_type>() const - { - return tag == type_tag::procedure ? this->procedure : nullptr; - } - - template<> - std::shared_ptr<enumeration_type> type::get<enumeration_type>() const - { - return tag == type_tag::enumeration ? this->enumeration : nullptr; - } + // Explicit instantiation for all types used by callers. + template std::shared_ptr<alias_type> type::get<alias_type>() const; + template std::shared_ptr<primitive_type> type::get<primitive_type>() const; + template std::shared_ptr<record_type> type::get<record_type>() const; + template std::shared_ptr<pointer_type> type::get<pointer_type>() const; + template std::shared_ptr<array_type> type::get<array_type>() const; + template std::shared_ptr<constant_type> type::get<constant_type>() const; + template std::shared_ptr<procedure_type> type::get<procedure_type>() const; + template std::shared_ptr<enumeration_type> type::get<enumeration_type>() const; bool type::operator==(const std::nullptr_t&) const { @@ -293,61 +141,54 @@ namespace elna::boot bool type::empty() const { - return tag == type_tag::empty; + return std::holds_alternative<std::monostate>(payload); } std::string type::to_string() const { - switch (tag) - { - case type_tag::empty: + return std::visit([](const auto& p) -> std::string { + using T = std::decay_t<decltype(p)>; + if constexpr (std::is_same_v<T, std::monostate>) return "<empty>"; - case type_tag::alias: - return alias.lock()->name; - case type_tag::primitive: - return primitive->identifier; - case type_tag::pointer: - return "^" + pointer->base.to_string(); - case type_tag::constant: - return "const " + constant->unqualified.to_string(); - case type_tag::array: - return "[" + std::to_string(array->size) + "]" + array->base.to_string(); - case type_tag::record: - if (record->base.empty()) - { + else if constexpr (std::is_same_v<T, std::weak_ptr<alias_type>>) + return p.lock()->name; + else if constexpr (std::is_same_v<T, std::shared_ptr<primitive_type>>) + return p->identifier; + else if constexpr (std::is_same_v<T, std::shared_ptr<pointer_type>>) + return "^" + p->base.to_string(); + else if constexpr (std::is_same_v<T, std::shared_ptr<constant_type>>) + return "const " + p->unqualified.to_string(); + else if constexpr (std::is_same_v<T, std::shared_ptr<array_type>>) + return "[" + std::to_string(p->size) + "]" + p->base.to_string(); + else if constexpr (std::is_same_v<T, std::shared_ptr<record_type>>) + { + if (p->base.empty()) return "record ... end"; - } else + return "record(" + p->base.to_string() + ") ... end"; + } + else if constexpr (std::is_same_v<T, std::shared_ptr<procedure_type>>) + { + std::string result = "proc("; + for (std::size_t i = 0; i < p->parameters.size(); ++i) { - return "record(" + record->base.to_string() + ") ... end"; - } - case type_tag::procedure: - { - std::string result = "proc("; - for (std::size_t i = 0; i < procedure->parameters.size(); ++i) - { - if (i > 0) result += ", "; - result += procedure->parameters[i].to_string(); - } - result += ")"; - if (procedure->return_type.no_return) - { - result += ": !"; - } - else if (!procedure->return_type.proper_type.empty()) - { - result += ": " + procedure->return_type.proper_type.to_string(); - } - return result; + if (i > 0) result += ", "; + result += p->parameters[i].to_string(); } - case type_tag::enumeration: + result += ")"; + if (p->return_type.no_return) + result += ": !"; + else if (!p->return_type.proper_type.empty()) + result += ": " + p->return_type.proper_type.to_string(); + return result; + } + else if constexpr (std::is_same_v<T, std::shared_ptr<enumeration_type>>) return "(enumeration)"; - } - __builtin_unreachable(); + }, payload); } alias_type::alias_type(const std::string& name) - : name(name), reference() + : name(name), referent() { } @@ -517,7 +358,7 @@ namespace elna::boot { auto unresolved_declaration = this->unresolved.at(symbol_name); - unresolved_declaration->reference = resolution; + unresolved_declaration->referent = resolution; return unresolved_declaration; } @@ -544,7 +385,7 @@ namespace elna::boot type resolve_underlying_type(std::shared_ptr<alias_type> alias) { - return resolve_underlying_type(alias->reference); + return resolve_underlying_type(alias->referent); } type resolve_underlying_type(const type& alias) @@ -565,7 +406,7 @@ namespace elna::boot { if (auto alias = checked.get<alias_type>()) { - return resolve_aliases(alias->reference); + return resolve_aliases(alias->referent); } return checked; } diff --git a/boot/type_check.cc b/boot/type_check.cc index 3667007..b42792b 100644 --- a/boot/type_check.cc +++ b/boot/type_check.cc @@ -212,7 +212,8 @@ namespace elna::boot return true; } } - return !record->base.empty() && contains_constant_member(record->base); + return !record->base.empty() + && contains_constant_member(resolve_underlying_type(record->base)); } else if (auto array = referent.get<array_type>()) { @@ -230,7 +231,7 @@ namespace elna::boot } alias_path.push_back(alias->name); - if (auto another_alias = alias->reference.get<alias_type>()) + if (auto another_alias = alias->referent.get<alias_type>()) { return check_unresolved_symbol(another_alias, alias_path); } |
