Rename AST types to type expressions

This commit is contained in:
Eugen Wissner 2025-03-02 23:35:07 +01:00
parent 09f204bd16
commit c5930285bf
Signed by: belka
GPG Key ID: A27FDC1E8EE902C0
13 changed files with 462 additions and 280 deletions

View File

@ -23,215 +23,167 @@ namespace boot
{
void empty_visitor::visit(variable_declaration *)
{
__builtin_unreachable();
}
void empty_visitor::visit(constant_definition *definition)
void empty_visitor::visit(constant_definition *)
{
definition->body().accept(this);
__builtin_unreachable();
}
void empty_visitor::visit(procedure_definition *definition)
void empty_visitor::visit(procedure_definition *)
{
definition->heading().accept(this);
if (definition->body != nullptr)
{
definition->body->accept(this);
}
__builtin_unreachable();
}
void empty_visitor::visit(type_definition *definition)
void empty_visitor::visit(type_definition *)
{
definition->body().accept(this);
__builtin_unreachable();
}
void empty_visitor::visit(procedure_call *call)
void empty_visitor::visit(procedure_call *)
{
for (expression *const argument : call->arguments)
{
argument->accept(this);
}
__builtin_unreachable();
}
void empty_visitor::visit(traits_expression *trait)
void empty_visitor::visit(traits_expression *)
{
trait->type().accept(this);
__builtin_unreachable();
}
void empty_visitor::visit(cast_expression *expression)
void empty_visitor::visit(cast_expression *)
{
expression->target().accept(this);
expression->value().accept(this);
__builtin_unreachable();
}
void empty_visitor::visit(assign_statement *statement)
void empty_visitor::visit(assign_statement *)
{
statement->rvalue().accept(this);
__builtin_unreachable();
}
void empty_visitor::visit(if_statement *statement)
void empty_visitor::visit(if_statement *)
{
statement->body().prerequisite().accept(this);
for (const auto body_statement : statement->body().statements)
{
body_statement->accept(this);
}
__builtin_unreachable();
}
void empty_visitor::visit(while_statement *statement)
void empty_visitor::visit(while_statement *)
{
statement->body().prerequisite().accept(this);
for (const auto body_statement : statement->body().statements)
{
body_statement->accept(this);
}
__builtin_unreachable();
}
void empty_visitor::visit(return_statement *statement)
void empty_visitor::visit(return_statement *)
{
expression *return_expression = statement->return_expression();
if (return_expression != nullptr)
{
return_expression->accept(this);
}
__builtin_unreachable();
}
void empty_visitor::visit(defer_statement *defer)
void empty_visitor::visit(defer_statement *)
{
for (statement *const body_statement : defer->statements)
{
body_statement->accept(this);
}
__builtin_unreachable();
}
void empty_visitor::visit(block *block)
void empty_visitor::visit(block *)
{
for (constant_definition *const constant : block->constants)
{
constant->accept(this);
}
for (variable_declaration *const variable : block->variables)
{
variable->accept(this);
}
for (statement *const body_statement : block->body)
{
body_statement->accept(this);
}
__builtin_unreachable();
}
void empty_visitor::visit(program *program)
void empty_visitor::visit(program *)
{
visit(reinterpret_cast<block *>(program));
for (type_definition *const type : program->types)
{
type->accept(this);
}
for (procedure_definition *const procedure : program->procedures)
{
procedure->accept(this);
}
__builtin_unreachable();
}
void empty_visitor::visit(binary_expression *expression)
void empty_visitor::visit(binary_expression *)
{
expression->lhs().accept(this);
expression->rhs().accept(this);
__builtin_unreachable();
}
void empty_visitor::visit(unary_expression *expression)
void empty_visitor::visit(unary_expression *)
{
expression->operand().accept(this);
__builtin_unreachable();
}
void empty_visitor::visit(basic_type *)
void empty_visitor::visit(primitive_type_expression *)
{
__builtin_unreachable();
}
void empty_visitor::visit(array_type *expression)
void empty_visitor::visit(array_type_expression *)
{
expression->base().accept(this);
__builtin_unreachable();
}
void empty_visitor::visit(pointer_type *expression)
void empty_visitor::visit(pointer_type_expression *)
{
expression->base().accept(this);
__builtin_unreachable();
}
void empty_visitor::visit(record_type *expression)
void empty_visitor::visit(record_type_expression *)
{
for (auto& field : expression->fields)
{
field.second->accept(this);
}
__builtin_unreachable();
}
void empty_visitor::visit(union_type *expression)
void empty_visitor::visit(union_type_expression *)
{
for (auto& field : expression->fields)
{
field.second->accept(this);
}
__builtin_unreachable();
}
void empty_visitor::visit(procedure_type *expression)
void empty_visitor::visit(procedure_type_expression *)
{
for (auto parameter : expression->parameters)
{
parameter->accept(this);
}
if (expression->return_type != nullptr)
{
expression->return_type->accept(this);
}
__builtin_unreachable();
}
void empty_visitor::visit(variable_expression *)
{
__builtin_unreachable();
}
void empty_visitor::visit(array_access_expression *expression)
void empty_visitor::visit(array_access_expression *)
{
expression->base().accept(this);
expression->index().accept(this);
__builtin_unreachable();
}
void empty_visitor::visit(field_access_expression *expression)
void empty_visitor::visit(field_access_expression *)
{
expression->base().accept(this);
__builtin_unreachable();
}
void empty_visitor::visit(dereference_expression *expression)
void empty_visitor::visit(dereference_expression *)
{
expression->base().accept(this);
__builtin_unreachable();
}
void empty_visitor::visit(number_literal<std::int32_t> *)
{
__builtin_unreachable();
}
void empty_visitor::visit(number_literal<std::uint32_t> *)
{
__builtin_unreachable();
}
void empty_visitor::visit(number_literal<double> *)
{
__builtin_unreachable();
}
void empty_visitor::visit(number_literal<bool> *)
{
__builtin_unreachable();
}
void empty_visitor::visit(number_literal<unsigned char> *)
{
__builtin_unreachable();
}
void empty_visitor::visit(number_literal<std::nullptr_t> *)
{
__builtin_unreachable();
}
void empty_visitor::visit(number_literal<std::string> *)
{
__builtin_unreachable();
}
node::node(const struct position position)
@ -252,78 +204,130 @@ namespace boot
{
}
top_type::top_type(const struct position position)
type_expression::type_expression(const struct position position)
: node(position)
{
}
basic_type::basic_type(const struct position position, const std::string& name)
: top_type(position), m_name(name)
std::shared_ptr<primitive_type_expression> type_expression::is_primitive()
{
return nullptr;
}
std::shared_ptr<array_type_expression> type_expression::is_array()
{
return nullptr;
}
std::shared_ptr<pointer_type_expression> type_expression::is_pointer()
{
return nullptr;
}
std::shared_ptr<record_type_expression> type_expression::is_record()
{
return nullptr;
}
std::shared_ptr<union_type_expression> type_expression::is_union()
{
return nullptr;
}
std::shared_ptr<procedure_type_expression> type_expression::is_procedure()
{
return nullptr;
}
primitive_type_expression::primitive_type_expression(const struct position position, const std::string& name)
: type_expression(position), name(name)
{
}
void basic_type::accept(parser_visitor *visitor)
void primitive_type_expression::accept(parser_visitor *visitor)
{
visitor->visit(this);
}
const std::string& basic_type::base_name()
std::shared_ptr<primitive_type_expression> primitive_type_expression::is_primitive()
{
return m_name;
return std::static_pointer_cast<primitive_type_expression>(shared_from_this());
}
array_type::array_type(const struct position position, std::shared_ptr<top_type> base, const std::uint32_t size)
: top_type(position), m_base(base), size(size)
array_type_expression::array_type_expression(const struct position position,
std::shared_ptr<type_expression> base, const std::uint32_t size)
: type_expression(position), m_base(base), size(size)
{
}
void array_type::accept(parser_visitor *visitor)
void array_type_expression::accept(parser_visitor *visitor)
{
visitor->visit(this);
}
top_type& array_type::base()
std::shared_ptr<array_type_expression> array_type_expression::is_array()
{
return std::static_pointer_cast<array_type_expression>(shared_from_this());
}
type_expression& array_type_expression::base()
{
return *m_base;
}
pointer_type::pointer_type(const struct position position, std::shared_ptr<top_type> base)
: top_type(position), m_base(base)
pointer_type_expression::pointer_type_expression(const struct position position,
std::shared_ptr<type_expression> base)
: type_expression(position), m_base(base)
{
}
void pointer_type::accept(parser_visitor *visitor)
void pointer_type_expression::accept(parser_visitor *visitor)
{
visitor->visit(this);
}
top_type& pointer_type::base()
std::shared_ptr<pointer_type_expression> pointer_type_expression::is_pointer()
{
return std::static_pointer_cast<pointer_type_expression>(shared_from_this());
}
type_expression& pointer_type_expression::base()
{
return *m_base;
}
record_type::record_type(const struct position position, fields_t&& fields)
: top_type(position), fields(std::move(fields))
record_type_expression::record_type_expression(const struct position position, fields_t&& fields)
: type_expression(position), fields(std::move(fields))
{
}
void record_type::accept(parser_visitor *visitor)
void record_type_expression::accept(parser_visitor *visitor)
{
visitor->visit(this);
}
union_type::union_type(const struct position position, fields_t&& fields)
: top_type(position), fields(std::move(fields))
std::shared_ptr<record_type_expression> record_type_expression::is_record()
{
return std::static_pointer_cast<record_type_expression>(shared_from_this());
}
union_type_expression::union_type_expression(const struct position position, fields_t&& fields)
: type_expression(position), fields(std::move(fields))
{
}
void union_type::accept(parser_visitor *visitor)
void union_type_expression::accept(parser_visitor *visitor)
{
visitor->visit(this);
}
std::shared_ptr<union_type_expression> union_type_expression::is_union()
{
return std::static_pointer_cast<union_type_expression>(shared_from_this());
}
variable_declaration::variable_declaration(const struct position position, const std::string& identifier,
std::shared_ptr<top_type> type, const bool exported)
std::shared_ptr<type_expression> type, const bool exported)
: definition(position, identifier, exported), m_type(type)
{
}
@ -333,7 +337,7 @@ namespace boot
visitor->visit(this);
}
top_type& variable_declaration::variable_type()
type_expression& variable_declaration::variable_type()
{
return *m_type;
}
@ -364,22 +368,23 @@ namespace boot
delete m_body;
}
procedure_type::procedure_type(const struct position position, std::shared_ptr<top_type> return_type)
: top_type(position), return_type(return_type), no_return(false)
procedure_type_expression::procedure_type_expression(const struct position position,
std::shared_ptr<type_expression> return_type)
: type_expression(position), return_type(return_type), no_return(false)
{
}
procedure_type::procedure_type(const struct position position, no_return_t)
: top_type(position), return_type(nullptr), no_return(true)
procedure_type_expression::procedure_type_expression(const struct position position, no_return_t)
: type_expression(position), return_type(nullptr), no_return(true)
{
}
void procedure_type::accept(parser_visitor *visitor)
void procedure_type_expression::accept(parser_visitor *visitor)
{
visitor->visit(this);
}
procedure_type::~procedure_type()
procedure_type_expression::~procedure_type_expression()
{
for (auto parameter : this->parameters)
{
@ -388,7 +393,7 @@ namespace boot
}
procedure_definition::procedure_definition(const struct position position, const std::string& identifier,
const bool exported, std::shared_ptr<procedure_type> heading, block *body)
const bool exported, std::shared_ptr<procedure_type_expression> heading, block *body)
: definition(position, identifier, exported), m_heading(heading), body(body)
{
}
@ -398,7 +403,12 @@ namespace boot
visitor->visit(this);
}
procedure_type& procedure_definition::heading()
std::shared_ptr<procedure_type_expression> procedure_type_expression::is_procedure()
{
return std::static_pointer_cast<procedure_type_expression>(shared_from_this());
}
procedure_type_expression& procedure_definition::heading()
{
return *m_heading;
}
@ -409,7 +419,7 @@ namespace boot
}
type_definition::type_definition(const struct position position, const std::string& identifier,
const bool exported, std::shared_ptr<top_type> body)
const bool exported, std::shared_ptr<type_expression> body)
: definition(position, identifier, exported), m_body(body)
{
}
@ -419,7 +429,7 @@ namespace boot
visitor->visit(this);
}
top_type& type_definition::body()
type_expression& type_definition::body()
{
return *m_body;
}
@ -685,7 +695,7 @@ namespace boot
}
cast_expression::cast_expression(const struct position position,
std::shared_ptr<top_type> target, expression *value)
std::shared_ptr<type_expression> target, expression *value)
: node(position), m_target(target), m_value(value)
{
}
@ -695,7 +705,7 @@ namespace boot
visitor->visit(this);
}
top_type& cast_expression::target()
type_expression& cast_expression::target()
{
return *m_target;
}
@ -711,7 +721,7 @@ namespace boot
}
traits_expression::traits_expression(const struct position position,
const std::string& name, std::shared_ptr<top_type> type)
const std::string& name, std::shared_ptr<type_expression> type)
: node(position), m_type(type), name(name)
{
}
@ -721,7 +731,7 @@ namespace boot
visitor->visit(this);
}
top_type& traits_expression::type()
type_expression& traits_expression::type()
{
return *m_type;
}

View File

@ -125,7 +125,7 @@ along with GCC; see the file COPYING3. If not see
%type <std::vector<elna::boot::variable_declaration *>> variable_declarations variable_part variable_declaration
formal_parameters formal_parameter_list;
%type <elna::boot::variable_declaration *> formal_parameter
%type <std::shared_ptr<elna::boot::top_type>> type_expression;
%type <std::shared_ptr<elna::boot::type_expression>> type_expression;
%type <elna::boot::traits_expression *> traits_expression;
%type <elna::boot::expression *> expression operand;
%type <elna::boot::unary_expression *> unary_expression;
@ -140,13 +140,14 @@ along with GCC; see the file COPYING3. If not see
%type <elna::boot::statement *> statement;
%type <std::vector<elna::boot::statement *>> statements;
%type <elna::boot::procedure_definition *> procedure_definition;
%type <std::shared_ptr<elna::boot::procedure_type>> procedure_heading;
%type <std::shared_ptr<elna::boot::procedure_type_expression>> procedure_heading;
%type <std::vector<elna::boot::procedure_definition *>> procedure_definitions procedure_part;
%type <elna::boot::type_definition *> type_definition;
%type <std::vector<elna::boot::type_definition *>> type_definitions type_part;
%type <elna::boot::block *> block;
%type <elna::boot::field_t> field_declaration;
%type <std::vector<std::pair<std::string, std::shared_ptr<elna::boot::top_type>>>> optional_fields required_fields;
%type <std::vector<std::pair<std::string, std::shared_ptr<elna::boot::type_expression>>>>
optional_fields required_fields;
%type <std::vector<elna::boot::conditional_statements *>> elsif_then_statements elsif_do_statements;
%type <elna::boot::cast_expression *> cast_expression;
%type <elna::boot::defer_statement *> defer_statement;
@ -193,17 +194,18 @@ identifier_definitions:
procedure_heading:
formal_parameter_list
{
$$ = std::make_shared<elna::boot::procedure_type>(elna::boot::make_position(@1));
$$ = std::make_shared<elna::boot::procedure_type_expression>(elna::boot::make_position(@1));
std::swap($1, $$->parameters);
}
| formal_parameter_list "->" "!"
{
$$ = std::make_shared<elna::boot::procedure_type>(elna::boot::make_position(@1), elna::boot::no_return);
$$ = std::make_shared<elna::boot::procedure_type_expression>(elna::boot::make_position(@1),
elna::boot::no_return);
std::swap($1, $$->parameters);
}
| formal_parameter_list "->" type_expression
{
$$ = std::make_shared<elna::boot::procedure_type>(elna::boot::make_position(@1), $3);
$$ = std::make_shared<elna::boot::procedure_type_expression>(elna::boot::make_position(@1), $3);
std::swap($1, $$->parameters);
}
procedure_definition:
@ -484,19 +486,19 @@ optional_fields:
type_expression:
"[" INTEGER "]" type_expression
{
$$ = std::make_shared<elna::boot::array_type>(elna::boot::make_position(@1), $4, $2);
$$ = std::make_shared<elna::boot::array_type_expression>(elna::boot::make_position(@1), $4, $2);
}
| "^" type_expression
{
$$ = std::make_shared<elna::boot::pointer_type>(elna::boot::make_position(@1), $2);
$$ = std::make_shared<elna::boot::pointer_type_expression>(elna::boot::make_position(@1), $2);
}
| "record" optional_fields "end"
{
$$ = std::make_shared<elna::boot::record_type>(elna::boot::make_position(@1), std::move($2));
$$ = std::make_shared<elna::boot::record_type_expression>(elna::boot::make_position(@1), std::move($2));
}
| "union" required_fields "end"
{
$$ = std::make_shared<elna::boot::union_type>(elna::boot::make_position(@1), std::move($2));
$$ = std::make_shared<elna::boot::union_type_expression>(elna::boot::make_position(@1), std::move($2));
}
| "proc" procedure_heading
{
@ -504,7 +506,7 @@ type_expression:
}
| IDENTIFIER
{
$$ = std::make_shared<elna::boot::basic_type>(elna::boot::make_position(@1), $1);
$$ = std::make_shared<elna::boot::primitive_type_expression>(elna::boot::make_position(@1), $1);
}
variable_declaration: identifier_definitions ":" type_expression
{

33
boot/semantic.cc Normal file
View File

@ -0,0 +1,33 @@
/* Semantic analysis visitors.
Copyright (C) 2025 Free Software Foundation, Inc.
GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include "elna/boot/semantic.h"
namespace elna
{
namespace boot
{
declaration_visitor::declaration_visitor(std::shared_ptr<symbol_table> table)
: table(table)
{
}
void declaration_visitor::visit(program *program)
{
}
}
}

37
boot/symbol.cc Normal file
View File

@ -0,0 +1,37 @@
/* Symbol definitions.
Copyright (C) 2025 Free Software Foundation, Inc.
GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include "elna/boot/symbol.h"
namespace elna
{
namespace boot
{
type::~type()
{
}
info::~info()
{
}
type_info::type_info(const std::string& name)
: name(name)
{
}
}
}

View File

@ -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) $<

View File

@ -180,6 +180,23 @@ namespace gcc
constant->accept(this);
}
for (boot::type_definition *const type : program->types)
{
tree type_node = NULL_TREE;
if (type->body().is_record())
{
type_node = make_node(RECORD_TYPE);
}
else if (type->body().is_union())
{
type_node = make_node(UNION_TYPE);
}
if (type_node != NULL_TREE)
{
this->symbol_map->enter(type->identifier, type_node);
}
}
for (boot::type_definition *const type : program->types)
{
type->accept(this);
}
@ -731,33 +748,34 @@ namespace gcc
void generic_visitor::visit(boot::type_definition *definition)
{
location_t definition_location = get_location(&definition->position());
this->current_expression = this->symbol_map->lookup(definition->identifier);
definition->body().accept(this);
tree definition_tree = build_decl(definition_location, TYPE_DECL,
get_identifier(definition->identifier.c_str()), this->current_expression);
auto result = this->symbol_map->enter(definition->identifier, this->current_expression);
if (result)
{
/* if (result)
{ */
TREE_PUBLIC(definition_tree) = definition->exported;
TYPE_NAME(this->current_expression) = get_identifier(definition->identifier.c_str());
}
else
// }
/* else
{
error_at(get_location(&definition->position()),
"type '%s' already declared in this scope",
definition->identifier.c_str());
}
} */
this->current_expression = NULL_TREE;
}
tree generic_visitor::build_procedure_type(boot::procedure_type& type)
tree generic_visitor::build_procedure_type(boot::procedure_type_expression& type)
{
std::vector<tree> parameter_types(type.parameters.size());
for (std::size_t i = 0; i < type.parameters.size(); ++i)
{
boot::top_type& parameter_type = type.parameters.at(i)->variable_type();
boot::type_expression& parameter_type = type.parameters.at(i)->variable_type();
parameter_type.accept(this);
parameter_types[i] = this->current_expression;
}
@ -1102,14 +1120,14 @@ namespace gcc
this->current_expression = NULL_TREE;
}
void generic_visitor::visit(boot::basic_type *type)
void generic_visitor::visit(boot::primitive_type_expression *type)
{
tree symbol = this->lookup(type->base_name());
tree symbol = this->lookup(type->name);
if (symbol == NULL_TREE && TYPE_P(symbol))
{
error_at(get_location(&type->position()),
"type '%s' not declared", type->base_name().c_str());
"type '%s' not declared", type->name.c_str());
this->current_expression = error_mark_node;
}
@ -1119,7 +1137,7 @@ namespace gcc
}
}
void generic_visitor::visit(boot::array_type *type)
void generic_visitor::visit(boot::array_type_expression *type)
{
tree lower_bound = build_int_cst_type(integer_type_node, 0);
tree upper_bound = build_int_cst_type(integer_type_node, type->size);
@ -1133,7 +1151,7 @@ namespace gcc
}
}
void generic_visitor::visit(boot::pointer_type *type)
void generic_visitor::visit(boot::pointer_type_expression *type)
{
type->base().accept(this);
@ -1143,10 +1161,12 @@ namespace gcc
}
}
void generic_visitor::visit(boot::record_type *type)
void generic_visitor::visit(boot::record_type_expression *type)
{
std::set<std::string> field_names;
tree record_type_node = make_node(RECORD_TYPE);
tree record_type_node = this->current_expression == NULL_TREE
? make_node(RECORD_TYPE)
: this->current_expression;
for (auto& field : type->fields)
{
@ -1166,16 +1186,19 @@ namespace gcc
tree field_declaration = build_field(get_location(&field.second->position()),
record_type_node, field.first, this->current_expression);
TYPE_FIELDS(record_type_node) = chainon(TYPE_FIELDS(record_type_node), field_declaration);
this->current_expression = NULL_TREE;
}
layout_type(record_type_node);
this->current_expression = record_type_node;
}
void generic_visitor::visit(boot::union_type *type)
void generic_visitor::visit(boot::union_type_expression *type)
{
std::set<std::string> field_names;
tree union_type_node = make_node(UNION_TYPE);
tree union_type_node = this->current_expression == NULL_TREE
? make_node(UNION_TYPE)
: this->current_expression;
for (auto& field : type->fields)
{
@ -1195,13 +1218,14 @@ namespace gcc
tree field_declaration = build_field(get_location(&field.second->position()),
union_type_node, field.first, this->current_expression);
TYPE_FIELDS(union_type_node) = chainon(TYPE_FIELDS(union_type_node), field_declaration);
this->current_expression = NULL_TREE;
}
layout_type(union_type_node);
this->current_expression = union_type_node;
}
void generic_visitor::visit(boot::procedure_type *type)
void generic_visitor::visit(boot::procedure_type_expression *type)
{
tree procedure_type_node = build_procedure_type(*type);
this->current_expression = build_pointer_type_for_mode(procedure_type_node, VOIDmode, true);

View File

@ -30,6 +30,7 @@ along with GCC; see the file COPYING3. If not see
#include <fstream>
#include "elna/boot/driver.h"
#include "elna/boot/semantic.h"
#include "elna/gcc/elna-tree.h"
#include "elna/gcc/elna-generic.h"
#include "elna/gcc/elna-diagnostic.h"
@ -88,8 +89,10 @@ static void elna_parse_file(const char *filename)
}
else
{
elna::boot::declaration_visitor declaration_visitor{ std::make_shared<elna::boot::symbol_table>() };
elna::gcc::generic_visitor generic_visitor{ std::make_shared<elna::gcc::symbol_table>() };
declaration_visitor.visit(driver.tree.get());
generic_visitor.visit(driver.tree.get());
}
linemap_add(line_table, LC_LEAVE, 0, NULL, 0);

View File

@ -69,12 +69,12 @@ namespace boot
class program;
class binary_expression;
class unary_expression;
class basic_type;
class array_type;
class pointer_type;
class record_type;
class union_type;
class procedure_type;
class primitive_type_expression;
class array_type_expression;
class pointer_type_expression;
class record_type_expression;
class union_type_expression;
class procedure_type_expression;
class variable_expression;
class array_access_expression;
class field_access_expression;
@ -104,16 +104,16 @@ namespace boot
virtual void visit(program *) = 0;
virtual void visit(binary_expression *) = 0;
virtual void visit(unary_expression *) = 0;
virtual void visit(basic_type *) = 0;
virtual void visit(array_type *) = 0;
virtual void visit(pointer_type *) = 0;
virtual void visit(record_type *) = 0;
virtual void visit(union_type *) = 0;
virtual void visit(procedure_type *) = 0;
virtual void visit(primitive_type_expression *) = 0;
virtual void visit(array_type_expression *) = 0;
virtual void visit(pointer_type_expression *) = 0;
virtual void visit(record_type_expression *) = 0;
virtual void visit(union_type_expression *) = 0;
virtual void visit(procedure_type_expression *) = 0;
virtual void visit(variable_expression *) = 0;
virtual void visit(array_access_expression *) = 0;
virtual void visit(field_access_expression *is_field_access) = 0;
virtual void visit(dereference_expression *is_dereference) = 0;
virtual void visit(field_access_expression *) = 0;
virtual void visit(dereference_expression *) = 0;
virtual void visit(number_literal<std::int32_t> *) = 0;
virtual void visit(number_literal<std::uint32_t> *) = 0;
virtual void visit(number_literal<double> *) = 0;
@ -129,31 +129,31 @@ namespace boot
struct empty_visitor : parser_visitor
{
virtual void visit(variable_declaration *) override;
virtual void visit(constant_definition *definition) override;
virtual void visit(procedure_definition *definition) override;
virtual void visit(type_definition *definition) override;
virtual void visit(traits_expression *trait) override;
virtual void visit(procedure_call *call) override;
virtual void visit(cast_expression *expression) override;
virtual void visit(assign_statement *statement) override;
virtual void visit(constant_definition *) override;
virtual void visit(procedure_definition *) override;
virtual void visit(type_definition *) override;
virtual void visit(traits_expression *) override;
virtual void visit(procedure_call *) override;
virtual void visit(cast_expression *) override;
virtual void visit(assign_statement *) override;
virtual void visit(if_statement *) override;
virtual void visit(while_statement *) override;
virtual void visit(return_statement *) override;
virtual void visit(defer_statement *defer) override;
virtual void visit(block *block) override;
virtual void visit(program *program) override;
virtual void visit(binary_expression *expression) override;
virtual void visit(unary_expression *expression) override;
virtual void visit(basic_type *) override;
virtual void visit(array_type *expression) override;
virtual void visit(pointer_type *) override;
virtual void visit(record_type *expression) override;
virtual void visit(union_type *expression) override;
virtual void visit(procedure_type *expression) override;
virtual void visit(defer_statement *) override;
virtual void visit(block *) override;
virtual void visit(program *) override;
virtual void visit(binary_expression *) override;
virtual void visit(unary_expression *) override;
virtual void visit(primitive_type_expression *) override;
virtual void visit(array_type_expression *) override;
virtual void visit(pointer_type_expression *) override;
virtual void visit(record_type_expression *) override;
virtual void visit(union_type_expression *) override;
virtual void visit(procedure_type_expression *) override;
virtual void visit(variable_expression *) override;
virtual void visit(array_access_expression *expression) override;
virtual void visit(field_access_expression *expression) override;
virtual void visit(dereference_expression *expression) override;
virtual void visit(array_access_expression *) override;
virtual void visit(field_access_expression *) override;
virtual void visit(dereference_expression *) override;
virtual void visit(number_literal<std::int32_t> *) override;
virtual void visit(number_literal<std::uint32_t> *) override;
virtual void visit(number_literal<double> *) override;
@ -214,75 +214,83 @@ namespace boot
/**
* Some type expression.
*/
class top_type : public node, public std::enable_shared_from_this<top_type>
class type_expression : public node, public std::enable_shared_from_this<type_expression>
{
public:
virtual std::shared_ptr<primitive_type_expression> is_primitive();
virtual std::shared_ptr<array_type_expression> is_array();
virtual std::shared_ptr<pointer_type_expression> is_pointer();
virtual std::shared_ptr<record_type_expression> is_record();
virtual std::shared_ptr<union_type_expression> is_union();
virtual std::shared_ptr<procedure_type_expression> is_procedure();
protected:
top_type(const struct position position);
type_expression(const struct position position);
};
/**
* Expression defining a basic type.
*/
class basic_type : public top_type
class primitive_type_expression : public type_expression
{
const std::string m_name;
public:
/**
* \param position Source code position.
* \param name Type name.
*/
basic_type(const struct position position, const std::string& name);
virtual void accept(parser_visitor *visitor) override;
const std::string name;
const std::string& base_name();
primitive_type_expression(const struct position position, const std::string& name);
virtual void accept(parser_visitor *visitor) override;
std::shared_ptr<primitive_type_expression> is_primitive() override;
};
class array_type : public top_type
class array_type_expression : public type_expression
{
std::shared_ptr<top_type> m_base;
std::shared_ptr<type_expression> m_base;
public:
const std::uint32_t size;
array_type(const struct position position, std::shared_ptr<top_type> base, const std::uint32_t size);
array_type_expression(const struct position position,
std::shared_ptr<type_expression> base, const std::uint32_t size);
virtual void accept(parser_visitor *visitor) override;
std::shared_ptr<array_type_expression> is_array() override;
top_type& base();
type_expression& base();
};
class pointer_type : public top_type
class pointer_type_expression : public type_expression
{
std::shared_ptr<top_type> m_base;
std::shared_ptr<type_expression> m_base;
public:
pointer_type(const struct position position, std::shared_ptr<top_type> base);
pointer_type_expression(const struct position position, std::shared_ptr<type_expression> base);
virtual void accept(parser_visitor *visitor) override;
std::shared_ptr<pointer_type_expression> is_pointer() override;
top_type& base();
type_expression& base();
};
using field_t = std::pair<std::string, std::shared_ptr<top_type>>;
using field_t = std::pair<std::string, std::shared_ptr<type_expression>>;
using fields_t = std::vector<field_t>;
class record_type : public top_type
class record_type_expression : public type_expression
{
public:
fields_t fields;
record_type(const struct position position, fields_t&& fields);
record_type_expression(const struct position position, fields_t&& fields);
virtual void accept(parser_visitor *visitor) override;
std::shared_ptr<record_type_expression> is_record() override;
};
class union_type : public top_type
class union_type_expression : public type_expression
{
public:
fields_t fields;
union_type(const struct position position, fields_t&& fields);
union_type_expression(const struct position position, fields_t&& fields);
virtual void accept(parser_visitor *visitor) override;
std::shared_ptr<union_type_expression> is_union() override;
};
/**
@ -290,14 +298,14 @@ namespace boot
*/
class variable_declaration : public definition
{
std::shared_ptr<top_type> m_type;
std::shared_ptr<type_expression> m_type;
public:
variable_declaration(const struct position position, const std::string& identifier,
std::shared_ptr<top_type> type, const bool exported = false);
std::shared_ptr<type_expression> type, const bool exported = false);
virtual void accept(parser_visitor *visitor) override;
top_type& variable_type();
type_expression& variable_type();
};
/**
@ -342,19 +350,21 @@ namespace boot
/**
* Procedure type.
*/
class procedure_type : public top_type
class procedure_type_expression : public type_expression
{
public:
const std::shared_ptr<top_type> return_type;
const std::shared_ptr<type_expression> return_type;
const bool no_return;
std::vector<variable_declaration *> parameters;
procedure_type(const struct position position, std::shared_ptr<top_type> return_type = nullptr);
procedure_type(const struct position position, no_return_t);
procedure_type_expression(const struct position position,
std::shared_ptr<type_expression> return_type = nullptr);
procedure_type_expression(const struct position position, no_return_t);
virtual void accept(parser_visitor *visitor) override;
std::shared_ptr<procedure_type_expression> is_procedure() override;
virtual ~procedure_type() override;
virtual ~procedure_type_expression() override;
};
/**
@ -362,16 +372,16 @@ namespace boot
*/
class procedure_definition : public definition
{
std::shared_ptr<procedure_type> m_heading;
std::shared_ptr<procedure_type_expression> m_heading;
public:
block *const body;
procedure_definition(const struct position position, const std::string& identifier,
const bool exported, std::shared_ptr<procedure_type> heading, block *body = nullptr);
const bool exported, std::shared_ptr<procedure_type_expression> heading, block *body = nullptr);
virtual void accept(parser_visitor *visitor) override;
procedure_type& heading();
procedure_type_expression& heading();
virtual ~procedure_definition() override;
};
@ -381,14 +391,14 @@ namespace boot
*/
class type_definition : public definition
{
std::shared_ptr<top_type> m_body;
std::shared_ptr<type_expression> m_body;
public:
type_definition(const struct position position, const std::string& identifier,
const bool exported, std::shared_ptr<top_type> expression);
const bool exported, std::shared_ptr<type_expression> expression);
virtual void accept(parser_visitor *visitor) override;
top_type& body();
type_expression& body();
};
/**
@ -396,14 +406,14 @@ namespace boot
*/
class cast_expression : public expression
{
std::shared_ptr<top_type> m_target;
std::shared_ptr<type_expression> m_target;
expression *m_value;
public:
cast_expression(const struct position position, std::shared_ptr<top_type> target, expression *value);
cast_expression(const struct position position, std::shared_ptr<type_expression> target, expression *value);
virtual void accept(parser_visitor *visitor) override;
top_type& target();
type_expression& target();
expression& value();
virtual ~cast_expression() override;
@ -411,15 +421,16 @@ namespace boot
class traits_expression : public expression
{
std::shared_ptr<top_type> m_type;
std::shared_ptr<type_expression> m_type;
public:
const std::string name;
traits_expression(const struct position position, const std::string& name, std::shared_ptr<top_type> type);
traits_expression(const struct position position, const std::string& name,
std::shared_ptr<type_expression> type);
virtual void accept(parser_visitor *visitor) override;
top_type& type();
type_expression& type();
};
/**

View File

@ -0,0 +1,37 @@
/* Semantic analysis visitors.
Copyright (C) 2025 Free Software Foundation, Inc.
GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#pragma once
#include "elna/boot/ast.h"
#include "elna/boot/symbol.h"
namespace elna
{
namespace boot
{
class declaration_visitor : public empty_visitor
{
std::shared_ptr<symbol_table> table;
public:
declaration_visitor(std::shared_ptr<symbol_table> table);
void visit(program *program) override;
};
}
}

View File

@ -26,20 +26,49 @@ namespace elna
{
namespace boot
{
class info
{
public:
virtual ~info() = 0;
protected:
info() = default;
};
class type
{
public:
virtual ~type() = 0;
protected:
type() = default;
};
class type_info : public info, public type
{
public:
const std::string name;
type_info(const std::string& name);
};
/**
* Symbol table.
*/
template<typename T, T nothing>
class symbol_table
template<typename T, typename U, U nothing>
class symbol_map
{
public:
using symbol_ptr = T;
using symbol_ptr = typename std::enable_if<
std::is_convertible<U, T>::value || std::is_assignable<T, U>::value,
T
>::type;
using iterator = typename std::unordered_map<std::string, symbol_ptr>::iterator;
using const_iterator = typename std::unordered_map<std::string, symbol_ptr>::const_iterator;
private:
std::unordered_map<std::string, symbol_ptr> entries;
std::shared_ptr<symbol_table> outer_scope;
std::shared_ptr<symbol_map> outer_scope;
public:
/**
@ -47,7 +76,7 @@ namespace boot
*
* \param scope Outer scope.
*/
explicit symbol_table(std::shared_ptr<symbol_table> scope = nullptr)
explicit symbol_map(std::shared_ptr<symbol_map> scope = nullptr)
: outer_scope(scope)
{
}
@ -104,14 +133,7 @@ namespace boot
*/
bool enter(const std::string& name, symbol_ptr entry)
{
if (lookup(name) == nothing)
{
return entries.insert({ name, entry }).second;
}
else
{
return nothing;
}
return lookup(name) == nothing && entries.insert({ name, entry }).second;
}
/**
@ -119,10 +141,12 @@ namespace boot
*
* \return Outer scope.
*/
std::shared_ptr<symbol_table> scope()
std::shared_ptr<symbol_map> scope()
{
return this->outer_scope;
}
};
using symbol_table = symbol_map<std::shared_ptr<info>, std::nullptr_t, nullptr>;
}
}

View File

@ -40,7 +40,7 @@ namespace gcc
std::shared_ptr<symbol_table> symbol_map;
tree build_label_decl(const char *name, location_t loc);
tree build_procedure_type(boot::procedure_type& type);
tree build_procedure_type(boot::procedure_type_expression& type);
void enter_scope();
tree leave_scope();
@ -89,12 +89,12 @@ namespace gcc
void visit(boot::assign_statement *statement) override;
void visit(boot::if_statement *statement) override;
void visit(boot::while_statement *statement) override;
void visit(boot::basic_type *type) override;
void visit(boot::array_type *type) override;
void visit(boot::pointer_type *type) override;
void visit(boot::record_type *type) override;
void visit(boot::union_type *type) override;
void visit(boot::procedure_type *type) override;
void visit(boot::primitive_type_expression *type) override;
void visit(boot::array_type_expression *type) override;
void visit(boot::pointer_type_expression *type) override;
void visit(boot::record_type_expression *type) override;
void visit(boot::union_type_expression *type) override;
void visit(boot::procedure_type_expression *type) override;
void visit(boot::return_statement *statement) override;
void visit(boot::defer_statement *statement) override;
};

View File

@ -33,7 +33,7 @@ namespace elna
{
namespace gcc
{
using symbol_table = boot::symbol_table<tree, NULL_TREE>;
using symbol_table = boot::symbol_map<tree, tree, NULL_TREE>;
bool is_pointer_type(tree type);
bool is_integral_type(tree type);

View File

@ -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
Token* = record
kind: Int
value: union
int_value: Int
string: String
boolean_value: Bool
char_value: Char
end
Token* = record
kind: Int
value: TokenValue
location: Location
end
CommandLine* = record