diff --git a/boot/ast.cc b/boot/ast.cc index 89a1ad0..89ee549 100644 --- a/boot/ast.cc +++ b/boot/ast.cc @@ -33,14 +33,6 @@ namespace elna::boot return this->source_position; } - statement::statement() - { - } - - statement::~statement() - { - } - assign_statement *statement::is_assign() { return nullptr; @@ -71,14 +63,6 @@ namespace elna::boot return nullptr; } - expression::expression() - { - } - - expression::~expression() - { - } - cast_expression *expression::is_cast() { return nullptr; @@ -114,39 +98,6 @@ namespace elna::boot return nullptr; } - void expression::accept(parser_visitor *visitor) - { - if (cast_expression *node = is_cast()) - { - return node->accept(visitor); - } - else if (traits_expression *node = is_traits()) - { - return node->accept(visitor); - } - else if (binary_expression *node = is_binary()) - { - return node->accept(visitor); - } - else if (unary_expression *node = is_unary()) - { - return node->accept(visitor); - } - else if (designator_expression *node = is_designator()) - { - return node->accept(visitor); - } - else if (procedure_call *node = is_call_expression()) - { - return node->accept(visitor); - } - else if (literal_expression *node = is_literal()) - { - return node->accept(visitor); - } - __builtin_unreachable(); - } - type_expression::type_expression(const struct position position) : node(position) { @@ -182,35 +133,6 @@ namespace elna::boot return nullptr; } - void type_expression::accept(parser_visitor *visitor) - { - if (std::shared_ptr node = is_primitive()) - { - return node->accept(visitor); - } - else if (std::shared_ptr node = is_array()) - { - return node->accept(visitor); - } - else if (std::shared_ptr node = is_pointer()) - { - return node->accept(visitor); - } - else if (std::shared_ptr node = is_record()) - { - return node->accept(visitor); - } - else if (std::shared_ptr node = is_union()) - { - return node->accept(visitor); - } - else if (std::shared_ptr node = is_procedure()) - { - return node->accept(visitor); - } - __builtin_unreachable(); - } - primitive_type_expression::primitive_type_expression(const struct position position, const std::string& name) : type_expression(position), name(name) { @@ -301,8 +223,8 @@ namespace elna::boot } variable_declaration::variable_declaration(const struct position position, const std::string& identifier, - std::shared_ptr type, const bool exported) - : definition(position, identifier, exported), m_type(type) + std::shared_ptr variable_type, const bool exported) + : definition(position, identifier, exported), m_variable_type(variable_type) { } @@ -313,7 +235,7 @@ namespace elna::boot type_expression& variable_declaration::variable_type() { - return *m_type; + return *m_variable_type; } definition::definition(const struct position position, const std::string& identifier, const bool exported) @@ -462,47 +384,16 @@ namespace elna::boot return this; } - void literal_expression::accept(parser_visitor *visitor) - { - if (literal *node = is_int()) - { - return node->accept(visitor); - } - else if (literal *node = is_word()) - { - return node->accept(visitor); - } - else if (literal *node = is_float()) - { - return node->accept(visitor); - } - else if (literal *node = is_bool()) - { - return node->accept(visitor); - } - else if (literal *node = is_char()) - { - return node->accept(visitor); - } - else if (literal *node = is_nil()) - { - return node->accept(visitor); - } - else if (literal *node = is_string()) - { - return node->accept(visitor); - } - else - { - __builtin_unreachable(); - } - } - defer_statement::defer_statement(const struct position position) : node(position) { } + void defer_statement::accept(parser_visitor *visitor) + { + visitor->visit(this); + } + defer_statement *defer_statement::is_defer() { return this; @@ -529,11 +420,37 @@ namespace elna::boot return this; } + void designator_expression::accept(parser_visitor *visitor) + { + if (variable_expression *node = is_variable()) + { + return visitor->visit(node); + } + else if (array_access_expression *node = is_array_access()) + { + return visitor->visit(node); + } + else if (field_access_expression *node = is_field_access()) + { + return visitor->visit(node); + } + else if (dereference_expression *node = is_dereference()) + { + return visitor->visit(node); + } + __builtin_unreachable(); + } + variable_expression::variable_expression(const struct position position, const std::string& name) : node(position), name(name) { } + void variable_expression::accept(parser_visitor *visitor) + { + visitor->visit(this); + } + variable_expression *variable_expression::is_variable() { return this; @@ -545,6 +462,11 @@ namespace elna::boot { } + void array_access_expression::accept(parser_visitor *visitor) + { + visitor->visit(this); + } + expression& array_access_expression::index() { return *m_index; @@ -572,6 +494,11 @@ namespace elna::boot { } + void field_access_expression::accept(parser_visitor *visitor) + { + visitor->visit(this); + } + expression& field_access_expression::base() { return *m_base; @@ -598,6 +525,11 @@ namespace elna::boot { } + void dereference_expression::accept(parser_visitor *visitor) + { + visitor->visit(this); + } + expression& dereference_expression::base() { return *m_base; @@ -686,6 +618,11 @@ namespace elna::boot { } + void procedure_call::accept(parser_visitor *visitor) + { + visitor->visit(this); + } + procedure_call *procedure_call::is_call_statement() { return this; @@ -780,6 +717,11 @@ namespace elna::boot { } + void return_statement::accept(parser_visitor *visitor) + { + visitor->visit(this); + } + return_statement *return_statement::is_return() { return this; @@ -801,6 +743,11 @@ namespace elna::boot { } + void assign_statement::accept(parser_visitor *visitor) + { + visitor->visit(this); + } + assign_statement *assign_statement::is_assign() { return this; @@ -847,6 +794,11 @@ namespace elna::boot { } + void if_statement::accept(parser_visitor *visitor) + { + visitor->visit(this); + } + if_statement *if_statement::is_if() { return this; @@ -877,6 +829,11 @@ namespace elna::boot { } + void while_statement::accept(parser_visitor *visitor) + { + visitor->visit(this); + } + while_statement *while_statement::is_while() { return this; diff --git a/boot/parser.yy b/boot/parser.yy index e0dbfaf..bdd629e 100644 --- a/boot/parser.yy +++ b/boot/parser.yy @@ -286,10 +286,15 @@ if_statement: $$ = new boot::if_statement(boot::make_position(@1), then, _else); std::swap($5, $$->branches); } -return_statement: "return" expression +return_statement: + "return" expression { $$ = new boot::return_statement(boot::make_position(@1), $2); } + | "return" + { + $$ = new boot::return_statement(boot::make_position(@1)); + } defer_statement: DEFER statements "end" { $$ = new boot::defer_statement(boot::make_position(@1)); diff --git a/boot/semantic.cc b/boot/semantic.cc index 7211103..9670449 100644 --- a/boot/semantic.cc +++ b/boot/semantic.cc @@ -65,6 +65,18 @@ namespace elna::boot auto info = std::make_shared(type_info(type(unresolved.second))); this->symbols->enter(std::move(unresolved.first), info); } + for (variable_declaration *const variable : program->variables) + { + variable->accept(this); + } + for (procedure_definition *const procedure : program->procedures) + { + procedure->accept(this); + } + for (statement *const statement : program->body) + { + statement->accept(this); + } } void declaration_visitor::visit(type_definition *definition) @@ -120,128 +132,191 @@ namespace elna::boot { } - void declaration_visitor::visit(variable_declaration *) + void declaration_visitor::visit(variable_declaration *declaration) { - __builtin_unreachable(); + declaration->variable_type().accept(this); } void declaration_visitor::visit(constant_definition *) { - __builtin_unreachable(); } - void declaration_visitor::visit(procedure_definition *) + void declaration_visitor::visit(procedure_definition *definition) { - __builtin_unreachable(); + for (auto heading_parameter : definition->heading().parameters) + { + heading_parameter->accept(this); + } + if (definition->heading().return_type.type != nullptr) + { + definition->heading().return_type.type->accept(this); + } + if (definition->body != nullptr) + { + definition->body->accept(this); + } } - void declaration_visitor::visit(assign_statement *) + void declaration_visitor::visit(assign_statement *statement) { - __builtin_unreachable(); + statement->lvalue().accept(this); + statement->rvalue().accept(this); } - void declaration_visitor::visit(if_statement *) + void declaration_visitor::visit(if_statement *statement) { - __builtin_unreachable(); + statement->body().prerequisite().accept(this); + for (struct statement *const statement : statement->body().statements) + { + statement->accept(this); + } + for (const auto branch : statement->branches) + { + branch->prerequisite().accept(this); + + for (struct statement *const statement : branch->statements) + { + statement->accept(this); + } + } + if (statement->alternative() != nullptr) + { + for (struct statement *const statement : *statement->alternative()) + { + statement->accept(this); + } + } } - void declaration_visitor::visit(while_statement *) + void declaration_visitor::visit(while_statement *statement) { - __builtin_unreachable(); + statement->body().prerequisite().accept(this); + for (struct statement *const statement : statement->body().statements) + { + statement->accept(this); + } + for (const auto branch : statement->branches) + { + branch->prerequisite().accept(this); + + for (struct statement *const statement : branch->statements) + { + statement->accept(this); + } + } } - void declaration_visitor::visit(return_statement *) + void declaration_visitor::visit(return_statement *statement) { - __builtin_unreachable(); + if (statement->return_expression() != nullptr) + { + statement->return_expression()->accept(this); + } } - void declaration_visitor::visit(defer_statement *) + void declaration_visitor::visit(defer_statement *statement) { - __builtin_unreachable(); + for (struct statement *const statement : statement->statements) + { + statement->accept(this); + } } - void declaration_visitor::visit(procedure_call *) + void declaration_visitor::visit(procedure_call *call) { - __builtin_unreachable(); + call->callable().accept(this); + for (expression *const argument: call->arguments) + { + argument->accept(this); + } } - void declaration_visitor::visit(block *) + void declaration_visitor::visit(block *block) { - __builtin_unreachable(); + for (constant_definition *const constant : block->constants) + { + constant->accept(this); + } + for (variable_declaration *const variable : block->variables) + { + variable->accept(this); + } + for (statement *const statement : block->body) + { + statement->accept(this); + } } - void declaration_visitor::visit(traits_expression *) + void declaration_visitor::visit(traits_expression *trait) { - __builtin_unreachable(); + if (!trait->parameters.empty()) + { + trait->parameters.front()->accept(this); + } } - void declaration_visitor::visit(cast_expression *) + void declaration_visitor::visit(cast_expression *expression) { - __builtin_unreachable(); + expression->value().accept(this); + expression->target().accept(this); } - void declaration_visitor::visit(binary_expression *) + void declaration_visitor::visit(binary_expression *expression) { - __builtin_unreachable(); + expression->lhs().accept(this); + expression->rhs().accept(this); } - void declaration_visitor::visit(unary_expression *) + void declaration_visitor::visit(unary_expression *expression) { - __builtin_unreachable(); + expression->operand().accept(this); } void declaration_visitor::visit(variable_expression *) { - __builtin_unreachable(); } - void declaration_visitor::visit(array_access_expression *) + void declaration_visitor::visit(array_access_expression *expression) { - __builtin_unreachable(); + expression->base().accept(this); + expression->index().accept(this); } - void declaration_visitor::visit(field_access_expression *) + void declaration_visitor::visit(field_access_expression *expression) { - __builtin_unreachable(); + expression->base().accept(this); } - void declaration_visitor::visit(dereference_expression *) + void declaration_visitor::visit(dereference_expression *expression) { - __builtin_unreachable(); + expression->base().accept(this); } void declaration_visitor::visit(literal *) { - __builtin_unreachable(); } void declaration_visitor::visit(literal *) { - __builtin_unreachable(); } void declaration_visitor::visit(literal *) { - __builtin_unreachable(); } void declaration_visitor::visit(literal *) { - __builtin_unreachable(); } void declaration_visitor::visit(literal *) { - __builtin_unreachable(); } void declaration_visitor::visit(literal *) { - __builtin_unreachable(); } void declaration_visitor::visit(literal *) { - __builtin_unreachable(); } } diff --git a/gcc/elna-builtins.cc b/gcc/elna-builtins.cc index 576b61b..60b929c 100644 --- a/gcc/elna-builtins.cc +++ b/gcc/elna-builtins.cc @@ -49,17 +49,29 @@ namespace elna::gcc layout_type(elna_string_type_node); } + static + void declare_builtin_type(std::shared_ptr symbol_table, const char *name, tree type) + { + tree identifier = get_identifier(name); + tree type_declaration = build_decl(UNKNOWN_LOCATION, TYPE_DECL, identifier, type); + + TREE_PUBLIC(type_declaration) = 1; + TYPE_NAME(type_declaration) = identifier; + + symbol_table->enter(name, type_declaration); + } + std::shared_ptr builtin_symbol_table() { std::shared_ptr symbol_table = std::make_shared(); - 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); + declare_builtin_type(symbol_table, "Int", elna_int_type_node); + declare_builtin_type(symbol_table, "Word", elna_word_type_node); + declare_builtin_type(symbol_table, "Char", elna_char_type_node); + declare_builtin_type(symbol_table, "Bool", elna_bool_type_node); + declare_builtin_type(symbol_table, "Byte", elna_byte_type_node); + declare_builtin_type(symbol_table, "Float", elna_float_type_node); + declare_builtin_type(symbol_table, "String", elna_string_type_node); return symbol_table; } diff --git a/gcc/elna-generic.cc b/gcc/elna-generic.cc index 284ac5d..a9401b3 100644 --- a/gcc/elna-generic.cc +++ b/gcc/elna-generic.cc @@ -36,11 +36,20 @@ along with GCC; see the file COPYING3. If not see namespace elna::gcc { - tree get_inner_alias(const boot::type& type, std::shared_ptr symbols) + tree get_inner_alias(const boot::type& type, std::shared_ptr symbols, + std::unordered_map& unresolved) { if (auto reference = type.get()) { - return symbols->lookup(reference->identifier); + auto looked_up = unresolved.find(reference->identifier); + if (looked_up == unresolved.cend()) + { + return symbols->lookup(reference->identifier); + } + else + { + return looked_up->second; + } } else if (auto reference = type.get()) { @@ -52,7 +61,7 @@ namespace elna::gcc } else if (auto reference = type.get()) { - return build_pointer_type_for_mode(get_inner_alias(reference->base, symbols), VOIDmode, true); + return build_pointer_type_for_mode(get_inner_alias(reference->base, symbols, unresolved), VOIDmode, true); } else if (auto reference = type.get()) { @@ -60,30 +69,31 @@ namespace elna::gcc tree upper_bound = build_int_cst_type(integer_type_node, reference->size); tree range_type = build_range_type(integer_type_node, lower_bound, upper_bound); - return build_array_type(get_inner_alias(reference->base, symbols), range_type); + return build_array_type(get_inner_alias(reference->base, symbols, unresolved), range_type); } else if (auto reference = type.get()) { - return handle_symbol(reference->name, reference->reference, symbols); + return handle_symbol(reference->name, reference->reference, symbols, unresolved); } return error_mark_node; } - tree handle_symbol(const std::string& symbol_name, const boot::type& type, std::shared_ptr symbols) + tree handle_symbol(const std::string& symbol_name, const boot::type& type, + std::shared_ptr symbols, std::unordered_map& unresolved) { auto looked_up = symbols->lookup(symbol_name); if (looked_up == NULL_TREE) { - looked_up = get_inner_alias(type, symbols); - symbols->enter(symbol_name, looked_up); + looked_up = get_inner_alias(type, symbols, unresolved); + unresolved.insert({ symbol_name, looked_up }); } return looked_up; } std::deque> do_semantic_analysis(const char *path, std::unique_ptr& ast, std::shared_ptr info_table, - std::shared_ptr symbols) + std::shared_ptr symbols, std::unordered_map& unresolved) { boot::declaration_visitor declaration_visitor(path, info_table); @@ -93,15 +103,16 @@ namespace elna::gcc { for (auto& [symbol_name, symbol_info] : declaration_visitor.unresolved) { - handle_symbol(symbol_name, boot::type(symbol_info), symbols); + handle_symbol(symbol_name, boot::type(symbol_info), symbols, unresolved); } } return std::move(declaration_visitor.errors()); } - generic_visitor::generic_visitor(std::shared_ptr symbol_table) + generic_visitor::generic_visitor(std::shared_ptr symbol_table, + std::unordered_map&& unresolved) + : symbols(symbol_table), unresolved(std::move(unresolved)) { - this->symbols = symbol_table; } void generic_visitor::build_procedure_call(location_t call_location, @@ -201,9 +212,9 @@ namespace elna::gcc ? this->current_expression : TREE_TYPE(this->current_expression); - if (TYPE_P(this->current_expression) && TREE_CODE(expression_type) == RECORD_TYPE) + if (TREE_CODE(expression_type) == RECORD_TYPE) { - build_record_call(call_location, this->current_expression, call->arguments); + build_record_call(call_location, expression_type, call->arguments); } else if (TREE_CODE(expression_type) == FUNCTION_TYPE) { @@ -763,8 +774,7 @@ namespace elna::gcc } else { - error_at(definition_location, - "variable '%s' already declared in this scope", + error_at(definition_location, "Variable '%s' already declared in this scope", definition->identifier.c_str()); } this->current_expression = NULL_TREE; @@ -773,15 +783,18 @@ namespace elna::gcc void generic_visitor::visit(boot::type_definition *definition) { location_t definition_location = get_location(&definition->position()); - this->current_expression = this->symbols->lookup(definition->identifier); + this->current_expression = this->unresolved.at(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->symbols->enter(definition->identifier, this->current_expression); TREE_PUBLIC(definition_tree) = definition->exported; TYPE_NAME(this->current_expression) = get_identifier(definition->identifier.c_str()); + + auto result = this->symbols->enter(definition->identifier, definition_tree); + gcc_assert(result); + this->current_expression = NULL_TREE; } @@ -878,8 +891,7 @@ namespace elna::gcc if (symbol == NULL_TREE) { - error_at(get_location(&expression->position()), - "symbol '%s' not declared in the current scope", + error_at(get_location(&expression->position()), "Symbol '%s' not declared in the current scope", expression->name.c_str()); this->current_expression = error_mark_node; } @@ -1225,29 +1237,65 @@ namespace elna::gcc void generic_visitor::visit(boot::return_statement *statement) { boot::expression *return_expression = statement->return_expression(); + location_t statement_position = get_location(&statement->position()); + tree set_result{ NULL_TREE }; + tree return_type = TREE_TYPE(TREE_TYPE(current_function_decl)); - if (return_expression == nullptr) + if (TREE_THIS_VOLATILE(current_function_decl) == 1) { + error_at(statement_position, "This procedure is not allowed to return"); return; } - return_expression->accept(this); - - tree set_result = build2(INIT_EXPR, void_type_node, DECL_RESULT(current_function_decl), - this->current_expression); - tree return_stmt = build1(RETURN_EXPR, void_type_node, set_result); - append_statement(return_stmt); + if (return_expression != nullptr) + { + return_expression->accept(this); + set_result = build2(INIT_EXPR, void_type_node, DECL_RESULT(current_function_decl), + this->current_expression); + } + if (return_type == void_type_node && set_result != NULL_TREE) + { + error_at(statement_position, "Proper procedure is not allowed to return a value"); + } + else if (return_type != void_type_node && set_result == NULL_TREE) + { + error_at(statement_position, "Procedure is expected to return a value of type '%s'", + print_type(return_type).c_str()); + } + else if (return_type != void_type_node && !is_assignable_from(return_type, this->current_expression)) + { + error_at(statement_position, "Cannot return '%s' from a procedure returning '%s'", + print_type(return_type).c_str(), + print_type(TREE_TYPE(this->current_expression)).c_str()); + } + else + { + tree return_stmt = build1_loc(statement_position, RETURN_EXPR, void_type_node, set_result); + append_statement(return_stmt); + } this->current_expression = NULL_TREE; } void generic_visitor::visit(boot::primitive_type_expression *type) { - tree symbol = this->symbols->lookup(type->name); + auto looked_up = this->unresolved.find(type->name); + tree symbol; + if (looked_up == this->unresolved.cend()) + { + symbol = this->symbols->lookup(type->name); + if (symbol != NULL_TREE) + { + symbol = TREE_TYPE(symbol); + } + } + else + { + symbol = looked_up->second; + } if (symbol == NULL_TREE || !TYPE_P(symbol)) { - error_at(get_location(&type->position()), - "type '%s' not declared", type->name.c_str()); + error_at(get_location(&type->position()), "Type '%s' not declared", type->name.c_str()); this->current_expression = error_mark_node; } diff --git a/gcc/elna1.cc b/gcc/elna1.cc index 1d45781..8ea613a 100644 --- a/gcc/elna1.cc +++ b/gcc/elna1.cc @@ -85,12 +85,14 @@ static void elna_parse_file(const char *filename) { std::shared_ptr info_table = elna::boot::builtin_symbol_table(); std::shared_ptr symbol_table = elna::gcc::builtin_symbol_table(); + std::unordered_map unresolved; - auto semantic_errors = elna::gcc::do_semantic_analysis(filename, driver.tree, info_table, symbol_table); + auto semantic_errors = elna::gcc::do_semantic_analysis(filename, driver.tree, + info_table, symbol_table, unresolved); if (semantic_errors.empty()) { - elna::gcc::generic_visitor generic_visitor{ symbol_table }; + elna::gcc::generic_visitor generic_visitor{ symbol_table, std::move(unresolved) }; generic_visitor.visit(driver.tree.get()); } else diff --git a/include/elna/boot/ast.h b/include/elna/boot/ast.h index 59de3fc..a3ef2ca 100644 --- a/include/elna/boot/ast.h +++ b/include/elna/boot/ast.h @@ -138,6 +138,7 @@ namespace elna::boot explicit node(const position position); public: + virtual void accept(parser_visitor *visitor) = 0; virtual ~node() = 0; /** @@ -155,41 +156,6 @@ namespace elna::boot virtual return_statement *is_return(); virtual defer_statement *is_defer(); virtual procedure_call *is_call_statement(); - - template - void accept(V *visitor) - { - if (assign_statement *node = is_assign()) - { - return visitor->visit(node); - } - else if (if_statement *node = is_if()) - { - return visitor->visit(node); - } - else if (while_statement *node = is_while()) - { - return visitor->visit(node); - } - else if (return_statement *node = is_return()) - { - return visitor->visit(node); - } - else if (defer_statement *node = is_defer()) - { - return visitor->visit(node); - } - else if (procedure_call *node = is_call_statement()) - { - return visitor->visit(node); - } - __builtin_unreachable(); - } - - ~statement() = 0; - - protected: - statement(); }; class expression : public virtual node @@ -202,12 +168,6 @@ namespace elna::boot virtual designator_expression *is_designator(); virtual procedure_call *is_call_expression(); virtual literal_expression *is_literal(); - - void accept(parser_visitor *visitor); - ~expression() = 0; - - protected: - expression(); }; /** @@ -236,8 +196,6 @@ namespace elna::boot virtual std::shared_ptr is_union(); virtual std::shared_ptr is_procedure(); - void accept(parser_visitor *visitor); - protected: type_expression(const struct position position); }; @@ -251,7 +209,7 @@ namespace elna::boot const std::string name; primitive_type_expression(const struct position position, const std::string& name); - void accept(parser_visitor *visitor); + void accept(parser_visitor *visitor) override; std::shared_ptr is_primitive() override; }; @@ -264,7 +222,7 @@ namespace elna::boot array_type_expression(const struct position position, std::shared_ptr base, const std::uint32_t size); - void accept(parser_visitor *visitor); + void accept(parser_visitor *visitor) override; std::shared_ptr is_array() override; type_expression& base(); @@ -276,7 +234,7 @@ namespace elna::boot public: pointer_type_expression(const struct position position, std::shared_ptr base); - void accept(parser_visitor *visitor); + void accept(parser_visitor *visitor) override; std::shared_ptr is_pointer() override; type_expression& base(); @@ -291,7 +249,7 @@ namespace elna::boot record_type_expression(const struct position position, std::vector&& fields); - void accept(parser_visitor *visitor); + void accept(parser_visitor *visitor) override; std::shared_ptr is_record() override; }; @@ -302,7 +260,7 @@ namespace elna::boot union_type_expression(const struct position position, std::vector&& fields); - void accept(parser_visitor *visitor); + void accept(parser_visitor *visitor) override; std::shared_ptr is_union() override; }; @@ -311,12 +269,12 @@ namespace elna::boot */ class variable_declaration : public definition { - std::shared_ptr m_type; + std::shared_ptr m_variable_type; public: variable_declaration(const struct position position, const std::string& identifier, - std::shared_ptr type, const bool exported = false); - void accept(parser_visitor *visitor); + std::shared_ptr variable_type, const bool exported = false); + void accept(parser_visitor *visitor) override; type_expression& variable_type(); }; @@ -336,7 +294,6 @@ namespace elna::boot virtual literal *is_string() = 0; literal_expression *is_literal() override; - void accept(parser_visitor *visitor); protected: literal_expression(); @@ -350,14 +307,9 @@ namespace elna::boot literal_expression *m_body; public: - /** - * \param position Source code position. - * \param identifier Constant name. - * \param body Constant value. - */ constant_definition(const struct position position, const std::string& identifier, const bool exported, literal_expression *body); - void accept(parser_visitor *visitor); + void accept(parser_visitor *visitor) override; literal_expression& body(); @@ -389,7 +341,7 @@ namespace elna::boot procedure_type_expression(const struct position position, return_declaration return_type = return_declaration()); - void accept(parser_visitor *visitor); + void accept(parser_visitor *visitor) override; std::shared_ptr is_procedure() override; }; @@ -406,7 +358,7 @@ namespace elna::boot procedure_definition(const struct position position, const std::string& identifier, const bool exported, std::shared_ptr heading, block *body = nullptr); - void accept(parser_visitor *visitor); + void accept(parser_visitor *visitor) override; procedure_type_expression& heading(); @@ -423,7 +375,7 @@ namespace elna::boot public: type_definition(const struct position position, const std::string& identifier, const bool exported, std::shared_ptr expression); - void accept(parser_visitor *visitor); + void accept(parser_visitor *visitor) override; type_expression& body(); }; @@ -438,7 +390,7 @@ namespace elna::boot public: cast_expression(const struct position position, std::shared_ptr target, expression *value); - void accept(parser_visitor *visitor); + void accept(parser_visitor *visitor) override; cast_expression *is_cast() override; type_expression& target(); @@ -454,7 +406,7 @@ namespace elna::boot const std::string name; traits_expression(const struct position position, const std::string& name); - void accept(parser_visitor *visitor); + void accept(parser_visitor *visitor) override; traits_expression *is_traits() override; }; @@ -480,17 +432,12 @@ namespace elna::boot expression *m_return_expression{ nullptr }; public: - return_statement(const struct position position, expression *return_expression); - - template - void accept(V *visitor) - { - visitor->visit(this); - } + return_statement(const struct position position, expression *return_expression = nullptr); + void accept(parser_visitor *visitor) override; + virtual return_statement *is_return() override; expression *return_expression(); - virtual return_statement *is_return() override; virtual ~return_statement() override; }; @@ -502,29 +449,8 @@ namespace elna::boot virtual field_access_expression *is_field_access(); virtual dereference_expression *is_dereference(); - template - void accept(V *visitor) - { - if (variable_expression *node = is_variable()) - { - return visitor->visit(node); - } - else if (array_access_expression *node = is_array_access()) - { - return visitor->visit(node); - } - else if (field_access_expression *node = is_field_access()) - { - return visitor->visit(node); - } - else if (dereference_expression *node = is_dereference()) - { - return visitor->visit(node); - } - __builtin_unreachable(); - } - designator_expression *is_designator() override; + void accept(parser_visitor *visitor); ~designator_expression() = 0; protected: @@ -537,12 +463,7 @@ namespace elna::boot const std::string name; variable_expression(const struct position position, const std::string& name); - - template - void accept(V *visitor) - { - visitor->visit(this); - } + void accept(parser_visitor *visitor) override; variable_expression *is_variable() override; }; @@ -554,12 +475,7 @@ namespace elna::boot public: array_access_expression(const struct position position, expression *base, expression *index); - - template - void accept(V *visitor) - { - visitor->visit(this); - } + void accept(parser_visitor *visitor) override; expression& base(); expression& index(); @@ -577,12 +493,7 @@ namespace elna::boot public: field_access_expression(const struct position position, expression *base, const std::string& field); - - template - void accept(V *visitor) - { - visitor->visit(this); - } + void accept(parser_visitor *visitor) override; expression& base(); std::string& field(); @@ -598,16 +509,12 @@ namespace elna::boot public: dereference_expression(const struct position position, expression *base); - - template - void accept(parser_visitor *visitor) - { - visitor->visit(this); - } + void accept(parser_visitor *visitor) override; expression& base(); dereference_expression *is_dereference() override; + ~dereference_expression() override; }; @@ -622,17 +529,12 @@ namespace elna::boot std::vector arguments; procedure_call(const struct position position, designator_expression *callable); - - template - void accept(V *visitor) - { - visitor->visit(this); - } + void accept(parser_visitor *visitor) override; + virtual procedure_call *is_call_statement() override; + virtual procedure_call *is_call_expression() override; designator_expression& callable(); - virtual procedure_call *is_call_statement() override; - virtual procedure_call *is_call_expression() override; virtual ~procedure_call() override; }; @@ -649,18 +551,13 @@ namespace elna::boot */ assign_statement(const struct position position, designator_expression *lvalue, expression *rvalue); - - template - void accept(V *visitor) - { - visitor->visit(this); - } + void accept(parser_visitor *visitor) override; designator_expression& lvalue(); expression& rvalue(); - assign_statement *is_assign() override; virtual ~assign_statement() override; + assign_statement *is_assign() override; }; /** @@ -676,17 +573,12 @@ namespace elna::boot if_statement(const struct position position, conditional_statements *body, std::vector *alternative = nullptr); - - template - void accept(V *visitor) - { - visitor->visit(this); - } + void accept(parser_visitor *visitor) override; + virtual if_statement *is_if() override; conditional_statements& body(); std::vector *alternative(); - virtual if_statement *is_if() override; virtual ~if_statement() override; }; @@ -700,16 +592,11 @@ namespace elna::boot public: std::vector branches; while_statement(const struct position position, conditional_statements *body); - - template - void accept(V *visitor) - { - visitor->visit(this); - } + void accept(parser_visitor *visitor) override; + while_statement *is_while() override; conditional_statements& body(); - while_statement *is_while() override; virtual ~while_statement() override; }; @@ -721,7 +608,7 @@ namespace elna::boot std::vector body; block(const struct position position); - void accept(parser_visitor *visitor); + virtual void accept(parser_visitor *visitor) override; virtual ~block() override; }; @@ -733,7 +620,7 @@ namespace elna::boot std::vector procedures; program(const struct position position); - void accept(parser_visitor *visitor); + void accept(parser_visitor *visitor) override; virtual ~program() override; }; @@ -833,8 +720,7 @@ namespace elna::boot } } - template - void accept(V *visitor) + void accept(parser_visitor *visitor) override { visitor->visit(this); } @@ -846,14 +732,9 @@ namespace elna::boot std::vector statements; defer_statement(const struct position position); - - template - void accept(V *visitor) - { - visitor->visit(this); - } - + void accept(parser_visitor *visitor) override; defer_statement *is_defer() override; + virtual ~defer_statement() override; }; @@ -867,7 +748,7 @@ namespace elna::boot binary_expression(const struct position position, expression *lhs, expression *rhs, const binary_operator operation); - void accept(parser_visitor *visitor); + void accept(parser_visitor *visitor) override; binary_expression *is_binary() override; expression& lhs(); @@ -886,7 +767,7 @@ namespace elna::boot unary_expression(const struct position position, expression *operand, const unary_operator operation); - void accept(parser_visitor *visitor); + void accept(parser_visitor *visitor) override; unary_expression *is_unary() override; expression& operand(); diff --git a/include/elna/boot/semantic.h b/include/elna/boot/semantic.h index a682325..5fef097 100644 --- a/include/elna/boot/semantic.h +++ b/include/elna/boot/semantic.h @@ -65,24 +65,24 @@ namespace elna::boot void visit(union_type_expression *) override; void visit(procedure_type_expression *) override; - void visit(variable_declaration *) override; + void visit(variable_declaration *declaration) override; void visit(constant_definition *) override; - void visit(procedure_definition *) override; - void visit(assign_statement *) override; - void visit(if_statement *) override; - void visit(while_statement *) override; - void visit(return_statement *) override; - void visit(defer_statement *) override; - void visit(procedure_call *) override; - void visit(block *) override; - void visit(cast_expression *) override; - void visit(traits_expression *) override; - void visit(binary_expression *) override; - void visit(unary_expression *) override; + void visit(procedure_definition *definition) override; + void visit(assign_statement *statement) override; + void visit(if_statement *statement) override; + void visit(while_statement *statement) override; + void visit(return_statement *statement) override; + void visit(defer_statement *statement) override; + void visit(procedure_call *call) override; + void visit(block *block) override; + void visit(cast_expression *expression) override; + void visit(traits_expression *trait) override; + void visit(binary_expression *expression) override; + void visit(unary_expression *expression) override; void visit(variable_expression *) override; - void visit(array_access_expression *) override; - void visit(field_access_expression *) override; - void visit(dereference_expression *) override; + void visit(array_access_expression *expression) override; + void visit(field_access_expression *expression) override; + void visit(dereference_expression *expression) override; void visit(literal *) override; void visit(literal *) override; void visit(literal *) override; diff --git a/include/elna/gcc/elna-generic.h b/include/elna/gcc/elna-generic.h index 1a85f68..95ee7d7 100644 --- a/include/elna/gcc/elna-generic.h +++ b/include/elna/gcc/elna-generic.h @@ -34,13 +34,15 @@ namespace elna::gcc { std::deque> do_semantic_analysis(const char *path, std::unique_ptr& ast, std::shared_ptr info_table, - std::shared_ptr symbols); - tree handle_symbol(const std::string& symbol_name, const boot::type& type, std::shared_ptr symbols); + std::shared_ptr symbols, std::unordered_map& unresolved); + tree handle_symbol(const std::string& symbol_name, const boot::type& type, + std::shared_ptr symbols, std::unordered_map& unresolved); class generic_visitor final : public boot::parser_visitor { tree current_expression{ NULL_TREE }; std::shared_ptr symbols; + std::unordered_map unresolved; tree build_label_decl(const char *name, location_t loc); tree build_procedure_type(boot::procedure_type_expression& type); @@ -68,7 +70,8 @@ namespace elna::gcc void visit_statements(const std::vector& statements); public: - generic_visitor(std::shared_ptr symbol_table); + generic_visitor(std::shared_ptr symbol_table, + std::unordered_map&& unresolved); void visit(boot::program *program) override; void visit(boot::procedure_definition *definition) override;