Implement enumeration type
This commit is contained in:
@ -57,6 +57,10 @@ namespace elna::gcc
|
||||
{
|
||||
return make_node(UNION_TYPE);
|
||||
}
|
||||
else if (auto reference = type.get<boot::enumeration_type>())
|
||||
{
|
||||
return make_node(ENUMERAL_TYPE);
|
||||
}
|
||||
else if (auto reference = type.get<boot::pointer_type>())
|
||||
{
|
||||
return build_global_pointer_type(get_inner_alias(reference->base, symbols, unresolved, path));
|
||||
@ -227,7 +231,7 @@ namespace elna::gcc
|
||||
build_global_pointer_type(expression_type), this->current_expression);
|
||||
build_procedure_call(call_location, this->current_expression, call->arguments);
|
||||
}
|
||||
else if (is_pointer_type(expression_type) && TREE_CODE(TREE_TYPE(expression_type)) == FUNCTION_TYPE)
|
||||
else if (POINTER_TYPE_P(expression_type) && TREE_CODE(TREE_TYPE(expression_type)) == FUNCTION_TYPE)
|
||||
{
|
||||
build_procedure_call(call_location, this->current_expression, call->arguments);
|
||||
}
|
||||
@ -247,8 +251,7 @@ namespace elna::gcc
|
||||
expression->value().accept(this);
|
||||
tree cast_source = TREE_TYPE(this->current_expression);
|
||||
|
||||
if ((is_primitive_type(cast_target) || is_pointer_type(cast_target))
|
||||
&& (is_primitive_type(cast_source) || is_pointer_type(cast_source)))
|
||||
if (is_castable_type(cast_target) && (is_castable_type(cast_source)))
|
||||
{
|
||||
this->current_expression = build1_loc(get_location(&expression->position()), CONVERT_EXPR,
|
||||
cast_target, this->current_expression);
|
||||
@ -303,7 +306,8 @@ namespace elna::gcc
|
||||
for (boot::constant_definition *const constant : program->constants)
|
||||
{
|
||||
constant->accept(this);
|
||||
} for (boot::type_definition *const type : program->types)
|
||||
}
|
||||
for (boot::type_definition *const type : program->types)
|
||||
{
|
||||
type->accept(this);
|
||||
}
|
||||
@ -514,7 +518,7 @@ namespace elna::gcc
|
||||
tree generic_visitor::build_comparison_operation(boot::binary_expression *expression,
|
||||
tree_code operator_code, tree left, tree right)
|
||||
{
|
||||
return build_binary_operation(is_numeric_type(TREE_TYPE(left)) || is_pointer_type(TREE_TYPE(left)),
|
||||
return build_binary_operation(is_numeric_type(TREE_TYPE(left)) || POINTER_TYPE_P(TREE_TYPE(left)),
|
||||
expression, operator_code, left, right, elna_bool_type_node);
|
||||
}
|
||||
|
||||
@ -624,7 +628,7 @@ namespace elna::gcc
|
||||
|
||||
location_t expression_location = get_location(&expression->position());
|
||||
|
||||
if ((is_pointer_type(left_type) || is_pointer_type(right_type))
|
||||
if ((POINTER_TYPE_P(left_type) || POINTER_TYPE_P(right_type))
|
||||
&& (expression->operation() == boot::binary_operator::sum
|
||||
|| expression->operation() == boot::binary_operator::subtraction))
|
||||
{
|
||||
@ -867,7 +871,7 @@ namespace elna::gcc
|
||||
get_identifier(declaration->identifier.c_str()), this->current_expression);
|
||||
bool result = this->symbols->enter(declaration->identifier, declaration_tree);
|
||||
|
||||
if (is_pointer_type(this->current_expression))
|
||||
if (POINTER_TYPE_P(this->current_expression))
|
||||
{
|
||||
DECL_INITIAL(declaration_tree) = elna_pointer_nil_node;
|
||||
}
|
||||
@ -976,7 +980,7 @@ namespace elna::gcc
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (!is_integral_type(this->current_expression))
|
||||
else if (!is_integral_type(this->current_expression) && TREE_CODE(this->current_expression) != ENUMERAL_TYPE)
|
||||
{
|
||||
error_at(get_location(&trait->position()), "Type '%s' does not support trait '%s'",
|
||||
print_type(this->current_expression).c_str(), trait->name.c_str());
|
||||
@ -1030,7 +1034,7 @@ namespace elna::gcc
|
||||
return;
|
||||
}
|
||||
trait->parameters.front()->accept(this);
|
||||
auto field_type = trait->parameters.at(1)->is_primitive();
|
||||
auto field_type = trait->parameters.at(1)->is_named();
|
||||
|
||||
if (field_type == nullptr)
|
||||
{
|
||||
@ -1076,6 +1080,21 @@ namespace elna::gcc
|
||||
this->current_expression = build1(ADDR_EXPR,
|
||||
build_qualified_type(ptr_type, TYPE_QUAL_CONST), this->current_expression);
|
||||
}
|
||||
else if (TREE_CODE(aggregate_type) == ENUMERAL_TYPE)
|
||||
{
|
||||
tree iterator{ NULL_TREE };
|
||||
|
||||
for (iterator = TYPE_VALUES(aggregate_type); iterator != NULL_TREE; iterator = TREE_CHAIN(iterator))
|
||||
{
|
||||
if (IDENTIFIER_POINTER(TREE_PURPOSE(iterator)) == expression->field())
|
||||
{
|
||||
this->current_expression = TREE_VALUE(iterator);
|
||||
return;
|
||||
}
|
||||
}
|
||||
this->current_expression = error_mark_node;
|
||||
error_at(expression_location, "Unknown enumeration member '%s'", expression->field().c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
tree field_declaration = find_field_by_name(expression_location,
|
||||
@ -1096,7 +1115,7 @@ namespace elna::gcc
|
||||
location_t expression_location = get_location(&expression->position());
|
||||
tree expression_type = TREE_TYPE(this->current_expression);
|
||||
|
||||
if (is_pointer_type(expression_type))
|
||||
if (POINTER_TYPE_P(expression_type))
|
||||
{
|
||||
this->current_expression = build1_loc(expression_location, INDIRECT_REF,
|
||||
TREE_TYPE(expression_type), this->current_expression);
|
||||
@ -1201,16 +1220,6 @@ namespace elna::gcc
|
||||
append_statement(else_label_expr);
|
||||
}
|
||||
|
||||
tree generic_visitor::build_label_decl(const char *name, location_t loc)
|
||||
{
|
||||
auto label_decl = build_decl(loc,
|
||||
LABEL_DECL, get_identifier(name), void_type_node);
|
||||
|
||||
DECL_CONTEXT(label_decl) = current_function_decl;
|
||||
|
||||
return label_decl;
|
||||
}
|
||||
|
||||
void generic_visitor::visit(boot::while_statement *statement)
|
||||
{
|
||||
auto prerequisite_location = get_location(&statement->body().prerequisite().position());
|
||||
@ -1245,7 +1254,7 @@ namespace elna::gcc
|
||||
|
||||
void generic_visitor::visit(boot::return_statement *statement)
|
||||
{
|
||||
boot::expression *return_expression = statement->return_expression();
|
||||
boot::expression *return_expression = statement->return_expression;
|
||||
location_t statement_position = get_location(&statement->position());
|
||||
tree set_result{ NULL_TREE };
|
||||
tree return_type = TREE_TYPE(TREE_TYPE(current_function_decl));
|
||||
@ -1285,7 +1294,7 @@ namespace elna::gcc
|
||||
this->current_expression = NULL_TREE;
|
||||
}
|
||||
|
||||
void generic_visitor::visit(boot::primitive_type_expression *type)
|
||||
void generic_visitor::visit(boot::named_type_expression *type)
|
||||
{
|
||||
auto looked_up = this->unresolved.find(type->name);
|
||||
tree symbol;
|
||||
@ -1362,10 +1371,85 @@ namespace elna::gcc
|
||||
this->current_expression = build_global_pointer_type(procedure_type_node);
|
||||
}
|
||||
|
||||
void generic_visitor::visit(boot::enumeration_type_expression *type)
|
||||
{
|
||||
tree composite_type_node = this->current_expression == NULL_TREE
|
||||
? make_node(ENUMERAL_TYPE)
|
||||
: this->current_expression;
|
||||
location_t enum_location = get_location(&type->position());
|
||||
const tree base_type = integer_type_node;
|
||||
|
||||
TREE_TYPE(composite_type_node) = base_type;
|
||||
ENUM_IS_SCOPED(composite_type_node) = 1;
|
||||
|
||||
tree *pp = &TYPE_VALUES(composite_type_node);
|
||||
std::size_t order{ 1 };
|
||||
|
||||
for (const std::string& member : type->members)
|
||||
{
|
||||
tree member_name = get_identifier(member.c_str());
|
||||
tree member_declaration = build_decl(enum_location, CONST_DECL, member_name, composite_type_node);
|
||||
|
||||
DECL_CONTEXT(member_declaration) = composite_type_node;
|
||||
DECL_INITIAL(member_declaration) = build_int_cst_type(composite_type_node, order++);
|
||||
TREE_CONSTANT(member_declaration) = 1;
|
||||
TREE_READONLY(member_declaration) = 1;
|
||||
|
||||
TYPE_MAX_VALUE(composite_type_node) = DECL_INITIAL(member_declaration);
|
||||
|
||||
*pp = build_tree_list(member_name, member_declaration);
|
||||
pp = &TREE_CHAIN(*pp);
|
||||
}
|
||||
TYPE_MIN_VALUE(composite_type_node) = DECL_INITIAL(TREE_VALUE(TYPE_VALUES(composite_type_node)));
|
||||
TYPE_UNSIGNED(composite_type_node) = TYPE_UNSIGNED(base_type);
|
||||
SET_TYPE_ALIGN(composite_type_node, TYPE_ALIGN(base_type));
|
||||
TYPE_SIZE(composite_type_node) = NULL_TREE;
|
||||
TYPE_PRECISION(composite_type_node) = TYPE_PRECISION(base_type);
|
||||
|
||||
layout_type(composite_type_node);
|
||||
}
|
||||
|
||||
void generic_visitor::visit(boot::defer_statement *statement)
|
||||
{
|
||||
enter_scope();
|
||||
visit_statements(statement->statements);
|
||||
defer(leave_scope());
|
||||
}
|
||||
|
||||
void generic_visitor::visit(boot::case_statement *statement)
|
||||
{
|
||||
statement->condition().accept(this);
|
||||
|
||||
tree condition_expression = this->current_expression;
|
||||
tree end_label_declaration = create_artificial_label(UNKNOWN_LOCATION);
|
||||
tree switch_statements = alloc_stmt_list();
|
||||
|
||||
for (const boot::switch_case& case_block : statement->cases)
|
||||
{
|
||||
for (boot::literal_expression *const case_label : case_block.labels)
|
||||
{
|
||||
case_label->accept(this);
|
||||
tree case_label_declaration = create_artificial_label(get_location(&case_label->position()));
|
||||
tree case_expression = build_case_label(this->current_expression, NULL_TREE, case_label_declaration);
|
||||
|
||||
append_to_statement_list(case_expression, &switch_statements);
|
||||
}
|
||||
enter_scope();
|
||||
visit_statements(case_block.statements);
|
||||
append_to_statement_list(leave_scope(), &switch_statements);
|
||||
tree goto_end = fold_build1(GOTO_EXPR, void_type_node, end_label_declaration);
|
||||
|
||||
append_to_statement_list(goto_end, &switch_statements);
|
||||
TREE_USED(end_label_declaration) = 1;
|
||||
}
|
||||
tree switch_expression = build2(SWITCH_EXPR, TREE_TYPE(condition_expression),
|
||||
condition_expression, switch_statements);
|
||||
|
||||
append_statement(switch_expression);
|
||||
|
||||
tree end_label_expression = build1(LABEL_EXPR, void_type_node, end_label_declaration);
|
||||
append_statement(end_label_expression);
|
||||
|
||||
this->current_expression = NULL_TREE;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user