Support variable declaration initializer

This commit is contained in:
2025-08-19 22:58:39 +02:00
parent 569139d44a
commit 0c2a396320
10 changed files with 175 additions and 102 deletions

View File

@@ -408,9 +408,10 @@ namespace elna::boot
return this;
}
variable_declaration::variable_declaration(const struct position position, identifier_definition identifier,
std::shared_ptr<type_expression> variable_type)
: declaration(position, identifier), m_variable_type(variable_type)
variable_declaration::variable_declaration(const struct position position,
std::vector<identifier_definition>&& identifier, std::shared_ptr<type_expression> variable_type,
expression *body)
: node(position), m_variable_type(variable_type), identifiers(std::move(identifier)), body(body)
{
}

View File

@@ -53,7 +53,7 @@ namespace elna::boot
if (!declaration_visitor.errors().empty())
{
std::swap(outcome.errors(), parse_driver.errors());
std::swap(outcome.errors(), declaration_visitor.errors());
}
outcome.unresolved = declaration_visitor.unresolved;

View File

@@ -135,7 +135,8 @@ along with GCC; see the file COPYING3. If not see
%type <std::vector<elna::boot::switch_case>> switch_cases;
%type <elna::boot::constant_declaration *> constant_declaration;
%type <std::vector<elna::boot::constant_declaration *>> constant_part constant_declarations;
%type <std::vector<elna::boot::variable_declaration *>> variable_declarations variable_part variable_declaration;
%type <elna::boot::variable_declaration *> variable_declaration;
%type <std::vector<elna::boot::variable_declaration *>> variable_declarations variable_part;
%type <elna::boot::type_expression *> type_expression;
%type <std::vector<elna::boot::type_expression *>> type_expressions;
%type <elna::boot::traits_expression *> traits_expression;
@@ -501,24 +502,23 @@ identifiers:
$$.emplace($$.cbegin(), std::move($1));
}
| IDENTIFIER { $$.emplace_back(std::move($1)); }
variable_declaration: identifier_definitions ":" type_expression ";"
variable_declaration:
identifier_definitions ":" type_expression ";"
{
std::shared_ptr<boot::type_expression> shared_type{ $3 };
for (boot::identifier_definition& identifier : $1)
{
boot::variable_declaration *declaration = new boot::variable_declaration(
boot::make_position(@2), std::move(identifier), shared_type);
$$.push_back(declaration);
}
$$ = new boot::variable_declaration( boot::make_position(@2), std::move($1), shared_type);
}
| identifier_definitions ":" type_expression ":=" expression ";"
{
std::shared_ptr<boot::type_expression> shared_type{ $3 };
$$ = new boot::variable_declaration( boot::make_position(@2), std::move($1), shared_type, $5);
}
variable_declarations:
/* no variable declarations */ {}
| variable_declaration variable_declarations
{
std::swap($$, $1);
$$.reserve($$.size() + $2.size());
$$.insert(std::end($$), std::begin($2), std::end($2));
std::swap($$, $2);
$$.insert(std::cbegin($$), $1);
}
variable_part:
/* no variable declarations */ {}
@@ -531,7 +531,7 @@ constant_declarations:
constant_declaration constant_declarations
{
std::swap($$, $2);
$$.insert($$.cbegin(), $1);
$$.insert(std::cbegin($$), $1);
}
| /* no constant definitions */ {}
constant_part:

View File

@@ -83,6 +83,16 @@ namespace elna::boot
return "Procedure '" + identifier + "' is expected to return, but does not have a return statement";
}
variable_initializer_error::variable_initializer_error(const char *path, const struct position position)
: error(path, position)
{
}
std::string variable_initializer_error::what() const
{
return "Only one variable can be initialized";
}
type_analysis_visitor::type_analysis_visitor(const char *path)
: error_container(path)
{
@@ -289,7 +299,10 @@ namespace elna::boot
{
declaration->variable_type().accept(this);
this->bag.enter(declaration->identifier.identifier, std::make_shared<variable_info>(this->current_type));
for (const auto& variable_identifier : declaration->identifiers)
{
this->bag.enter(variable_identifier.identifier, std::make_shared<variable_info>(this->current_type));
}
}
void name_analysis_visitor::visit(constant_declaration *definition)
@@ -584,5 +597,33 @@ namespace elna::boot
add_error<already_declared_error>(type->identifier.identifier, this->input_file, type->position());
}
}
for (variable_declaration *const variable : unit->variables)
{
variable->accept(this);
}
for (procedure_declaration *const procedure : unit->procedures)
{
procedure->accept(this);
}
}
void declaration_visitor::visit(variable_declaration *declaration)
{
if (declaration->body != nullptr && declaration->identifiers.size() > 1)
{
add_error<variable_initializer_error>(this->input_file, declaration->position());
}
}
void declaration_visitor::visit(procedure_declaration *definition)
{
if (!definition->body.has_value())
{
return;
}
for (boot::variable_declaration *const variable : definition->body.value().variables())
{
variable->accept(this);
}
}
}