Implement elsif

This commit is contained in:
2025-01-27 01:16:27 +01:00
parent 1f7c1b4cb8
commit 6c14e7433b
5 changed files with 71 additions and 60 deletions

View File

@ -733,70 +733,62 @@ namespace gcc
void generic_visitor::visit(source::if_statement *statement)
{
statement->body().prerequisite().accept(this);
tree endif_label_decl = build_label_decl("endif", UNKNOWN_LOCATION);
tree goto_endif = build1(GOTO_EXPR, void_type_node, endif_label_decl);
if (TREE_TYPE(this->current_expression) != boolean_type_node)
make_if_branch(statement->body(), goto_endif);
for (const auto branch : statement->branches)
{
error_at(get_location(&statement->body().prerequisite().position()),
"expected expression of boolean type but its type is %s",
print_type(TREE_TYPE(this->current_expression)));
this->current_expression = error_mark_node;
return;
}
auto then_location = get_location(&statement->position());
auto prerequisite_location = get_location(&statement->body().prerequisite().position());
auto then_label_decl = build_label_decl("then", then_location);
auto endif_label_decl = build_label_decl("end_if", then_location);
auto goto_then = build1_loc(prerequisite_location, GOTO_EXPR,
void_type_node, then_label_decl);
auto goto_endif = build1_loc(prerequisite_location, GOTO_EXPR,
void_type_node, endif_label_decl);
tree else_label_decl = NULL_TREE;
tree goto_else_or_endif = NULL_TREE;
if (statement->alternative() != nullptr)
{
auto else_location = get_location(&statement->position());
else_label_decl = build_label_decl("else", else_location);
goto_else_or_endif = build1_loc(else_location, GOTO_EXPR, void_type_node, else_label_decl);
}
else
{
goto_else_or_endif = goto_endif;
}
auto cond_expr = build3_loc(prerequisite_location, COND_EXPR,
void_type_node, this->current_expression, goto_then, goto_else_or_endif);
append_to_statement_list(cond_expr, &this->current_statements);
auto then_label_expr = build1_loc(then_location, LABEL_EXPR,
void_type_node, then_label_decl);
append_to_statement_list(then_label_expr, &this->current_statements);
for (const auto body_statement : statement->body().statements)
{
body_statement->accept(this);
make_if_branch(*branch, goto_endif);
}
if (statement->alternative() != nullptr)
{
append_to_statement_list(goto_endif, &this->current_statements);
auto else_label_expr = build1(LABEL_EXPR, void_type_node, else_label_decl);
append_to_statement_list(else_label_expr, &this->current_statements);
for (const auto body_statement : *statement->alternative())
{
body_statement->accept(this);
}
}
auto endif_label_expr = build1(LABEL_EXPR, void_type_node, endif_label_decl);
append_to_statement_list(endif_label_expr, &this->current_statements);
tree endif_label_expr = build1(LABEL_EXPR, void_type_node, endif_label_decl);
append_to_statement_list(endif_label_expr, &this->current_statements);
this->current_expression = NULL_TREE;
}
void generic_visitor::make_if_branch(source::conditional_statements& branch, tree goto_endif)
{
branch.prerequisite().accept(this);
if (TREE_TYPE(this->current_expression) != boolean_type_node)
{
error_at(get_location(&branch.prerequisite().position()),
"expected expression of boolean type but its type is %s",
print_type(TREE_TYPE(this->current_expression)));
this->current_expression = error_mark_node;
return;
}
tree then_label_decl = build_label_decl("then", UNKNOWN_LOCATION);
tree goto_then = build1(GOTO_EXPR, void_type_node, then_label_decl);
tree else_label_decl = build_label_decl("else", UNKNOWN_LOCATION);
tree goto_else = build1(GOTO_EXPR, void_type_node, else_label_decl);
auto cond_expr = build3(COND_EXPR, void_type_node, this->current_expression, goto_then, goto_else);
append_to_statement_list(cond_expr, &this->current_statements);
tree then_label_expr = build1(LABEL_EXPR, void_type_node, then_label_decl);
append_to_statement_list(then_label_expr, &this->current_statements);
for (const auto body_statement : branch.statements)
{
body_statement->accept(this);
}
append_to_statement_list(goto_endif, &this->current_statements);
tree else_label_expr = build1(LABEL_EXPR, void_type_node, else_label_decl);
append_to_statement_list(else_label_expr, &this->current_statements);
}
tree generic_visitor::build_label_decl(const char *name, location_t loc)
{
auto label_decl = build_decl(loc,