From 7559df5896c552bd34d04dd3a5e240f24131eb6c Mon Sep 17 00:00:00 2001 From: Eugen Wissner <belka@caraus.de> Date: Thu, 6 Mar 2025 22:59:41 +0100 Subject: [PATCH] Unify the build_type function --- boot/ast.cc | 6 ++- boot/parser.yy | 2 +- boot/semantic.cc | 61 ++++++++++++++++++++++ gcc/elna-generic.cc | 89 ++++----------------------------- gcc/elna1.cc | 11 +++- include/elna/boot/ast.h | 11 ++-- include/elna/boot/semantic.h | 28 ++++++++++- include/elna/gcc/elna-generic.h | 18 +------ 8 files changed, 116 insertions(+), 110 deletions(-) diff --git a/boot/ast.cc b/boot/ast.cc index 20b755c..d3e0b9f 100644 --- a/boot/ast.cc +++ b/boot/ast.cc @@ -464,7 +464,8 @@ namespace boot return *m_base; } - record_type_expression::record_type_expression(const struct position position, fields_t&& fields) + record_type_expression::record_type_expression(const struct position position, + std::vector<field_declaration>&& fields) : type_expression(position), fields(std::move(fields)) { } @@ -479,7 +480,8 @@ namespace boot return std::static_pointer_cast<record_type_expression>(shared_from_this()); } - union_type_expression::union_type_expression(const struct position position, fields_t&& fields) + union_type_expression::union_type_expression(const struct position position, + std::vector<field_declaration>&& fields) : type_expression(position), fields(std::move(fields)) { } diff --git a/boot/parser.yy b/boot/parser.yy index 13f9fe7..e5ed856 100644 --- a/boot/parser.yy +++ b/boot/parser.yy @@ -145,7 +145,7 @@ along with GCC; see the file COPYING3. If not see %type <elna::boot::type_definition *> type_definition; %type <std::vector<elna::boot::type_definition *>> type_definitions type_part; %type <elna::boot::block *> block; -%type <elna::boot::field_t> field_declaration; +%type <elna::boot::field_declaration> field_declaration; %type <std::vector<std::pair<std::string, std::shared_ptr<elna::boot::type_expression>>>> optional_fields required_fields; %type <std::vector<elna::boot::conditional_statements *>> elsif_then_statements elsif_do_statements; diff --git a/boot/semantic.cc b/boot/semantic.cc index 6735976..ae1157d 100644 --- a/boot/semantic.cc +++ b/boot/semantic.cc @@ -69,5 +69,66 @@ namespace boot { return this; } + + void declaration_visitor::visit(program *program) + { + for (type_definition *const type : program->types) + { + this->unresolved.insert({ type->identifier, new alias_type() }); + } + for (type_definition *const type : program->types) + { + type->accept(this); + } + } + + void declaration_visitor::visit(type_definition *definition) + { + auto unresolved_declaration = this->unresolved.at(definition->identifier); + + definition->body().accept(this); + + if (this->current_type != nullptr) + { + unresolved_declaration->reference = this->current_type; + } + this->current_type = nullptr; + } + + void declaration_visitor::visit(primitive_type_expression *type) + { + auto unresolved_alias = this->unresolved.find(type->name); + + if (unresolved_alias != this->unresolved.end()) + { + this->current_type = unresolved_alias->second; + } + else + { + this->current_type = new primitive_type(type->name); + } + } + + void declaration_visitor::visit(array_type_expression *type) + { + } + + void declaration_visitor::visit(pointer_type_expression *type) + { + } + + void declaration_visitor::visit(record_type_expression *type) + { + this->current_type = new record_type(); + } + + void declaration_visitor::visit(union_type_expression *type) + { + this->current_type = new union_type(); + } + + void declaration_visitor::visit(procedure_type_expression *type) + { + } } } diff --git a/gcc/elna-generic.cc b/gcc/elna-generic.cc index 3ee4f94..33af896 100644 --- a/gcc/elna-generic.cc +++ b/gcc/elna-generic.cc @@ -38,19 +38,7 @@ namespace elna { namespace gcc { - declaration_visitor::declaration_visitor(std::shared_ptr<symbol_table> symbol_table) - : symbols(symbol_table) - { - 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 declaration_visitor::get_inner_alias(const boot::alias_type& t) + static tree get_inner_alias(std::shared_ptr<symbol_table> symbol_table, const boot::alias_type& t) { if (t.reference == nullptr) { @@ -58,11 +46,11 @@ namespace gcc } else if (auto reference = t.reference->is_primitive()) { - return this->symbols->lookup(reference->identifier); + return symbol_table->lookup(reference->identifier); } else if (auto reference = t.reference->is_alias()) { - return get_inner_alias(*reference); + return get_inner_alias(symbol_table, *reference); } else if (auto reference = t.reference->is_record()) { @@ -75,75 +63,16 @@ namespace gcc return NULL_TREE; } - boot::type *declaration_visitor::build_type(boot::type_expression *type_expression) + void do_semantic_analysis(std::shared_ptr<symbol_table> symbols, std::unique_ptr<boot::program>& ast) { - 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::declaration_visitor declaration_visitor; - 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) - { - for (boot::type_definition *const type : program->types) + declaration_visitor.visit(ast.get()); + for (auto unresolved : declaration_visitor.unresolved) { - type->accept(this); + auto inner_alias = elna::gcc::get_inner_alias(symbols, *unresolved.second); + symbols->enter(unresolved.first, inner_alias); } - for (boot::type_definition *const type : program->types) - { - auto unresolved_declaration = this->unresolved.at(type->identifier); - - if (auto alias_node = type->body().is_primitive()) - { - auto unresolved_alias = this->unresolved.find(alias_node->name); - - if (unresolved_alias != this->unresolved.end()) - { - 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->reference = build_record(alias_node.get()); - } - else if (auto alias_node = type->body().is_union()) - { - unresolved_declaration->reference = build_union(alias_node.get()); - } - } - for (auto unresolved : this->unresolved) - { - 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, new boot::alias_type() }); } generic_visitor::generic_visitor(std::shared_ptr<symbol_table> symbol_table) diff --git a/gcc/elna1.cc b/gcc/elna1.cc index 5713719..07d8a31 100644 --- a/gcc/elna1.cc +++ b/gcc/elna1.cc @@ -90,10 +90,17 @@ static void elna_parse_file(const char *filename) { std::shared_ptr<elna::gcc::symbol_table> symbol_table = std::make_shared<elna::gcc::symbol_table>(); - elna::gcc::declaration_visitor declaration_visitor{ symbol_table }; + symbol_table->enter("Int", elna_int_type_node); + symbol_table->enter("Word", elna_word_type_node); + symbol_table->enter("Char", elna_char_type_node); + symbol_table->enter("Bool", elna_bool_type_node); + symbol_table->enter("Byte", elna_byte_type_node); + symbol_table->enter("Float", elna_float_type_node); + symbol_table->enter("String", elna_string_type_node); + + elna::gcc::do_semantic_analysis(symbol_table, driver.tree); elna::gcc::generic_visitor generic_visitor{ symbol_table }; - declaration_visitor.visit(driver.tree.get()); generic_visitor.visit(driver.tree.get()); } linemap_add(line_table, LC_LEAVE, 0, NULL, 0); diff --git a/include/elna/boot/ast.h b/include/elna/boot/ast.h index 0727a39..6c32a54 100644 --- a/include/elna/boot/ast.h +++ b/include/elna/boot/ast.h @@ -294,15 +294,14 @@ namespace boot type_expression& base(); }; - using field_t = std::pair<std::string, std::shared_ptr<type_expression>>; - using fields_t = std::vector<field_t>; + using field_declaration = std::pair<std::string, std::shared_ptr<type_expression>>; class record_type_expression : public type_expression { public: - fields_t fields; + const std::vector<field_declaration> fields; - record_type_expression(const struct position position, fields_t&& fields); + record_type_expression(const struct position position, std::vector<field_declaration>&& fields); void accept(parser_visitor *visitor); std::shared_ptr<record_type_expression> is_record() override; @@ -311,9 +310,9 @@ namespace boot class union_type_expression : public type_expression { public: - fields_t fields; + std::vector<field_declaration> fields; - union_type_expression(const struct position position, fields_t&& fields); + union_type_expression(const struct position position, std::vector<field_declaration>&& fields); void accept(parser_visitor *visitor); std::shared_ptr<union_type_expression> is_union() override; diff --git a/include/elna/boot/semantic.h b/include/elna/boot/semantic.h index de6030a..a078f98 100644 --- a/include/elna/boot/semantic.h +++ b/include/elna/boot/semantic.h @@ -17,6 +17,9 @@ along with GCC; see the file COPYING3. If not see #include <string> #include <vector> +#include <unordered_map> + +#include "elna/boot/ast.h" namespace elna { @@ -56,10 +59,12 @@ namespace boot primitive_type *is_primitive() override; }; + using type_field = typename std::pair<std::string, type *>; + class record_type : public type { public: - std::vector<std::pair<std::string, type *>> fields; + std::vector<type_field> fields; record_type *is_record() override; }; @@ -67,9 +72,28 @@ namespace boot class union_type : public type { public: - std::vector<std::pair<std::string, type *>> fields; + std::vector<type_field> fields; union_type *is_union() override; }; + + class declaration_visitor final : public empty_visitor + { + type *current_type{ nullptr }; + + public: + std::unordered_map<std::string, alias_type *> unresolved; + + declaration_visitor() = default; + + void visit(primitive_type_expression *type) override; + void visit(array_type_expression *type) override; + void visit(pointer_type_expression *type) override; + void visit(program *program) override; + void visit(type_definition *definition) override; + void visit(record_type_expression *type) override; + void visit(union_type_expression *type) override; + void visit(procedure_type_expression *type) override; + }; } } diff --git a/include/elna/gcc/elna-generic.h b/include/elna/gcc/elna-generic.h index 4f4c635..2dfb2d9 100644 --- a/include/elna/gcc/elna-generic.h +++ b/include/elna/gcc/elna-generic.h @@ -28,29 +28,13 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "tree-iterator.h" -#include <unordered_map> #include <string> namespace elna { namespace gcc { - class declaration_visitor final : public boot::empty_visitor - { - std::shared_ptr<symbol_table> symbols; - std::unordered_map<std::string, boot::alias_type *> 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> symbol_table); - - void visit(boot::program *program) override; - void visit(boot::type_definition *definition) override; - }; + void do_semantic_analysis(std::shared_ptr<symbol_table> symbols, std::unique_ptr<boot::program>& ast); class generic_visitor final : public boot::empty_visitor {