diff --git a/boot/ast.cc b/boot/ast.cc index 71c5b24..14e4230 100644 --- a/boot/ast.cc +++ b/boot/ast.cc @@ -239,36 +239,6 @@ namespace boot { } - std::shared_ptr top_type::is_basic() - { - return nullptr; - } - - std::shared_ptr top_type::is_array() - { - return nullptr; - } - - std::shared_ptr top_type::is_record() - { - return nullptr; - } - - std::shared_ptr top_type::is_union() - { - return nullptr; - } - - std::shared_ptr top_type::is_pointer() - { - return nullptr; - } - - std::shared_ptr top_type::is_procedure() - { - return nullptr; - } - basic_type::basic_type(const struct position position, const std::string& name) : top_type(position), m_name(name) { @@ -284,11 +254,6 @@ namespace boot return m_name; } - std::shared_ptr basic_type::is_basic() - { - return std::static_pointer_cast(shared_from_this()); - } - array_type::array_type(const struct position position, std::shared_ptr base, const std::uint32_t size) : top_type(position), m_base(base), size(size) { @@ -304,11 +269,6 @@ namespace boot return *m_base; } - std::shared_ptr array_type::is_array() - { - return std::static_pointer_cast(shared_from_this()); - } - pointer_type::pointer_type(const struct position position, std::shared_ptr base) : top_type(position), m_base(base) { @@ -324,11 +284,6 @@ namespace boot return *m_base; } - std::shared_ptr pointer_type::is_pointer() - { - return std::static_pointer_cast(shared_from_this()); - } - record_type::record_type(const struct position position, fields_t&& fields) : top_type(position), fields(std::move(fields)) { @@ -339,21 +294,11 @@ namespace boot visitor->visit(this); } - std::shared_ptr record_type::is_record() - { - return std::static_pointer_cast(shared_from_this()); - } - union_type::union_type(const struct position position, fields_t&& fields) : top_type(position), fields(std::move(fields)) { } - std::shared_ptr union_type::is_union() - { - return std::static_pointer_cast(shared_from_this()); - } - void union_type::accept(parser_visitor *visitor) { visitor->visit(this); @@ -416,11 +361,6 @@ namespace boot visitor->visit(this); } - std::shared_ptr procedure_type::is_procedure() - { - return std::static_pointer_cast(shared_from_this()); - } - procedure_type::~procedure_type() { for (auto parameter : this->parameters) diff --git a/gcc/elna-generic.cc b/gcc/elna-generic.cc index 0a110e9..ad2d9d5 100644 --- a/gcc/elna-generic.cc +++ b/gcc/elna-generic.cc @@ -164,8 +164,8 @@ namespace gcc void generic_visitor::visit(boot::cast_expression *expression) { - tree cast_target = build_type(expression->target()); - gcc_assert(cast_target != NULL_TREE); + expression->target().accept(this); + tree cast_target = this->current_expression; expression->value().accept(this); @@ -732,15 +732,16 @@ namespace gcc void generic_visitor::visit(boot::type_definition *definition) { location_t definition_location = get_location(&definition->position()); - tree tree_type = build_type(definition->body()); + definition->body().accept(this); + tree definition_tree = build_decl(definition_location, TYPE_DECL, - get_identifier(definition->identifier.c_str()), tree_type); - auto result = this->symbol_map->enter(definition->identifier, tree_type); + get_identifier(definition->identifier.c_str()), this->current_expression); + auto result = this->symbol_map->enter(definition->identifier, this->current_expression); if (result) { TREE_PUBLIC(definition_tree) = definition->exported; - TYPE_NAME(tree_type) = get_identifier(definition->identifier.c_str()); + TYPE_NAME(this->current_expression) = get_identifier(definition->identifier.c_str()); } else { @@ -748,6 +749,7 @@ namespace gcc "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) @@ -756,130 +758,36 @@ namespace gcc for (std::size_t i = 0; i < type.parameters.size(); ++i) { - parameter_types[i] = build_type(type.parameters.at(i)->variable_type()); + boot::top_type& parameter_type = type.parameters.at(i)->variable_type(); + parameter_type.accept(this); + parameter_types[i] = this->current_expression; } - tree return_type = type.return_type == nullptr - ? void_type_node - : build_type(*type.return_type); + tree return_type = void_type_node; + + if (type.return_type != nullptr) + { + type.return_type->accept(this); + return_type = this->current_expression; + } + this->current_expression = NULL_TREE; return build_function_type_array(return_type, type.parameters.size(), parameter_types.data()); } - tree generic_visitor::build_type(boot::top_type& type) - { - if (std::shared_ptr basic_type = type.is_basic()) - { - tree symbol = this->lookup(basic_type->base_name()); - - if (symbol != NULL_TREE && TYPE_P(symbol)) - { - return symbol; - } - error_at(get_location(&basic_type->position()), - "type '%s' not declared", basic_type->base_name().c_str()); - - return error_mark_node; - } - else if (std::shared_ptr array_type = type.is_array()) - { - tree lower_bound = build_int_cst_type(integer_type_node, 0); - tree upper_bound = build_int_cst_type(integer_type_node, array_type->size); - tree base_type = build_type(array_type->base()); - - if (base_type == NULL_TREE || base_type == error_mark_node) - { - return base_type; - } - tree range_type = build_range_type(integer_type_node, lower_bound, upper_bound); - - return build_array_type(base_type, range_type); - } - else if (std::shared_ptr pointer_type = type.is_pointer()) - { - tree base_type = build_type(pointer_type->base()); - - if (base_type == NULL_TREE || base_type == error_mark_node) - { - return base_type; - } - return build_pointer_type_for_mode(base_type, VOIDmode, true); - } - else if (std::shared_ptr record_type = type.is_record()) - { - std::set field_names; - tree record_type_node = make_node(RECORD_TYPE); - - for (auto& field : record_type->fields) - { - if (field_names.find(field.first) != field_names.cend()) - { - error_at(get_location(&field.second->position()), "repeated field name"); - return error_mark_node; - } - field_names.insert(field.first); - - tree field_type = build_type(*field.second); - if (field_type == NULL_TREE || field_type == error_mark_node) - { - return field_type; - } - tree field_declaration = build_field(get_location(&field.second->position()), - record_type_node, field.first, field_type); - TYPE_FIELDS(record_type_node) = chainon(TYPE_FIELDS(record_type_node), field_declaration); - } - layout_type(record_type_node); - - return record_type_node; - } - else if (std::shared_ptr union_type = type.is_union()) - { - std::set field_names; - tree union_type_node = make_node(UNION_TYPE); - - for (auto& field : union_type->fields) - { - if (field_names.find(field.first) != field_names.cend()) - { - error_at(get_location(&field.second->position()), "repeated field name"); - return error_mark_node; - } - field_names.insert(field.first); - - tree field_type = build_type(*field.second); - if (field_type == NULL_TREE || field_type == error_mark_node) - { - return field_type; - } - tree field_declaration = build_field(get_location(&field.second->position()), - union_type_node, field.first, field_type); - TYPE_FIELDS(union_type_node) = chainon(TYPE_FIELDS(union_type_node), field_declaration); - } - layout_type(union_type_node); - - return union_type_node; - } - else if (std::shared_ptr procedure_type = type.is_procedure()) - { - tree procedure_type_node = build_procedure_type(*procedure_type); - return build_pointer_type_for_mode(procedure_type_node, VOIDmode, true); - } - return NULL_TREE; - } - void generic_visitor::visit(boot::variable_declaration *declaration) { - tree declaration_type = build_type(declaration->variable_type()); - gcc_assert(declaration_type != NULL_TREE); + declaration->variable_type().accept(this); location_t declaration_location = get_location(&declaration->position()); tree declaration_tree = build_decl(declaration_location, VAR_DECL, - get_identifier(declaration->identifier.c_str()), declaration_type); + get_identifier(declaration->identifier.c_str()), this->current_expression); bool result = this->symbol_map->enter(declaration->identifier, declaration_tree); - if (is_pointer_type(declaration_type)) + if (is_pointer_type(this->current_expression)) { DECL_INITIAL(declaration_tree) = elna_pointer_nil_node; } + this->current_expression = NULL_TREE; if (!result) { error_at(declaration_location, "variable '%s' already declared in this scope", @@ -967,28 +875,30 @@ namespace gcc void generic_visitor::visit(boot::traits_expression *trait) { - tree type_expression = build_type(trait->type()); + trait->type().accept(this); if (trait->name == "size") { - this->current_expression = build1(CONVERT_EXPR, elna_word_type_node, size_in_bytes(type_expression)); + this->current_expression = build1(CONVERT_EXPR, elna_word_type_node, + size_in_bytes(this->current_expression)); } else if (trait->name == "alignment") { - this->current_expression = build_int_cstu(elna_word_type_node, TYPE_ALIGN_UNIT(type_expression)); + this->current_expression = build_int_cstu(elna_word_type_node, + TYPE_ALIGN_UNIT(this->current_expression)); } - else if (trait->name == "min" && is_integral_type(type_expression)) + else if (trait->name == "min" && is_integral_type(this->current_expression)) { - this->current_expression = TYPE_MIN_VALUE(type_expression); + this->current_expression = TYPE_MIN_VALUE(this->current_expression); } - else if (trait->name == "max" && is_integral_type(type_expression)) + else if (trait->name == "max" && is_integral_type(this->current_expression)) { - this->current_expression = TYPE_MAX_VALUE(type_expression); + this->current_expression = TYPE_MAX_VALUE(this->current_expression); } else { error_at(get_location(&trait->position()), "type '%s' does not have property '%s'", - print_type(type_expression).c_str(), trait->name.c_str()); + print_type(this->current_expression).c_str(), trait->name.c_str()); this->current_expression = error_mark_node; } } @@ -1190,5 +1100,111 @@ namespace gcc this->current_expression = NULL_TREE; } + + void generic_visitor::visit(boot::basic_type *type) + { + tree symbol = this->lookup(type->base_name()); + + if (symbol == NULL_TREE && TYPE_P(symbol)) + { + error_at(get_location(&type->position()), + "type '%s' not declared", type->base_name().c_str()); + + this->current_expression = error_mark_node; + } + else + { + this->current_expression = symbol; + } + } + + void generic_visitor::visit(boot::array_type *type) + { + tree lower_bound = build_int_cst_type(integer_type_node, 0); + tree upper_bound = build_int_cst_type(integer_type_node, type->size); + type->base().accept(this); + + if (this->current_expression != NULL_TREE && this->current_expression != error_mark_node) + { + tree range_type = build_range_type(integer_type_node, lower_bound, upper_bound); + + this->current_expression = build_array_type(this->current_expression, range_type); + } + } + + void generic_visitor::visit(boot::pointer_type *type) + { + type->base().accept(this); + + if (this->current_expression != NULL_TREE && this->current_expression != error_mark_node) + { + this->current_expression = build_pointer_type_for_mode(this->current_expression, VOIDmode, true); + } + } + + void generic_visitor::visit(boot::record_type *type) + { + std::set field_names; + tree record_type_node = make_node(RECORD_TYPE); + + for (auto& field : type->fields) + { + if (field_names.find(field.first) != field_names.cend()) + { + error_at(get_location(&field.second->position()), "repeated field name"); + this->current_expression = error_mark_node; + return; + } + field_names.insert(field.first); + + field.second->accept(this); + if (this->current_expression == NULL_TREE || this->current_expression == error_mark_node) + { + return; + } + 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); + } + layout_type(record_type_node); + + this->current_expression = record_type_node; + } + + void generic_visitor::visit(boot::union_type *type) + { + std::set field_names; + tree union_type_node = make_node(UNION_TYPE); + + for (auto& field : type->fields) + { + if (field_names.find(field.first) != field_names.cend()) + { + error_at(get_location(&field.second->position()), "repeated field name"); + this->current_expression = error_mark_node; + return; + } + field_names.insert(field.first); + + field.second->accept(this); + if (this->current_expression == NULL_TREE || this->current_expression == error_mark_node) + { + return; + } + 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); + } + layout_type(union_type_node); + + this->current_expression = union_type_node; + } + + void generic_visitor::visit(boot::procedure_type *type) + { + tree procedure_type_node = build_procedure_type(*type); + this->current_expression = build_pointer_type_for_mode(procedure_type_node, VOIDmode, true); + } + } } diff --git a/include/elna/boot/ast.h b/include/elna/boot/ast.h index bc8169e..3002cbe 100644 --- a/include/elna/boot/ast.h +++ b/include/elna/boot/ast.h @@ -210,14 +210,6 @@ namespace boot */ class top_type : public node, public std::enable_shared_from_this { - public: - virtual std::shared_ptr is_basic(); - virtual std::shared_ptr is_array(); - virtual std::shared_ptr is_pointer(); - virtual std::shared_ptr is_record(); - virtual std::shared_ptr is_union(); - virtual std::shared_ptr is_procedure(); - protected: top_type(const struct position position); }; @@ -238,8 +230,6 @@ namespace boot virtual void accept(parser_visitor *visitor) override; const std::string& base_name(); - - std::shared_ptr is_basic() override; }; class array_type : public top_type @@ -253,8 +243,6 @@ namespace boot virtual void accept(parser_visitor *visitor) override; top_type& base(); - - std::shared_ptr is_array() override; }; class pointer_type : public top_type @@ -266,8 +254,6 @@ namespace boot virtual void accept(parser_visitor *visitor) override; top_type& base(); - - std::shared_ptr is_pointer() override; }; using field_t = std::pair>; @@ -281,7 +267,6 @@ namespace boot record_type(const struct position position, fields_t&& fields); virtual void accept(parser_visitor *visitor) override; - std::shared_ptr is_record() override; }; class union_type : public top_type @@ -292,7 +277,6 @@ namespace boot union_type(const struct position position, fields_t&& fields); virtual void accept(parser_visitor *visitor) override; - std::shared_ptr is_union() override; }; /** @@ -363,7 +347,6 @@ namespace boot procedure_type(const struct position position, no_return_t); virtual void accept(parser_visitor *visitor) override; - std::shared_ptr is_procedure() override; virtual ~procedure_type() override; }; diff --git a/include/elna/gcc/elna-generic.h b/include/elna/gcc/elna-generic.h index a4ba4fb..668b759 100644 --- a/include/elna/gcc/elna-generic.h +++ b/include/elna/gcc/elna-generic.h @@ -41,7 +41,6 @@ namespace gcc tree build_label_decl(const char *name, location_t loc); tree build_procedure_type(boot::procedure_type& type); - tree build_type(boot::top_type& type); void enter_scope(); tree leave_scope(); @@ -66,31 +65,37 @@ namespace gcc public: generic_visitor(std::shared_ptr symbol_table); - void visit(boot::program *program) override; - void visit(boot::procedure_definition *definition) override; - void visit(boot::procedure_call *call) override; - void visit(boot::cast_expression *expression) override; - void visit(boot::traits_expression *trait) override; - void visit(boot::number_literal *literal) override; - void visit(boot::number_literal *literal) override; - void visit(boot::number_literal *literal) override; - void visit(boot::number_literal *boolean) override; - void visit(boot::number_literal *character) override; - void visit(boot::number_literal *) override; - void visit(boot::number_literal *string) override; - void visit(boot::binary_expression *expression) override; - void visit(boot::unary_expression *expression) override; - void visit(boot::constant_definition *definition) override; - void visit(boot::type_definition *definition) override; - void visit(boot::variable_declaration *declaration) override; - void visit(boot::variable_expression *expression) override; - void visit(boot::array_access_expression *expression) override; - void visit(boot::field_access_expression *expression) override; - void visit(boot::dereference_expression *expression) override; - void visit(boot::block *block) override; - void visit(boot::assign_statement *statement) override; - void visit(boot::if_statement *statement) override; - void visit(boot::while_statement *statement) override; + virtual void visit(boot::program *program) override; + virtual void visit(boot::procedure_definition *definition) override; + virtual void visit(boot::procedure_call *call) override; + virtual void visit(boot::cast_expression *expression) override; + virtual void visit(boot::traits_expression *trait) override; + virtual void visit(boot::number_literal *literal) override; + virtual void visit(boot::number_literal *literal) override; + virtual void visit(boot::number_literal *literal) override; + virtual void visit(boot::number_literal *boolean) override; + virtual void visit(boot::number_literal *character) override; + virtual void visit(boot::number_literal *) override; + virtual void visit(boot::number_literal *string) override; + virtual void visit(boot::binary_expression *expression) override; + virtual void visit(boot::unary_expression *expression) override; + virtual void visit(boot::constant_definition *definition) override; + virtual void visit(boot::type_definition *definition) override; + virtual void visit(boot::variable_declaration *declaration) override; + virtual void visit(boot::variable_expression *expression) override; + virtual void visit(boot::array_access_expression *expression) override; + virtual void visit(boot::field_access_expression *expression) override; + virtual void visit(boot::dereference_expression *expression) override; + virtual void visit(boot::block *block) override; + virtual void visit(boot::assign_statement *statement) override; + virtual void visit(boot::if_statement *statement) override; + virtual void visit(boot::while_statement *statement) override; + virtual void visit(boot::basic_type *type) override; + virtual void visit(boot::array_type *type) override; + virtual void visit(boot::pointer_type *type) override; + virtual void visit(boot::record_type *type) override; + virtual void visit(boot::union_type *type) override; + virtual void visit(boot::procedure_type *type) override; }; } }