diff --git a/boot/semantic.cc b/boot/semantic.cc
new file mode 100644
index 0000000..6735976
--- /dev/null
+++ b/boot/semantic.cc
@@ -0,0 +1,73 @@
+/* Name analysis.
+ 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
+. */
+
+#include "elna/boot/semantic.h"
+
+namespace elna
+{
+namespace boot
+{
+ alias_type *type::is_alias()
+ {
+ return nullptr;
+ }
+
+ primitive_type *type::is_primitive()
+ {
+ return nullptr;
+ }
+
+ record_type *type::is_record()
+ {
+ return nullptr;
+ }
+
+ union_type *type::is_union()
+ {
+ return nullptr;
+ }
+
+ type::~type()
+ {
+ }
+
+ alias_type *alias_type::is_alias()
+ {
+ return this;
+ }
+
+ primitive_type::primitive_type(const std::string& identifier)
+ : identifier(identifier)
+ {
+ }
+
+ primitive_type *primitive_type::is_primitive()
+ {
+ return this;
+ }
+
+ record_type *record_type::is_record()
+ {
+ return this;
+ }
+
+ union_type *union_type::is_union()
+ {
+ return this;
+ }
+}
+}
diff --git a/gcc/Make-lang.in b/gcc/Make-lang.in
index f8f8385..54a2807 100644
--- a/gcc/Make-lang.in
+++ b/gcc/Make-lang.in
@@ -46,6 +46,7 @@ elna_OBJS = \
elna/driver.o \
elna/lexer.o \
elna/parser.o \
+ elna/semantic.o \
elna/result.o \
$(END)
diff --git a/gcc/elna-generic.cc b/gcc/elna-generic.cc
index 497c92a..3ee4f94 100644
--- a/gcc/elna-generic.cc
+++ b/gcc/elna-generic.cc
@@ -41,25 +41,65 @@ namespace gcc
declaration_visitor::declaration_visitor(std::shared_ptr symbol_table)
: symbols(symbol_table)
{
- this->unresolved.insert({ "Int", std::make_shared(elna_int_type_node) });
- this->unresolved.insert({ "Word", std::make_shared(elna_word_type_node) });
- this->unresolved.insert({ "Char", std::make_shared(elna_char_type_node) });
- this->unresolved.insert({ "Bool", std::make_shared(elna_bool_type_node) });
- this->unresolved.insert({ "Byte", std::make_shared(elna_byte_type_node) });
- this->unresolved.insert({ "Float", std::make_shared(elna_float_type_node) });
- this->unresolved.insert({ "String", std::make_shared(elna_string_type_node) });
+ this->symbols->enter("Int", elna_int_type_node);
+ this->symbols->enter("Word", elna_word_type_node);
+ this->symbols->enter("Char", elna_char_type_node);
+ this->symbols->enter("Bool", elna_bool_type_node);
+ this->symbols->enter("Byte", elna_byte_type_node);
+ this->symbols->enter("Float", elna_float_type_node);
+ this->symbols->enter("String", elna_string_type_node);
}
- tree get_inner_alias(const type& t)
+ tree declaration_visitor::get_inner_alias(const boot::alias_type& t)
{
if (t.reference == nullptr)
{
- return t.resolved;
+ return NULL_TREE;
}
- else
+ else if (auto reference = t.reference->is_primitive())
{
- return get_inner_alias(*t.reference);
+ return this->symbols->lookup(reference->identifier);
}
+ else if (auto reference = t.reference->is_alias())
+ {
+ return get_inner_alias(*reference);
+ }
+ else if (auto reference = t.reference->is_record())
+ {
+ return make_node(RECORD_TYPE);
+ }
+ else if (auto reference = t.reference->is_union())
+ {
+ return make_node(UNION_TYPE);
+ }
+ return NULL_TREE;
+ }
+
+ boot::type *declaration_visitor::build_type(boot::type_expression *type_expression)
+ {
+ if (auto alias_node = type_expression->is_primitive())
+ {
+ return this->unresolved.at(alias_node->name);
+ }
+ else if (auto alias_node = type_expression->is_record())
+ {
+ return build_record(alias_node.get());
+ }
+ else if (auto alias_node = type_expression->is_union())
+ {
+ return build_union(alias_node.get());
+ }
+ return nullptr;
+ }
+
+ boot::record_type *declaration_visitor::build_record(boot::record_type_expression *type_expression)
+ {
+ return new boot::record_type();
+ }
+
+ boot::union_type *declaration_visitor::build_union(boot::union_type_expression *type_expression)
+ {
+ return new boot::union_type();
}
void declaration_visitor::visit(boot::program *program)
@@ -80,26 +120,30 @@ namespace gcc
{
unresolved_declaration->reference = unresolved_alias->second;
}
+ else
+ {
+ unresolved_declaration->reference = new boot::primitive_type(alias_node->name);
+ }
}
else if (auto alias_node = type->body().is_record())
{
- unresolved_declaration->resolved = make_node(RECORD_TYPE);
+ unresolved_declaration->reference = build_record(alias_node.get());
}
else if (auto alias_node = type->body().is_union())
{
- unresolved_declaration->resolved = make_node(UNION_TYPE);
+ unresolved_declaration->reference = build_union(alias_node.get());
}
}
for (auto unresolved : this->unresolved)
{
- auto inner_alias = get_inner_alias(unresolved.second);
+ auto inner_alias = get_inner_alias(*unresolved.second);
this->symbols->enter(unresolved.first, inner_alias);
}
}
void declaration_visitor::visit(boot::type_definition *definition)
{
- this->unresolved.insert({ definition->identifier, std::make_shared() });
+ this->unresolved.insert({ definition->identifier, new boot::alias_type() });
}
generic_visitor::generic_visitor(std::shared_ptr symbol_table)
diff --git a/include/elna/boot/semantic.h b/include/elna/boot/semantic.h
new file mode 100644
index 0000000..de6030a
--- /dev/null
+++ b/include/elna/boot/semantic.h
@@ -0,0 +1,75 @@
+/* Name analysis.
+ 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
+. */
+
+#include
+#include
+
+namespace elna
+{
+namespace boot
+{
+ class alias_type;
+ class record_type;
+ class union_type;
+ class primitive_type;
+
+ class type
+ {
+ public:
+ virtual alias_type *is_alias();
+ virtual primitive_type *is_primitive();
+ virtual record_type *is_record();
+ virtual union_type *is_union();
+
+ virtual ~type() = 0;
+ };
+
+ class alias_type : public type
+ {
+ public:
+ alias_type *is_alias() override;
+
+ type *reference{ nullptr };
+ };
+
+ class primitive_type : public type
+ {
+ public:
+ std::string identifier;
+
+ primitive_type(const std::string& identifier);
+
+ primitive_type *is_primitive() override;
+ };
+
+ class record_type : public type
+ {
+ public:
+ std::vector> fields;
+
+ record_type *is_record() override;
+ };
+
+ class union_type : public type
+ {
+ public:
+ std::vector> fields;
+
+ union_type *is_union() override;
+ };
+}
+}
diff --git a/include/elna/gcc/elna-generic.h b/include/elna/gcc/elna-generic.h
index 921236f..4f4c635 100644
--- a/include/elna/gcc/elna-generic.h
+++ b/include/elna/gcc/elna-generic.h
@@ -19,6 +19,7 @@ along with GCC; see the file COPYING3. If not see
#include "elna/boot/ast.h"
#include "elna/boot/symbol.h"
+#include "elna/boot/semantic.h"
#include "elna/gcc/elna-tree.h"
#include "config.h"
@@ -34,20 +35,15 @@ namespace elna
{
namespace gcc
{
- struct type
- {
- type() {}
- type(tree resolved): resolved(resolved) {}
- type(std::shared_ptr reference): reference(reference) {}
-
- tree resolved{ NULL_TREE };
- std::shared_ptr reference;
- };
-
class declaration_visitor final : public boot::empty_visitor
{
std::shared_ptr symbols;
- std::unordered_map> unresolved;
+ std::unordered_map unresolved;
+
+ boot::type *build_type(boot::type_expression *type_expression);
+ boot::record_type *build_record(boot::record_type_expression *type_expression);
+ boot::union_type *build_union(boot::union_type_expression *type_expression);
+ tree get_inner_alias(const boot::alias_type& t);
public:
declaration_visitor(std::shared_ptr symbol_table);