Add error handling for binary operators
This commit is contained in:
parent
d46608b358
commit
02efda5e70
@ -13,12 +13,37 @@ namespace gcc
|
||||
{
|
||||
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[] = {
|
||||
build_string_literal(strlen(format_integer) + 1, format_integer),
|
||||
this->current_expression
|
||||
argument_tree
|
||||
};
|
||||
tree fndecl_type_param[] = {
|
||||
build_pointer_type(build_qualified_type(char_type_node, TYPE_QUAL_CONST)) /* const char* */
|
||||
@ -84,11 +109,14 @@ namespace gcc
|
||||
{
|
||||
expression->lhs().accept(this);
|
||||
auto left = this->current_expression;
|
||||
auto left_type = TREE_TYPE(left);
|
||||
|
||||
expression->rhs().accept(this);
|
||||
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())
|
||||
{
|
||||
@ -104,11 +132,51 @@ namespace gcc
|
||||
case source::binary_operator::multiplication:
|
||||
operator_code = MULT_EXPR;
|
||||
break;
|
||||
default:
|
||||
gcc_unreachable();
|
||||
}
|
||||
|
||||
this->current_expression = build2(operator_code, integer_type_node, left, right);
|
||||
if (operator_code != ERROR_MARK) // An arithmetic operation.
|
||||
{
|
||||
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)
|
||||
|
@ -486,5 +486,7 @@ namespace source
|
||||
expression& operand();
|
||||
unary_operator operation() const noexcept;
|
||||
};
|
||||
|
||||
const char *print_binary_operator(const binary_operator operation);
|
||||
}
|
||||
}
|
||||
|
@ -525,5 +525,32 @@ namespace source
|
||||
{
|
||||
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 ">=";
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user