From e676e74efbbbf62887b9442326399eebccc4d108 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Fri, 17 Jul 2026 16:16:23 +0200 Subject: Handle base type constness --- boot/symbol.cc | 289 +++++++--------------------- boot/type_check.cc | 5 +- gcc/gcc/elna-builtins.cc | 2 +- include/elna/boot/symbol.h | 58 ++---- testsuite/compilable/record_const_base.elna | 18 ++ 5 files changed, 105 insertions(+), 267 deletions(-) create mode 100644 testsuite/compilable/record_const_base.elna 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) - : tag(type_tag::alias), alias(alias) + : payload(alias) { } type::type(std::shared_ptr primitive) - : tag(type_tag::primitive), primitive(primitive) + : payload(primitive) { } type::type(std::shared_ptr record) - : tag(type_tag::record), record(record) + : payload(record) { } type::type(std::shared_ptr pointer) - : tag(type_tag::pointer), pointer(pointer) + : payload(pointer) { } type::type(std::shared_ptr constant) - : tag(type_tag::constant), constant(constant) + : payload(constant) { } type::type(std::shared_ptr array) - : tag(type_tag::array), array(array) + : payload(array) { } type::type(std::shared_ptr procedure) - : tag(type_tag::procedure), procedure(procedure) + : payload(procedure) { } type::type(std::shared_ptr enumeration) - : tag(type_tag::enumeration), enumeration(enumeration) + : payload(enumeration) { } - void type::copy(const type& other) + template + std::shared_ptr type::get() const { - switch (other.tag) + if constexpr (std::is_same_v) { - case type_tag::empty: - break; - case type_tag::alias: - new (&alias) std::weak_ptr(other.alias); - break; - case type_tag::primitive: - new (&primitive) std::shared_ptr(other.primitive); - break; - case type_tag::record: - new (&record) std::shared_ptr(other.record); - break; - case type_tag::pointer: - new (&pointer) std::shared_ptr(other.pointer); - break; - case type_tag::constant: - new (&constant) std::shared_ptr(other.constant); - break; - case type_tag::array: - new (&array) std::shared_ptr(other.array); - break; - case type_tag::procedure: - new (&procedure) std::shared_ptr(other.procedure); - break; - case type_tag::enumeration: - new (&enumeration) std::shared_ptr(other.enumeration); - break; + if (auto *wp = std::get_if>(&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(std::move(other.alias)); - break; - case type_tag::primitive: - new (&primitive) std::shared_ptr(std::move(other.primitive)); - break; - case type_tag::record: - new (&record) std::shared_ptr(std::move(other.record)); - break; - case type_tag::pointer: - new (&pointer) std::shared_ptr(std::move(other.pointer)); - break; - case type_tag::constant: - new (&constant) std::shared_ptr(std::move(other.constant)); - break; - case type_tag::array: - new (&array) std::shared_ptr(std::move(other.array)); - break; - case type_tag::procedure: - new (&procedure) std::shared_ptr(std::move(other.procedure)); - break; - case type_tag::enumeration: - new (&enumeration) std::shared_ptr(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(); - break; - case type_tag::primitive: - this->primitive.~shared_ptr(); - break; - case type_tag::record: - this->record.~shared_ptr(); - break; - case type_tag::pointer: - this->pointer.~shared_ptr(); - break; - case type_tag::constant: - this->constant.~shared_ptr(); - break; - case type_tag::array: - this->array.~shared_ptr(); - break; - case type_tag::procedure: - this->procedure.~shared_ptr(); - break; - case type_tag::enumeration: - this->enumeration.~shared_ptr(); - break; + if (auto *sp = std::get_if>(&payload)) + return *sp; + return nullptr; } } - template<> - std::shared_ptr type::get() const - { - return tag == type_tag::alias ? this->alias.lock() : nullptr; - } - - template<> - std::shared_ptr type::get() const - { - return tag == type_tag::primitive ? this->primitive : nullptr; - } - - template<> - std::shared_ptr type::get() const - { - return tag == type_tag::record ? this->record : nullptr; - } - - template<> - std::shared_ptr type::get() const - { - return tag == type_tag::pointer ? this->pointer : nullptr; - } - - template<> - std::shared_ptr type::get() const - { - return tag == type_tag::array ? this->array : nullptr; - } - - template<> - std::shared_ptr type::get() const - { - return tag == type_tag::constant ? this->constant : nullptr; - } - - template<> - std::shared_ptr type::get() const - { - return tag == type_tag::procedure ? this->procedure : nullptr; - } - - template<> - std::shared_ptr type::get() const - { - return tag == type_tag::enumeration ? this->enumeration : nullptr; - } + // Explicit instantiation for all types used by callers. + template std::shared_ptr type::get() const; + template std::shared_ptr type::get() const; + template std::shared_ptr type::get() const; + template std::shared_ptr type::get() const; + template std::shared_ptr type::get() const; + template std::shared_ptr type::get() const; + template std::shared_ptr type::get() const; + template std::shared_ptr type::get() 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(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; + if constexpr (std::is_same_v) return ""; - 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>) + return p.lock()->name; + else if constexpr (std::is_same_v>) + return p->identifier; + else if constexpr (std::is_same_v>) + return "^" + p->base.to_string(); + else if constexpr (std::is_same_v>) + return "const " + p->unqualified.to_string(); + else if constexpr (std::is_same_v>) + return "[" + std::to_string(p->size) + "]" + p->base.to_string(); + else if constexpr (std::is_same_v>) + { + if (p->base.empty()) return "record ... end"; - } else + return "record(" + p->base.to_string() + ") ... end"; + } + else if constexpr (std::is_same_v>) + { + 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>) 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) { - 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()) { - 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()) { @@ -230,7 +231,7 @@ namespace elna::boot } alias_path.push_back(alias->name); - if (auto another_alias = alias->reference.get()) + if (auto another_alias = alias->referent.get()) { return check_unresolved_symbol(another_alias, alias_path); } diff --git a/gcc/gcc/elna-builtins.cc b/gcc/gcc/elna-builtins.cc index 3c424f8..5284563 100644 --- a/gcc/gcc/elna-builtins.cc +++ b/gcc/gcc/elna-builtins.cc @@ -178,7 +178,7 @@ namespace elna::gcc if (looked_up == NULL_TREE) { - tree type_tree = get_inner_alias(reference->reference, symbols); + tree type_tree = get_inner_alias(reference->referent, symbols); looked_up = build_decl(UNKNOWN_LOCATION, TYPE_DECL, get_identifier(symbol_name.c_str()), type_tree); diff --git a/include/elna/boot/symbol.h b/include/elna/boot/symbol.h index 6884dd7..216021e 100644 --- a/include/elna/boot/symbol.h +++ b/include/elna/boot/symbol.h @@ -18,11 +18,12 @@ along with GCC; see the file COPYING3. If not see #pragma once #include -#include -#include +#include #include +#include +#include +#include #include -#include #include "elna/boot/result.h" @@ -39,36 +40,21 @@ namespace elna::boot class type { - enum class type_tag - { - empty, - alias, - primitive, - record, - pointer, - constant, - array, - procedure, - enumeration - }; - type_tag tag{ type_tag::empty }; - union - { - std::weak_ptr alias; - std::shared_ptr primitive; - std::shared_ptr record; - std::shared_ptr pointer; - std::shared_ptr constant; - std::shared_ptr array; - std::shared_ptr procedure; - std::shared_ptr enumeration; - }; - - void copy(const type& other); - void move(type&& other); + std::variant< + std::monostate, + std::weak_ptr, + std::shared_ptr, + std::shared_ptr, + std::shared_ptr, + std::shared_ptr, + std::shared_ptr, + std::shared_ptr, + std::shared_ptr + > payload; public: - type(); + type() = default; + explicit type(std::shared_ptr alias); explicit type(std::shared_ptr primitive); explicit type(std::shared_ptr record); @@ -78,14 +64,6 @@ namespace elna::boot explicit type(std::shared_ptr procedure); explicit type(std::shared_ptr enumeration); - type(const type& other); - type& operator=(const type& other); - - type(type&& other); - type& operator=(type&& other); - - ~type(); - template std::shared_ptr get() const; @@ -104,7 +82,7 @@ namespace elna::boot struct alias_type { const std::string name; - type reference; + type referent; explicit alias_type(const std::string& name); }; diff --git a/testsuite/compilable/record_const_base.elna b/testsuite/compilable/record_const_base.elna new file mode 100644 index 0000000..f24d27b --- /dev/null +++ b/testsuite/compilable/record_const_base.elna @@ -0,0 +1,18 @@ +type + B = record + x: Int + end + CB = const B + D = record(CB) + y: Int + end + +proc f() +var + d: D +begin + d.x := 1; + d.y := 2 +return + +end. -- cgit v1.2.3