Support else in if then conditions
This commit is contained in:
@ -118,20 +118,25 @@ namespace gcc
|
||||
|
||||
auto expression_location = get_location(&expression->position());
|
||||
tree_code operator_code = ERROR_MARK;
|
||||
tree target_type = error_mark_node;
|
||||
|
||||
switch (expression->operation())
|
||||
{
|
||||
case source::binary_operator::sum:
|
||||
operator_code = PLUS_EXPR;
|
||||
target_type = integer_type_node;
|
||||
break;
|
||||
case source::binary_operator::subtraction:
|
||||
operator_code = MINUS_EXPR;
|
||||
target_type = integer_type_node;
|
||||
break;
|
||||
case source::binary_operator::division:
|
||||
operator_code = TRUNC_DIV_EXPR;
|
||||
target_type = integer_type_node;
|
||||
break;
|
||||
case source::binary_operator::multiplication:
|
||||
operator_code = MULT_EXPR;
|
||||
target_type = integer_type_node;
|
||||
break;
|
||||
}
|
||||
if (operator_code != ERROR_MARK) // An arithmetic operation.
|
||||
@ -150,21 +155,27 @@ namespace gcc
|
||||
{
|
||||
case source::binary_operator::equals:
|
||||
operator_code = EQ_EXPR;
|
||||
target_type = boolean_type_node;
|
||||
break;
|
||||
case source::binary_operator::not_equals:
|
||||
operator_code = NE_EXPR;
|
||||
target_type = boolean_type_node;
|
||||
break;
|
||||
case source::binary_operator::less:
|
||||
operator_code = LT_EXPR;
|
||||
target_type = boolean_type_node;
|
||||
break;
|
||||
case source::binary_operator::greater:
|
||||
operator_code = GT_EXPR;
|
||||
target_type = boolean_type_node;
|
||||
break;
|
||||
case source::binary_operator::less_equal:
|
||||
operator_code = LE_EXPR;
|
||||
target_type = boolean_type_node;
|
||||
break;
|
||||
case source::binary_operator::greater_equal:
|
||||
operator_code = GE_EXPR;
|
||||
target_type = boolean_type_node;
|
||||
break;
|
||||
}
|
||||
if (left_type != right_type)
|
||||
@ -176,8 +187,11 @@ namespace gcc
|
||||
this->current_expression = error_mark_node;
|
||||
return;
|
||||
}
|
||||
gcc_assert(operator_code != ERROR_MARK);
|
||||
gcc_assert(target_type != error_mark_node);
|
||||
|
||||
this->current_expression = build2_loc(expression_location,
|
||||
operator_code, integer_type_node, left, right);
|
||||
operator_code, target_type, left, right);
|
||||
}
|
||||
|
||||
void generic_visitor::visit(source::constant_definition *definition)
|
||||
@ -210,16 +224,25 @@ namespace gcc
|
||||
|
||||
void generic_visitor::visit(source::declaration *declaration)
|
||||
{
|
||||
if (declaration->type().base() != "Int" && declaration->type().base() != "Bool")
|
||||
tree declaration_type = error_mark_node;
|
||||
|
||||
if (declaration->type().base() == "Int")
|
||||
{
|
||||
declaration_type = integer_type_node;
|
||||
}
|
||||
else if (declaration->type().base() == "Bool")
|
||||
{
|
||||
declaration_type = boolean_type_node;
|
||||
}
|
||||
else
|
||||
{
|
||||
error_at(get_location(&declaration->type().position()),
|
||||
"type '%s' not declared",
|
||||
declaration->type().base().c_str());
|
||||
"type '%s' not declared", declaration->type().base().c_str());
|
||||
return;
|
||||
}
|
||||
auto declaration_location = get_location(&declaration->position());
|
||||
tree declaration_tree = build_decl(declaration_location, VAR_DECL,
|
||||
get_identifier(declaration->identifier().c_str()), integer_type_node);
|
||||
get_identifier(declaration->identifier().c_str()), declaration_type);
|
||||
auto result = this->symbol_map.insert({ declaration->identifier(), declaration_tree });
|
||||
|
||||
if (result.second)
|
||||
@ -312,8 +335,21 @@ namespace gcc
|
||||
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->alternative()->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_endif);
|
||||
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,
|
||||
@ -322,6 +358,13 @@ namespace gcc
|
||||
|
||||
statement->body().accept(this);
|
||||
|
||||
if (statement->alternative() != nullptr)
|
||||
{
|
||||
auto else_label_expr = build1(LABEL_EXPR, void_type_node, else_label_decl);
|
||||
append_to_statement_list(else_label_expr, &this->current_statements);
|
||||
|
||||
statement->alternative()->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);
|
||||
|
||||
|
Reference in New Issue
Block a user