diff --git a/boot/ast.cc b/boot/ast.cc index ac0b57e..50253df 100644 --- a/boot/ast.cc +++ b/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(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 *) { + __builtin_unreachable(); } void empty_visitor::visit(number_literal *) { + __builtin_unreachable(); } void empty_visitor::visit(number_literal *) { + __builtin_unreachable(); } void empty_visitor::visit(number_literal *) { + __builtin_unreachable(); } void empty_visitor::visit(number_literal *) { + __builtin_unreachable(); } void empty_visitor::visit(number_literal *) { + __builtin_unreachable(); } void empty_visitor::visit(number_literal *) { + __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 type_expression::is_primitive() + { + return nullptr; + } + + std::shared_ptr type_expression::is_array() + { + return nullptr; + } + + std::shared_ptr type_expression::is_pointer() + { + return nullptr; + } + + std::shared_ptr type_expression::is_record() + { + return nullptr; + } + + std::shared_ptr type_expression::is_union() + { + return nullptr; + } + + std::shared_ptr 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::is_primitive() { - return m_name; + 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) + array_type_expression::array_type_expression(const struct position position, + std::shared_ptr 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::is_array() + { + return std::static_pointer_cast(shared_from_this()); + } + + type_expression& array_type_expression::base() { return *m_base; } - pointer_type::pointer_type(const struct position position, std::shared_ptr base) - : top_type(position), m_base(base) + pointer_type_expression::pointer_type_expression(const struct position position, + std::shared_ptr 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::is_pointer() + { + return std::static_pointer_cast(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::is_record() + { + return std::static_pointer_cast(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::is_union() + { + return std::static_pointer_cast(shared_from_this()); + } + variable_declaration::variable_declaration(const struct position position, const std::string& identifier, - std::shared_ptr type, const bool exported) + std::shared_ptr 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 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 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 heading, block *body) + const bool exported, std::shared_ptr 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::is_procedure() + { + return std::static_pointer_cast(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 body) + const bool exported, std::shared_ptr 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 target, expression *value) + std::shared_ptr 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 type) + const std::string& name, std::shared_ptr 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; } diff --git a/boot/parser.yy b/boot/parser.yy index b740b70..13f9fe7 100644 --- a/boot/parser.yy +++ b/boot/parser.yy @@ -125,7 +125,7 @@ along with GCC; see the file COPYING3. If not see %type > variable_declarations variable_part variable_declaration formal_parameters formal_parameter_list; %type formal_parameter -%type > type_expression; +%type > type_expression; %type traits_expression; %type expression operand; %type unary_expression; @@ -140,13 +140,14 @@ along with GCC; see the file COPYING3. If not see %type statement; %type > statements; %type procedure_definition; -%type > procedure_heading; +%type > procedure_heading; %type > procedure_definitions procedure_part; %type type_definition; %type > type_definitions type_part; %type block; %type field_declaration; -%type >>> optional_fields required_fields; +%type >>> + optional_fields required_fields; %type > elsif_then_statements elsif_do_statements; %type cast_expression; %type defer_statement; @@ -193,17 +194,18 @@ identifier_definitions: procedure_heading: formal_parameter_list { - $$ = std::make_shared(elna::boot::make_position(@1)); + $$ = std::make_shared(elna::boot::make_position(@1)); std::swap($1, $$->parameters); } | formal_parameter_list "->" "!" { - $$ = std::make_shared(elna::boot::make_position(@1), elna::boot::no_return); + $$ = std::make_shared(elna::boot::make_position(@1), + elna::boot::no_return); std::swap($1, $$->parameters); } | formal_parameter_list "->" type_expression { - $$ = std::make_shared(elna::boot::make_position(@1), $3); + $$ = std::make_shared(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::make_position(@1), $4, $2); + $$ = std::make_shared(elna::boot::make_position(@1), $4, $2); } | "^" type_expression { - $$ = std::make_shared(elna::boot::make_position(@1), $2); + $$ = std::make_shared(elna::boot::make_position(@1), $2); } | "record" optional_fields "end" { - $$ = std::make_shared(elna::boot::make_position(@1), std::move($2)); + $$ = std::make_shared(elna::boot::make_position(@1), std::move($2)); } | "union" required_fields "end" { - $$ = std::make_shared(elna::boot::make_position(@1), std::move($2)); + $$ = std::make_shared(elna::boot::make_position(@1), std::move($2)); } | "proc" procedure_heading { @@ -504,7 +506,7 @@ type_expression: } | IDENTIFIER { - $$ = std::make_shared(elna::boot::make_position(@1), $1); + $$ = std::make_shared(elna::boot::make_position(@1), $1); } variable_declaration: identifier_definitions ":" type_expression { diff --git a/boot/semantic.cc b/boot/semantic.cc new file mode 100644 index 0000000..55a06ce --- /dev/null +++ b/boot/semantic.cc @@ -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 +. */ + +#include "elna/boot/semantic.h" + +namespace elna +{ +namespace boot +{ + declaration_visitor::declaration_visitor(std::shared_ptr table) + : table(table) + { + } + + void declaration_visitor::visit(program *program) + { + } +} +} diff --git a/boot/symbol.cc b/boot/symbol.cc new file mode 100644 index 0000000..9c01ba0 --- /dev/null +++ b/boot/symbol.cc @@ -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 +. */ + +#include "elna/boot/symbol.h" + +namespace elna +{ +namespace boot +{ + type::~type() + { + } + + info::~info() + { + } + + type_info::type_info(const std::string& name) + : name(name) + { + } +} +} diff --git a/gcc/Make-lang.in b/gcc/Make-lang.in index 3e7190b..a9fed82 100644 --- a/gcc/Make-lang.in +++ b/gcc/Make-lang.in @@ -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) $< diff --git a/gcc/elna-generic.cc b/gcc/elna-generic.cc index aa32df6..496a74e 100644 --- a/gcc/elna-generic.cc +++ b/gcc/elna-generic.cc @@ -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 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 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 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); diff --git a/gcc/elna1.cc b/gcc/elna1.cc index a6d8331..92203fe 100644 --- a/gcc/elna1.cc +++ b/gcc/elna1.cc @@ -30,6 +30,7 @@ along with GCC; see the file COPYING3. If not see #include #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::gcc::generic_visitor generic_visitor{ std::make_shared() }; + declaration_visitor.visit(driver.tree.get()); generic_visitor.visit(driver.tree.get()); } linemap_add(line_table, LC_LEAVE, 0, NULL, 0); diff --git a/include/elna/boot/ast.h b/include/elna/boot/ast.h index 9bc523f..f3efc82 100644 --- a/include/elna/boot/ast.h +++ b/include/elna/boot/ast.h @@ -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 *) = 0; virtual void visit(number_literal *) = 0; virtual void visit(number_literal *) = 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 *) override; virtual void visit(number_literal *) override; virtual void visit(number_literal *) override; @@ -214,75 +214,83 @@ namespace boot /** * Some type expression. */ - class top_type : public node, public std::enable_shared_from_this + class type_expression : public node, public std::enable_shared_from_this { + public: + virtual std::shared_ptr is_primitive(); + 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); + 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 is_primitive() override; }; - class array_type : public top_type + class array_type_expression : public type_expression { - std::shared_ptr m_base; + std::shared_ptr m_base; public: const std::uint32_t size; - array_type(const struct position position, std::shared_ptr base, const std::uint32_t size); + array_type_expression(const struct position position, + std::shared_ptr base, const std::uint32_t size); virtual void accept(parser_visitor *visitor) override; + std::shared_ptr 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 m_base; + std::shared_ptr m_base; public: - pointer_type(const struct position position, std::shared_ptr base); + pointer_type_expression(const struct position position, std::shared_ptr base); virtual void accept(parser_visitor *visitor) override; + std::shared_ptr is_pointer() override; - top_type& base(); + type_expression& base(); }; - using field_t = std::pair>; + using field_t = std::pair>; using fields_t = std::vector; - 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 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 is_union() override; }; /** @@ -290,14 +298,14 @@ namespace boot */ class variable_declaration : public definition { - std::shared_ptr m_type; + std::shared_ptr m_type; public: variable_declaration(const struct position position, const std::string& identifier, - std::shared_ptr type, const bool exported = false); + std::shared_ptr 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 return_type; + const std::shared_ptr return_type; const bool no_return; std::vector parameters; - procedure_type(const struct position position, std::shared_ptr return_type = nullptr); - procedure_type(const struct position position, no_return_t); + procedure_type_expression(const struct position position, + std::shared_ptr return_type = nullptr); + procedure_type_expression(const struct position position, no_return_t); virtual void accept(parser_visitor *visitor) override; + std::shared_ptr 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 m_heading; + std::shared_ptr m_heading; public: block *const body; procedure_definition(const struct position position, const std::string& identifier, - const bool exported, std::shared_ptr heading, block *body = nullptr); + const bool exported, std::shared_ptr 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 m_body; + std::shared_ptr m_body; public: type_definition(const struct position position, const std::string& identifier, - const bool exported, std::shared_ptr expression); + const bool exported, std::shared_ptr 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 m_target; + std::shared_ptr m_target; expression *m_value; public: - cast_expression(const struct position position, std::shared_ptr target, expression *value); + cast_expression(const struct position position, std::shared_ptr 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 m_type; + std::shared_ptr m_type; public: const std::string name; - traits_expression(const struct position position, const std::string& name, std::shared_ptr type); + traits_expression(const struct position position, const std::string& name, + std::shared_ptr type); virtual void accept(parser_visitor *visitor) override; - top_type& type(); + type_expression& type(); }; /** diff --git a/include/elna/boot/semantic.h b/include/elna/boot/semantic.h new file mode 100644 index 0000000..4401e93 --- /dev/null +++ b/include/elna/boot/semantic.h @@ -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 +. */ + +#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 table; + + public: + declaration_visitor(std::shared_ptr table); + + void visit(program *program) override; + }; +} +} diff --git a/include/elna/boot/symbol.h b/include/elna/boot/symbol.h index 30bac72..9d92f3b 100644 --- a/include/elna/boot/symbol.h +++ b/include/elna/boot/symbol.h @@ -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 - class symbol_table + template + class symbol_map { public: - using symbol_ptr = T; + using symbol_ptr = typename std::enable_if< + std::is_convertible::value || std::is_assignable::value, + T + >::type; using iterator = typename std::unordered_map::iterator; using const_iterator = typename std::unordered_map::const_iterator; private: std::unordered_map entries; - std::shared_ptr outer_scope; + std::shared_ptr outer_scope; public: /** @@ -47,7 +76,7 @@ namespace boot * * \param scope Outer scope. */ - explicit symbol_table(std::shared_ptr scope = nullptr) + explicit symbol_map(std::shared_ptr 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 scope() + std::shared_ptr scope() { return this->outer_scope; } }; + + using symbol_table = symbol_map, std::nullptr_t, nullptr>; } } diff --git a/include/elna/gcc/elna-generic.h b/include/elna/gcc/elna-generic.h index d3ddde9..55ff981 100644 --- a/include/elna/gcc/elna-generic.h +++ b/include/elna/gcc/elna-generic.h @@ -40,7 +40,7 @@ namespace gcc std::shared_ptr 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; }; diff --git a/include/elna/gcc/elna-tree.h b/include/elna/gcc/elna-tree.h index 1f83b05..636a817 100644 --- a/include/elna/gcc/elna-tree.h +++ b/include/elna/gcc/elna-tree.h @@ -33,7 +33,7 @@ namespace elna { namespace gcc { - using symbol_table = boot::symbol_table; + using symbol_table = boot::symbol_map; bool is_pointer_type(tree type); bool is_integral_type(tree type); diff --git a/source.elna b/source.elna index aae4bc6..f04657f 100644 --- a/source.elna +++ b/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