Type check the return statement

This commit is contained in:
2025-03-25 11:29:29 +01:00
parent c022805c53
commit d359056354
13 changed files with 483 additions and 477 deletions

View File

@ -33,14 +33,6 @@ namespace elna::boot
return this->source_position;
}
statement::statement()
{
}
statement::~statement()
{
}
assign_statement *statement::is_assign()
{
return nullptr;
@ -71,14 +63,6 @@ namespace elna::boot
return nullptr;
}
expression::expression()
{
}
expression::~expression()
{
}
cast_expression *expression::is_cast()
{
return nullptr;
@ -114,39 +98,6 @@ namespace elna::boot
return nullptr;
}
void expression::accept(parser_visitor *visitor)
{
if (cast_expression *node = is_cast())
{
return node->accept(visitor);
}
else if (traits_expression *node = is_traits())
{
return node->accept(visitor);
}
else if (binary_expression *node = is_binary())
{
return node->accept(visitor);
}
else if (unary_expression *node = is_unary())
{
return node->accept(visitor);
}
else if (designator_expression *node = is_designator())
{
return node->accept(visitor);
}
else if (procedure_call *node = is_call_expression())
{
return node->accept(visitor);
}
else if (literal_expression *node = is_literal())
{
return node->accept(visitor);
}
__builtin_unreachable();
}
type_expression::type_expression(const struct position position)
: node(position)
{
@ -182,35 +133,6 @@ namespace elna::boot
return nullptr;
}
void type_expression::accept(parser_visitor *visitor)
{
if (std::shared_ptr<primitive_type_expression> node = is_primitive())
{
return node->accept(visitor);
}
else if (std::shared_ptr<array_type_expression> node = is_array())
{
return node->accept(visitor);
}
else if (std::shared_ptr<pointer_type_expression> node = is_pointer())
{
return node->accept(visitor);
}
else if (std::shared_ptr<record_type_expression> node = is_record())
{
return node->accept(visitor);
}
else if (std::shared_ptr<union_type_expression> node = is_union())
{
return node->accept(visitor);
}
else if (std::shared_ptr<procedure_type_expression> node = is_procedure())
{
return node->accept(visitor);
}
__builtin_unreachable();
}
primitive_type_expression::primitive_type_expression(const struct position position, const std::string& name)
: type_expression(position), name(name)
{
@ -301,8 +223,8 @@ namespace elna::boot
}
variable_declaration::variable_declaration(const struct position position, const std::string& identifier,
std::shared_ptr<type_expression> type, const bool exported)
: definition(position, identifier, exported), m_type(type)
std::shared_ptr<type_expression> variable_type, const bool exported)
: definition(position, identifier, exported), m_variable_type(variable_type)
{
}
@ -313,7 +235,7 @@ namespace elna::boot
type_expression& variable_declaration::variable_type()
{
return *m_type;
return *m_variable_type;
}
definition::definition(const struct position position, const std::string& identifier, const bool exported)
@ -462,47 +384,16 @@ namespace elna::boot
return this;
}
void literal_expression::accept(parser_visitor *visitor)
{
if (literal<std::int32_t> *node = is_int())
{
return node->accept(visitor);
}
else if (literal<std::uint32_t> *node = is_word())
{
return node->accept(visitor);
}
else if (literal<double> *node = is_float())
{
return node->accept(visitor);
}
else if (literal<bool> *node = is_bool())
{
return node->accept(visitor);
}
else if (literal<unsigned char> *node = is_char())
{
return node->accept(visitor);
}
else if (literal<std::nullptr_t> *node = is_nil())
{
return node->accept(visitor);
}
else if (literal<std::string> *node = is_string())
{
return node->accept(visitor);
}
else
{
__builtin_unreachable();
}
}
defer_statement::defer_statement(const struct position position)
: node(position)
{
}
void defer_statement::accept(parser_visitor *visitor)
{
visitor->visit(this);
}
defer_statement *defer_statement::is_defer()
{
return this;
@ -529,11 +420,37 @@ namespace elna::boot
return this;
}
void designator_expression::accept(parser_visitor *visitor)
{
if (variable_expression *node = is_variable())
{
return visitor->visit(node);
}
else if (array_access_expression *node = is_array_access())
{
return visitor->visit(node);
}
else if (field_access_expression *node = is_field_access())
{
return visitor->visit(node);
}
else if (dereference_expression *node = is_dereference())
{
return visitor->visit(node);
}
__builtin_unreachable();
}
variable_expression::variable_expression(const struct position position, const std::string& name)
: node(position), name(name)
{
}
void variable_expression::accept(parser_visitor *visitor)
{
visitor->visit(this);
}
variable_expression *variable_expression::is_variable()
{
return this;
@ -545,6 +462,11 @@ namespace elna::boot
{
}
void array_access_expression::accept(parser_visitor *visitor)
{
visitor->visit(this);
}
expression& array_access_expression::index()
{
return *m_index;
@ -572,6 +494,11 @@ namespace elna::boot
{
}
void field_access_expression::accept(parser_visitor *visitor)
{
visitor->visit(this);
}
expression& field_access_expression::base()
{
return *m_base;
@ -598,6 +525,11 @@ namespace elna::boot
{
}
void dereference_expression::accept(parser_visitor *visitor)
{
visitor->visit(this);
}
expression& dereference_expression::base()
{
return *m_base;
@ -686,6 +618,11 @@ namespace elna::boot
{
}
void procedure_call::accept(parser_visitor *visitor)
{
visitor->visit(this);
}
procedure_call *procedure_call::is_call_statement()
{
return this;
@ -780,6 +717,11 @@ namespace elna::boot
{
}
void return_statement::accept(parser_visitor *visitor)
{
visitor->visit(this);
}
return_statement *return_statement::is_return()
{
return this;
@ -801,6 +743,11 @@ namespace elna::boot
{
}
void assign_statement::accept(parser_visitor *visitor)
{
visitor->visit(this);
}
assign_statement *assign_statement::is_assign()
{
return this;
@ -847,6 +794,11 @@ namespace elna::boot
{
}
void if_statement::accept(parser_visitor *visitor)
{
visitor->visit(this);
}
if_statement *if_statement::is_if()
{
return this;
@ -877,6 +829,11 @@ namespace elna::boot
{
}
void while_statement::accept(parser_visitor *visitor)
{
visitor->visit(this);
}
while_statement *while_statement::is_while()
{
return this;

View File

@ -286,10 +286,15 @@ if_statement:
$$ = new boot::if_statement(boot::make_position(@1), then, _else);
std::swap($5, $$->branches);
}
return_statement: "return" expression
return_statement:
"return" expression
{
$$ = new boot::return_statement(boot::make_position(@1), $2);
}
| "return"
{
$$ = new boot::return_statement(boot::make_position(@1));
}
defer_statement: DEFER statements "end"
{
$$ = new boot::defer_statement(boot::make_position(@1));
@ -472,9 +477,9 @@ statements:
field_declaration:
IDENTIFIER ":" type_expression { $$ = std::make_pair($1, $3); }
required_fields:
field_declaration required_fields
field_declaration ";" required_fields
{
std::swap($$, $2);
std::swap($$, $3);
$$.emplace($$.cbegin(), $1);
}
| field_declaration { $$.emplace_back($1); }
@ -534,14 +539,14 @@ constant_definition: identifier_definition "=" literal
$$ = new boot::constant_definition(boot::make_position(@1), $1.first, $1.second, $3);
}
constant_definitions:
constant_definition constant_definitions
constant_definition ";" constant_definitions
{
std::swap($$, $2);
std::swap($$, $3);
$$.insert($$.cbegin(), $1);
}
| /* no constant definitions */ {}
constant_part:
{}
/* no constant definitions */ {}
| "const" constant_definitions { std::swap($$, $2); }
type_definition: identifier_definition "=" type_expression
{
@ -553,10 +558,9 @@ type_definitions:
std::swap($$, $2);
$$.insert($$.cbegin(), $1);
}
| type_definition { $$.push_back($1); }
| /* no type definitions */ {}
type_part:
/* no type definitions */ {}
| "type" {}
| "type" type_definitions { std::swap($$, $2); }
formal_parameter: IDENTIFIER ":" type_expression
{

View File

@ -65,6 +65,18 @@ namespace elna::boot
auto info = std::make_shared<type_info>(type_info(type(unresolved.second)));
this->symbols->enter(std::move(unresolved.first), info);
}
for (variable_declaration *const variable : program->variables)
{
variable->accept(this);
}
for (procedure_definition *const procedure : program->procedures)
{
procedure->accept(this);
}
for (statement *const statement : program->body)
{
statement->accept(this);
}
}
void declaration_visitor::visit(type_definition *definition)
@ -106,142 +118,219 @@ namespace elna::boot
this->current_type = type(std::make_shared<array_type>(this->current_type, type_expression->size));
}
void declaration_visitor::visit(record_type_expression *)
void declaration_visitor::visit(record_type_expression *type_expression)
{
this->current_type = type(std::make_shared<record_type>());
auto result_type = std::make_shared<record_type>();
for (auto& field : type_expression->fields)
{
field.second->accept(this);
result_type->fields.push_back(std::make_pair(field.first, this->current_type));
}
this->current_type = type(result_type);
}
void declaration_visitor::visit(union_type_expression *)
void declaration_visitor::visit(union_type_expression *type_expression)
{
this->current_type = type(std::make_shared<union_type>());
auto result_type = std::make_shared<union_type>();
for (auto& field : type_expression->fields)
{
field.second->accept(this);
result_type->fields.push_back(std::make_pair(field.first, this->current_type));
}
this->current_type = type(result_type);
}
void declaration_visitor::visit(procedure_type_expression *)
{
}
void declaration_visitor::visit(variable_declaration *)
void declaration_visitor::visit(variable_declaration *declaration)
{
__builtin_unreachable();
declaration->variable_type().accept(this);
}
void declaration_visitor::visit(constant_definition *)
{
__builtin_unreachable();
}
void declaration_visitor::visit(procedure_definition *)
void declaration_visitor::visit(procedure_definition *definition)
{
__builtin_unreachable();
for (auto heading_parameter : definition->heading().parameters)
{
heading_parameter->accept(this);
}
if (definition->heading().return_type.type != nullptr)
{
definition->heading().return_type.type->accept(this);
}
if (definition->body != nullptr)
{
definition->body->accept(this);
}
}
void declaration_visitor::visit(assign_statement *)
void declaration_visitor::visit(assign_statement *statement)
{
__builtin_unreachable();
statement->lvalue().accept(this);
statement->rvalue().accept(this);
}
void declaration_visitor::visit(if_statement *)
void declaration_visitor::visit(if_statement *statement)
{
__builtin_unreachable();
statement->body().prerequisite().accept(this);
for (struct statement *const statement : statement->body().statements)
{
statement->accept(this);
}
for (const auto branch : statement->branches)
{
branch->prerequisite().accept(this);
for (struct statement *const statement : branch->statements)
{
statement->accept(this);
}
}
if (statement->alternative() != nullptr)
{
for (struct statement *const statement : *statement->alternative())
{
statement->accept(this);
}
}
}
void declaration_visitor::visit(while_statement *)
void declaration_visitor::visit(while_statement *statement)
{
__builtin_unreachable();
statement->body().prerequisite().accept(this);
for (struct statement *const statement : statement->body().statements)
{
statement->accept(this);
}
for (const auto branch : statement->branches)
{
branch->prerequisite().accept(this);
for (struct statement *const statement : branch->statements)
{
statement->accept(this);
}
}
}
void declaration_visitor::visit(return_statement *)
void declaration_visitor::visit(return_statement *statement)
{
__builtin_unreachable();
if (statement->return_expression() != nullptr)
{
statement->return_expression()->accept(this);
}
}
void declaration_visitor::visit(defer_statement *)
void declaration_visitor::visit(defer_statement *statement)
{
__builtin_unreachable();
for (struct statement *const statement : statement->statements)
{
statement->accept(this);
}
}
void declaration_visitor::visit(procedure_call *)
void declaration_visitor::visit(procedure_call *call)
{
__builtin_unreachable();
call->callable().accept(this);
for (expression *const argument: call->arguments)
{
argument->accept(this);
}
}
void declaration_visitor::visit(block *)
void declaration_visitor::visit(block *block)
{
__builtin_unreachable();
for (constant_definition *const constant : block->constants)
{
constant->accept(this);
}
for (variable_declaration *const variable : block->variables)
{
variable->accept(this);
}
for (statement *const statement : block->body)
{
statement->accept(this);
}
}
void declaration_visitor::visit(traits_expression *)
void declaration_visitor::visit(traits_expression *trait)
{
__builtin_unreachable();
if (!trait->parameters.empty())
{
trait->parameters.front()->accept(this);
}
}
void declaration_visitor::visit(cast_expression *)
void declaration_visitor::visit(cast_expression *expression)
{
__builtin_unreachable();
expression->value().accept(this);
expression->target().accept(this);
}
void declaration_visitor::visit(binary_expression *)
void declaration_visitor::visit(binary_expression *expression)
{
__builtin_unreachable();
expression->lhs().accept(this);
expression->rhs().accept(this);
}
void declaration_visitor::visit(unary_expression *)
void declaration_visitor::visit(unary_expression *expression)
{
__builtin_unreachable();
expression->operand().accept(this);
}
void declaration_visitor::visit(variable_expression *)
{
__builtin_unreachable();
}
void declaration_visitor::visit(array_access_expression *)
void declaration_visitor::visit(array_access_expression *expression)
{
__builtin_unreachable();
expression->base().accept(this);
expression->index().accept(this);
}
void declaration_visitor::visit(field_access_expression *)
void declaration_visitor::visit(field_access_expression *expression)
{
__builtin_unreachable();
expression->base().accept(this);
}
void declaration_visitor::visit(dereference_expression *)
void declaration_visitor::visit(dereference_expression *expression)
{
__builtin_unreachable();
expression->base().accept(this);
}
void declaration_visitor::visit(literal<std::int32_t> *)
{
__builtin_unreachable();
}
void declaration_visitor::visit(literal<std::uint32_t> *)
{
__builtin_unreachable();
}
void declaration_visitor::visit(literal<double> *)
{
__builtin_unreachable();
}
void declaration_visitor::visit(literal<bool> *)
{
__builtin_unreachable();
}
void declaration_visitor::visit(literal<unsigned char> *)
{
__builtin_unreachable();
}
void declaration_visitor::visit(literal<std::nullptr_t> *)
{
__builtin_unreachable();
}
void declaration_visitor::visit(literal<std::string> *)
{
__builtin_unreachable();
}
}