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