Rename AST types to type expressions
This commit is contained in:
		
							
								
								
									
										292
									
								
								boot/ast.cc
									
									
									
									
									
								
							
							
						
						
									
										292
									
								
								boot/ast.cc
									
									
									
									
									
								
							| @@ -23,215 +23,167 @@ namespace boot | ||||
| { | ||||
|     void empty_visitor::visit(variable_declaration *) | ||||
|     { | ||||
|         __builtin_unreachable(); | ||||
|     } | ||||
|  | ||||
|     void empty_visitor::visit(constant_definition *definition) | ||||
|     void empty_visitor::visit(constant_definition *) | ||||
|     { | ||||
|         definition->body().accept(this); | ||||
|         __builtin_unreachable(); | ||||
|     } | ||||
|  | ||||
|     void empty_visitor::visit(procedure_definition *definition) | ||||
|     void empty_visitor::visit(procedure_definition *) | ||||
|     { | ||||
|         definition->heading().accept(this); | ||||
|         if (definition->body != nullptr) | ||||
|         { | ||||
|             definition->body->accept(this); | ||||
|         } | ||||
|         __builtin_unreachable(); | ||||
|     } | ||||
|  | ||||
|     void empty_visitor::visit(type_definition *definition) | ||||
|     void empty_visitor::visit(type_definition *) | ||||
|     { | ||||
|         definition->body().accept(this); | ||||
|         __builtin_unreachable(); | ||||
|     } | ||||
|  | ||||
|     void empty_visitor::visit(procedure_call *call) | ||||
|     void empty_visitor::visit(procedure_call *) | ||||
|     { | ||||
|         for (expression *const argument : call->arguments) | ||||
|         { | ||||
|             argument->accept(this); | ||||
|         } | ||||
|         __builtin_unreachable(); | ||||
|     } | ||||
|  | ||||
|     void empty_visitor::visit(traits_expression *trait) | ||||
|     void empty_visitor::visit(traits_expression *) | ||||
|     { | ||||
|         trait->type().accept(this); | ||||
|         __builtin_unreachable(); | ||||
|     } | ||||
|  | ||||
|     void empty_visitor::visit(cast_expression *expression) | ||||
|     void empty_visitor::visit(cast_expression *) | ||||
|     { | ||||
|         expression->target().accept(this); | ||||
|         expression->value().accept(this); | ||||
|         __builtin_unreachable(); | ||||
|     } | ||||
|  | ||||
|     void empty_visitor::visit(assign_statement *statement) | ||||
|     void empty_visitor::visit(assign_statement *) | ||||
|     { | ||||
|         statement->rvalue().accept(this); | ||||
|         __builtin_unreachable(); | ||||
|     } | ||||
|  | ||||
|     void empty_visitor::visit(if_statement *statement) | ||||
|     void empty_visitor::visit(if_statement *) | ||||
|     { | ||||
|         statement->body().prerequisite().accept(this); | ||||
|         for (const auto body_statement : statement->body().statements) | ||||
|         { | ||||
|             body_statement->accept(this); | ||||
|         } | ||||
|         __builtin_unreachable(); | ||||
|     } | ||||
|  | ||||
|     void empty_visitor::visit(while_statement *statement) | ||||
|     void empty_visitor::visit(while_statement *) | ||||
|     { | ||||
|         statement->body().prerequisite().accept(this); | ||||
|         for (const auto body_statement : statement->body().statements) | ||||
|         { | ||||
|             body_statement->accept(this); | ||||
|         } | ||||
|         __builtin_unreachable(); | ||||
|     } | ||||
|  | ||||
|     void empty_visitor::visit(return_statement *statement) | ||||
|     void empty_visitor::visit(return_statement *) | ||||
|     { | ||||
|         expression *return_expression = statement->return_expression(); | ||||
|  | ||||
|         if (return_expression != nullptr) | ||||
|         { | ||||
|             return_expression->accept(this); | ||||
|         } | ||||
|         __builtin_unreachable(); | ||||
|     } | ||||
|  | ||||
|     void empty_visitor::visit(defer_statement *defer) | ||||
|     void empty_visitor::visit(defer_statement *) | ||||
|     { | ||||
|         for (statement *const body_statement : defer->statements) | ||||
|         { | ||||
|             body_statement->accept(this); | ||||
|         } | ||||
|         __builtin_unreachable(); | ||||
|     } | ||||
|  | ||||
|     void empty_visitor::visit(block *block) | ||||
|     void empty_visitor::visit(block *) | ||||
|     { | ||||
|         for (constant_definition *const constant : block->constants) | ||||
|         { | ||||
|             constant->accept(this); | ||||
|         } | ||||
|         for (variable_declaration *const variable : block->variables) | ||||
|         { | ||||
|             variable->accept(this); | ||||
|         } | ||||
|         for (statement *const body_statement : block->body) | ||||
|         { | ||||
|             body_statement->accept(this); | ||||
|         } | ||||
|         __builtin_unreachable(); | ||||
|     } | ||||
|  | ||||
|     void empty_visitor::visit(program *program) | ||||
|     void empty_visitor::visit(program *) | ||||
|     { | ||||
|         visit(reinterpret_cast<block *>(program)); | ||||
|         for (type_definition *const type : program->types) | ||||
|         { | ||||
|             type->accept(this); | ||||
|         } | ||||
|         for (procedure_definition *const procedure : program->procedures) | ||||
|         { | ||||
|             procedure->accept(this); | ||||
|         } | ||||
|         __builtin_unreachable(); | ||||
|     } | ||||
|  | ||||
|     void empty_visitor::visit(binary_expression *expression) | ||||
|     void empty_visitor::visit(binary_expression *) | ||||
|     { | ||||
|         expression->lhs().accept(this); | ||||
|         expression->rhs().accept(this); | ||||
|         __builtin_unreachable(); | ||||
|     } | ||||
|  | ||||
|     void empty_visitor::visit(unary_expression *expression) | ||||
|     void empty_visitor::visit(unary_expression *) | ||||
|     { | ||||
|         expression->operand().accept(this); | ||||
|         __builtin_unreachable(); | ||||
|     } | ||||
|  | ||||
|     void empty_visitor::visit(basic_type *) | ||||
|     void empty_visitor::visit(primitive_type_expression *) | ||||
|     { | ||||
|         __builtin_unreachable(); | ||||
|     } | ||||
|  | ||||
|     void empty_visitor::visit(array_type *expression) | ||||
|     void empty_visitor::visit(array_type_expression *) | ||||
|     { | ||||
|         expression->base().accept(this); | ||||
|         __builtin_unreachable(); | ||||
|     } | ||||
|  | ||||
|     void empty_visitor::visit(pointer_type *expression) | ||||
|     void empty_visitor::visit(pointer_type_expression *) | ||||
|     { | ||||
|         expression->base().accept(this); | ||||
|         __builtin_unreachable(); | ||||
|     } | ||||
|  | ||||
|     void empty_visitor::visit(record_type *expression) | ||||
|     void empty_visitor::visit(record_type_expression *) | ||||
|     { | ||||
|         for (auto& field : expression->fields) | ||||
|         { | ||||
|             field.second->accept(this); | ||||
|         } | ||||
|         __builtin_unreachable(); | ||||
|     } | ||||
|  | ||||
|     void empty_visitor::visit(union_type *expression) | ||||
|     void empty_visitor::visit(union_type_expression *) | ||||
|     { | ||||
|         for (auto& field : expression->fields) | ||||
|         { | ||||
|             field.second->accept(this); | ||||
|         } | ||||
|         __builtin_unreachable(); | ||||
|     } | ||||
|  | ||||
|     void empty_visitor::visit(procedure_type *expression) | ||||
|     void empty_visitor::visit(procedure_type_expression *) | ||||
|     { | ||||
|         for (auto parameter : expression->parameters) | ||||
|         { | ||||
|             parameter->accept(this); | ||||
|         } | ||||
|         if (expression->return_type != nullptr) | ||||
|         { | ||||
|             expression->return_type->accept(this); | ||||
|         } | ||||
|         __builtin_unreachable(); | ||||
|     } | ||||
|  | ||||
|     void empty_visitor::visit(variable_expression *) | ||||
|     { | ||||
|         __builtin_unreachable(); | ||||
|     } | ||||
|  | ||||
|     void empty_visitor::visit(array_access_expression *expression) | ||||
|     void empty_visitor::visit(array_access_expression *) | ||||
|     { | ||||
|         expression->base().accept(this); | ||||
|         expression->index().accept(this); | ||||
|         __builtin_unreachable(); | ||||
|     } | ||||
|  | ||||
|     void empty_visitor::visit(field_access_expression *expression) | ||||
|     void empty_visitor::visit(field_access_expression *) | ||||
|     { | ||||
|         expression->base().accept(this); | ||||
|         __builtin_unreachable(); | ||||
|     } | ||||
|  | ||||
|     void empty_visitor::visit(dereference_expression *expression) | ||||
|     void empty_visitor::visit(dereference_expression *) | ||||
|     { | ||||
|         expression->base().accept(this); | ||||
|         __builtin_unreachable(); | ||||
|     } | ||||
|  | ||||
|     void empty_visitor::visit(number_literal<std::int32_t> *) | ||||
|     { | ||||
|         __builtin_unreachable(); | ||||
|     } | ||||
|  | ||||
|     void empty_visitor::visit(number_literal<std::uint32_t> *) | ||||
|     { | ||||
|         __builtin_unreachable(); | ||||
|     } | ||||
|  | ||||
|     void empty_visitor::visit(number_literal<double> *) | ||||
|     { | ||||
|         __builtin_unreachable(); | ||||
|     } | ||||
|  | ||||
|     void empty_visitor::visit(number_literal<bool> *) | ||||
|     { | ||||
|         __builtin_unreachable(); | ||||
|     } | ||||
|  | ||||
|     void empty_visitor::visit(number_literal<unsigned char> *) | ||||
|     { | ||||
|         __builtin_unreachable(); | ||||
|     } | ||||
|  | ||||
|     void empty_visitor::visit(number_literal<std::nullptr_t> *) | ||||
|     { | ||||
|         __builtin_unreachable(); | ||||
|     } | ||||
|  | ||||
|     void empty_visitor::visit(number_literal<std::string> *) | ||||
|     { | ||||
|         __builtin_unreachable(); | ||||
|     } | ||||
|  | ||||
|     node::node(const struct position position) | ||||
| @@ -252,78 +204,130 @@ namespace boot | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     top_type::top_type(const struct position position) | ||||
|     type_expression::type_expression(const struct position position) | ||||
|         : node(position) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     basic_type::basic_type(const struct position position, const std::string& name) | ||||
|         : top_type(position), m_name(name) | ||||
|     std::shared_ptr<primitive_type_expression> type_expression::is_primitive() | ||||
|     { | ||||
|         return nullptr; | ||||
|     } | ||||
|  | ||||
|     std::shared_ptr<array_type_expression> type_expression::is_array() | ||||
|     { | ||||
|         return nullptr; | ||||
|     } | ||||
|  | ||||
|     std::shared_ptr<pointer_type_expression> type_expression::is_pointer() | ||||
|     { | ||||
|         return nullptr; | ||||
|     } | ||||
|  | ||||
|     std::shared_ptr<record_type_expression> type_expression::is_record() | ||||
|     { | ||||
|         return nullptr; | ||||
|     } | ||||
|  | ||||
|     std::shared_ptr<union_type_expression> type_expression::is_union() | ||||
|     { | ||||
|         return nullptr; | ||||
|     } | ||||
|  | ||||
|     std::shared_ptr<procedure_type_expression> type_expression::is_procedure() | ||||
|     { | ||||
|         return nullptr; | ||||
|     } | ||||
|  | ||||
|     primitive_type_expression::primitive_type_expression(const struct position position, const std::string& name) | ||||
|         : type_expression(position), name(name) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     void basic_type::accept(parser_visitor *visitor) | ||||
|     void primitive_type_expression::accept(parser_visitor *visitor) | ||||
|     { | ||||
|         visitor->visit(this); | ||||
|     } | ||||
|  | ||||
|     const std::string& basic_type::base_name() | ||||
|     std::shared_ptr<primitive_type_expression> primitive_type_expression::is_primitive() | ||||
|     { | ||||
|         return m_name; | ||||
|         return std::static_pointer_cast<primitive_type_expression>(shared_from_this()); | ||||
|     } | ||||
|  | ||||
|     array_type::array_type(const struct position position, std::shared_ptr<top_type> base, const std::uint32_t size) | ||||
|         : top_type(position), m_base(base), size(size) | ||||
|     array_type_expression::array_type_expression(const struct position position, | ||||
|             std::shared_ptr<type_expression> base, const std::uint32_t size) | ||||
|         : type_expression(position), m_base(base), size(size) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     void array_type::accept(parser_visitor *visitor) | ||||
|     void array_type_expression::accept(parser_visitor *visitor) | ||||
|     { | ||||
|         visitor->visit(this); | ||||
|     } | ||||
|  | ||||
|     top_type& array_type::base() | ||||
|     std::shared_ptr<array_type_expression> array_type_expression::is_array() | ||||
|     { | ||||
|         return std::static_pointer_cast<array_type_expression>(shared_from_this()); | ||||
|     } | ||||
|  | ||||
|     type_expression& array_type_expression::base() | ||||
|     { | ||||
|         return *m_base; | ||||
|     } | ||||
|  | ||||
|     pointer_type::pointer_type(const struct position position, std::shared_ptr<top_type> base) | ||||
|         : top_type(position), m_base(base) | ||||
|     pointer_type_expression::pointer_type_expression(const struct position position, | ||||
|             std::shared_ptr<type_expression> base) | ||||
|         : type_expression(position), m_base(base) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     void pointer_type::accept(parser_visitor *visitor) | ||||
|     void pointer_type_expression::accept(parser_visitor *visitor) | ||||
|     { | ||||
|         visitor->visit(this); | ||||
|     } | ||||
|  | ||||
|     top_type& pointer_type::base() | ||||
|     std::shared_ptr<pointer_type_expression> pointer_type_expression::is_pointer() | ||||
|     { | ||||
|         return std::static_pointer_cast<pointer_type_expression>(shared_from_this()); | ||||
|     } | ||||
|  | ||||
|     type_expression& pointer_type_expression::base() | ||||
|     { | ||||
|         return *m_base; | ||||
|     } | ||||
|  | ||||
|     record_type::record_type(const struct position position, fields_t&& fields) | ||||
|         : top_type(position), fields(std::move(fields)) | ||||
|     record_type_expression::record_type_expression(const struct position position, fields_t&& fields) | ||||
|         : type_expression(position), fields(std::move(fields)) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     void record_type::accept(parser_visitor *visitor) | ||||
|     void record_type_expression::accept(parser_visitor *visitor) | ||||
|     { | ||||
|         visitor->visit(this); | ||||
|     } | ||||
|  | ||||
|     union_type::union_type(const struct position position, fields_t&& fields) | ||||
|         : top_type(position), fields(std::move(fields)) | ||||
|     std::shared_ptr<record_type_expression> record_type_expression::is_record() | ||||
|     { | ||||
|         return std::static_pointer_cast<record_type_expression>(shared_from_this()); | ||||
|     } | ||||
|  | ||||
|     union_type_expression::union_type_expression(const struct position position, fields_t&& fields) | ||||
|         : type_expression(position), fields(std::move(fields)) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     void union_type::accept(parser_visitor *visitor) | ||||
|     void union_type_expression::accept(parser_visitor *visitor) | ||||
|     { | ||||
|         visitor->visit(this); | ||||
|     } | ||||
|  | ||||
|     std::shared_ptr<union_type_expression> union_type_expression::is_union() | ||||
|     { | ||||
|         return std::static_pointer_cast<union_type_expression>(shared_from_this()); | ||||
|     } | ||||
|  | ||||
|     variable_declaration::variable_declaration(const struct position position, const std::string& identifier, | ||||
|             std::shared_ptr<top_type> type, const bool exported) | ||||
|             std::shared_ptr<type_expression> type, const bool exported) | ||||
|         : definition(position, identifier, exported), m_type(type) | ||||
|     { | ||||
|     } | ||||
| @@ -333,7 +337,7 @@ namespace boot | ||||
|         visitor->visit(this); | ||||
|     } | ||||
|  | ||||
|     top_type& variable_declaration::variable_type() | ||||
|     type_expression& variable_declaration::variable_type() | ||||
|     { | ||||
|         return *m_type; | ||||
|     } | ||||
| @@ -364,22 +368,23 @@ namespace boot | ||||
|         delete m_body; | ||||
|     } | ||||
|  | ||||
|     procedure_type::procedure_type(const struct position position, std::shared_ptr<top_type> return_type) | ||||
|         : top_type(position), return_type(return_type), no_return(false) | ||||
|     procedure_type_expression::procedure_type_expression(const struct position position, | ||||
|             std::shared_ptr<type_expression> return_type) | ||||
|         : type_expression(position), return_type(return_type), no_return(false) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     procedure_type::procedure_type(const struct position position, no_return_t) | ||||
|         : top_type(position), return_type(nullptr), no_return(true) | ||||
|     procedure_type_expression::procedure_type_expression(const struct position position, no_return_t) | ||||
|         : type_expression(position), return_type(nullptr), no_return(true) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     void procedure_type::accept(parser_visitor *visitor) | ||||
|     void procedure_type_expression::accept(parser_visitor *visitor) | ||||
|     { | ||||
|         visitor->visit(this); | ||||
|     } | ||||
|  | ||||
|     procedure_type::~procedure_type() | ||||
|     procedure_type_expression::~procedure_type_expression() | ||||
|     { | ||||
|         for (auto parameter : this->parameters) | ||||
|         { | ||||
| @@ -388,7 +393,7 @@ namespace boot | ||||
|     } | ||||
|  | ||||
|     procedure_definition::procedure_definition(const struct position position, const std::string& identifier, | ||||
|             const bool exported, std::shared_ptr<procedure_type> heading, block *body) | ||||
|             const bool exported, std::shared_ptr<procedure_type_expression> heading, block *body) | ||||
|         : definition(position, identifier, exported), m_heading(heading), body(body) | ||||
|     { | ||||
|     } | ||||
| @@ -398,7 +403,12 @@ namespace boot | ||||
|         visitor->visit(this); | ||||
|     } | ||||
|  | ||||
|     procedure_type& procedure_definition::heading() | ||||
|     std::shared_ptr<procedure_type_expression> procedure_type_expression::is_procedure() | ||||
|     { | ||||
|         return std::static_pointer_cast<procedure_type_expression>(shared_from_this()); | ||||
|     } | ||||
|  | ||||
|     procedure_type_expression& procedure_definition::heading() | ||||
|     { | ||||
|         return *m_heading; | ||||
|     } | ||||
| @@ -409,7 +419,7 @@ namespace boot | ||||
|     } | ||||
|  | ||||
|     type_definition::type_definition(const struct position position, const std::string& identifier, | ||||
|             const bool exported, std::shared_ptr<top_type> body) | ||||
|             const bool exported, std::shared_ptr<type_expression> body) | ||||
|         : definition(position, identifier, exported), m_body(body) | ||||
|     { | ||||
|     } | ||||
| @@ -419,7 +429,7 @@ namespace boot | ||||
|         visitor->visit(this); | ||||
|     } | ||||
|  | ||||
|     top_type& type_definition::body() | ||||
|     type_expression& type_definition::body() | ||||
|     { | ||||
|         return *m_body; | ||||
|     } | ||||
| @@ -685,7 +695,7 @@ namespace boot | ||||
|     } | ||||
|  | ||||
|     cast_expression::cast_expression(const struct position position, | ||||
|             std::shared_ptr<top_type> target, expression *value) | ||||
|             std::shared_ptr<type_expression> target, expression *value) | ||||
|         : node(position), m_target(target), m_value(value) | ||||
|     { | ||||
|     } | ||||
| @@ -695,7 +705,7 @@ namespace boot | ||||
|         visitor->visit(this); | ||||
|     } | ||||
|  | ||||
|     top_type& cast_expression::target() | ||||
|     type_expression& cast_expression::target() | ||||
|     { | ||||
|         return *m_target; | ||||
|     } | ||||
| @@ -711,7 +721,7 @@ namespace boot | ||||
|     } | ||||
|  | ||||
|     traits_expression::traits_expression(const struct position position, | ||||
|             const std::string& name, std::shared_ptr<top_type> type) | ||||
|             const std::string& name, std::shared_ptr<type_expression> type) | ||||
|         : node(position), m_type(type), name(name) | ||||
|     { | ||||
|     } | ||||
| @@ -721,7 +731,7 @@ namespace boot | ||||
|         visitor->visit(this); | ||||
|     } | ||||
|  | ||||
|     top_type& traits_expression::type() | ||||
|     type_expression& traits_expression::type() | ||||
|     { | ||||
|         return *m_type; | ||||
|     } | ||||
|   | ||||
| @@ -125,7 +125,7 @@ along with GCC; see the file COPYING3.  If not see | ||||
| %type <std::vector<elna::boot::variable_declaration *>> variable_declarations variable_part variable_declaration | ||||
|     formal_parameters formal_parameter_list; | ||||
| %type <elna::boot::variable_declaration *> formal_parameter | ||||
| %type <std::shared_ptr<elna::boot::top_type>> type_expression; | ||||
| %type <std::shared_ptr<elna::boot::type_expression>> type_expression; | ||||
| %type <elna::boot::traits_expression *> traits_expression; | ||||
| %type <elna::boot::expression *> expression operand; | ||||
| %type <elna::boot::unary_expression *> unary_expression; | ||||
| @@ -140,13 +140,14 @@ along with GCC; see the file COPYING3.  If not see | ||||
| %type <elna::boot::statement *> statement; | ||||
| %type <std::vector<elna::boot::statement *>> statements; | ||||
| %type <elna::boot::procedure_definition *> procedure_definition; | ||||
| %type <std::shared_ptr<elna::boot::procedure_type>> procedure_heading; | ||||
| %type <std::shared_ptr<elna::boot::procedure_type_expression>> procedure_heading; | ||||
| %type <std::vector<elna::boot::procedure_definition *>> procedure_definitions procedure_part; | ||||
| %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 <std::vector<std::pair<std::string, std::shared_ptr<elna::boot::top_type>>>> optional_fields required_fields; | ||||
| %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; | ||||
| %type <elna::boot::cast_expression *> cast_expression; | ||||
| %type <elna::boot::defer_statement *> defer_statement; | ||||
| @@ -193,17 +194,18 @@ identifier_definitions: | ||||
| procedure_heading: | ||||
|     formal_parameter_list | ||||
|         { | ||||
|             $$ = std::make_shared<elna::boot::procedure_type>(elna::boot::make_position(@1)); | ||||
|             $$ = std::make_shared<elna::boot::procedure_type_expression>(elna::boot::make_position(@1)); | ||||
|             std::swap($1, $$->parameters); | ||||
|         } | ||||
|     | formal_parameter_list "->" "!" | ||||
|         { | ||||
|             $$ = std::make_shared<elna::boot::procedure_type>(elna::boot::make_position(@1), elna::boot::no_return); | ||||
|             $$ = std::make_shared<elna::boot::procedure_type_expression>(elna::boot::make_position(@1), | ||||
|                 elna::boot::no_return); | ||||
|             std::swap($1, $$->parameters); | ||||
|         } | ||||
|     | formal_parameter_list "->" type_expression | ||||
|         { | ||||
|             $$ = std::make_shared<elna::boot::procedure_type>(elna::boot::make_position(@1), $3); | ||||
|             $$ = std::make_shared<elna::boot::procedure_type_expression>(elna::boot::make_position(@1), $3); | ||||
|             std::swap($1, $$->parameters); | ||||
|         } | ||||
| procedure_definition: | ||||
| @@ -484,19 +486,19 @@ optional_fields: | ||||
| type_expression: | ||||
|     "[" INTEGER "]" type_expression | ||||
|         { | ||||
|             $$ = std::make_shared<elna::boot::array_type>(elna::boot::make_position(@1), $4, $2); | ||||
|             $$ = std::make_shared<elna::boot::array_type_expression>(elna::boot::make_position(@1), $4, $2); | ||||
|         } | ||||
|     | "^" type_expression | ||||
|         { | ||||
|             $$ = std::make_shared<elna::boot::pointer_type>(elna::boot::make_position(@1), $2); | ||||
|             $$ = std::make_shared<elna::boot::pointer_type_expression>(elna::boot::make_position(@1), $2); | ||||
|         } | ||||
|     | "record" optional_fields "end" | ||||
|         { | ||||
|             $$ = std::make_shared<elna::boot::record_type>(elna::boot::make_position(@1), std::move($2)); | ||||
|             $$ = std::make_shared<elna::boot::record_type_expression>(elna::boot::make_position(@1), std::move($2)); | ||||
|         } | ||||
|     | "union" required_fields "end" | ||||
|         { | ||||
|             $$ = std::make_shared<elna::boot::union_type>(elna::boot::make_position(@1), std::move($2)); | ||||
|             $$ = std::make_shared<elna::boot::union_type_expression>(elna::boot::make_position(@1), std::move($2)); | ||||
|         } | ||||
|     | "proc" procedure_heading | ||||
|         { | ||||
| @@ -504,7 +506,7 @@ type_expression: | ||||
|         } | ||||
|     | IDENTIFIER | ||||
|         { | ||||
|             $$ = std::make_shared<elna::boot::basic_type>(elna::boot::make_position(@1), $1); | ||||
|             $$ = std::make_shared<elna::boot::primitive_type_expression>(elna::boot::make_position(@1), $1); | ||||
|         } | ||||
| variable_declaration: identifier_definitions ":" type_expression | ||||
|         { | ||||
|   | ||||
							
								
								
									
										33
									
								
								boot/semantic.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								boot/semantic.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | ||||
| /* Semantic analysis visitors. | ||||
|    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 | ||||
| { | ||||
|     declaration_visitor::declaration_visitor(std::shared_ptr<symbol_table> table) | ||||
|         : table(table) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     void declaration_visitor::visit(program *program) | ||||
|     { | ||||
|     } | ||||
| } | ||||
| } | ||||
							
								
								
									
										37
									
								
								boot/symbol.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								boot/symbol.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | ||||
| /* Symbol definitions. | ||||
|    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/symbol.h" | ||||
|  | ||||
| namespace elna | ||||
| { | ||||
| namespace boot | ||||
| { | ||||
|     type::~type() | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     info::~info() | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     type_info::type_info(const std::string& name) | ||||
|         : name(name) | ||||
|     { | ||||
|     } | ||||
| } | ||||
| } | ||||
| @@ -46,6 +46,8 @@ elna_OBJS = \ | ||||
| 	elna/driver.o \ | ||||
| 	elna/lexer.o \ | ||||
| 	elna/parser.o \ | ||||
| 	elna/semantic.o \ | ||||
| 	elna/symbol.o \ | ||||
| 	elna/result.o \ | ||||
| 	$(END) | ||||
|  | ||||
| @@ -134,7 +136,7 @@ elna.stagefeedback: stagefeedback-start | ||||
| 	-mv elna/*$(objext) stagefeedback/elna | ||||
|  | ||||
| ELNA_INCLUDES = -I $(srcdir)/elna/include -I elna/generated | ||||
| ELNA_CXXFLAGS = -std=c++11 | ||||
| ELNA_CXXFLAGS = -std=c++14 | ||||
|  | ||||
| elna/%.o: elna/boot/%.cc elna/generated/parser.hh elna/generated/location.hh | ||||
| 	$(COMPILE) $(ELNA_CXXFLAGS) $(ELNA_INCLUDES) $< | ||||
|   | ||||
| @@ -180,6 +180,23 @@ namespace gcc | ||||
|             constant->accept(this); | ||||
|         } | ||||
|         for (boot::type_definition *const type : program->types) | ||||
|         { | ||||
|             tree type_node = NULL_TREE; | ||||
|  | ||||
|             if (type->body().is_record()) | ||||
|             { | ||||
|                 type_node = make_node(RECORD_TYPE); | ||||
|             } | ||||
|             else if (type->body().is_union()) | ||||
|             { | ||||
|                 type_node = make_node(UNION_TYPE); | ||||
|             } | ||||
|             if (type_node != NULL_TREE) | ||||
|             { | ||||
|                 this->symbol_map->enter(type->identifier, type_node); | ||||
|             } | ||||
|         } | ||||
|         for (boot::type_definition *const type : program->types) | ||||
|         { | ||||
|             type->accept(this); | ||||
|         } | ||||
| @@ -731,33 +748,34 @@ namespace gcc | ||||
|     void generic_visitor::visit(boot::type_definition *definition) | ||||
|     { | ||||
|         location_t definition_location = get_location(&definition->position()); | ||||
|         this->current_expression = this->symbol_map->lookup(definition->identifier); | ||||
|         definition->body().accept(this); | ||||
|  | ||||
|         tree definition_tree = build_decl(definition_location, TYPE_DECL, | ||||
|                 get_identifier(definition->identifier.c_str()), this->current_expression); | ||||
|         auto result = this->symbol_map->enter(definition->identifier, this->current_expression); | ||||
|  | ||||
|         if (result) | ||||
|         { | ||||
|         /* if (result) | ||||
|         { */ | ||||
|             TREE_PUBLIC(definition_tree) = definition->exported; | ||||
|             TYPE_NAME(this->current_expression) = get_identifier(definition->identifier.c_str()); | ||||
|         } | ||||
|         else | ||||
|         // } | ||||
|         /* else | ||||
|         { | ||||
|             error_at(get_location(&definition->position()), | ||||
|                     "type '%s' already declared in this scope", | ||||
|                     definition->identifier.c_str()); | ||||
|         } | ||||
|         } */ | ||||
|         this->current_expression = NULL_TREE; | ||||
|     } | ||||
|  | ||||
|     tree generic_visitor::build_procedure_type(boot::procedure_type& type) | ||||
|     tree generic_visitor::build_procedure_type(boot::procedure_type_expression& type) | ||||
|     { | ||||
|         std::vector<tree> parameter_types(type.parameters.size()); | ||||
|  | ||||
|         for (std::size_t i = 0; i < type.parameters.size(); ++i) | ||||
|         { | ||||
|             boot::top_type& parameter_type = type.parameters.at(i)->variable_type(); | ||||
|             boot::type_expression& parameter_type = type.parameters.at(i)->variable_type(); | ||||
|             parameter_type.accept(this); | ||||
|             parameter_types[i] = this->current_expression; | ||||
|         } | ||||
| @@ -1102,14 +1120,14 @@ namespace gcc | ||||
|         this->current_expression = NULL_TREE; | ||||
|     } | ||||
|  | ||||
|     void generic_visitor::visit(boot::basic_type *type) | ||||
|     void generic_visitor::visit(boot::primitive_type_expression *type) | ||||
|     { | ||||
|         tree symbol = this->lookup(type->base_name()); | ||||
|         tree symbol = this->lookup(type->name); | ||||
|  | ||||
|         if (symbol == NULL_TREE && TYPE_P(symbol)) | ||||
|         { | ||||
|             error_at(get_location(&type->position()), | ||||
|                     "type '%s' not declared", type->base_name().c_str()); | ||||
|                     "type '%s' not declared", type->name.c_str()); | ||||
|  | ||||
|             this->current_expression = error_mark_node; | ||||
|         } | ||||
| @@ -1119,7 +1137,7 @@ namespace gcc | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void generic_visitor::visit(boot::array_type *type) | ||||
|     void generic_visitor::visit(boot::array_type_expression *type) | ||||
|     { | ||||
|         tree lower_bound = build_int_cst_type(integer_type_node, 0); | ||||
|         tree upper_bound = build_int_cst_type(integer_type_node, type->size); | ||||
| @@ -1133,7 +1151,7 @@ namespace gcc | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void generic_visitor::visit(boot::pointer_type *type) | ||||
|     void generic_visitor::visit(boot::pointer_type_expression *type) | ||||
|     { | ||||
|         type->base().accept(this); | ||||
|  | ||||
| @@ -1143,10 +1161,12 @@ namespace gcc | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void generic_visitor::visit(boot::record_type *type) | ||||
|     void generic_visitor::visit(boot::record_type_expression *type) | ||||
|     { | ||||
|         std::set<std::string> field_names; | ||||
|         tree record_type_node = make_node(RECORD_TYPE); | ||||
|         tree record_type_node = this->current_expression == NULL_TREE | ||||
|             ? make_node(RECORD_TYPE) | ||||
|             : this->current_expression; | ||||
|  | ||||
|         for (auto& field : type->fields) | ||||
|         { | ||||
| @@ -1166,16 +1186,19 @@ namespace gcc | ||||
|             tree field_declaration = build_field(get_location(&field.second->position()), | ||||
|                     record_type_node, field.first, this->current_expression); | ||||
|             TYPE_FIELDS(record_type_node) = chainon(TYPE_FIELDS(record_type_node), field_declaration); | ||||
|             this->current_expression = NULL_TREE; | ||||
|         } | ||||
|         layout_type(record_type_node); | ||||
|  | ||||
|         this->current_expression = record_type_node; | ||||
|     } | ||||
|  | ||||
|     void generic_visitor::visit(boot::union_type *type) | ||||
|     void generic_visitor::visit(boot::union_type_expression *type) | ||||
|     { | ||||
|         std::set<std::string> field_names; | ||||
|         tree union_type_node = make_node(UNION_TYPE); | ||||
|         tree union_type_node = this->current_expression == NULL_TREE | ||||
|             ? make_node(UNION_TYPE) | ||||
|             : this->current_expression; | ||||
|  | ||||
|         for (auto& field : type->fields) | ||||
|         { | ||||
| @@ -1195,13 +1218,14 @@ namespace gcc | ||||
|             tree field_declaration = build_field(get_location(&field.second->position()), | ||||
|                     union_type_node, field.first, this->current_expression); | ||||
|             TYPE_FIELDS(union_type_node) = chainon(TYPE_FIELDS(union_type_node), field_declaration); | ||||
|             this->current_expression = NULL_TREE; | ||||
|         } | ||||
|         layout_type(union_type_node); | ||||
|  | ||||
|         this->current_expression = union_type_node; | ||||
|     } | ||||
|  | ||||
|     void generic_visitor::visit(boot::procedure_type *type) | ||||
|     void generic_visitor::visit(boot::procedure_type_expression *type) | ||||
|     { | ||||
|         tree procedure_type_node = build_procedure_type(*type); | ||||
|         this->current_expression = build_pointer_type_for_mode(procedure_type_node, VOIDmode, true); | ||||
|   | ||||
| @@ -30,6 +30,7 @@ along with GCC; see the file COPYING3.  If not see | ||||
|  | ||||
| #include <fstream> | ||||
| #include "elna/boot/driver.h" | ||||
| #include "elna/boot/semantic.h" | ||||
| #include "elna/gcc/elna-tree.h" | ||||
| #include "elna/gcc/elna-generic.h" | ||||
| #include "elna/gcc/elna-diagnostic.h" | ||||
| @@ -88,8 +89,10 @@ static void elna_parse_file(const char *filename) | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         elna::boot::declaration_visitor declaration_visitor{ std::make_shared<elna::boot::symbol_table>() }; | ||||
|         elna::gcc::generic_visitor generic_visitor{ std::make_shared<elna::gcc::symbol_table>() }; | ||||
|  | ||||
|         declaration_visitor.visit(driver.tree.get()); | ||||
|         generic_visitor.visit(driver.tree.get()); | ||||
|     } | ||||
|     linemap_add(line_table, LC_LEAVE, 0, NULL, 0); | ||||
|   | ||||
| @@ -69,12 +69,12 @@ namespace boot | ||||
|     class program; | ||||
|     class binary_expression; | ||||
|     class unary_expression; | ||||
|     class basic_type; | ||||
|     class array_type; | ||||
|     class pointer_type; | ||||
|     class record_type; | ||||
|     class union_type; | ||||
|     class procedure_type; | ||||
|     class primitive_type_expression; | ||||
|     class array_type_expression; | ||||
|     class pointer_type_expression; | ||||
|     class record_type_expression; | ||||
|     class union_type_expression; | ||||
|     class procedure_type_expression; | ||||
|     class variable_expression; | ||||
|     class array_access_expression; | ||||
|     class field_access_expression; | ||||
| @@ -104,16 +104,16 @@ namespace boot | ||||
|         virtual void visit(program *) = 0; | ||||
|         virtual void visit(binary_expression *) = 0; | ||||
|         virtual void visit(unary_expression *) = 0; | ||||
|         virtual void visit(basic_type *) = 0; | ||||
|         virtual void visit(array_type *) = 0; | ||||
|         virtual void visit(pointer_type *) = 0; | ||||
|         virtual void visit(record_type *) = 0; | ||||
|         virtual void visit(union_type *) = 0; | ||||
|         virtual void visit(procedure_type *) = 0; | ||||
|         virtual void visit(primitive_type_expression *) = 0; | ||||
|         virtual void visit(array_type_expression *) = 0; | ||||
|         virtual void visit(pointer_type_expression *) = 0; | ||||
|         virtual void visit(record_type_expression *) = 0; | ||||
|         virtual void visit(union_type_expression *) = 0; | ||||
|         virtual void visit(procedure_type_expression *) = 0; | ||||
|         virtual void visit(variable_expression *) = 0; | ||||
|         virtual void visit(array_access_expression *) = 0; | ||||
|         virtual void visit(field_access_expression *is_field_access) = 0; | ||||
|         virtual void visit(dereference_expression *is_dereference) = 0; | ||||
|         virtual void visit(field_access_expression *) = 0; | ||||
|         virtual void visit(dereference_expression *) = 0; | ||||
|         virtual void visit(number_literal<std::int32_t> *) = 0; | ||||
|         virtual void visit(number_literal<std::uint32_t> *) = 0; | ||||
|         virtual void visit(number_literal<double> *) = 0; | ||||
| @@ -129,31 +129,31 @@ namespace boot | ||||
|     struct empty_visitor : parser_visitor | ||||
|     { | ||||
|         virtual void visit(variable_declaration *) override; | ||||
|         virtual void visit(constant_definition *definition) override; | ||||
|         virtual void visit(procedure_definition *definition) override; | ||||
|         virtual void visit(type_definition *definition) override; | ||||
|         virtual void visit(traits_expression *trait) override; | ||||
|         virtual void visit(procedure_call *call) override; | ||||
|         virtual void visit(cast_expression *expression) override; | ||||
|         virtual void visit(assign_statement *statement) override; | ||||
|         virtual void visit(constant_definition *) override; | ||||
|         virtual void visit(procedure_definition *) override; | ||||
|         virtual void visit(type_definition *) override; | ||||
|         virtual void visit(traits_expression *) override; | ||||
|         virtual void visit(procedure_call *) override; | ||||
|         virtual void visit(cast_expression *) override; | ||||
|         virtual void visit(assign_statement *) override; | ||||
|         virtual void visit(if_statement *) override; | ||||
|         virtual void visit(while_statement *) override; | ||||
|         virtual void visit(return_statement *) override; | ||||
|         virtual void visit(defer_statement *defer) override; | ||||
|         virtual void visit(block *block) override; | ||||
|         virtual void visit(program *program) override; | ||||
|         virtual void visit(binary_expression *expression) override; | ||||
|         virtual void visit(unary_expression *expression) override; | ||||
|         virtual void visit(basic_type *) override; | ||||
|         virtual void visit(array_type *expression) override; | ||||
|         virtual void visit(pointer_type *) override; | ||||
|         virtual void visit(record_type *expression) override; | ||||
|         virtual void visit(union_type *expression) override; | ||||
|         virtual void visit(procedure_type *expression) override; | ||||
|         virtual void visit(defer_statement *) override; | ||||
|         virtual void visit(block *) override; | ||||
|         virtual void visit(program *) override; | ||||
|         virtual void visit(binary_expression *) override; | ||||
|         virtual void visit(unary_expression *) override; | ||||
|         virtual void visit(primitive_type_expression *) override; | ||||
|         virtual void visit(array_type_expression *) override; | ||||
|         virtual void visit(pointer_type_expression *) override; | ||||
|         virtual void visit(record_type_expression *) override; | ||||
|         virtual void visit(union_type_expression *) override; | ||||
|         virtual void visit(procedure_type_expression *) override; | ||||
|         virtual void visit(variable_expression *) override; | ||||
|         virtual void visit(array_access_expression *expression) override; | ||||
|         virtual void visit(field_access_expression *expression) override; | ||||
|         virtual void visit(dereference_expression *expression) override; | ||||
|         virtual void visit(array_access_expression *) override; | ||||
|         virtual void visit(field_access_expression *) override; | ||||
|         virtual void visit(dereference_expression *) override; | ||||
|         virtual void visit(number_literal<std::int32_t> *) override; | ||||
|         virtual void visit(number_literal<std::uint32_t> *) override; | ||||
|         virtual void visit(number_literal<double> *) override; | ||||
| @@ -214,75 +214,83 @@ namespace boot | ||||
|     /** | ||||
|      * Some type expression. | ||||
|      */ | ||||
|     class top_type : public node, public std::enable_shared_from_this<top_type> | ||||
|     class type_expression : public node, public std::enable_shared_from_this<type_expression> | ||||
|     { | ||||
|     public: | ||||
|         virtual std::shared_ptr<primitive_type_expression> is_primitive(); | ||||
|         virtual std::shared_ptr<array_type_expression> is_array(); | ||||
|         virtual std::shared_ptr<pointer_type_expression> is_pointer(); | ||||
|         virtual std::shared_ptr<record_type_expression> is_record(); | ||||
|         virtual std::shared_ptr<union_type_expression> is_union(); | ||||
|         virtual std::shared_ptr<procedure_type_expression> is_procedure(); | ||||
|  | ||||
|     protected: | ||||
|         top_type(const struct position position); | ||||
|         type_expression(const struct position position); | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * Expression defining a basic type. | ||||
|      */ | ||||
|     class basic_type : public top_type | ||||
|     class primitive_type_expression : public type_expression | ||||
|     { | ||||
|         const std::string m_name; | ||||
|  | ||||
|     public: | ||||
|         /** | ||||
|          * \param position Source code position. | ||||
|          * \param name Type name. | ||||
|          */ | ||||
|         basic_type(const struct position position, const std::string& name); | ||||
|         virtual void accept(parser_visitor *visitor) override; | ||||
|         const std::string name; | ||||
|  | ||||
|         const std::string& base_name(); | ||||
|         primitive_type_expression(const struct position position, const std::string& name); | ||||
|         virtual void accept(parser_visitor *visitor) override; | ||||
|         std::shared_ptr<primitive_type_expression> is_primitive() override; | ||||
|     }; | ||||
|  | ||||
|     class array_type : public top_type | ||||
|     class array_type_expression : public type_expression | ||||
|     { | ||||
|         std::shared_ptr<top_type> m_base; | ||||
|         std::shared_ptr<type_expression> m_base; | ||||
|  | ||||
|     public: | ||||
|         const std::uint32_t size; | ||||
|  | ||||
|         array_type(const struct position position, std::shared_ptr<top_type> base, const std::uint32_t size); | ||||
|         array_type_expression(const struct position position, | ||||
|                 std::shared_ptr<type_expression> base, const std::uint32_t size); | ||||
|         virtual void accept(parser_visitor *visitor) override; | ||||
|         std::shared_ptr<array_type_expression> is_array() override; | ||||
|  | ||||
|         top_type& base(); | ||||
|         type_expression& base(); | ||||
|     }; | ||||
|  | ||||
|     class pointer_type : public top_type | ||||
|     class pointer_type_expression : public type_expression | ||||
|     { | ||||
|         std::shared_ptr<top_type> m_base; | ||||
|         std::shared_ptr<type_expression> m_base; | ||||
|  | ||||
|     public: | ||||
|         pointer_type(const struct position position, std::shared_ptr<top_type> base); | ||||
|         pointer_type_expression(const struct position position, std::shared_ptr<type_expression> base); | ||||
|         virtual void accept(parser_visitor *visitor) override; | ||||
|         std::shared_ptr<pointer_type_expression> is_pointer() override; | ||||
|  | ||||
|         top_type& base(); | ||||
|         type_expression& base(); | ||||
|     }; | ||||
|  | ||||
|     using field_t = std::pair<std::string, std::shared_ptr<top_type>>; | ||||
|     using field_t = std::pair<std::string, std::shared_ptr<type_expression>>; | ||||
|     using fields_t = std::vector<field_t>; | ||||
|  | ||||
|     class record_type : public top_type | ||||
|     class record_type_expression : public type_expression | ||||
|     { | ||||
|     public: | ||||
|         fields_t fields; | ||||
|  | ||||
|         record_type(const struct position position, fields_t&& fields); | ||||
|         record_type_expression(const struct position position, fields_t&& fields); | ||||
|  | ||||
|         virtual void accept(parser_visitor *visitor) override; | ||||
|         std::shared_ptr<record_type_expression> is_record() override; | ||||
|     }; | ||||
|  | ||||
|     class union_type : public top_type | ||||
|     class union_type_expression : public type_expression | ||||
|     { | ||||
|     public: | ||||
|         fields_t fields; | ||||
|  | ||||
|         union_type(const struct position position, fields_t&& fields); | ||||
|         union_type_expression(const struct position position, fields_t&& fields); | ||||
|  | ||||
|         virtual void accept(parser_visitor *visitor) override; | ||||
|         std::shared_ptr<union_type_expression> is_union() override; | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
| @@ -290,14 +298,14 @@ namespace boot | ||||
|      */ | ||||
|     class variable_declaration : public definition | ||||
|     { | ||||
|         std::shared_ptr<top_type> m_type; | ||||
|         std::shared_ptr<type_expression> m_type; | ||||
|  | ||||
|     public: | ||||
|         variable_declaration(const struct position position, const std::string& identifier, | ||||
|                 std::shared_ptr<top_type> type, const bool exported = false); | ||||
|                 std::shared_ptr<type_expression> type, const bool exported = false); | ||||
|         virtual void accept(parser_visitor *visitor) override; | ||||
|  | ||||
|         top_type& variable_type(); | ||||
|         type_expression& variable_type(); | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
| @@ -342,19 +350,21 @@ namespace boot | ||||
|     /** | ||||
|      * Procedure type. | ||||
|      */ | ||||
|     class procedure_type : public top_type | ||||
|     class procedure_type_expression : public type_expression | ||||
|     { | ||||
|     public: | ||||
|         const std::shared_ptr<top_type> return_type; | ||||
|         const std::shared_ptr<type_expression> return_type; | ||||
|         const bool no_return; | ||||
|         std::vector<variable_declaration *> parameters; | ||||
|  | ||||
|         procedure_type(const struct position position, std::shared_ptr<top_type> return_type = nullptr); | ||||
|         procedure_type(const struct position position, no_return_t); | ||||
|         procedure_type_expression(const struct position position, | ||||
|                 std::shared_ptr<type_expression> return_type = nullptr); | ||||
|         procedure_type_expression(const struct position position, no_return_t); | ||||
|  | ||||
|         virtual void accept(parser_visitor *visitor) override; | ||||
|         std::shared_ptr<procedure_type_expression> is_procedure() override; | ||||
|  | ||||
|         virtual ~procedure_type() override; | ||||
|         virtual ~procedure_type_expression() override; | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
| @@ -362,16 +372,16 @@ namespace boot | ||||
|      */ | ||||
|     class procedure_definition : public definition | ||||
|     { | ||||
|         std::shared_ptr<procedure_type> m_heading; | ||||
|         std::shared_ptr<procedure_type_expression> m_heading; | ||||
|  | ||||
|     public: | ||||
|         block *const body; | ||||
|  | ||||
|         procedure_definition(const struct position position, const std::string& identifier, | ||||
|                 const bool exported, std::shared_ptr<procedure_type> heading, block *body = nullptr); | ||||
|                 const bool exported, std::shared_ptr<procedure_type_expression> heading, block *body = nullptr); | ||||
|         virtual void accept(parser_visitor *visitor) override; | ||||
|  | ||||
|         procedure_type& heading(); | ||||
|         procedure_type_expression& heading(); | ||||
|  | ||||
|         virtual ~procedure_definition() override; | ||||
|     }; | ||||
| @@ -381,14 +391,14 @@ namespace boot | ||||
|      */ | ||||
|     class type_definition : public definition | ||||
|     { | ||||
|         std::shared_ptr<top_type> m_body; | ||||
|         std::shared_ptr<type_expression> m_body; | ||||
|  | ||||
|     public: | ||||
|         type_definition(const struct position position, const std::string& identifier, | ||||
|                 const bool exported, std::shared_ptr<top_type> expression); | ||||
|                 const bool exported, std::shared_ptr<type_expression> expression); | ||||
|         virtual void accept(parser_visitor *visitor) override; | ||||
|  | ||||
|         top_type& body(); | ||||
|         type_expression& body(); | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
| @@ -396,14 +406,14 @@ namespace boot | ||||
|      */ | ||||
|     class cast_expression : public expression | ||||
|     { | ||||
|         std::shared_ptr<top_type> m_target; | ||||
|         std::shared_ptr<type_expression> m_target; | ||||
|         expression *m_value; | ||||
|  | ||||
|     public: | ||||
|         cast_expression(const struct position position, std::shared_ptr<top_type> target, expression *value); | ||||
|         cast_expression(const struct position position, std::shared_ptr<type_expression> target, expression *value); | ||||
|         virtual void accept(parser_visitor *visitor) override; | ||||
|  | ||||
|         top_type& target(); | ||||
|         type_expression& target(); | ||||
|         expression& value(); | ||||
|  | ||||
|         virtual ~cast_expression() override; | ||||
| @@ -411,15 +421,16 @@ namespace boot | ||||
|  | ||||
|     class traits_expression : public expression | ||||
|     { | ||||
|         std::shared_ptr<top_type> m_type; | ||||
|         std::shared_ptr<type_expression> m_type; | ||||
|  | ||||
|     public: | ||||
|         const std::string name; | ||||
|  | ||||
|         traits_expression(const struct position position, const std::string& name, std::shared_ptr<top_type> type); | ||||
|         traits_expression(const struct position position, const std::string& name, | ||||
|                 std::shared_ptr<type_expression> type); | ||||
|         virtual void accept(parser_visitor *visitor) override; | ||||
|  | ||||
|         top_type& type(); | ||||
|         type_expression& type(); | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|   | ||||
							
								
								
									
										37
									
								
								include/elna/boot/semantic.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								include/elna/boot/semantic.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | ||||
| /* Semantic analysis visitors. | ||||
|    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/>.  */ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "elna/boot/ast.h" | ||||
| #include "elna/boot/symbol.h" | ||||
|  | ||||
| namespace elna | ||||
| { | ||||
| namespace boot | ||||
| { | ||||
|     class declaration_visitor : public empty_visitor | ||||
|     { | ||||
|         std::shared_ptr<symbol_table> table; | ||||
|  | ||||
|     public: | ||||
|         declaration_visitor(std::shared_ptr<symbol_table> table); | ||||
|  | ||||
|         void visit(program *program) override; | ||||
|     }; | ||||
| } | ||||
| } | ||||
| @@ -26,20 +26,49 @@ namespace elna | ||||
| { | ||||
| namespace boot | ||||
| { | ||||
|     class info | ||||
|     { | ||||
|     public: | ||||
|         virtual ~info() = 0; | ||||
|  | ||||
|     protected: | ||||
|         info() = default; | ||||
|     }; | ||||
|  | ||||
|     class type | ||||
|     { | ||||
|     public: | ||||
|         virtual ~type() = 0; | ||||
|  | ||||
|     protected: | ||||
|         type() = default; | ||||
|     }; | ||||
|  | ||||
|     class type_info : public info, public type | ||||
|     { | ||||
|     public: | ||||
|         const std::string name; | ||||
|  | ||||
|         type_info(const std::string& name); | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * Symbol table. | ||||
|      */ | ||||
|     template<typename T, T nothing> | ||||
|     class symbol_table | ||||
|     template<typename T, typename U, U nothing> | ||||
|     class symbol_map | ||||
|     { | ||||
|     public: | ||||
|         using symbol_ptr = T; | ||||
|         using symbol_ptr = typename std::enable_if< | ||||
|             std::is_convertible<U, T>::value || std::is_assignable<T, U>::value, | ||||
|             T | ||||
|         >::type; | ||||
|         using iterator = typename std::unordered_map<std::string, symbol_ptr>::iterator; | ||||
|         using const_iterator = typename std::unordered_map<std::string, symbol_ptr>::const_iterator; | ||||
|  | ||||
|     private: | ||||
|         std::unordered_map<std::string, symbol_ptr> entries; | ||||
|         std::shared_ptr<symbol_table> outer_scope; | ||||
|         std::shared_ptr<symbol_map> outer_scope; | ||||
|  | ||||
|     public: | ||||
|         /** | ||||
| @@ -47,7 +76,7 @@ namespace boot | ||||
|          * | ||||
|          * \param scope Outer scope. | ||||
|          */ | ||||
|         explicit symbol_table(std::shared_ptr<symbol_table> scope = nullptr) | ||||
|         explicit symbol_map(std::shared_ptr<symbol_map> scope = nullptr) | ||||
|             : outer_scope(scope) | ||||
|         { | ||||
|         } | ||||
| @@ -104,14 +133,7 @@ namespace boot | ||||
|          */ | ||||
|         bool enter(const std::string& name, symbol_ptr entry) | ||||
|         { | ||||
|             if (lookup(name) == nothing) | ||||
|             { | ||||
|                 return entries.insert({ name, entry }).second; | ||||
|             } | ||||
|             else  | ||||
|             { | ||||
|                 return nothing; | ||||
|             } | ||||
|             return lookup(name) == nothing && entries.insert({ name, entry }).second; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
| @@ -119,10 +141,12 @@ namespace boot | ||||
|          * | ||||
|          * \return Outer scope. | ||||
|          */ | ||||
|         std::shared_ptr<symbol_table> scope() | ||||
|         std::shared_ptr<symbol_map> scope() | ||||
|         { | ||||
|             return this->outer_scope; | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     using symbol_table = symbol_map<std::shared_ptr<info>, std::nullptr_t, nullptr>; | ||||
| } | ||||
| } | ||||
|   | ||||
| @@ -40,7 +40,7 @@ namespace gcc | ||||
|         std::shared_ptr<symbol_table> symbol_map; | ||||
|  | ||||
|         tree build_label_decl(const char *name, location_t loc); | ||||
|         tree build_procedure_type(boot::procedure_type& type); | ||||
|         tree build_procedure_type(boot::procedure_type_expression& type); | ||||
|  | ||||
|         void enter_scope(); | ||||
|         tree leave_scope(); | ||||
| @@ -89,12 +89,12 @@ namespace gcc | ||||
|         void visit(boot::assign_statement *statement) override; | ||||
|         void visit(boot::if_statement *statement) override; | ||||
|         void visit(boot::while_statement *statement) override; | ||||
|         void visit(boot::basic_type *type) override; | ||||
|         void visit(boot::array_type *type) override; | ||||
|         void visit(boot::pointer_type *type) override; | ||||
|         void visit(boot::record_type *type) override; | ||||
|         void visit(boot::union_type *type) override; | ||||
|         void visit(boot::procedure_type *type) override; | ||||
|         void visit(boot::primitive_type_expression *type) override; | ||||
|         void visit(boot::array_type_expression *type) override; | ||||
|         void visit(boot::pointer_type_expression *type) override; | ||||
|         void visit(boot::record_type_expression *type) override; | ||||
|         void visit(boot::union_type_expression *type) override; | ||||
|         void visit(boot::procedure_type_expression *type) override; | ||||
|         void visit(boot::return_statement *statement) override; | ||||
|         void visit(boot::defer_statement *statement) override; | ||||
|     }; | ||||
|   | ||||
| @@ -33,7 +33,7 @@ namespace elna | ||||
| { | ||||
| namespace gcc | ||||
| { | ||||
|     using symbol_table = boot::symbol_table<tree, NULL_TREE>; | ||||
|     using symbol_table = boot::symbol_map<tree, tree, NULL_TREE>; | ||||
|  | ||||
|     bool is_pointer_type(tree type); | ||||
|     bool is_integral_type(tree type); | ||||
|   | ||||
							
								
								
									
										15
									
								
								source.elna
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								source.elna
									
									
									
									
									
								
							| @@ -72,13 +72,13 @@ type | ||||
|     first: Position | ||||
| 	last: Position | ||||
|   end | ||||
|   FILE* = record end | ||||
|   SourceFile* = record | ||||
| 	buffer: [1024]Char | ||||
| 	handle: ^FILE | ||||
| 	size: Word | ||||
| 	index: Word | ||||
|   end | ||||
|   FILE* = record end | ||||
|   StringBuffer* = record | ||||
|     data: ^Byte | ||||
|     size: Word | ||||
| @@ -92,15 +92,14 @@ type | ||||
| 	advance: proc(data: ^Byte) | ||||
| 	head: proc(data: ^Byte) -> Char | ||||
|   end | ||||
|   TokenValue* = union | ||||
|     int_value: Int | ||||
|     string: String | ||||
| 	boolean_value: Bool | ||||
| 	char_value: Char | ||||
|   end | ||||
|   Token* = record | ||||
|     kind: Int | ||||
|     value: TokenValue | ||||
|     value: union | ||||
|       int_value: Int | ||||
|       string: String | ||||
| 	  boolean_value: Bool | ||||
| 	  char_value: Char | ||||
|     end | ||||
| 	location: Location | ||||
|   end | ||||
|   CommandLine* = record | ||||
|   | ||||
		Reference in New Issue
	
	Block a user