Add error handling for binary operators

This commit is contained in:
Eugen Wissner 2024-12-28 14:33:35 +01:00
parent d46608b358
commit 02efda5e70
Signed by: belka
GPG Key ID: A27FDC1E8EE902C0
3 changed files with 106 additions and 9 deletions

View File

@ -13,12 +13,37 @@ namespace gcc
{ {
void generic_visitor::visit(source::call_statement *statement) void generic_visitor::visit(source::call_statement *statement)
{ {
empty_visitor::visit(statement); if (statement->name() != "writei")
{
error_at(elna_gcc_location(&statement->position()),
"procedure '%s' not declared",
statement->name().c_str());
return;
}
if (statement->arguments().size() != 1)
{
error_at(elna_gcc_location(&statement->position()),
"procedure '%s' expects 1 argument, %i given",
statement->name().c_str(), statement->arguments().size());
return;
}
auto& argument = statement->arguments().at(0);
argument->accept(this);
auto argument_type = TREE_TYPE(this->current_expression);
auto argument_tree = this->current_expression;
this->current_expression = NULL_TREE;
const char *format_integer = "%d\n"; if (argument_type != integer_type_node)
{
error_at(elna_gcc_location(&argument->position()),
"invalid argument of type %s for procedure %s",
elna_gcc_print_type(argument_type), statement->name().c_str());
return;
}
constexpr const char *format_integer = "%d\n";
tree args[] = { tree args[] = {
build_string_literal(strlen(format_integer) + 1, format_integer), build_string_literal(strlen(format_integer) + 1, format_integer),
this->current_expression argument_tree
}; };
tree fndecl_type_param[] = { tree fndecl_type_param[] = {
build_pointer_type(build_qualified_type(char_type_node, TYPE_QUAL_CONST)) /* const char* */ build_pointer_type(build_qualified_type(char_type_node, TYPE_QUAL_CONST)) /* const char* */
@ -84,11 +109,14 @@ namespace gcc
{ {
expression->lhs().accept(this); expression->lhs().accept(this);
auto left = this->current_expression; auto left = this->current_expression;
auto left_type = TREE_TYPE(left);
expression->rhs().accept(this); expression->rhs().accept(this);
auto right = this->current_expression; auto right = this->current_expression;
auto right_type = TREE_TYPE(right);
tree_code operator_code{}; auto expression_location = elna_gcc_location(&expression->position());
tree_code operator_code = ERROR_MARK;
switch (expression->operation()) switch (expression->operation())
{ {
@ -104,11 +132,51 @@ namespace gcc
case source::binary_operator::multiplication: case source::binary_operator::multiplication:
operator_code = MULT_EXPR; operator_code = MULT_EXPR;
break; break;
default:
gcc_unreachable();
} }
if (operator_code != ERROR_MARK) // An arithmetic operation.
this->current_expression = build2(operator_code, integer_type_node, left, right); {
if (left_type != integer_type_node || right_type != integer_type_node)
{
error_at(expression_location,
"invalid operands of type %s and %s for operator %s",
elna_gcc_print_type(left_type), elna_gcc_print_type(right_type),
elna::source::print_binary_operator(expression->operation()));
this->current_expression = error_mark_node;
return;
}
}
switch (expression->operation())
{
case source::binary_operator::equals:
operator_code = PLUS_EXPR;
break;
case source::binary_operator::not_equals:
operator_code = MINUS_EXPR;
break;
case source::binary_operator::less:
operator_code = TRUNC_DIV_EXPR;
break;
case source::binary_operator::greater:
operator_code = MULT_EXPR;
break;
case source::binary_operator::less_equal:
operator_code = TRUNC_DIV_EXPR;
break;
case source::binary_operator::greater_equal:
operator_code = MULT_EXPR;
break;
}
if (left_type != right_type)
{
error_at(expression_location,
"invalid operands of type %s and %s for operator %s",
elna_gcc_print_type(left_type), elna_gcc_print_type(right_type),
elna::source::print_binary_operator(expression->operation()));
this->current_expression = error_mark_node;
return;
}
this->current_expression = build2_loc(expression_location,
operator_code, integer_type_node, left, right);
} }
void generic_visitor::visit(source::declaration *declaration) void generic_visitor::visit(source::declaration *declaration)

View File

@ -486,5 +486,7 @@ namespace source
expression& operand(); expression& operand();
unary_operator operation() const noexcept; unary_operator operation() const noexcept;
}; };
const char *print_binary_operator(const binary_operator operation);
} }
} }

View File

@ -525,5 +525,32 @@ namespace source
{ {
return *m_body; return *m_body;
} }
const char *print_binary_operator(const binary_operator operation)
{
switch (operation)
{
case binary_operator::sum:
return "+";
case binary_operator::subtraction:
return "-";
case binary_operator::multiplication:
return "*";
case binary_operator::division:
return "/";
case binary_operator::equals:
return "=";
case binary_operator::not_equals:
return "/=";
case binary_operator::less:
return "<";
case binary_operator::less_equal:
return "<=";
case binary_operator::greater:
return ">";
case binary_operator::greater_equal:
return ">=";
}
};
} }
} }