Implement case statements
This commit is contained in:
parent
18c4e79012
commit
f68667d5e5
@ -275,7 +275,7 @@ namespace elna::boot
|
|||||||
}
|
}
|
||||||
|
|
||||||
constant_definition::constant_definition(const struct position position, const std::string& identifier,
|
constant_definition::constant_definition(const struct position position, const std::string& identifier,
|
||||||
const bool exported, literal_expression *body)
|
const bool exported, expression *body)
|
||||||
: definition(position, identifier, exported), m_body(body)
|
: definition(position, identifier, exported), m_body(body)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -285,7 +285,7 @@ namespace elna::boot
|
|||||||
visitor->visit(this);
|
visitor->visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
literal_expression& constant_definition::body()
|
expression& constant_definition::body()
|
||||||
{
|
{
|
||||||
return *m_body;
|
return *m_body;
|
||||||
}
|
}
|
||||||
|
@ -127,7 +127,7 @@ along with GCC; see the file COPYING3. If not see
|
|||||||
%left "*" "/" "%"
|
%left "*" "/" "%"
|
||||||
|
|
||||||
%type <elna::boot::literal_expression *> literal;
|
%type <elna::boot::literal_expression *> literal;
|
||||||
%type <std::vector<elna::boot::literal_expression *>> case_labels;
|
%type <std::vector<elna::boot::expression *>> case_labels;
|
||||||
%type <elna::boot::switch_case> switch_case;
|
%type <elna::boot::switch_case> switch_case;
|
||||||
%type <std::vector<elna::boot::switch_case>> switch_cases;
|
%type <std::vector<elna::boot::switch_case>> switch_cases;
|
||||||
%type <elna::boot::constant_definition *> constant_definition;
|
%type <elna::boot::constant_definition *> constant_definition;
|
||||||
@ -137,7 +137,6 @@ along with GCC; see the file COPYING3. If not see
|
|||||||
%type <std::vector<elna::boot::type_expression *>> type_expressions;
|
%type <std::vector<elna::boot::type_expression *>> type_expressions;
|
||||||
%type <elna::boot::traits_expression *> traits_expression;
|
%type <elna::boot::traits_expression *> traits_expression;
|
||||||
%type <elna::boot::expression *> expression operand simple_expression;
|
%type <elna::boot::expression *> expression operand simple_expression;
|
||||||
%type <elna::boot::field_access_expression *> qualident;
|
|
||||||
%type <elna::boot::unary_expression *> unary_expression;
|
%type <elna::boot::unary_expression *> unary_expression;
|
||||||
%type <elna::boot::binary_expression *> binary_expression;
|
%type <elna::boot::binary_expression *> binary_expression;
|
||||||
%type <std::vector<elna::boot::expression *>> expressions actual_parameter_list;
|
%type <std::vector<elna::boot::expression *>> expressions actual_parameter_list;
|
||||||
@ -296,34 +295,13 @@ return_statement:
|
|||||||
$$ = new boot::return_statement(boot::make_position(@1));
|
$$ = new boot::return_statement(boot::make_position(@1));
|
||||||
}
|
}
|
||||||
literal:
|
literal:
|
||||||
INTEGER
|
INTEGER { $$ = new boot::literal<std::int32_t>(boot::make_position(@1), $1); }
|
||||||
{
|
| WORD { $$ = new boot::literal<std::uint32_t>(boot::make_position(@1), $1); }
|
||||||
$$ = new boot::literal<std::int32_t>(boot::make_position(@1), $1);
|
| FLOAT { $$ = new boot::literal<double>(boot::make_position(@1), $1); }
|
||||||
}
|
| BOOLEAN { $$ = new boot::literal<bool>(boot::make_position(@1), $1); }
|
||||||
| WORD
|
| CHARACTER { $$ = new boot::literal<unsigned char>(boot::make_position(@1), $1.at(0)); }
|
||||||
{
|
| "nil" { $$ = new boot::literal<std::nullptr_t>(boot::make_position(@1), nullptr); }
|
||||||
$$ = new boot::literal<std::uint32_t>(boot::make_position(@1), $1);
|
| STRING { $$ = new boot::literal<std::string>(boot::make_position(@1), $1); }
|
||||||
}
|
|
||||||
| FLOAT
|
|
||||||
{
|
|
||||||
$$ = new boot::literal<double>(boot::make_position(@1), $1);
|
|
||||||
}
|
|
||||||
| BOOLEAN
|
|
||||||
{
|
|
||||||
$$ = new boot::literal<bool>(boot::make_position(@1), $1);
|
|
||||||
}
|
|
||||||
| CHARACTER
|
|
||||||
{
|
|
||||||
$$ = new boot::literal<unsigned char>(boot::make_position(@1), $1.at(0));
|
|
||||||
}
|
|
||||||
| "nil"
|
|
||||||
{
|
|
||||||
$$ = new boot::literal<std::nullptr_t>(boot::make_position(@1), nullptr);
|
|
||||||
}
|
|
||||||
| STRING
|
|
||||||
{
|
|
||||||
$$ = new boot::literal<std::string>(boot::make_position(@1), $1);
|
|
||||||
}
|
|
||||||
traits_expression:
|
traits_expression:
|
||||||
TRAIT "(" type_expressions ")"
|
TRAIT "(" type_expressions ")"
|
||||||
{
|
{
|
||||||
@ -439,33 +417,22 @@ type_expressions:
|
|||||||
| type_expression { $$.push_back($1); }
|
| type_expression { $$.push_back($1); }
|
||||||
designator_expression:
|
designator_expression:
|
||||||
simple_expression "[" expression "]"
|
simple_expression "[" expression "]"
|
||||||
{
|
{ $$ = new boot::array_access_expression(boot::make_position(@2), $1, $3); }
|
||||||
$$ = new boot::array_access_expression(boot::make_position(@2), $1, $3);
|
| simple_expression "." IDENTIFIER
|
||||||
}
|
{ $$ = new boot::field_access_expression(boot::make_position(@2), $1, $3); }
|
||||||
| qualident { $$ = $1; }
|
|
||||||
| simple_expression "^"
|
| simple_expression "^"
|
||||||
{
|
{ $$ = new boot::dereference_expression(boot::make_position(@1), $1); }
|
||||||
$$ = new boot::dereference_expression(boot::make_position(@1), $1);
|
|
||||||
}
|
|
||||||
| IDENTIFIER
|
| IDENTIFIER
|
||||||
{
|
{ $$ = new boot::variable_expression(boot::make_position(@1), $1); }
|
||||||
$$ = new boot::variable_expression(boot::make_position(@1), $1);
|
|
||||||
}
|
|
||||||
qualident: simple_expression "." IDENTIFIER
|
|
||||||
{
|
|
||||||
$$ = new boot::field_access_expression(boot::make_position(@2), $1, $3);
|
|
||||||
}
|
|
||||||
statement:
|
statement:
|
||||||
designator_expression ":=" expression
|
designator_expression ":=" expression
|
||||||
{
|
{ $$ = new boot::assign_statement(boot::make_position(@1), $1, $3); }
|
||||||
$$ = new boot::assign_statement(boot::make_position(@1), $1, $3);
|
|
||||||
}
|
|
||||||
| while_statement { $$ = $1; }
|
| while_statement { $$ = $1; }
|
||||||
| if_statement { $$ = $1; }
|
| if_statement { $$ = $1; }
|
||||||
| return_statement { $$ = $1; }
|
| return_statement { $$ = $1; }
|
||||||
| call_expression { $$ = $1; }
|
| call_expression { $$ = $1; }
|
||||||
| DEFER statements "end" { $$ = new boot::defer_statement(boot::make_position(@1), std::move($2)); }
|
| "defer" statements "end" { $$ = new boot::defer_statement(boot::make_position(@1), std::move($2)); }
|
||||||
| CASE expression "of" switch_cases "end"
|
| "case" expression "of" switch_cases "end"
|
||||||
{ $$ = new boot::case_statement(boot::make_position(@1), $2, std::move($4)); }
|
{ $$ = new boot::case_statement(boot::make_position(@1), $2, std::move($4)); }
|
||||||
switch_case: case_labels ":" statements { $$ = { .labels = std::move($1), .statements = std::move($3) }; }
|
switch_case: case_labels ":" statements { $$ = { .labels = std::move($1), .statements = std::move($3) }; }
|
||||||
switch_cases:
|
switch_cases:
|
||||||
@ -476,12 +443,12 @@ switch_cases:
|
|||||||
}
|
}
|
||||||
| switch_case { $$.push_back($1); }
|
| switch_case { $$.push_back($1); }
|
||||||
case_labels:
|
case_labels:
|
||||||
literal "," case_labels
|
expression "," case_labels
|
||||||
{
|
{
|
||||||
std::swap($$, $3);
|
std::swap($$, $3);
|
||||||
$$.emplace($$.cbegin(), $1);
|
$$.emplace($$.cbegin(), $1);
|
||||||
}
|
}
|
||||||
| literal { $$.push_back($1); }
|
| expression { $$.push_back($1); }
|
||||||
statements:
|
statements:
|
||||||
statement ";" statements
|
statement ";" statements
|
||||||
{
|
{
|
||||||
@ -562,7 +529,7 @@ variable_declarations:
|
|||||||
variable_part:
|
variable_part:
|
||||||
/* no variable declarations */ {}
|
/* no variable declarations */ {}
|
||||||
| "var" variable_declarations { std::swap($$, $2); }
|
| "var" variable_declarations { std::swap($$, $2); }
|
||||||
constant_definition: identifier_definition "=" literal
|
constant_definition: identifier_definition "=" expression
|
||||||
{
|
{
|
||||||
$$ = new boot::constant_definition(boot::make_position(@1), $1.first, $1.second, $3);
|
$$ = new boot::constant_definition(boot::make_position(@1), $1.first, $1.second, $3);
|
||||||
}
|
}
|
||||||
|
@ -278,7 +278,7 @@ namespace elna::boot
|
|||||||
statement->condition().accept(this);
|
statement->condition().accept(this);
|
||||||
for (const switch_case& case_block : statement->cases)
|
for (const switch_case& case_block : statement->cases)
|
||||||
{
|
{
|
||||||
for (literal_expression *const case_label : case_block.labels)
|
for (expression *const case_label : case_block.labels)
|
||||||
{
|
{
|
||||||
case_label->accept(this);
|
case_label->accept(this);
|
||||||
}
|
}
|
||||||
|
@ -292,6 +292,16 @@ namespace elna::boot
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<constant_info> info::is_constant()
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<variable_info> info::is_variable()
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
type_info::type_info(const type symbol)
|
type_info::type_info(const type symbol)
|
||||||
: symbol(symbol)
|
: symbol(symbol)
|
||||||
{
|
{
|
||||||
@ -317,6 +327,21 @@ namespace elna::boot
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<constant_info> constant_info::is_constant()
|
||||||
|
{
|
||||||
|
return std::static_pointer_cast<constant_info>(shared_from_this());
|
||||||
|
}
|
||||||
|
|
||||||
|
variable_info::variable_info(const std::string& name, const type symbol)
|
||||||
|
: name(name), symbol(symbol)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<variable_info> variable_info::is_variable()
|
||||||
|
{
|
||||||
|
return std::static_pointer_cast<variable_info>(shared_from_this());;
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_ptr<symbol_table> builtin_symbol_table()
|
std::shared_ptr<symbol_table> builtin_symbol_table()
|
||||||
{
|
{
|
||||||
auto result = std::make_shared<symbol_table>();
|
auto result = std::make_shared<symbol_table>();
|
||||||
|
@ -138,7 +138,7 @@ namespace elna::gcc
|
|||||||
location_t argument_location = get_location(&argument->position());
|
location_t argument_location = get_location(&argument->position());
|
||||||
if (VOID_TYPE_P(TREE_VALUE(current_parameter)))
|
if (VOID_TYPE_P(TREE_VALUE(current_parameter)))
|
||||||
{
|
{
|
||||||
error_at(argument_location, "too many arguments, expected %i, got %lu",
|
error_at(argument_location, "Too many arguments, expected %i, got %lu",
|
||||||
list_length(TYPE_ARG_TYPES(symbol_type)) - 1, arguments.size());
|
list_length(TYPE_ARG_TYPES(symbol_type)) - 1, arguments.size());
|
||||||
this->current_expression = error_mark_node;
|
this->current_expression = error_mark_node;
|
||||||
break;
|
break;
|
||||||
@ -182,7 +182,7 @@ namespace elna::gcc
|
|||||||
|
|
||||||
if (is_void_type(record_fields))
|
if (is_void_type(record_fields))
|
||||||
{
|
{
|
||||||
error_at(argument_location, "too many arguments, expected %i, got %lu",
|
error_at(argument_location, "Too many arguments, expected %i, got %lu",
|
||||||
list_length(TYPE_FIELDS(symbol)), arguments.size());
|
list_length(TYPE_FIELDS(symbol)), arguments.size());
|
||||||
this->current_expression = error_mark_node;
|
this->current_expression = error_mark_node;
|
||||||
break;
|
break;
|
||||||
@ -632,7 +632,8 @@ namespace elna::gcc
|
|||||||
&& (expression->operation() == boot::binary_operator::sum
|
&& (expression->operation() == boot::binary_operator::sum
|
||||||
|| expression->operation() == boot::binary_operator::subtraction))
|
|| expression->operation() == boot::binary_operator::subtraction))
|
||||||
{
|
{
|
||||||
this->current_expression = do_pointer_arithmetic(expression->operation(), left, right);
|
this->current_expression = do_pointer_arithmetic(expression->operation(),
|
||||||
|
left, right, expression_location);
|
||||||
if (this->current_expression == error_mark_node)
|
if (this->current_expression == error_mark_node)
|
||||||
{
|
{
|
||||||
error_at(expression_location,
|
error_at(expression_location,
|
||||||
@ -767,6 +768,15 @@ namespace elna::gcc
|
|||||||
location_t definition_location = get_location(&definition->position());
|
location_t definition_location = get_location(&definition->position());
|
||||||
definition->body().accept(this);
|
definition->body().accept(this);
|
||||||
|
|
||||||
|
if (extract_constant(definition_location))
|
||||||
|
{
|
||||||
|
this->current_expression = fold_init(this->current_expression);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->current_expression = NULL_TREE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
tree definition_tree = build_decl(definition_location, CONST_DECL,
|
tree definition_tree = build_decl(definition_location, CONST_DECL,
|
||||||
get_identifier(definition->identifier.c_str()), TREE_TYPE(this->current_expression));
|
get_identifier(definition->identifier.c_str()), TREE_TYPE(this->current_expression));
|
||||||
auto result = this->symbols->enter(definition->identifier, definition_tree);
|
auto result = this->symbols->enter(definition->identifier, definition_tree);
|
||||||
@ -923,17 +933,16 @@ namespace elna::gcc
|
|||||||
expression->index().accept(this);
|
expression->index().accept(this);
|
||||||
if (!is_integral_type(TREE_TYPE(this->current_expression)))
|
if (!is_integral_type(TREE_TYPE(this->current_expression)))
|
||||||
{
|
{
|
||||||
error_at(location, "type '%s' cannot be used as index",
|
error_at(location, "Type '%s' cannot be used as index",
|
||||||
print_type(TREE_TYPE(this->current_expression)).c_str());
|
print_type(TREE_TYPE(this->current_expression)).c_str());
|
||||||
this->current_expression = error_mark_node;
|
this->current_expression = error_mark_node;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this->current_expression != elna_word_type_node)
|
if (this->current_expression != elna_word_type_node)
|
||||||
{
|
{
|
||||||
this->current_expression = fold_convert(elna_word_type_node, this->current_expression);
|
this->current_expression = convert(elna_word_type_node, this->current_expression);
|
||||||
}
|
}
|
||||||
tree offset = build2(MINUS_EXPR, elna_word_type_node,
|
tree offset = build2(MINUS_EXPR, elna_word_type_node, this->current_expression, size_one_node);
|
||||||
this->current_expression, size_one_node);
|
|
||||||
|
|
||||||
if (is_array_type(TREE_TYPE(designator)))
|
if (is_array_type(TREE_TYPE(designator)))
|
||||||
{
|
{
|
||||||
@ -947,14 +956,14 @@ namespace elna::gcc
|
|||||||
tree string_ptr = build3_loc(location, COMPONENT_REF, TREE_TYPE(elna_string_ptr_field_node),
|
tree string_ptr = build3_loc(location, COMPONENT_REF, TREE_TYPE(elna_string_ptr_field_node),
|
||||||
designator, elna_string_ptr_field_node, NULL_TREE);
|
designator, elna_string_ptr_field_node, NULL_TREE);
|
||||||
|
|
||||||
tree target_pointer = do_pointer_arithmetic(boot::binary_operator::sum, string_ptr, offset);
|
tree target_pointer = do_pointer_arithmetic(boot::binary_operator::sum, string_ptr, offset, location);
|
||||||
|
|
||||||
this->current_expression = build1_loc(location, INDIRECT_REF,
|
this->current_expression = build1_loc(location, INDIRECT_REF,
|
||||||
elna_char_type_node, target_pointer);
|
elna_char_type_node, target_pointer);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
error_at(location, "indexing is not allowed on type '%s'",
|
error_at(location, "Indexing is not allowed on type '%s'",
|
||||||
print_type(TREE_TYPE(designator)).c_str());
|
print_type(TREE_TYPE(designator)).c_str());
|
||||||
this->current_expression = error_mark_node;
|
this->current_expression = error_mark_node;
|
||||||
}
|
}
|
||||||
@ -1071,7 +1080,7 @@ namespace elna::gcc
|
|||||||
|
|
||||||
if (is_array_type(aggregate_type) && expression->field() == "length")
|
if (is_array_type(aggregate_type) && expression->field() == "length")
|
||||||
{
|
{
|
||||||
this->current_expression = fold_convert(build_qualified_type(elna_word_type_node, TYPE_QUAL_CONST),
|
this->current_expression = convert(build_qualified_type(elna_word_type_node, TYPE_QUAL_CONST),
|
||||||
TYPE_MAX_VALUE(TYPE_DOMAIN(aggregate_type)));
|
TYPE_MAX_VALUE(TYPE_DOMAIN(aggregate_type)));
|
||||||
}
|
}
|
||||||
else if (is_array_type(aggregate_type) && expression->field() == "ptr")
|
else if (is_array_type(aggregate_type) && expression->field() == "ptr")
|
||||||
@ -1419,17 +1428,36 @@ namespace elna::gcc
|
|||||||
void generic_visitor::visit(boot::case_statement *statement)
|
void generic_visitor::visit(boot::case_statement *statement)
|
||||||
{
|
{
|
||||||
statement->condition().accept(this);
|
statement->condition().accept(this);
|
||||||
|
|
||||||
tree condition_expression = this->current_expression;
|
tree condition_expression = this->current_expression;
|
||||||
tree end_label_declaration = create_artificial_label(UNKNOWN_LOCATION);
|
tree unqualified_condition = get_qualified_type(TREE_TYPE(this->current_expression), TYPE_UNQUALIFIED);
|
||||||
|
|
||||||
|
if (!INTEGRAL_TYPE_P(unqualified_condition))
|
||||||
|
{
|
||||||
|
error_at(get_location(&statement->condition().position()),
|
||||||
|
"Case expressions can only be integral numbers, characters and enumerations, given '%s'",
|
||||||
|
print_type(unqualified_condition).c_str());
|
||||||
|
this->current_expression = NULL_TREE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tree end_label_declaration = create_artificial_label(get_location(&statement->position()));
|
||||||
tree switch_statements = alloc_stmt_list();
|
tree switch_statements = alloc_stmt_list();
|
||||||
|
|
||||||
for (const boot::switch_case& case_block : statement->cases)
|
for (const boot::switch_case& case_block : statement->cases)
|
||||||
{
|
{
|
||||||
for (boot::literal_expression *const case_label : case_block.labels)
|
for (boot::expression *const case_label : case_block.labels)
|
||||||
{
|
{
|
||||||
case_label->accept(this);
|
case_label->accept(this);
|
||||||
tree case_label_declaration = create_artificial_label(get_location(&case_label->position()));
|
location_t case_location = get_location(&case_label->position());
|
||||||
|
|
||||||
|
if (extract_constant(case_location)
|
||||||
|
&& !is_assignable_from(unqualified_condition, this->current_expression))
|
||||||
|
{
|
||||||
|
error_at(case_location, "Case type '%s' does not match the expression type '%s'",
|
||||||
|
print_type(TREE_TYPE(this->current_expression)).c_str(),
|
||||||
|
print_type(unqualified_condition).c_str());
|
||||||
|
this->current_expression = error_mark_node;
|
||||||
|
}
|
||||||
|
tree case_label_declaration = create_artificial_label(case_location);
|
||||||
tree case_expression = build_case_label(this->current_expression, NULL_TREE, case_label_declaration);
|
tree case_expression = build_case_label(this->current_expression, NULL_TREE, case_label_declaration);
|
||||||
|
|
||||||
append_to_statement_list(case_expression, &switch_statements);
|
append_to_statement_list(case_expression, &switch_statements);
|
||||||
@ -1452,4 +1480,21 @@ namespace elna::gcc
|
|||||||
|
|
||||||
this->current_expression = NULL_TREE;
|
this->current_expression = NULL_TREE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool generic_visitor::extract_constant(location_t expression_location)
|
||||||
|
{
|
||||||
|
int code = TREE_CODE(this->current_expression);
|
||||||
|
|
||||||
|
if (code == CONST_DECL)
|
||||||
|
{
|
||||||
|
this->current_expression = DECL_INITIAL(this->current_expression);
|
||||||
|
}
|
||||||
|
else if (TREE_CODE_CLASS(code) != tcc_constant)
|
||||||
|
{
|
||||||
|
error_at(expression_location, "Expected a constant expression");
|
||||||
|
this->current_expression = error_mark_node;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,14 +37,6 @@ namespace elna::gcc
|
|||||||
return is_integral_type(type) || type == elna_float_type_node;
|
return is_integral_type(type) || type == elna_float_type_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_primitive_type(tree type)
|
|
||||||
{
|
|
||||||
gcc_assert(TYPE_P(type));
|
|
||||||
return TREE_CODE(type) == INTEGER_TYPE
|
|
||||||
|| type == elna_float_type_node
|
|
||||||
|| type == elna_bool_type_node;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_array_type(tree type)
|
bool is_array_type(tree type)
|
||||||
{
|
{
|
||||||
gcc_assert(TYPE_P(type));
|
gcc_assert(TYPE_P(type));
|
||||||
@ -59,9 +51,7 @@ namespace elna::gcc
|
|||||||
bool is_castable_type(tree type)
|
bool is_castable_type(tree type)
|
||||||
{
|
{
|
||||||
gcc_assert(TYPE_P(type));
|
gcc_assert(TYPE_P(type));
|
||||||
auto code = TREE_CODE(type);
|
return INTEGRAL_TYPE_P(type) || POINTER_TYPE_P(type) || TREE_CODE(type) == REAL_TYPE;
|
||||||
|
|
||||||
return is_primitive_type(type) || POINTER_TYPE_P(type) || code == ENUMERAL_TYPE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool are_compatible_pointers(tree lhs_type, tree rhs)
|
bool are_compatible_pointers(tree lhs_type, tree rhs)
|
||||||
@ -139,7 +129,8 @@ namespace elna::gcc
|
|||||||
return field_declaration;
|
return field_declaration;
|
||||||
}
|
}
|
||||||
|
|
||||||
tree do_pointer_arithmetic(boot::binary_operator binary_operator, tree left, tree right)
|
tree do_pointer_arithmetic(boot::binary_operator binary_operator,
|
||||||
|
tree left, tree right, location_t operation_location)
|
||||||
{
|
{
|
||||||
tree left_type = get_qualified_type(TREE_TYPE(left), TYPE_UNQUALIFIED);
|
tree left_type = get_qualified_type(TREE_TYPE(left), TYPE_UNQUALIFIED);
|
||||||
tree right_type = get_qualified_type(TREE_TYPE(right), TYPE_UNQUALIFIED);
|
tree right_type = get_qualified_type(TREE_TYPE(right), TYPE_UNQUALIFIED);
|
||||||
@ -167,7 +158,7 @@ namespace elna::gcc
|
|||||||
offset = fold_build2(MULT_EXPR, TREE_TYPE(offset), offset, size_exp);
|
offset = fold_build2(MULT_EXPR, TREE_TYPE(offset), offset, size_exp);
|
||||||
offset = fold_convert(sizetype, offset);
|
offset = fold_convert(sizetype, offset);
|
||||||
|
|
||||||
return fold_build2(POINTER_PLUS_EXPR, TREE_TYPE(pointer), pointer, offset);
|
return fold_build2_loc(operation_location, POINTER_PLUS_EXPR, TREE_TYPE(pointer), pointer, offset);
|
||||||
}
|
}
|
||||||
else if (binary_operator == boot::binary_operator::subtraction)
|
else if (binary_operator == boot::binary_operator::subtraction)
|
||||||
{
|
{
|
||||||
@ -181,11 +172,11 @@ namespace elna::gcc
|
|||||||
convert_expression = fold_convert(sizetype, convert_expression);
|
convert_expression = fold_convert(sizetype, convert_expression);
|
||||||
|
|
||||||
convert_expression = fold_build1(NEGATE_EXPR, sizetype, convert_expression);
|
convert_expression = fold_build1(NEGATE_EXPR, sizetype, convert_expression);
|
||||||
return fold_build2(POINTER_PLUS_EXPR, pointer_type, left, convert_expression);
|
return fold_build2_loc(operation_location, POINTER_PLUS_EXPR, pointer_type, left, convert_expression);
|
||||||
}
|
}
|
||||||
else if (POINTER_TYPE_P(left_type) && POINTER_TYPE_P(right_type) && left_type == right_type)
|
else if (POINTER_TYPE_P(left_type) && POINTER_TYPE_P(right_type) && left_type == right_type)
|
||||||
{
|
{
|
||||||
return fold_build2(POINTER_DIFF_EXPR, ssizetype, left, right);
|
return fold_build2_loc(operation_location, POINTER_DIFF_EXPR, ssizetype, left, right);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gcc_unreachable();
|
gcc_unreachable();
|
||||||
@ -200,7 +191,7 @@ namespace elna::gcc
|
|||||||
|
|
||||||
if (condition)
|
if (condition)
|
||||||
{
|
{
|
||||||
return build2_loc(expression_location, operator_code, target_type, left, right);
|
return fold_build2_loc(expression_location, operator_code, target_type, left, right);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -321,14 +321,14 @@ namespace elna::boot
|
|||||||
*/
|
*/
|
||||||
class constant_definition : public definition
|
class constant_definition : public definition
|
||||||
{
|
{
|
||||||
literal_expression *m_body;
|
expression *m_body;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
constant_definition(const struct position position, const std::string& identifier,
|
constant_definition(const struct position position, const std::string& identifier,
|
||||||
const bool exported, literal_expression *body);
|
const bool exported, expression *body);
|
||||||
void accept(parser_visitor *visitor) override;
|
void accept(parser_visitor *visitor) override;
|
||||||
|
|
||||||
literal_expression& body();
|
expression& body();
|
||||||
|
|
||||||
virtual ~constant_definition() override;
|
virtual ~constant_definition() override;
|
||||||
};
|
};
|
||||||
@ -451,7 +451,7 @@ namespace elna::boot
|
|||||||
|
|
||||||
struct switch_case
|
struct switch_case
|
||||||
{
|
{
|
||||||
std::vector<literal_expression *> labels;
|
std::vector<expression *> labels;
|
||||||
std::vector<statement *> statements;
|
std::vector<statement *> statements;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -483,7 +483,7 @@ namespace elna::boot
|
|||||||
designator_expression();
|
designator_expression();
|
||||||
};
|
};
|
||||||
|
|
||||||
class variable_expression : public designator_expression
|
class variable_expression : public designator_expression, public literal_expression
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
const std::string name;
|
const std::string name;
|
||||||
|
@ -155,6 +155,7 @@ namespace elna::boot
|
|||||||
class type_info;
|
class type_info;
|
||||||
class procedure_info;
|
class procedure_info;
|
||||||
class constant_info;
|
class constant_info;
|
||||||
|
class variable_info;
|
||||||
|
|
||||||
class info : public std::enable_shared_from_this<info>
|
class info : public std::enable_shared_from_this<info>
|
||||||
{
|
{
|
||||||
@ -163,6 +164,8 @@ namespace elna::boot
|
|||||||
|
|
||||||
virtual std::shared_ptr<type_info> is_type();
|
virtual std::shared_ptr<type_info> is_type();
|
||||||
virtual std::shared_ptr<procedure_info> is_procedure();
|
virtual std::shared_ptr<procedure_info> is_procedure();
|
||||||
|
virtual std::shared_ptr<constant_info> is_constant();
|
||||||
|
virtual std::shared_ptr<variable_info> is_variable();
|
||||||
};
|
};
|
||||||
|
|
||||||
class type_info : public info
|
class type_info : public info
|
||||||
@ -171,7 +174,6 @@ namespace elna::boot
|
|||||||
const type symbol;
|
const type symbol;
|
||||||
|
|
||||||
explicit type_info(const type symbol);
|
explicit type_info(const type symbol);
|
||||||
|
|
||||||
std::shared_ptr<type_info> is_type() override;
|
std::shared_ptr<type_info> is_type() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -182,7 +184,6 @@ namespace elna::boot
|
|||||||
const std::vector<std::string> names;
|
const std::vector<std::string> names;
|
||||||
|
|
||||||
procedure_info(const procedure_type symbol, const std::vector<std::string> names);
|
procedure_info(const procedure_type symbol, const std::vector<std::string> names);
|
||||||
|
|
||||||
std::shared_ptr<procedure_info> is_procedure() override;
|
std::shared_ptr<procedure_info> is_procedure() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -195,6 +196,17 @@ namespace elna::boot
|
|||||||
const variant symbol;
|
const variant symbol;
|
||||||
|
|
||||||
explicit constant_info(const variant& symbol);
|
explicit constant_info(const variant& symbol);
|
||||||
|
std::shared_ptr<constant_info> is_constant() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class variable_info : public info
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const std::string name;
|
||||||
|
const type symbol;
|
||||||
|
|
||||||
|
variable_info(const std::string& name, const type symbol);
|
||||||
|
std::shared_ptr<variable_info> is_variable() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -70,6 +70,7 @@ namespace elna::gcc
|
|||||||
bool expect_trait_type_only(boot::traits_expression *trait);
|
bool expect_trait_type_only(boot::traits_expression *trait);
|
||||||
bool expect_trait_for_integral_type(boot::traits_expression *trait);
|
bool expect_trait_for_integral_type(boot::traits_expression *trait);
|
||||||
void visit_statements(const std::vector<boot::statement *>& statements);
|
void visit_statements(const std::vector<boot::statement *>& statements);
|
||||||
|
bool extract_constant(location_t expression_location);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
generic_visitor(std::shared_ptr<symbol_table> symbol_table,
|
generic_visitor(std::shared_ptr<symbol_table> symbol_table,
|
||||||
|
@ -35,7 +35,6 @@ namespace elna::gcc
|
|||||||
|
|
||||||
bool is_integral_type(tree type);
|
bool is_integral_type(tree type);
|
||||||
bool is_numeric_type(tree type);
|
bool is_numeric_type(tree type);
|
||||||
bool is_primitive_type(tree type);
|
|
||||||
bool is_array_type(tree type);
|
bool is_array_type(tree type);
|
||||||
bool is_void_type(tree type);
|
bool is_void_type(tree type);
|
||||||
|
|
||||||
@ -73,7 +72,8 @@ namespace elna::gcc
|
|||||||
void defer(tree statement_tree);
|
void defer(tree statement_tree);
|
||||||
tree chain_defer();
|
tree chain_defer();
|
||||||
|
|
||||||
tree do_pointer_arithmetic(boot::binary_operator binary_operator, tree left, tree right);
|
tree do_pointer_arithmetic(boot::binary_operator binary_operator,
|
||||||
|
tree left, tree right, location_t expression_location);
|
||||||
tree build_binary_operation(bool condition, boot::binary_expression *expression,
|
tree build_binary_operation(bool condition, boot::binary_expression *expression,
|
||||||
tree_code operator_code, tree left, tree right, tree target_type);
|
tree_code operator_code, tree left, tree right, tree target_type);
|
||||||
tree build_arithmetic_operation(boot::binary_expression *expression,
|
tree build_arithmetic_operation(boot::binary_expression *expression,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user