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)
|
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)
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 ">=";
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user