Compare commits

..

No commits in common. "16266b63ce5869cb4bdc9b9dc9878378568cdfe1" and "b141dc1a5a419bdab2e73e106e617da610dda0ef" have entirely different histories.

16 changed files with 462 additions and 642 deletions

View File

@ -23,167 +23,197 @@ namespace boot
{ {
void empty_visitor::visit(variable_declaration *) void empty_visitor::visit(variable_declaration *)
{ {
__builtin_unreachable();
} }
void empty_visitor::visit(constant_definition *) void empty_visitor::visit(constant_definition *definition)
{ {
__builtin_unreachable(); definition->body().accept(this);
} }
void empty_visitor::visit(procedure_definition *) void empty_visitor::visit(procedure_definition *definition)
{ {
__builtin_unreachable(); definition->heading().accept(this);
if (definition->body != nullptr)
{
definition->body->accept(this);
}
} }
void empty_visitor::visit(type_definition *) void empty_visitor::visit(type_definition *definition)
{ {
__builtin_unreachable(); definition->body().accept(this);
} }
void empty_visitor::visit(procedure_call *) void empty_visitor::visit(procedure_call *call)
{ {
__builtin_unreachable(); for (expression *const argument : call->arguments)
{
argument->accept(this);
}
} }
void empty_visitor::visit(traits_expression *) void empty_visitor::visit(traits_expression *trait)
{ {
__builtin_unreachable(); trait->type().accept(this);
} }
void empty_visitor::visit(cast_expression *) void empty_visitor::visit(cast_expression *expression)
{ {
__builtin_unreachable(); expression->target().accept(this);
expression->value().accept(this);
} }
void empty_visitor::visit(assign_statement *) void empty_visitor::visit(assign_statement *statement)
{ {
__builtin_unreachable(); statement->rvalue().accept(this);
} }
void empty_visitor::visit(if_statement *) void empty_visitor::visit(if_statement *statement)
{ {
__builtin_unreachable(); statement->body().prerequisite().accept(this);
for (const auto body_statement : statement->body().statements)
{
body_statement->accept(this);
}
} }
void empty_visitor::visit(while_statement *) void empty_visitor::visit(while_statement *statement)
{ {
__builtin_unreachable(); statement->body().prerequisite().accept(this);
for (const auto body_statement : statement->body().statements)
{
body_statement->accept(this);
}
} }
void empty_visitor::visit(return_statement *) void empty_visitor::visit(block *block)
{ {
__builtin_unreachable(); for (constant_definition *const constant : block->constants)
{
constant->accept(this);
}
for (variable_declaration *const variable : block->variables)
{
variable->accept(this);
}
for (statement *const body_statement : block->body)
{
body_statement->accept(this);
}
} }
void empty_visitor::visit(defer_statement *) void empty_visitor::visit(program *program)
{ {
__builtin_unreachable(); 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);
}
} }
void empty_visitor::visit(block *) void empty_visitor::visit(binary_expression *expression)
{ {
__builtin_unreachable(); expression->lhs().accept(this);
expression->rhs().accept(this);
} }
void empty_visitor::visit(program *) void empty_visitor::visit(unary_expression *expression)
{ {
__builtin_unreachable(); expression->operand().accept(this);
} }
void empty_visitor::visit(binary_expression *) void empty_visitor::visit(basic_type *)
{ {
__builtin_unreachable();
} }
void empty_visitor::visit(unary_expression *) void empty_visitor::visit(array_type *expression)
{ {
__builtin_unreachable(); expression->base().accept(this);
} }
void empty_visitor::visit(primitive_type_expression *) void empty_visitor::visit(pointer_type *expression)
{ {
__builtin_unreachable(); expression->base().accept(this);
} }
void empty_visitor::visit(array_type_expression *) void empty_visitor::visit(record_type *expression)
{ {
__builtin_unreachable(); for (auto& field : expression->fields)
{
field.second->accept(this);
}
} }
void empty_visitor::visit(pointer_type_expression *) void empty_visitor::visit(union_type *expression)
{ {
__builtin_unreachable(); for (auto& field : expression->fields)
{
field.second->accept(this);
}
} }
void empty_visitor::visit(record_type_expression *) void empty_visitor::visit(procedure_type *expression)
{ {
__builtin_unreachable(); for (auto parameter : expression->parameters)
{
parameter->accept(this);
} }
if (expression->return_type != nullptr)
void empty_visitor::visit(union_type_expression *)
{ {
__builtin_unreachable(); expression->return_type->accept(this);
} }
void empty_visitor::visit(procedure_type_expression *)
{
__builtin_unreachable();
} }
void empty_visitor::visit(variable_expression *) void empty_visitor::visit(variable_expression *)
{ {
__builtin_unreachable();
} }
void empty_visitor::visit(array_access_expression *) void empty_visitor::visit(array_access_expression *expression)
{ {
__builtin_unreachable(); expression->base().accept(this);
expression->index().accept(this);
} }
void empty_visitor::visit(field_access_expression *) void empty_visitor::visit(field_access_expression *expression)
{ {
__builtin_unreachable(); expression->base().accept(this);
} }
void empty_visitor::visit(dereference_expression *) void empty_visitor::visit(dereference_expression *expression)
{ {
__builtin_unreachable(); expression->base().accept(this);
} }
void empty_visitor::visit(number_literal<std::int32_t> *) void empty_visitor::visit(number_literal<std::int32_t> *)
{ {
__builtin_unreachable();
} }
void empty_visitor::visit(number_literal<std::uint32_t> *) void empty_visitor::visit(number_literal<std::uint32_t> *)
{ {
__builtin_unreachable();
} }
void empty_visitor::visit(number_literal<double> *) void empty_visitor::visit(number_literal<double> *)
{ {
__builtin_unreachable();
} }
void empty_visitor::visit(number_literal<bool> *) void empty_visitor::visit(number_literal<bool> *)
{ {
__builtin_unreachable();
} }
void empty_visitor::visit(number_literal<unsigned char> *) void empty_visitor::visit(number_literal<unsigned char> *)
{ {
__builtin_unreachable();
} }
void empty_visitor::visit(number_literal<std::nullptr_t> *) void empty_visitor::visit(number_literal<std::nullptr_t> *)
{ {
__builtin_unreachable();
} }
void empty_visitor::visit(number_literal<std::string> *) void empty_visitor::visit(number_literal<std::string> *)
{ {
__builtin_unreachable();
} }
node::node(const struct position position) node::node(const struct position position)
@ -204,80 +234,133 @@ namespace boot
{ {
} }
type_expression::type_expression(const struct position position) top_type::top_type(const struct position position)
: node(position) : node(position)
{ {
} }
primitive_type_expression::primitive_type_expression(const struct position position, const std::string& name) std::shared_ptr<basic_type> top_type::is_basic()
: type_expression(position), m_name(name) {
return nullptr;
}
std::shared_ptr<array_type> top_type::is_array()
{
return nullptr;
}
std::shared_ptr<record_type> top_type::is_record()
{
return nullptr;
}
std::shared_ptr<union_type> top_type::is_union()
{
return nullptr;
}
std::shared_ptr<pointer_type> top_type::is_pointer()
{
return nullptr;
}
std::shared_ptr<procedure_type> top_type::is_procedure()
{
return nullptr;
}
basic_type::basic_type(const struct position position, const std::string& name)
: top_type(position), m_name(name)
{ {
} }
void primitive_type_expression::accept(parser_visitor *visitor) void basic_type::accept(parser_visitor *visitor)
{ {
visitor->visit(this); visitor->visit(this);
} }
const std::string& primitive_type_expression::base_name() const std::string& basic_type::base_name()
{ {
return m_name; return m_name;
} }
array_type_expression::array_type_expression(const struct position position, std::shared_ptr<basic_type> basic_type::is_basic()
std::shared_ptr<type_expression> base, const std::uint32_t size) {
: type_expression(position), m_base(base), size(size) return std::static_pointer_cast<basic_type>(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)
{ {
} }
void array_type_expression::accept(parser_visitor *visitor) void array_type::accept(parser_visitor *visitor)
{ {
visitor->visit(this); visitor->visit(this);
} }
type_expression& array_type_expression::base() top_type& array_type::base()
{ {
return *m_base; return *m_base;
} }
pointer_type_expression::pointer_type_expression(const struct position position, std::shared_ptr<array_type> array_type::is_array()
std::shared_ptr<type_expression> base) {
: type_expression(position), m_base(base) return std::static_pointer_cast<array_type>(shared_from_this());
}
pointer_type::pointer_type(const struct position position, std::shared_ptr<top_type> base)
: top_type(position), m_base(base)
{ {
} }
void pointer_type_expression::accept(parser_visitor *visitor) void pointer_type::accept(parser_visitor *visitor)
{ {
visitor->visit(this); visitor->visit(this);
} }
type_expression& pointer_type_expression::base() top_type& pointer_type::base()
{ {
return *m_base; return *m_base;
} }
record_type_expression::record_type_expression(const struct position position, fields_t&& fields) std::shared_ptr<pointer_type> pointer_type::is_pointer()
: type_expression(position), fields(std::move(fields)) {
return std::static_pointer_cast<pointer_type>(shared_from_this());
}
record_type::record_type(const struct position position, fields_t&& fields)
: top_type(position), fields(std::move(fields))
{ {
} }
void record_type_expression::accept(parser_visitor *visitor) void record_type::accept(parser_visitor *visitor)
{ {
visitor->visit(this); visitor->visit(this);
} }
union_type_expression::union_type_expression(const struct position position, fields_t&& fields) std::shared_ptr<record_type> record_type::is_record()
: type_expression(position), fields(std::move(fields)) {
return std::static_pointer_cast<record_type>(shared_from_this());
}
union_type::union_type(const struct position position, fields_t&& fields)
: top_type(position), fields(std::move(fields))
{ {
} }
void union_type_expression::accept(parser_visitor *visitor) std::shared_ptr<union_type> union_type::is_union()
{
return std::static_pointer_cast<union_type>(shared_from_this());
}
void union_type::accept(parser_visitor *visitor)
{ {
visitor->visit(this); visitor->visit(this);
} }
variable_declaration::variable_declaration(const struct position position, const std::string& identifier, variable_declaration::variable_declaration(const struct position position, const std::string& identifier,
std::shared_ptr<type_expression> type, const bool exported) std::shared_ptr<top_type> type, const bool exported)
: definition(position, identifier, exported), m_type(type) : definition(position, identifier, exported), m_type(type)
{ {
} }
@ -287,7 +370,7 @@ namespace boot
visitor->visit(this); visitor->visit(this);
} }
type_expression& variable_declaration::variable_type() top_type& variable_declaration::variable_type()
{ {
return *m_type; return *m_type;
} }
@ -318,23 +401,27 @@ namespace boot
delete m_body; delete m_body;
} }
procedure_type_expression::procedure_type_expression(const struct position position, procedure_type::procedure_type(const struct position position, std::shared_ptr<top_type> return_type)
std::shared_ptr<type_expression> return_type) : top_type(position), return_type(return_type), no_return(false)
: type_expression(position), return_type(return_type), no_return(false)
{ {
} }
procedure_type_expression::procedure_type_expression(const struct position position, no_return_t) procedure_type::procedure_type(const struct position position, no_return_t)
: type_expression(position), return_type(nullptr), no_return(true) : top_type(position), return_type(nullptr), no_return(true)
{ {
} }
void procedure_type_expression::accept(parser_visitor *visitor) void procedure_type::accept(parser_visitor *visitor)
{ {
visitor->visit(this); visitor->visit(this);
} }
procedure_type_expression::~procedure_type_expression() std::shared_ptr<procedure_type> procedure_type::is_procedure()
{
return std::static_pointer_cast<procedure_type>(shared_from_this());
}
procedure_type::~procedure_type()
{ {
for (auto parameter : this->parameters) for (auto parameter : this->parameters)
{ {
@ -343,8 +430,9 @@ namespace boot
} }
procedure_definition::procedure_definition(const struct position position, const std::string& identifier, procedure_definition::procedure_definition(const struct position position, const std::string& identifier,
const bool exported, std::shared_ptr<procedure_type_expression> heading, block *body) const bool exported, std::shared_ptr<procedure_type> heading,
: definition(position, identifier, exported), m_heading(heading), body(body) block *const body, expression *const returning)
: definition(position, identifier, exported), m_heading(heading), body(body), returning(returning)
{ {
} }
@ -353,7 +441,7 @@ namespace boot
visitor->visit(this); visitor->visit(this);
} }
procedure_type_expression& procedure_definition::heading() procedure_type& procedure_definition::heading()
{ {
return *m_heading; return *m_heading;
} }
@ -361,10 +449,11 @@ namespace boot
procedure_definition::~procedure_definition() procedure_definition::~procedure_definition()
{ {
delete body; delete body;
delete returning;
} }
type_definition::type_definition(const struct position position, const std::string& identifier, type_definition::type_definition(const struct position position, const std::string& identifier,
const bool exported, std::shared_ptr<type_expression> body) const bool exported, std::shared_ptr<top_type> body)
: definition(position, identifier, exported), m_body(body) : definition(position, identifier, exported), m_body(body)
{ {
} }
@ -374,7 +463,7 @@ namespace boot
visitor->visit(this); visitor->visit(this);
} }
type_expression& type_definition::body() top_type& type_definition::body()
{ {
return *m_body; return *m_body;
} }
@ -431,24 +520,6 @@ namespace boot
{ {
} }
defer_statement::defer_statement(const struct position position)
: node(position)
{
}
void defer_statement::accept(parser_visitor *visitor)
{
visitor->visit(this);
}
defer_statement::~defer_statement()
{
for (statement *body_statement : statements)
{
delete body_statement;
}
}
designator_expression::designator_expression() designator_expression::designator_expression()
{ {
} }
@ -640,7 +711,7 @@ namespace boot
} }
cast_expression::cast_expression(const struct position position, cast_expression::cast_expression(const struct position position,
std::shared_ptr<type_expression> target, expression *value) std::shared_ptr<top_type> target, expression *value)
: node(position), m_target(target), m_value(value) : node(position), m_target(target), m_value(value)
{ {
} }
@ -650,7 +721,7 @@ namespace boot
visitor->visit(this); visitor->visit(this);
} }
type_expression& cast_expression::target() top_type& cast_expression::target()
{ {
return *m_target; return *m_target;
} }
@ -666,7 +737,7 @@ namespace boot
} }
traits_expression::traits_expression(const struct position position, traits_expression::traits_expression(const struct position position,
const std::string& name, std::shared_ptr<type_expression> type) const std::string& name, std::shared_ptr<top_type> type)
: node(position), m_type(type), name(name) : node(position), m_type(type), name(name)
{ {
} }
@ -676,7 +747,7 @@ namespace boot
visitor->visit(this); visitor->visit(this);
} }
type_expression& traits_expression::type() top_type& traits_expression::type()
{ {
return *m_type; return *m_type;
} }
@ -700,26 +771,6 @@ namespace boot
} }
} }
return_statement::return_statement(const struct position position, expression *return_expression)
: node(position), m_return_expression(return_expression)
{
}
void return_statement::accept(parser_visitor *visitor)
{
visitor->visit(this);
}
expression *return_statement::return_expression()
{
return m_return_expression;
}
return_statement::~return_statement()
{
delete m_return_expression;
}
void assign_statement::accept(parser_visitor *visitor) void assign_statement::accept(parser_visitor *visitor)
{ {
visitor->visit(this); visitor->visit(this);

View File

@ -125,9 +125,6 @@ return {
cast { cast {
return yy::parser::make_CAST(this->location); return yy::parser::make_CAST(this->location);
} }
defer {
return yy::parser::make_DEFER(this->location);
}
[A-Za-z_][A-Za-z0-9_]* { [A-Za-z_][A-Za-z0-9_]* {
return yy::parser::make_IDENTIFIER(yytext, this->location); return yy::parser::make_IDENTIFIER(yytext, this->location);
} }

View File

@ -106,7 +106,6 @@ along with GCC; see the file COPYING3. If not see
RETURN "return" RETURN "return"
BEGIN_BLOCK "begin" BEGIN_BLOCK "begin"
END_BLOCK "end" END_BLOCK "end"
DEFER "defer"
%token OR "or" AND "and" XOR "xor" %token OR "or" AND "and" XOR "xor"
EQUALS "=" NOT_EQUAL "<>" LESS_THAN "<" GREATER_THAN ">" LESS_EQUAL "<=" GREATER_EQUAL ">=" EQUALS "=" NOT_EQUAL "<>" LESS_THAN "<" GREATER_THAN ">" LESS_EQUAL "<=" GREATER_EQUAL ">="
SHIFT_LEFT "<<" SHIFT_RIGHT ">>" SHIFT_LEFT "<<" SHIFT_RIGHT ">>"
@ -125,7 +124,7 @@ along with GCC; see the file COPYING3. If not see
%type <std::vector<elna::boot::variable_declaration *>> variable_declarations variable_part variable_declaration %type <std::vector<elna::boot::variable_declaration *>> variable_declarations variable_part variable_declaration
formal_parameters formal_parameter_list; formal_parameters formal_parameter_list;
%type <elna::boot::variable_declaration *> formal_parameter %type <elna::boot::variable_declaration *> formal_parameter
%type <std::shared_ptr<elna::boot::type_expression>> type_expression; %type <std::shared_ptr<elna::boot::top_type>> type_expression;
%type <elna::boot::traits_expression *> traits_expression; %type <elna::boot::traits_expression *> traits_expression;
%type <elna::boot::expression *> expression operand; %type <elna::boot::expression *> expression operand;
%type <elna::boot::unary_expression *> unary_expression; %type <elna::boot::unary_expression *> unary_expression;
@ -136,26 +135,24 @@ along with GCC; see the file COPYING3. If not see
%type <elna::boot::procedure_call*> call_expression; %type <elna::boot::procedure_call*> call_expression;
%type <elna::boot::while_statement *> while_statement; %type <elna::boot::while_statement *> while_statement;
%type <elna::boot::if_statement *> if_statement; %type <elna::boot::if_statement *> if_statement;
%type <elna::boot::return_statement *> return_statement; %type <elna::boot::expression *> return_statement;
%type <elna::boot::statement *> statement; %type <elna::boot::statement *> statement;
%type <std::vector<elna::boot::statement *>> statements; %type <std::vector<elna::boot::statement *>> statements statement_part;
%type <elna::boot::procedure_definition *> procedure_definition; %type <elna::boot::procedure_definition *> procedure_definition;
%type <std::shared_ptr<elna::boot::procedure_type_expression>> procedure_heading; %type <std::shared_ptr<elna::boot::procedure_type>> procedure_heading;
%type <std::vector<elna::boot::procedure_definition *>> procedure_definitions procedure_part; %type <std::vector<elna::boot::procedure_definition *>> procedure_definitions;
%type <elna::boot::type_definition *> type_definition; %type <elna::boot::type_definition *> type_definition;
%type <std::vector<elna::boot::type_definition *>> type_definitions type_part; %type <std::vector<elna::boot::type_definition *>> type_definitions type_part;
%type <elna::boot::block *> block; %type <elna::boot::block *> block;
%type <elna::boot::field_t> field_declaration; %type <elna::boot::field_t> field_declaration;
%type <std::vector<std::pair<std::string, std::shared_ptr<elna::boot::type_expression>>>> %type <std::vector<std::pair<std::string, std::shared_ptr<elna::boot::top_type>>>> optional_fields required_fields;
optional_fields required_fields;
%type <std::vector<elna::boot::conditional_statements *>> elsif_then_statements elsif_do_statements; %type <std::vector<elna::boot::conditional_statements *>> elsif_then_statements elsif_do_statements;
%type <elna::boot::cast_expression *> cast_expression; %type <elna::boot::cast_expression *> cast_expression;
%type <elna::boot::defer_statement *> defer_statement;
%type <std::pair<std::string, bool>> identifier_definition; %type <std::pair<std::string, bool>> identifier_definition;
%type <std::vector<std::pair<std::string, bool>>> identifier_definitions; %type <std::vector<std::pair<std::string, bool>>> identifier_definitions;
%% %%
program: program:
constant_part type_part variable_part procedure_part "begin" statements "end" "." constant_part type_part variable_part procedure_definitions "begin" statements "end" "."
{ {
auto tree = new elna::boot::program(elna::boot::make_position(@5)); auto tree = new elna::boot::program(elna::boot::make_position(@5));
@ -167,13 +164,13 @@ program:
driver.tree.reset(tree); driver.tree.reset(tree);
} }
block: constant_part variable_part "begin" statements "end" block: constant_part variable_part statement_part
{ {
$$ = new elna::boot::block(elna::boot::make_position(@3)); $$ = new elna::boot::block(elna::boot::make_position(@1));
std::swap($$->constants, $1); std::swap($$->constants, $1);
std::swap($$->variables, $2); std::swap($$->variables, $2);
std::swap($$->body, $4); std::swap($$->body, $3);
} }
identifier_definition: identifier_definition:
IDENTIFIER "*" IDENTIFIER "*"
@ -194,24 +191,24 @@ identifier_definitions:
procedure_heading: procedure_heading:
formal_parameter_list formal_parameter_list
{ {
$$ = std::make_shared<elna::boot::procedure_type_expression>(elna::boot::make_position(@1)); $$ = std::make_shared<elna::boot::procedure_type>(elna::boot::make_position(@1));
std::swap($1, $$->parameters); std::swap($1, $$->parameters);
} }
| formal_parameter_list "->" "!" | formal_parameter_list "->" "!"
{ {
$$ = std::make_shared<elna::boot::procedure_type_expression>(elna::boot::make_position(@1), $$ = std::make_shared<elna::boot::procedure_type>(elna::boot::make_position(@1), elna::boot::no_return);
elna::boot::no_return);
std::swap($1, $$->parameters); std::swap($1, $$->parameters);
} }
| formal_parameter_list "->" type_expression | formal_parameter_list "->" type_expression
{ {
$$ = std::make_shared<elna::boot::procedure_type_expression>(elna::boot::make_position(@1), $3); $$ = std::make_shared<elna::boot::procedure_type>(elna::boot::make_position(@1), $3);
std::swap($1, $$->parameters); std::swap($1, $$->parameters);
} }
procedure_definition: procedure_definition:
"proc" identifier_definition procedure_heading ";" block "proc" identifier_definition procedure_heading ";" block return_statement "end"
{ {
$$ = new elna::boot::procedure_definition(elna::boot::make_position(@1), $2.first, $2.second, $3, $5); $$ = new elna::boot::procedure_definition(elna::boot::make_position(@1), $2.first, $2.second,
$3, $5, $6);
} }
| "proc" identifier_definition procedure_heading ";" "extern" | "proc" identifier_definition procedure_heading ";" "extern"
{ {
@ -223,10 +220,7 @@ procedure_definitions:
std::swap($$, $2); std::swap($$, $2);
$$.emplace($$.cbegin(), std::move($1)); $$.emplace($$.cbegin(), std::move($1));
} }
| procedure_definition { $$.emplace_back(std::move($1)); } | /* no procedure definitions */ {}
procedure_part:
/* no procedure definitions */ {}
| procedure_definitions { std::swap($$, $1); }
assign_statement: designator_expression ":=" expression assign_statement: designator_expression ":=" expression
{ {
$$ = new elna::boot::assign_statement(elna::boot::make_position(@1), $1, $3); $$ = new elna::boot::assign_statement(elna::boot::make_position(@1), $1, $3);
@ -281,15 +275,12 @@ if_statement:
$$ = new elna::boot::if_statement(elna::boot::make_position(@1), then, _else); $$ = new elna::boot::if_statement(elna::boot::make_position(@1), then, _else);
std::swap($5, $$->branches); std::swap($5, $$->branches);
} }
return_statement: "return" expression return_statement:
"return" expression
{ {
$$ = new elna::boot::return_statement(elna::boot::make_position(@1), $2); $$ = $2;
}
defer_statement: DEFER statements "end"
{
$$ = new elna::boot::defer_statement(elna::boot::make_position(@1));
std::swap($2, $$->statements);
} }
| /* no return statement */ { $$ = nullptr; }
literal: literal:
INTEGER INTEGER
{ {
@ -460,17 +451,21 @@ statement:
assign_statement { $$ = $1; } assign_statement { $$ = $1; }
| while_statement { $$ = $1; } | while_statement { $$ = $1; }
| if_statement { $$ = $1; } | if_statement { $$ = $1; }
| return_statement { $$ = $1; }
| call_expression { $$ = $1; } | call_expression { $$ = $1; }
| defer_statement { $$ = $1; }
statements: statements:
statement ";" statements statement ";" statements
{ {
std::swap($$, $3); std::swap($$, $3);
$$.insert($$.cbegin(), $1); $$.emplace($$.cbegin(), $1);
}
| statement
{
$$.push_back($1);
} }
| statement { $$.push_back($1); }
| /* no statements */ {} | /* no statements */ {}
statement_part:
"begin" statements { std::swap($$, $2); }
| {}
field_declaration: field_declaration:
IDENTIFIER ":" type_expression { $$ = std::make_pair($1, $3); } IDENTIFIER ":" type_expression { $$ = std::make_pair($1, $3); }
required_fields: required_fields:
@ -486,19 +481,19 @@ optional_fields:
type_expression: type_expression:
"[" INTEGER "]" type_expression "[" INTEGER "]" type_expression
{ {
$$ = std::make_shared<elna::boot::array_type_expression>(elna::boot::make_position(@1), $4, $2); $$ = std::make_shared<elna::boot::array_type>(elna::boot::make_position(@1), $4, $2);
} }
| "^" type_expression | "^" type_expression
{ {
$$ = std::make_shared<elna::boot::pointer_type_expression>(elna::boot::make_position(@1), $2); $$ = std::make_shared<elna::boot::pointer_type>(elna::boot::make_position(@1), $2);
} }
| "record" optional_fields "end" | "record" optional_fields "end"
{ {
$$ = std::make_shared<elna::boot::record_type_expression>(elna::boot::make_position(@1), std::move($2)); $$ = std::make_shared<elna::boot::record_type>(elna::boot::make_position(@1), std::move($2));
} }
| "union" required_fields "end" | "union" required_fields "end"
{ {
$$ = std::make_shared<elna::boot::union_type_expression>(elna::boot::make_position(@1), std::move($2)); $$ = std::make_shared<elna::boot::union_type>(elna::boot::make_position(@1), std::move($2));
} }
| "proc" procedure_heading | "proc" procedure_heading
{ {
@ -506,7 +501,7 @@ type_expression:
} }
| IDENTIFIER | IDENTIFIER
{ {
$$ = std::make_shared<elna::boot::primitive_type_expression>(elna::boot::make_position(@1), $1); $$ = std::make_shared<elna::boot::basic_type>(elna::boot::make_position(@1), $1);
} }
variable_declaration: identifier_definitions ":" type_expression variable_declaration: identifier_definitions ":" type_expression
{ {

View File

@ -1,33 +0,0 @@
/* 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
{
name_analysis_visitor::name_analysis_visitor(std::shared_ptr<symbol_table<>> table)
: table(table)
{
}
void name_analysis_visitor::visit(program *program)
{
}
}
}

View File

@ -1,32 +0,0 @@
/* 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()
{
}
}
}

View File

@ -46,8 +46,6 @@ elna_OBJS = \
elna/driver.o \ elna/driver.o \
elna/lexer.o \ elna/lexer.o \
elna/parser.o \ elna/parser.o \
elna/semantic.o \
elna/symbol.o \
elna/result.o \ elna/result.o \
$(END) $(END)
@ -136,7 +134,7 @@ elna.stagefeedback: stagefeedback-start
-mv elna/*$(objext) stagefeedback/elna -mv elna/*$(objext) stagefeedback/elna
ELNA_INCLUDES = -I $(srcdir)/elna/include -I elna/generated ELNA_INCLUDES = -I $(srcdir)/elna/include -I elna/generated
ELNA_CXXFLAGS = -std=c++14 ELNA_CXXFLAGS = -std=c++11
elna/%.o: elna/boot/%.cc elna/generated/parser.hh elna/generated/location.hh elna/%.o: elna/boot/%.cc elna/generated/parser.hh elna/generated/location.hh
$(COMPILE) $(ELNA_CXXFLAGS) $(ELNA_INCLUDES) $< $(COMPILE) $(ELNA_CXXFLAGS) $(ELNA_INCLUDES) $<

View File

@ -164,8 +164,8 @@ namespace gcc
void generic_visitor::visit(boot::cast_expression *expression) void generic_visitor::visit(boot::cast_expression *expression)
{ {
expression->target().accept(this); tree cast_target = build_type(expression->target());
tree cast_target = this->current_expression; gcc_assert(cast_target != NULL_TREE);
expression->value().accept(this); expression->value().accept(this);
@ -294,6 +294,7 @@ namespace gcc
if (definition->body != nullptr) if (definition->body != nullptr)
{ {
definition->body->accept(this); definition->body->accept(this);
visit_return(definition->returning);
tree mapping = leave_scope(); tree mapping = leave_scope();
BLOCK_SUPERCONTEXT(BIND_EXPR_BLOCK(mapping)) = fndecl; BLOCK_SUPERCONTEXT(BIND_EXPR_BLOCK(mapping)) = fndecl;
@ -334,7 +335,7 @@ namespace gcc
{ {
BLOCK_SUPERCONTEXT(it) = new_block; BLOCK_SUPERCONTEXT(it) = new_block;
} }
tree bind_expr = build3(BIND_EXPR, void_type_node, variables, chain_defer(), new_block); tree bind_expr = build3(BIND_EXPR, void_type_node, variables, f_binding_level->statement_list, new_block);
this->symbol_map = this->symbol_map->scope(); this->symbol_map = this->symbol_map->scope();
f_binding_level = f_binding_level->level_chain; f_binding_level = f_binding_level->level_chain;
@ -731,16 +732,15 @@ namespace gcc
void generic_visitor::visit(boot::type_definition *definition) void generic_visitor::visit(boot::type_definition *definition)
{ {
location_t definition_location = get_location(&definition->position()); location_t definition_location = get_location(&definition->position());
definition->body().accept(this); tree tree_type = build_type(definition->body());
tree definition_tree = build_decl(definition_location, TYPE_DECL, tree definition_tree = build_decl(definition_location, TYPE_DECL,
get_identifier(definition->identifier.c_str()), this->current_expression); get_identifier(definition->identifier.c_str()), tree_type);
auto result = this->symbol_map->enter(definition->identifier, this->current_expression); auto result = this->symbol_map->enter(definition->identifier, tree_type);
if (result) if (result)
{ {
TREE_PUBLIC(definition_tree) = definition->exported; TREE_PUBLIC(definition_tree) = definition->exported;
TYPE_NAME(this->current_expression) = get_identifier(definition->identifier.c_str()); TYPE_NAME(tree_type) = get_identifier(definition->identifier.c_str());
} }
else else
{ {
@ -748,45 +748,138 @@ namespace gcc
"type '%s' already declared in this scope", "type '%s' already declared in this scope",
definition->identifier.c_str()); definition->identifier.c_str());
} }
this->current_expression = NULL_TREE;
} }
tree generic_visitor::build_procedure_type(boot::procedure_type_expression& type) tree generic_visitor::build_procedure_type(boot::procedure_type& type)
{ {
std::vector<tree> parameter_types(type.parameters.size()); std::vector<tree> parameter_types(type.parameters.size());
for (std::size_t i = 0; i < type.parameters.size(); ++i) for (std::size_t i = 0; i < type.parameters.size(); ++i)
{ {
boot::type_expression& parameter_type = type.parameters.at(i)->variable_type(); parameter_types[i] = build_type(type.parameters.at(i)->variable_type());
parameter_type.accept(this);
parameter_types[i] = this->current_expression;
} }
tree return_type = void_type_node; tree return_type = type.return_type == nullptr
? void_type_node
if (type.return_type != nullptr) : build_type(*type.return_type);
{
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()); 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<boot::basic_type> 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<boot::array_type> 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<boot::pointer_type> 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<boot::record_type> record_type = type.is_record())
{
std::set<std::string> 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<boot::union_type> union_type = type.is_union())
{
std::set<std::string> 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<boot::procedure_type> 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) void generic_visitor::visit(boot::variable_declaration *declaration)
{ {
declaration->variable_type().accept(this); tree declaration_type = build_type(declaration->variable_type());
gcc_assert(declaration_type != NULL_TREE);
location_t declaration_location = get_location(&declaration->position()); location_t declaration_location = get_location(&declaration->position());
tree declaration_tree = build_decl(declaration_location, VAR_DECL, tree declaration_tree = build_decl(declaration_location, VAR_DECL,
get_identifier(declaration->identifier.c_str()), this->current_expression); get_identifier(declaration->identifier.c_str()), declaration_type);
bool result = this->symbol_map->enter(declaration->identifier, declaration_tree); bool result = this->symbol_map->enter(declaration->identifier, declaration_tree);
if (is_pointer_type(this->current_expression)) if (is_pointer_type(declaration_type))
{ {
DECL_INITIAL(declaration_tree) = elna_pointer_nil_node; DECL_INITIAL(declaration_tree) = elna_pointer_nil_node;
} }
this->current_expression = NULL_TREE;
if (!result) if (!result)
{ {
error_at(declaration_location, "variable '%s' already declared in this scope", error_at(declaration_location, "variable '%s' already declared in this scope",
@ -874,30 +967,28 @@ namespace gcc
void generic_visitor::visit(boot::traits_expression *trait) void generic_visitor::visit(boot::traits_expression *trait)
{ {
trait->type().accept(this); tree type_expression = build_type(trait->type());
if (trait->name == "size") if (trait->name == "size")
{ {
this->current_expression = build1(CONVERT_EXPR, elna_word_type_node, this->current_expression = build1(CONVERT_EXPR, elna_word_type_node, size_in_bytes(type_expression));
size_in_bytes(this->current_expression));
} }
else if (trait->name == "alignment") else if (trait->name == "alignment")
{ {
this->current_expression = build_int_cstu(elna_word_type_node, this->current_expression = build_int_cstu(elna_word_type_node, TYPE_ALIGN_UNIT(type_expression));
TYPE_ALIGN_UNIT(this->current_expression));
} }
else if (trait->name == "min" && is_integral_type(this->current_expression)) else if (trait->name == "min" && is_integral_type(type_expression))
{ {
this->current_expression = TYPE_MIN_VALUE(this->current_expression); this->current_expression = TYPE_MIN_VALUE(type_expression);
} }
else if (trait->name == "max" && is_integral_type(this->current_expression)) else if (trait->name == "max" && is_integral_type(type_expression))
{ {
this->current_expression = TYPE_MAX_VALUE(this->current_expression); this->current_expression = TYPE_MAX_VALUE(type_expression);
} }
else else
{ {
error_at(get_location(&trait->position()), "type '%s' does not have property '%s'", error_at(get_location(&trait->position()), "type '%s' does not have property '%s'",
print_type(this->current_expression).c_str(), trait->name.c_str()); print_type(type_expression).c_str(), trait->name.c_str());
this->current_expression = error_mark_node; this->current_expression = error_mark_node;
} }
} }
@ -1084,10 +1175,8 @@ namespace gcc
} }
} }
void generic_visitor::visit(boot::return_statement *statement) void generic_visitor::visit_return(boot::expression *const return_expression)
{ {
boot::expression *return_expression = statement->return_expression();
if (return_expression == nullptr) if (return_expression == nullptr)
{ {
return; return;
@ -1101,117 +1190,5 @@ namespace gcc
this->current_expression = NULL_TREE; this->current_expression = NULL_TREE;
} }
void generic_visitor::visit(boot::primitive_type_expression *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_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);
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_expression *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_expression *type)
{
std::set<std::string> 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_expression *type)
{
std::set<std::string> 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_expression *type)
{
tree procedure_type_node = build_procedure_type(*type);
this->current_expression = build_pointer_type_for_mode(procedure_type_node, VOIDmode, true);
}
void generic_visitor::visit(boot::defer_statement *statement)
{
enter_scope();
visit_statements(statement->statements);
defer(leave_scope());
}
} }
} }

View File

@ -90,42 +90,9 @@ namespace gcc
} }
void append_statement(tree statement_tree) void append_statement(tree statement_tree)
{
if (!vec_safe_is_empty(f_binding_level->defers))
{
append_to_statement_list(statement_tree, &f_binding_level->defers->begin()->try_statements);
}
else
{ {
append_to_statement_list(statement_tree, &f_binding_level->statement_list); append_to_statement_list(statement_tree, &f_binding_level->statement_list);
} }
}
void defer(tree statement_tree)
{
defer_scope new_defer{ statement_tree, alloc_stmt_list() };
vec_safe_insert(f_binding_level->defers, 0, new_defer);
}
tree chain_defer()
{
if (vec_safe_is_empty(f_binding_level->defers))
{
return f_binding_level->statement_list;
}
defer_scope *defer_iterator = f_binding_level->defers->begin();
tree defer_tree = build2(TRY_FINALLY_EXPR, void_type_node,
defer_iterator->try_statements, defer_iterator->defer_block);
int i;
FOR_EACH_VEC_ELT_FROM(*f_binding_level->defers, i, defer_iterator, 1)
{
append_to_statement_list(defer_tree, &defer_iterator->try_statements);
defer_tree = build2(TRY_FINALLY_EXPR, void_type_node,
defer_iterator->try_statements, defer_iterator->defer_block);
}
return build2(COMPOUND_EXPR, TREE_TYPE(defer_tree), f_binding_level->statement_list, defer_tree);
}
tree build_field(location_t location, tree record_type, const std::string name, tree type) tree build_field(location_t location, tree record_type, const std::string name, tree type)
{ {

View File

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

View File

@ -63,25 +63,23 @@ namespace boot
class assign_statement; class assign_statement;
class if_statement; class if_statement;
class while_statement; class while_statement;
class return_statement;
class traits_expression; class traits_expression;
class block; class block;
class program; class program;
class binary_expression; class binary_expression;
class unary_expression; class unary_expression;
class primitive_type_expression; class basic_type;
class array_type_expression; class array_type;
class pointer_type_expression; class pointer_type;
class record_type_expression; class record_type;
class union_type_expression; class union_type;
class procedure_type_expression; class procedure_type;
class variable_expression; class variable_expression;
class array_access_expression; class array_access_expression;
class field_access_expression; class field_access_expression;
class dereference_expression; class dereference_expression;
template<typename T> template<typename T>
class number_literal; class number_literal;
class defer_statement;
/** /**
* Interface for AST visitors. * Interface for AST visitors.
@ -98,22 +96,20 @@ namespace boot
virtual void visit(assign_statement *) = 0; virtual void visit(assign_statement *) = 0;
virtual void visit(if_statement *) = 0; virtual void visit(if_statement *) = 0;
virtual void visit(while_statement *) = 0; virtual void visit(while_statement *) = 0;
virtual void visit(return_statement *) = 0;
virtual void visit(defer_statement *) = 0;
virtual void visit(block *) = 0; virtual void visit(block *) = 0;
virtual void visit(program *) = 0; virtual void visit(program *) = 0;
virtual void visit(binary_expression *) = 0; virtual void visit(binary_expression *) = 0;
virtual void visit(unary_expression *) = 0; virtual void visit(unary_expression *) = 0;
virtual void visit(primitive_type_expression *) = 0; virtual void visit(basic_type *) = 0;
virtual void visit(array_type_expression *) = 0; virtual void visit(array_type *) = 0;
virtual void visit(pointer_type_expression *) = 0; virtual void visit(pointer_type *) = 0;
virtual void visit(record_type_expression *) = 0; virtual void visit(record_type *) = 0;
virtual void visit(union_type_expression *) = 0; virtual void visit(union_type *) = 0;
virtual void visit(procedure_type_expression *) = 0; virtual void visit(procedure_type *) = 0;
virtual void visit(variable_expression *) = 0; virtual void visit(variable_expression *) = 0;
virtual void visit(array_access_expression *) = 0; virtual void visit(array_access_expression *) = 0;
virtual void visit(field_access_expression *) = 0; virtual void visit(field_access_expression *is_field_access) = 0;
virtual void visit(dereference_expression *) = 0; virtual void visit(dereference_expression *is_dereference) = 0;
virtual void visit(number_literal<std::int32_t> *) = 0; virtual void visit(number_literal<std::int32_t> *) = 0;
virtual void visit(number_literal<std::uint32_t> *) = 0; virtual void visit(number_literal<std::uint32_t> *) = 0;
virtual void visit(number_literal<double> *) = 0; virtual void visit(number_literal<double> *) = 0;
@ -129,31 +125,29 @@ namespace boot
struct empty_visitor : parser_visitor struct empty_visitor : parser_visitor
{ {
virtual void visit(variable_declaration *) override; virtual void visit(variable_declaration *) override;
virtual void visit(constant_definition *) override; virtual void visit(constant_definition *definition) override;
virtual void visit(procedure_definition *) override; virtual void visit(procedure_definition *definition) override;
virtual void visit(type_definition *) override; virtual void visit(type_definition *definition) override;
virtual void visit(traits_expression *) override; virtual void visit(traits_expression *trait) override;
virtual void visit(procedure_call *) override; virtual void visit(procedure_call *call) override;
virtual void visit(cast_expression *) override; virtual void visit(cast_expression *expression) override;
virtual void visit(assign_statement *) override; virtual void visit(assign_statement *statement) override;
virtual void visit(if_statement *) override; virtual void visit(if_statement *) override;
virtual void visit(while_statement *) override; virtual void visit(while_statement *) override;
virtual void visit(return_statement *) override; virtual void visit(block *block) override;
virtual void visit(defer_statement *) override; virtual void visit(program *program) override;
virtual void visit(block *) override; virtual void visit(binary_expression *expression) override;
virtual void visit(program *) override; virtual void visit(unary_expression *expression) override;
virtual void visit(binary_expression *) override; virtual void visit(basic_type *) override;
virtual void visit(unary_expression *) override; virtual void visit(array_type *expression) override;
virtual void visit(primitive_type_expression *) override; virtual void visit(pointer_type *) override;
virtual void visit(array_type_expression *) override; virtual void visit(record_type *expression) override;
virtual void visit(pointer_type_expression *) override; virtual void visit(union_type *expression) override;
virtual void visit(record_type_expression *) override; virtual void visit(procedure_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(variable_expression *) override;
virtual void visit(array_access_expression *) override; virtual void visit(array_access_expression *expression) override;
virtual void visit(field_access_expression *) override; virtual void visit(field_access_expression *expression) override;
virtual void visit(dereference_expression *) override; virtual void visit(dereference_expression *expression) override;
virtual void visit(number_literal<std::int32_t> *) override; virtual void visit(number_literal<std::int32_t> *) override;
virtual void visit(number_literal<std::uint32_t> *) override; virtual void visit(number_literal<std::uint32_t> *) override;
virtual void visit(number_literal<double> *) override; virtual void visit(number_literal<double> *) override;
@ -214,16 +208,24 @@ namespace boot
/** /**
* Some type expression. * Some type expression.
*/ */
class type_expression : public node, public std::enable_shared_from_this<type_expression> class top_type : public node, public std::enable_shared_from_this<top_type>
{ {
public:
virtual std::shared_ptr<basic_type> is_basic();
virtual std::shared_ptr<array_type> is_array();
virtual std::shared_ptr<pointer_type> is_pointer();
virtual std::shared_ptr<record_type> is_record();
virtual std::shared_ptr<union_type> is_union();
virtual std::shared_ptr<procedure_type> is_procedure();
protected: protected:
type_expression(const struct position position); top_type(const struct position position);
}; };
/** /**
* Expression defining a basic type. * Expression defining a basic type.
*/ */
class primitive_type_expression : public type_expression class basic_type : public top_type
{ {
const std::string m_name; const std::string m_name;
@ -232,58 +234,65 @@ namespace boot
* \param position Source code position. * \param position Source code position.
* \param name Type name. * \param name Type name.
*/ */
primitive_type_expression(const struct position position, const std::string& name); basic_type(const struct position position, const std::string& name);
virtual void accept(parser_visitor *visitor) override; virtual void accept(parser_visitor *visitor) override;
const std::string& base_name(); const std::string& base_name();
std::shared_ptr<basic_type> is_basic() override;
}; };
class array_type_expression : public type_expression class array_type : public top_type
{ {
std::shared_ptr<type_expression> m_base; std::shared_ptr<top_type> m_base;
public: public:
const std::uint32_t size; const std::uint32_t size;
array_type_expression(const struct position position, array_type(const struct position position, std::shared_ptr<top_type> base, const std::uint32_t size);
std::shared_ptr<type_expression> base, const std::uint32_t size);
virtual void accept(parser_visitor *visitor) override; virtual void accept(parser_visitor *visitor) override;
type_expression& base(); top_type& base();
std::shared_ptr<array_type> is_array() override;
}; };
class pointer_type_expression : public type_expression class pointer_type : public top_type
{ {
std::shared_ptr<type_expression> m_base; std::shared_ptr<top_type> m_base;
public: public:
pointer_type_expression(const struct position position, std::shared_ptr<type_expression> base); pointer_type(const struct position position, std::shared_ptr<top_type> base);
virtual void accept(parser_visitor *visitor) override; virtual void accept(parser_visitor *visitor) override;
type_expression& base(); top_type& base();
std::shared_ptr<pointer_type> is_pointer() override;
}; };
using field_t = std::pair<std::string, std::shared_ptr<type_expression>>; using field_t = std::pair<std::string, std::shared_ptr<top_type>>;
using fields_t = std::vector<field_t>; using fields_t = std::vector<field_t>;
class record_type_expression : public type_expression class record_type : public top_type
{ {
public: public:
fields_t fields; fields_t fields;
record_type_expression(const struct position position, fields_t&& fields); record_type(const struct position position, fields_t&& fields);
virtual void accept(parser_visitor *visitor) override; virtual void accept(parser_visitor *visitor) override;
std::shared_ptr<record_type> is_record() override;
}; };
class union_type_expression : public type_expression class union_type : public top_type
{ {
public: public:
fields_t fields; fields_t fields;
union_type_expression(const struct position position, fields_t&& fields); union_type(const struct position position, fields_t&& fields);
virtual void accept(parser_visitor *visitor) override; virtual void accept(parser_visitor *visitor) override;
std::shared_ptr<union_type> is_union() override;
}; };
/** /**
@ -291,14 +300,14 @@ namespace boot
*/ */
class variable_declaration : public definition class variable_declaration : public definition
{ {
std::shared_ptr<type_expression> m_type; std::shared_ptr<top_type> m_type;
public: public:
variable_declaration(const struct position position, const std::string& identifier, variable_declaration(const struct position position, const std::string& identifier,
std::shared_ptr<type_expression> type, const bool exported = false); std::shared_ptr<top_type> type, const bool exported = false);
virtual void accept(parser_visitor *visitor) override; virtual void accept(parser_visitor *visitor) override;
type_expression& variable_type(); top_type& variable_type();
}; };
/** /**
@ -343,20 +352,20 @@ namespace boot
/** /**
* Procedure type. * Procedure type.
*/ */
class procedure_type_expression : public type_expression class procedure_type : public top_type
{ {
public: public:
const std::shared_ptr<type_expression> return_type; const std::shared_ptr<top_type> return_type;
const bool no_return; const bool no_return;
std::vector<variable_declaration *> parameters; std::vector<variable_declaration *> parameters;
procedure_type_expression(const struct position position, procedure_type(const struct position position, std::shared_ptr<top_type> return_type = nullptr);
std::shared_ptr<type_expression> return_type = nullptr); procedure_type(const struct position position, no_return_t);
procedure_type_expression(const struct position position, no_return_t);
virtual void accept(parser_visitor *visitor) override; virtual void accept(parser_visitor *visitor) override;
std::shared_ptr<procedure_type> is_procedure() override;
virtual ~procedure_type_expression() override; virtual ~procedure_type() override;
}; };
/** /**
@ -364,16 +373,18 @@ namespace boot
*/ */
class procedure_definition : public definition class procedure_definition : public definition
{ {
std::shared_ptr<procedure_type_expression> m_heading; std::shared_ptr<procedure_type> m_heading;
public: public:
block *const body; block *const body;
expression *const returning;
procedure_definition(const struct position position, const std::string& identifier, procedure_definition(const struct position position, const std::string& identifier,
const bool exported, std::shared_ptr<procedure_type_expression> heading, block *body = nullptr); const bool exported, std::shared_ptr<procedure_type> heading,
block *const body = nullptr, expression *const returning = nullptr);
virtual void accept(parser_visitor *visitor) override; virtual void accept(parser_visitor *visitor) override;
procedure_type_expression& heading(); procedure_type& heading();
virtual ~procedure_definition() override; virtual ~procedure_definition() override;
}; };
@ -383,14 +394,14 @@ namespace boot
*/ */
class type_definition : public definition class type_definition : public definition
{ {
std::shared_ptr<type_expression> m_body; std::shared_ptr<top_type> m_body;
public: public:
type_definition(const struct position position, const std::string& identifier, type_definition(const struct position position, const std::string& identifier,
const bool exported, std::shared_ptr<type_expression> expression); const bool exported, std::shared_ptr<top_type> expression);
virtual void accept(parser_visitor *visitor) override; virtual void accept(parser_visitor *visitor) override;
type_expression& body(); top_type& body();
}; };
/** /**
@ -398,14 +409,14 @@ namespace boot
*/ */
class cast_expression : public expression class cast_expression : public expression
{ {
std::shared_ptr<type_expression> m_target; std::shared_ptr<top_type> m_target;
expression *m_value; expression *m_value;
public: public:
cast_expression(const struct position position, std::shared_ptr<type_expression> target, expression *value); cast_expression(const struct position position, std::shared_ptr<top_type> target, expression *value);
virtual void accept(parser_visitor *visitor) override; virtual void accept(parser_visitor *visitor) override;
type_expression& target(); top_type& target();
expression& value(); expression& value();
virtual ~cast_expression() override; virtual ~cast_expression() override;
@ -413,16 +424,15 @@ namespace boot
class traits_expression : public expression class traits_expression : public expression
{ {
std::shared_ptr<type_expression> m_type; std::shared_ptr<top_type> m_type;
public: public:
const std::string name; const std::string name;
traits_expression(const struct position position, const std::string& name, traits_expression(const struct position position, const std::string& name, std::shared_ptr<top_type> type);
std::shared_ptr<type_expression> type);
virtual void accept(parser_visitor *visitor) override; virtual void accept(parser_visitor *visitor) override;
type_expression& type(); top_type& type();
}; };
/** /**
@ -442,19 +452,6 @@ namespace boot
virtual ~conditional_statements(); virtual ~conditional_statements();
}; };
class return_statement : public statement
{
expression *m_return_expression{ nullptr };
public:
return_statement(const struct position position, expression *return_expression);
virtual void accept(parser_visitor *visitor) override;
expression *return_expression();
virtual ~return_statement() override;
};
class designator_expression : public expression class designator_expression : public expression
{ {
public: public:
@ -647,17 +644,6 @@ namespace boot
} }
}; };
class defer_statement : public statement
{
public:
std::vector<statement *> statements;
defer_statement(const struct position position);
virtual void accept(parser_visitor *visitor) override;
virtual ~defer_statement() override;
};
class binary_expression : public expression class binary_expression : public expression
{ {
expression *m_lhs; expression *m_lhs;

View File

@ -1,37 +0,0 @@
/* 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 name_analysis_visitor : public empty_visitor
{
std::shared_ptr<symbol_table<>> table;
public:
name_analysis_visitor(std::shared_ptr<symbol_table<>> table);
void visit(program *program) override;
};
}
}

View File

@ -26,27 +26,10 @@ namespace elna
{ {
namespace boot namespace boot
{ {
class type
{
virtual ~type() = 0;
protected:
type() = default;
};
class info
{
public:
virtual ~info() = 0;
protected:
info() = default;
};
/** /**
* Symbol table. * Symbol table.
*/ */
template<typename T = std::shared_ptr<info>, typename U = std::nullptr_t, U nothing = nullptr> template<typename T, T nothing>
class symbol_table class symbol_table
{ {
public: public:

View File

@ -40,7 +40,8 @@ namespace gcc
std::shared_ptr<symbol_table> symbol_map; std::shared_ptr<symbol_table> symbol_map;
tree build_label_decl(const char *name, location_t loc); tree build_label_decl(const char *name, location_t loc);
tree build_procedure_type(boot::procedure_type_expression& type); tree build_procedure_type(boot::procedure_type& type);
tree build_type(boot::top_type& type);
void enter_scope(); void enter_scope();
tree leave_scope(); tree leave_scope();
@ -60,6 +61,7 @@ namespace gcc
void build_record_call(location_t call_location, void build_record_call(location_t call_location,
tree symbol, const std::vector<boot::expression *>& arguments); tree symbol, const std::vector<boot::expression *>& arguments);
void visit_statements(const std::vector<boot::statement *>& statements); void visit_statements(const std::vector<boot::statement *>& statements);
void visit_return(boot::expression *const return_expression);
public: public:
generic_visitor(std::shared_ptr<symbol_table> symbol_table); generic_visitor(std::shared_ptr<symbol_table> symbol_table);
@ -89,14 +91,6 @@ namespace gcc
void visit(boot::assign_statement *statement) override; void visit(boot::assign_statement *statement) override;
void visit(boot::if_statement *statement) override; void visit(boot::if_statement *statement) override;
void visit(boot::while_statement *statement) override; void visit(boot::while_statement *statement) 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 namespace gcc
{ {
using symbol_table = boot::symbol_table<tree, tree, NULL_TREE>; using symbol_table = boot::symbol_table<tree, NULL_TREE>;
bool is_pointer_type(tree type); bool is_pointer_type(tree type);
bool is_integral_type(tree type); bool is_integral_type(tree type);
@ -72,8 +72,6 @@ namespace gcc
bool is_assignable_from(tree assignee, tree assignment); bool is_assignable_from(tree assignee, tree assignment);
void append_statement(tree statement_tree); void append_statement(tree statement_tree);
void defer(tree statement_tree);
tree chain_defer();
tree do_pointer_arithmetic(boot::binary_operator binary_operator, tree left, tree right); tree do_pointer_arithmetic(boot::binary_operator binary_operator, tree left, tree right);
tree build_binary_operation(bool condition, boot::binary_expression *expression, tree build_binary_operation(bool condition, boot::binary_expression *expression,

View File

@ -58,12 +58,6 @@ struct GTY (()) lang_decl
{ {
}; };
struct GTY (()) defer_scope
{
tree defer_block;
tree try_statements;
};
struct GTY ((chain_next ("%h.level_chain"))) binding_level struct GTY ((chain_next ("%h.level_chain"))) binding_level
{ {
// A block chain is needed to call defer statements beloning to each block. // A block chain is needed to call defer statements beloning to each block.
@ -74,9 +68,6 @@ struct GTY ((chain_next ("%h.level_chain"))) binding_level
// Statements before the first defer has been seen. // Statements before the first defer has been seen.
tree statement_list; tree statement_list;
// Defer statement coupled with statements following it.
vec<defer_scope, va_gc> *defers;
}; };
struct GTY (()) language_function struct GTY (()) language_function

View File

@ -140,7 +140,6 @@ proc exit(code: Int) -> !; extern
Standard procedures. Standard procedures.
*) *)
proc reallocarray(ptr: ^Byte, n: Word, size: Word) -> ^Byte; proc reallocarray(ptr: ^Byte, n: Word, size: Word) -> ^Byte;
begin
return realloc(ptr, n * size) return realloc(ptr, n * size)
end end
@ -198,32 +197,26 @@ begin
end end
proc is_digit(c: Char) -> Bool; proc is_digit(c: Char) -> Bool;
begin
return cast(c: Int) >= cast('0': Int) and cast(c: Int) <= cast('9': Int) return cast(c: Int) >= cast('0': Int) and cast(c: Int) <= cast('9': Int)
end end
proc is_alpha(c: Char) -> Bool; proc is_alpha(c: Char) -> Bool;
begin
return cast(c: Int) >= cast('A': Int) and cast(c: Int) <= cast('z': Int) return cast(c: Int) >= cast('A': Int) and cast(c: Int) <= cast('z': Int)
end end
proc is_alnum(c: Char) -> Bool; proc is_alnum(c: Char) -> Bool;
begin
return is_digit(c) or is_alpha(c) return is_digit(c) or is_alpha(c)
end end
proc is_space(c: Char) -> Bool; proc is_space(c: Char) -> Bool;
begin
return c = ' ' or c = '\n' or c = '\t' return c = ' ' or c = '\n' or c = '\t'
end end
proc substring(string: String, start: Word, count: Word) -> String; proc substring(string: String, start: Word, count: Word) -> String;
begin
return String(string.ptr + start, count) return String(string.ptr + start, count)
end end
proc open_substring(string: String, start: Word) -> String; proc open_substring(string: String, start: Word) -> String;
begin
return substring(string, start, string.length - start) return substring(string, start, string.length - start)
end end
@ -277,7 +270,6 @@ end
*) *)
proc make_position() -> Position; proc make_position() -> Position;
begin
return Position(1u, 1u) return Position(1u, 1u)
end end
@ -293,7 +285,7 @@ begin
result^.handle := file_handle; result^.handle := file_handle;
result^.size := 0u; result^.size := 0u;
result^.index := 1u result^.index := 1u
end; end
return result return result
end end
@ -352,7 +344,7 @@ begin
if source_file^.index > source_file^.size then if source_file^.index > source_file^.size then
source_file^.size := fread(cast(@source_file^.buffer: ^Byte), 1u, 1024u, source_file^.handle); source_file^.size := fread(cast(@source_file^.buffer: ^Byte), 1u, 1024u, source_file^.handle);
source_file^.index := 1u source_file^.index := 1u
end; end
return source_file^.size = 0u return source_file^.size = 0u
end end
@ -376,12 +368,10 @@ begin
end end
proc source_code_empty(source_code: ^SourceCode) -> Bool; proc source_code_empty(source_code: ^SourceCode) -> Bool;
begin
return source_code^.empty(source_code^.input) return source_code^.empty(source_code^.input)
end end
proc source_code_head(source_code: SourceCode) -> Char; proc source_code_head(source_code: SourceCode) -> Char;
begin
return source_code.head(source_code.input) return source_code.head(source_code.input)
end end
@ -398,7 +388,6 @@ begin
end end
proc source_code_expect(source_code: ^SourceCode, expected: Char) -> Bool; proc source_code_expect(source_code: ^SourceCode, expected: Char) -> Bool;
begin
return not source_code_empty(source_code) and source_code_head(source_code^) = expected return not source_code_empty(source_code) and source_code_head(source_code^) = expected
end end
@ -413,7 +402,6 @@ begin
end end
proc is_ident(char: Char) -> Bool; proc is_ident(char: Char) -> Bool;
begin
return is_alnum(char) or char = '_' return is_alnum(char) or char = '_'
end end
@ -445,7 +433,7 @@ begin
trailing := 0u trailing := 0u
end; end;
source_code_advance(source_code) source_code_advance(source_code)
end; end
return trailing = 2u return trailing = 2u
end end
@ -468,7 +456,7 @@ begin
end; end;
if successful then if successful then
source_code_advance(source_code) source_code_advance(source_code)
end; end
return successful return successful
end end
@ -493,7 +481,7 @@ begin
source_code_advance(source_code) source_code_advance(source_code)
else else
is_valid := false is_valid := false
end; end
return is_valid return is_valid
end end
@ -722,7 +710,7 @@ begin
else else
current_token.kind := TOKEN_IDENTIFIER; current_token.kind := TOKEN_IDENTIFIER;
current_token.value.string := string_dup(token_content) current_token.value.string := string_dup(token_content)
end; end
return current_token return current_token
end end
@ -899,7 +887,7 @@ begin
write_c(first_char); write_c(first_char);
write_s("\".\n") write_s("\".\n")
end end
end; end
return tokens return tokens
end end
@ -916,7 +904,7 @@ begin
result^.syntax_tree := false; result^.syntax_tree := false;
result^.input := nil; result^.input := nil;
while i < argc do while i < argc and result <> nil do
parameter := argv + i; parameter := argv + i;
if strcmp(parameter^, "--tokenize\0".ptr) = 0 then if strcmp(parameter^, "--tokenize\0".ptr) = 0 then
@ -932,15 +920,15 @@ begin
write_z(parameter^); write_z(parameter^);
write_s(".\n"); write_s(".\n");
return nil result := nil
end; end;
i := i + 1 i := i + 1
end; end;
if result^.input = nil then if result <> nil and result^.input = nil then
write_s("Fatal error: no input files.\n"); write_s("Fatal error: no input files.\n");
return nil result := nil
end; end
return result return result
end end
@ -981,7 +969,7 @@ begin
if command_line^.tokenize then if command_line^.tokenize then
print_tokens(tokens, tokens_size) print_tokens(tokens, tokens_size)
end end
end; end
return return_code return return_code
end end