Add forward type declaration representation
This commit is contained in:
		
							
								
								
									
										73
									
								
								boot/semantic.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								boot/semantic.cc
									
									
									
									
									
										Normal file
									
								
							@@ -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
 | 
			
		||||
<http://www.gnu.org/licenses/>.  */
 | 
			
		||||
 | 
			
		||||
#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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
@@ -46,6 +46,7 @@ elna_OBJS = \
 | 
			
		||||
	elna/driver.o \
 | 
			
		||||
	elna/lexer.o \
 | 
			
		||||
	elna/parser.o \
 | 
			
		||||
	elna/semantic.o \
 | 
			
		||||
	elna/result.o \
 | 
			
		||||
	$(END)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -41,25 +41,65 @@ namespace gcc
 | 
			
		||||
    declaration_visitor::declaration_visitor(std::shared_ptr<symbol_table> symbol_table)
 | 
			
		||||
        : symbols(symbol_table)
 | 
			
		||||
    {
 | 
			
		||||
        this->unresolved.insert({ "Int", std::make_shared<type>(elna_int_type_node) });
 | 
			
		||||
        this->unresolved.insert({ "Word", std::make_shared<type>(elna_word_type_node) });
 | 
			
		||||
        this->unresolved.insert({ "Char", std::make_shared<type>(elna_char_type_node) });
 | 
			
		||||
        this->unresolved.insert({ "Bool", std::make_shared<type>(elna_bool_type_node) });
 | 
			
		||||
        this->unresolved.insert({ "Byte", std::make_shared<type>(elna_byte_type_node) });
 | 
			
		||||
        this->unresolved.insert({ "Float", std::make_shared<type>(elna_float_type_node) });
 | 
			
		||||
        this->unresolved.insert({ "String", std::make_shared<type>(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<type>() });
 | 
			
		||||
        this->unresolved.insert({ definition->identifier, new boot::alias_type() });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    generic_visitor::generic_visitor(std::shared_ptr<symbol_table> symbol_table)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										75
									
								
								include/elna/boot/semantic.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								include/elna/boot/semantic.h
									
									
									
									
									
										Normal file
									
								
							@@ -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
 | 
			
		||||
<http://www.gnu.org/licenses/>.  */
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
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<std::pair<std::string, type *>> fields;
 | 
			
		||||
 | 
			
		||||
        record_type *is_record() override;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class union_type : public type
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        std::vector<std::pair<std::string, type *>> fields;
 | 
			
		||||
 | 
			
		||||
        union_type *is_union() override;
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
@@ -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<type> reference): reference(reference) {}
 | 
			
		||||
 | 
			
		||||
        tree resolved{ NULL_TREE };
 | 
			
		||||
        std::shared_ptr<type> reference;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class declaration_visitor final : public boot::empty_visitor
 | 
			
		||||
    {
 | 
			
		||||
        std::shared_ptr<symbol_table> symbols;
 | 
			
		||||
        std::unordered_map<std::string, std::shared_ptr<type>> unresolved;
 | 
			
		||||
        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);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user