Unify the build_type function
This commit is contained in:
		@@ -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))
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										11
									
								
								gcc/elna1.cc
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								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);
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
    {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user