summaryrefslogtreecommitdiff
path: root/frontend/symbol.cc
diff options
context:
space:
mode:
Diffstat (limited to 'frontend/symbol.cc')
-rw-r--r--frontend/symbol.cc427
1 files changed, 427 insertions, 0 deletions
diff --git a/frontend/symbol.cc b/frontend/symbol.cc
new file mode 100644
index 0000000..bfecbd4
--- /dev/null
+++ b/frontend/symbol.cc
@@ -0,0 +1,427 @@
+/* Symbol definitions.
+ Copyright (C) 2025 Free Software Foundation, Inc.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#include "elna/frontend/symbol.h"
+
+namespace elna::frontend
+{
+ type::type()
+ {
+ }
+
+ type::type(std::shared_ptr<alias_type> alias)
+ : tag(type_tag::alias), alias(alias)
+ {
+ }
+
+ type::type(std::shared_ptr<primitive_type> primitive)
+ : tag(type_tag::primitive), primitive(primitive)
+ {
+ }
+
+ type::type(std::shared_ptr<record_type> record)
+ : tag(type_tag::record), record(record)
+ {
+ }
+
+ type::type(std::shared_ptr<union_type> _union)
+ : tag(type_tag::_union), _union(_union)
+ {
+ }
+
+ type::type(std::shared_ptr<pointer_type> pointer)
+ : tag(type_tag::pointer), pointer(pointer)
+ {
+ }
+
+ type::type(std::shared_ptr<array_type> array)
+ : tag(type_tag::array), array(array)
+ {
+ }
+
+ type::type(std::shared_ptr<procedure_type> procedure)
+ : tag(type_tag::procedure), procedure(procedure)
+ {
+ }
+
+ type::type(std::shared_ptr<enumeration_type> enumeration)
+ : tag(type_tag::enumeration), enumeration(enumeration)
+ {
+ }
+
+ void type::copy(const type& other)
+ {
+ switch (other.tag)
+ {
+ 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::_union:
+ new (&_union) std::shared_ptr<union_type>(other._union);
+ break;
+ case type_tag::pointer:
+ new (&pointer) std::shared_ptr<pointer_type>(other.pointer);
+ 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;
+ }
+ }
+
+ 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::_union:
+ new (&_union) std::shared_ptr<union_type>(std::move(other._union));
+ break;
+ case type_tag::pointer:
+ new (&pointer) std::shared_ptr<pointer_type>(std::move(other.pointer));
+ 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;
+ }
+
+ bool type::operator==(const std::nullptr_t&)
+ {
+ return empty();
+ }
+
+ type::~type()
+ {
+ switch (tag)
+ {
+ 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::_union:
+ this->_union.~shared_ptr<union_type>();
+ break;
+ case type_tag::pointer:
+ this->pointer.~shared_ptr<pointer_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;
+ }
+ }
+
+ 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<union_type> type::get<union_type>() const
+ {
+ return tag == type_tag::_union ? this->_union : 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<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;
+ }
+
+ bool type::empty() const
+ {
+ return tag == type_tag::empty;
+ }
+
+ alias_type::alias_type(const std::string& name)
+ : name(name), reference()
+ {
+ }
+
+ pointer_type::pointer_type(type base)
+ : base(base)
+ {
+ }
+
+ array_type::array_type(type base, std::uint64_t size)
+ : base(base), size(size)
+ {
+ }
+
+ primitive_type::primitive_type(const std::string& identifier)
+ : identifier(identifier)
+ {
+ }
+
+ procedure_type::procedure_type(return_t return_type)
+ : return_type(return_type)
+ {
+ }
+
+ enumeration_type::enumeration_type(const std::vector<std::string>& members)
+ : members(members)
+ {
+ }
+
+ info::~info()
+ {
+ }
+
+ std::shared_ptr<type_info> info::is_type()
+ {
+ return nullptr;
+ }
+
+ std::shared_ptr<procedure_info> info::is_procedure()
+ {
+ return nullptr;
+ }
+
+ std::shared_ptr<constant_info> info::is_constant()
+ {
+ return nullptr;
+ }
+
+ std::shared_ptr<variable_info> info::is_variable()
+ {
+ return nullptr;
+ }
+
+ type_info::type_info(const type symbol)
+ : symbol(symbol)
+ {
+ }
+
+ std::shared_ptr<type_info> type_info::is_type()
+ {
+ return std::static_pointer_cast<type_info>(shared_from_this());
+ }
+
+ procedure_info::procedure_info(const procedure_type symbol, const std::vector<std::string> names,
+ std::shared_ptr<symbol_table> scope)
+ : symbol(symbol), names(names), scope(scope)
+ {
+ }
+
+ std::shared_ptr<procedure_info> procedure_info::is_procedure()
+ {
+ return std::static_pointer_cast<procedure_info>(shared_from_this());
+ }
+
+ bool procedure_info::is_extern() const
+ {
+ return this->scope == nullptr;
+ }
+
+ constant_info::constant_info(const variant& symbol)
+ : symbol(symbol)
+ {
+ }
+
+ std::shared_ptr<constant_info> constant_info::is_constant()
+ {
+ return std::static_pointer_cast<constant_info>(shared_from_this());
+ }
+
+ variable_info::variable_info(const type symbol, bool is_extern)
+ : symbol(symbol), is_extern(is_extern)
+ {
+ }
+
+ std::shared_ptr<variable_info> variable_info::is_variable()
+ {
+ return std::static_pointer_cast<variable_info>(shared_from_this());
+ }
+
+ std::shared_ptr<symbol_table> builtin_symbol_table()
+ {
+ auto result = std::make_shared<symbol_table>();
+
+ result->enter("Int", std::make_shared<type_info>(type(std::make_shared<primitive_type>("Int"))));
+ result->enter("Word", std::make_shared<type_info>(type(std::make_shared<primitive_type>("Word"))));
+ result->enter("Char", std::make_shared<type_info>(type(std::make_shared<primitive_type>("Char"))));
+ result->enter("Bool", std::make_shared<type_info>(type(std::make_shared<primitive_type>("Bool"))));
+ result->enter("Pointer", std::make_shared<type_info>(type(std::make_shared<primitive_type>("Pointer"))));
+ result->enter("Float", std::make_shared<type_info>(type(std::make_shared<primitive_type>("Float"))));
+ result->enter("String", std::make_shared<type_info>(type(std::make_shared<primitive_type>("String"))));
+
+ return result;
+ }
+
+ symbol_bag::symbol_bag(forward_table&& unresolved, std::shared_ptr<symbol_table> global_table)
+ : unresolved(unresolved)
+ {
+ this->symbols = std::make_shared<symbol_table>(global_table);
+ }
+
+ std::shared_ptr<info> symbol_bag::lookup(const std::string& name)
+ {
+ for (auto import_bag : this->imports)
+ {
+ if (auto result = import_bag->lookup(name))
+ {
+ return result;
+ }
+ }
+ return this->symbols->lookup(name);
+ }
+
+ bool symbol_bag::enter(const std::string& name, std::shared_ptr<info> entry)
+ {
+ return this->symbols->enter(name, entry);
+ }
+
+ std::shared_ptr<symbol_table> symbol_bag::enter()
+ {
+ this->symbols = std::make_shared<symbol_table>(this->symbols);
+ return this->symbols;
+ }
+
+ void symbol_bag::enter(std::shared_ptr<symbol_table> child)
+ {
+ this->symbols = child;
+ }
+
+ std::shared_ptr<symbol_table> symbol_bag::leave()
+ {
+ std::shared_ptr<symbol_table> result = this->symbols;
+
+ this->symbols = result->scope();
+ return result;
+ }
+
+ std::shared_ptr<alias_type> symbol_bag::declared(const std::string& symbol_name)
+ {
+ auto unresolved_alias = this->unresolved.find(symbol_name);
+
+ return unresolved_alias == this->unresolved.end() ? std::shared_ptr<alias_type>() : unresolved_alias->second;
+ }
+
+ std::shared_ptr<alias_type> symbol_bag::resolve(const std::string& symbol_name, type& resolution)
+ {
+ auto unresolved_declaration = this->unresolved.at(symbol_name);
+
+ unresolved_declaration->reference = resolution;
+ return unresolved_declaration;
+ }
+
+ void symbol_bag::add_import(const symbol_bag& bag)
+ {
+ this->imports.push_front(bag.symbols);
+ }
+}