Use colon instead of as to cast
This commit is contained in:
@ -43,6 +43,94 @@ namespace gcc
|
||||
this->symbol_map = symbol_table;
|
||||
}
|
||||
|
||||
void generic_visitor::build_procedure_call(location_t call_location,
|
||||
tree symbol, const std::vector<boot::expression *>& arguments)
|
||||
{
|
||||
vec<tree, va_gc> *argument_trees = nullptr;
|
||||
tree current_parameter = TYPE_ARG_TYPES(TREE_TYPE(symbol));
|
||||
|
||||
vec_alloc(argument_trees, arguments.size());
|
||||
for (boot::expression *const argument : arguments)
|
||||
{
|
||||
location_t argument_location = get_location(&argument->position());
|
||||
if (is_void_type(TREE_VALUE(current_parameter)))
|
||||
{
|
||||
error_at(argument_location, "too many arguments, expected %i, got %lu",
|
||||
list_length(TYPE_ARG_TYPES(TREE_TYPE(symbol))) - 1, arguments.size());
|
||||
this->current_expression = error_mark_node;
|
||||
break;
|
||||
}
|
||||
argument->accept(this);
|
||||
if (!is_assignable_from(TREE_VALUE(current_parameter), this->current_expression))
|
||||
{
|
||||
error_at(argument_location,
|
||||
"cannot assign value of type '%s' to variable of type '%s'",
|
||||
print_type(TREE_TYPE(this->current_expression)).c_str(),
|
||||
print_type(TREE_VALUE(current_parameter)).c_str());
|
||||
this->current_expression = error_mark_node;
|
||||
}
|
||||
current_parameter = TREE_CHAIN(current_parameter);
|
||||
argument_trees->quick_push(this->current_expression);
|
||||
}
|
||||
tree stmt = build_call_expr_loc_vec(call_location, symbol, argument_trees);
|
||||
|
||||
if (!is_void_type(TREE_VALUE(current_parameter)))
|
||||
{
|
||||
error_at(call_location, "too few arguments, expected %i, got %lu",
|
||||
list_length(TYPE_ARG_TYPES(TREE_TYPE(symbol))) - 1, arguments.size());
|
||||
this->current_expression = error_mark_node;
|
||||
}
|
||||
else if (TREE_TYPE(TREE_TYPE(symbol)) == void_type_node)
|
||||
{
|
||||
append_statement(stmt);
|
||||
this->current_expression = NULL_TREE;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->current_expression = stmt;
|
||||
}
|
||||
}
|
||||
|
||||
void generic_visitor::build_record_call(location_t call_location,
|
||||
tree symbol, const std::vector<boot::expression *>& arguments)
|
||||
{
|
||||
vec<constructor_elt, va_gc> *tree_arguments = nullptr;
|
||||
tree record_fields = TYPE_FIELDS(symbol);
|
||||
for (boot::expression *const argument : arguments)
|
||||
{
|
||||
location_t argument_location = get_location(&argument->position());
|
||||
|
||||
if (is_void_type(record_fields))
|
||||
{
|
||||
error_at(argument_location, "too many arguments, expected %i, got %lu",
|
||||
list_length(TYPE_FIELDS(symbol)), arguments.size());
|
||||
this->current_expression = error_mark_node;
|
||||
break;
|
||||
}
|
||||
argument->accept(this);
|
||||
if (!is_assignable_from(TREE_TYPE(record_fields), this->current_expression))
|
||||
{
|
||||
error_at(argument_location,
|
||||
"cannot assign value of type '%s' to variable of type '%s'",
|
||||
print_type(TREE_TYPE(this->current_expression)).c_str(),
|
||||
print_type(TREE_TYPE(record_fields)).c_str());
|
||||
this->current_expression = error_mark_node;
|
||||
}
|
||||
CONSTRUCTOR_APPEND_ELT(tree_arguments, record_fields, this->current_expression);
|
||||
record_fields = TREE_CHAIN(record_fields);
|
||||
}
|
||||
if (!is_void_type(record_fields))
|
||||
{
|
||||
error_at(call_location, "too few arguments, expected %i, got %lu",
|
||||
list_length(TYPE_FIELDS(symbol)), arguments.size());
|
||||
this->current_expression = error_mark_node;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->current_expression = build_constructor(symbol, tree_arguments);
|
||||
}
|
||||
}
|
||||
|
||||
void generic_visitor::visit(boot::call_expression *expression)
|
||||
{
|
||||
tree symbol = this->lookup(expression->name());
|
||||
@ -56,37 +144,11 @@ namespace gcc
|
||||
}
|
||||
else if (DECL_P(symbol) && is_procedure_type(TREE_TYPE(symbol)))
|
||||
{
|
||||
vec<tree, va_gc> *arguments = nullptr;
|
||||
|
||||
vec_alloc(arguments, expression->arguments().size());
|
||||
for (boot::expression *const argument : expression->arguments())
|
||||
{
|
||||
argument->accept(this);
|
||||
arguments->quick_push(this->current_expression);
|
||||
}
|
||||
tree stmt = build_call_expr_loc_vec(get_location(&expression->position()), symbol, arguments);
|
||||
|
||||
if (TREE_TYPE(TREE_TYPE(symbol)) == void_type_node)
|
||||
{
|
||||
append_statement(stmt);
|
||||
this->current_expression = NULL_TREE;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->current_expression = stmt;
|
||||
}
|
||||
build_procedure_call(call_location, symbol, expression->arguments());
|
||||
}
|
||||
else if (TYPE_P(symbol) && is_record_type(symbol))
|
||||
{
|
||||
vec<constructor_elt, va_gc> *arguments = nullptr;
|
||||
tree record_fields = TYPE_FIELDS(symbol);
|
||||
for (boot::expression *const argument : expression->arguments())
|
||||
{
|
||||
argument->accept(this);
|
||||
CONSTRUCTOR_APPEND_ELT(arguments, record_fields, this->current_expression);
|
||||
record_fields = TREE_CHAIN(record_fields);
|
||||
}
|
||||
this->current_expression = build_constructor(symbol, arguments);
|
||||
build_record_call(call_location, symbol, expression->arguments());
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -315,12 +377,12 @@ namespace gcc
|
||||
|
||||
void generic_visitor::visit(boot::number_literal<std::int32_t> *literal)
|
||||
{
|
||||
this->current_expression = build_int_cst(elna_int_type_node, literal->number());
|
||||
this->current_expression = build_int_cst(elna_int_type_node, literal->value);
|
||||
}
|
||||
|
||||
void generic_visitor::visit(boot::number_literal<std::uint32_t> *literal)
|
||||
{
|
||||
this->current_expression = build_int_cstu(elna_word_type_node, literal->number());
|
||||
this->current_expression = build_int_cstu(elna_word_type_node, literal->value);
|
||||
}
|
||||
|
||||
void generic_visitor::visit(boot::number_literal<double> *literal)
|
||||
@ -329,7 +391,7 @@ namespace gcc
|
||||
|
||||
mpfr_t number;
|
||||
mpfr_init2(number, SIGNIFICAND_BITS);
|
||||
mpfr_set_d(number, literal->number(), MPFR_RNDN);
|
||||
mpfr_set_d(number, literal->value, MPFR_RNDN);
|
||||
|
||||
real_from_mpfr(&real_value1, number, double_type_node, MPFR_RNDN);
|
||||
|
||||
@ -340,12 +402,12 @@ namespace gcc
|
||||
|
||||
void generic_visitor::visit(boot::number_literal<bool> *boolean)
|
||||
{
|
||||
this->current_expression = boolean->number() ? boolean_true_node : boolean_false_node;
|
||||
this->current_expression = boolean->value ? boolean_true_node : boolean_false_node;
|
||||
}
|
||||
|
||||
void generic_visitor::visit(boot::number_literal<unsigned char> *character)
|
||||
{
|
||||
this->current_expression = build_int_cstu(elna_char_type_node, character->number());
|
||||
this->current_expression = build_int_cstu(elna_char_type_node, character->value);
|
||||
}
|
||||
|
||||
void generic_visitor::visit(boot::number_literal<nullptr_t> *)
|
||||
@ -355,10 +417,10 @@ namespace gcc
|
||||
|
||||
void generic_visitor::visit(boot::number_literal<std::string> *string)
|
||||
{
|
||||
tree index_constant = build_int_cstu(elna_word_type_node, string->number().size());
|
||||
tree index_constant = build_int_cstu(elna_word_type_node, string->value.size());
|
||||
tree string_type = build_array_type(elna_char_type_node, build_index_type(index_constant));
|
||||
|
||||
tree string_literal = build_string(string->number().size(), string->number().c_str());
|
||||
tree string_literal = build_string(string->value.size(), string->value.c_str());
|
||||
TREE_TYPE(string_literal) = string_type;
|
||||
TREE_CONSTANT(string_literal) = 1;
|
||||
TREE_READONLY(string_literal) = 1;
|
||||
@ -390,11 +452,49 @@ namespace gcc
|
||||
expression, operator_code, left, right, elna_bool_type_node);
|
||||
}
|
||||
|
||||
tree generic_visitor::build_logic_operation(boot::binary_expression *expression,
|
||||
tree_code operator_code, tree left, tree right)
|
||||
tree generic_visitor::build_bit_logic_operation(boot::binary_expression *expression, tree left, tree right)
|
||||
{
|
||||
return build_binary_operation(TREE_TYPE(left) == elna_bool_type_node,
|
||||
expression, operator_code, left, right, elna_bool_type_node);
|
||||
location_t expression_location = get_location(&expression->position());
|
||||
tree left_type = TREE_TYPE(left);
|
||||
tree right_type = TREE_TYPE(right);
|
||||
tree_code logical_code, bit_code;
|
||||
|
||||
if (expression->operation() == boot::binary_operator::conjunction)
|
||||
{
|
||||
bit_code = BIT_AND_EXPR;
|
||||
logical_code = TRUTH_ANDIF_EXPR;
|
||||
}
|
||||
else if (expression->operation() == boot::binary_operator::disjunction)
|
||||
{
|
||||
bit_code = BIT_IOR_EXPR;
|
||||
logical_code = TRUTH_ORIF_EXPR;
|
||||
}
|
||||
else if (expression->operation() == boot::binary_operator::exclusive_disjunction)
|
||||
{
|
||||
bit_code = BIT_XOR_EXPR;
|
||||
logical_code = TRUTH_XOR_EXPR;
|
||||
}
|
||||
else
|
||||
{
|
||||
gcc_unreachable();
|
||||
}
|
||||
|
||||
if (left_type == elna_bool_type_node)
|
||||
{
|
||||
return build2_loc(expression_location, logical_code, elna_bool_type_node, left, right);
|
||||
}
|
||||
else if (is_integral_type(left_type))
|
||||
{
|
||||
return build2_loc(expression_location, bit_code, left_type, left, right);
|
||||
}
|
||||
else
|
||||
{
|
||||
error_at(expression_location,
|
||||
"invalid operands of type '%s' and '%s' for operator %s",
|
||||
print_type(left_type).c_str(), print_type(right_type).c_str(),
|
||||
elna::boot::print_binary_operator(expression->operation()));
|
||||
return error_mark_node;
|
||||
}
|
||||
}
|
||||
|
||||
tree generic_visitor::build_equality_operation(boot::binary_expression *expression, tree left, tree right)
|
||||
@ -475,7 +575,9 @@ namespace gcc
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (left_type != right_type && !are_compatible_pointers(left, right) && !are_compatible_pointers(right, left))
|
||||
if (left_type != right_type
|
||||
&& !are_compatible_pointers(left_type, right)
|
||||
&& !are_compatible_pointers(right_type, left))
|
||||
{
|
||||
error_at(expression_location,
|
||||
"invalid operands of type %s and %s for operator %s",
|
||||
@ -514,10 +616,13 @@ namespace gcc
|
||||
this->current_expression = build_comparison_operation(expression, GE_EXPR, left, right);
|
||||
break;
|
||||
case boot::binary_operator::conjunction:
|
||||
this->current_expression = build_logic_operation(expression, TRUTH_ANDIF_EXPR, left, right);
|
||||
this->current_expression = build_bit_logic_operation(expression, left, right);
|
||||
break;
|
||||
case boot::binary_operator::disjunction:
|
||||
this->current_expression = build_logic_operation(expression, TRUTH_ORIF_EXPR, left, right);
|
||||
this->current_expression = build_bit_logic_operation(expression, left, right);
|
||||
break;
|
||||
case boot::binary_operator::exclusive_disjunction:
|
||||
this->current_expression = build_bit_logic_operation(expression, left, right);
|
||||
break;
|
||||
case boot::binary_operator::equals:
|
||||
this->current_expression = build_equality_operation(expression, left, right);
|
||||
@ -531,23 +636,47 @@ namespace gcc
|
||||
void generic_visitor::visit(boot::unary_expression *expression)
|
||||
{
|
||||
expression->operand().accept(this);
|
||||
location_t location = get_location(&expression->position());
|
||||
|
||||
switch (expression->operation())
|
||||
{
|
||||
case boot::unary_operator::reference:
|
||||
TREE_ADDRESSABLE(this->current_expression) = 1;
|
||||
this->current_expression = build_fold_addr_expr_with_type_loc(get_location(&expression->position()),
|
||||
this->current_expression = build_fold_addr_expr_with_type_loc(location,
|
||||
this->current_expression,
|
||||
build_pointer_type_for_mode(TREE_TYPE(this->current_expression), VOIDmode, true));
|
||||
TREE_NO_TRAMPOLINE(this->current_expression) = 1;
|
||||
break;
|
||||
case boot::unary_operator::negation:
|
||||
this->current_expression = build1_loc(get_location(&expression->position()), TRUTH_NOT_EXPR,
|
||||
boolean_type_node, this->current_expression);
|
||||
if (TREE_TYPE(this->current_expression) == elna_bool_type_node)
|
||||
{
|
||||
this->current_expression = build1_loc(location, TRUTH_NOT_EXPR,
|
||||
boolean_type_node, this->current_expression);
|
||||
}
|
||||
else if (is_integral_type(TREE_TYPE(this->current_expression)))
|
||||
{
|
||||
this->current_expression = build1_loc(location, BIT_NOT_EXPR,
|
||||
TREE_TYPE(this->current_expression), this->current_expression);
|
||||
}
|
||||
else
|
||||
{
|
||||
error_at(location, "type '%s' cannot be negated",
|
||||
print_type(TREE_TYPE(this->current_expression)).c_str());
|
||||
this->current_expression = error_mark_node;
|
||||
}
|
||||
break;
|
||||
case boot::unary_operator::minus:
|
||||
this->current_expression = fold_build1(NEGATE_EXPR, TREE_TYPE(this->current_expression),
|
||||
this->current_expression);
|
||||
if (is_integral_type(TREE_TYPE(this->current_expression)))
|
||||
{
|
||||
this->current_expression = fold_build1(NEGATE_EXPR, TREE_TYPE(this->current_expression),
|
||||
this->current_expression);
|
||||
}
|
||||
else
|
||||
{
|
||||
error_at(location, "type '%s' cannot be negated",
|
||||
print_type(TREE_TYPE(this->current_expression)).c_str());
|
||||
this->current_expression = error_mark_node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -709,6 +838,10 @@ namespace gcc
|
||||
get_identifier(declaration->identifier.c_str()), declaration_type);
|
||||
bool result = this->symbol_map->enter(declaration->identifier, declaration_tree);
|
||||
|
||||
if (is_pointer_type(declaration_type))
|
||||
{
|
||||
DECL_INITIAL(declaration_tree) = elna_pointer_nil_node;
|
||||
}
|
||||
if (!result)
|
||||
{
|
||||
error_at(declaration_location, "variable '%s' already declared in this scope",
|
||||
@ -848,8 +981,7 @@ namespace gcc
|
||||
this->current_expression = error_mark_node;
|
||||
return;
|
||||
}
|
||||
if (TREE_TYPE(this->current_expression) == TREE_TYPE(lvalue)
|
||||
|| are_compatible_pointers(lvalue, this->current_expression))
|
||||
if (is_assignable_from(TREE_TYPE(lvalue), this->current_expression))
|
||||
{
|
||||
tree assignment = build2_loc(statement_location, MODIFY_EXPR,
|
||||
void_type_node, lvalue, this->current_expression);
|
||||
|
@ -67,15 +67,21 @@ namespace gcc
|
||||
return TREE_CODE(type) == RECORD_TYPE;
|
||||
}
|
||||
|
||||
bool are_compatible_pointers(tree lhs, tree rhs)
|
||||
bool are_compatible_pointers(tree lhs_type, tree rhs)
|
||||
{
|
||||
tree lhs_type = TREE_TYPE(lhs);
|
||||
gcc_assert(TYPE_P(lhs_type));
|
||||
tree rhs_type = TREE_TYPE(rhs);
|
||||
|
||||
return (is_pointer_type(lhs_type) && rhs == elna_pointer_nil_node)
|
||||
|| (is_pointer_type(lhs_type) && lhs_type == rhs_type);
|
||||
}
|
||||
|
||||
bool is_assignable_from(tree assignee, tree assignment)
|
||||
{
|
||||
return TREE_TYPE(assignment) == assignee
|
||||
|| are_compatible_pointers(assignee, assignment);
|
||||
}
|
||||
|
||||
void append_statement(tree statement_tree)
|
||||
{
|
||||
if (!vec_safe_is_empty(f_binding_level->defers))
|
||||
|
Reference in New Issue
Block a user