Replace build_type with visitor functions
This commit is contained in:
@ -164,8 +164,8 @@ namespace gcc
|
||||
|
||||
void generic_visitor::visit(boot::cast_expression *expression)
|
||||
{
|
||||
tree cast_target = build_type(expression->target());
|
||||
gcc_assert(cast_target != NULL_TREE);
|
||||
expression->target().accept(this);
|
||||
tree cast_target = this->current_expression;
|
||||
|
||||
expression->value().accept(this);
|
||||
|
||||
@ -732,15 +732,16 @@ namespace gcc
|
||||
void generic_visitor::visit(boot::type_definition *definition)
|
||||
{
|
||||
location_t definition_location = get_location(&definition->position());
|
||||
tree tree_type = build_type(definition->body());
|
||||
definition->body().accept(this);
|
||||
|
||||
tree definition_tree = build_decl(definition_location, TYPE_DECL,
|
||||
get_identifier(definition->identifier.c_str()), tree_type);
|
||||
auto result = this->symbol_map->enter(definition->identifier, tree_type);
|
||||
get_identifier(definition->identifier.c_str()), this->current_expression);
|
||||
auto result = this->symbol_map->enter(definition->identifier, this->current_expression);
|
||||
|
||||
if (result)
|
||||
{
|
||||
TREE_PUBLIC(definition_tree) = definition->exported;
|
||||
TYPE_NAME(tree_type) = get_identifier(definition->identifier.c_str());
|
||||
TYPE_NAME(this->current_expression) = get_identifier(definition->identifier.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -748,6 +749,7 @@ namespace gcc
|
||||
"type '%s' already declared in this scope",
|
||||
definition->identifier.c_str());
|
||||
}
|
||||
this->current_expression = NULL_TREE;
|
||||
}
|
||||
|
||||
tree generic_visitor::build_procedure_type(boot::procedure_type& type)
|
||||
@ -756,130 +758,36 @@ namespace gcc
|
||||
|
||||
for (std::size_t i = 0; i < type.parameters.size(); ++i)
|
||||
{
|
||||
parameter_types[i] = build_type(type.parameters.at(i)->variable_type());
|
||||
boot::top_type& parameter_type = type.parameters.at(i)->variable_type();
|
||||
parameter_type.accept(this);
|
||||
parameter_types[i] = this->current_expression;
|
||||
}
|
||||
tree return_type = type.return_type == nullptr
|
||||
? void_type_node
|
||||
: build_type(*type.return_type);
|
||||
tree return_type = void_type_node;
|
||||
|
||||
if (type.return_type != nullptr)
|
||||
{
|
||||
type.return_type->accept(this);
|
||||
return_type = this->current_expression;
|
||||
}
|
||||
this->current_expression = NULL_TREE;
|
||||
|
||||
return build_function_type_array(return_type, type.parameters.size(), parameter_types.data());
|
||||
}
|
||||
|
||||
tree generic_visitor::build_type(boot::top_type& type)
|
||||
{
|
||||
if (std::shared_ptr<boot::basic_type> basic_type = type.is_basic())
|
||||
{
|
||||
tree symbol = this->lookup(basic_type->base_name());
|
||||
|
||||
if (symbol != NULL_TREE && TYPE_P(symbol))
|
||||
{
|
||||
return symbol;
|
||||
}
|
||||
error_at(get_location(&basic_type->position()),
|
||||
"type '%s' not declared", basic_type->base_name().c_str());
|
||||
|
||||
return error_mark_node;
|
||||
}
|
||||
else if (std::shared_ptr<boot::array_type> array_type = type.is_array())
|
||||
{
|
||||
tree lower_bound = build_int_cst_type(integer_type_node, 0);
|
||||
tree upper_bound = build_int_cst_type(integer_type_node, array_type->size);
|
||||
tree base_type = build_type(array_type->base());
|
||||
|
||||
if (base_type == NULL_TREE || base_type == error_mark_node)
|
||||
{
|
||||
return base_type;
|
||||
}
|
||||
tree range_type = build_range_type(integer_type_node, lower_bound, upper_bound);
|
||||
|
||||
return build_array_type(base_type, range_type);
|
||||
}
|
||||
else if (std::shared_ptr<boot::pointer_type> pointer_type = type.is_pointer())
|
||||
{
|
||||
tree base_type = build_type(pointer_type->base());
|
||||
|
||||
if (base_type == NULL_TREE || base_type == error_mark_node)
|
||||
{
|
||||
return base_type;
|
||||
}
|
||||
return build_pointer_type_for_mode(base_type, VOIDmode, true);
|
||||
}
|
||||
else if (std::shared_ptr<boot::record_type> record_type = type.is_record())
|
||||
{
|
||||
std::set<std::string> field_names;
|
||||
tree record_type_node = make_node(RECORD_TYPE);
|
||||
|
||||
for (auto& field : record_type->fields)
|
||||
{
|
||||
if (field_names.find(field.first) != field_names.cend())
|
||||
{
|
||||
error_at(get_location(&field.second->position()), "repeated field name");
|
||||
return error_mark_node;
|
||||
}
|
||||
field_names.insert(field.first);
|
||||
|
||||
tree field_type = build_type(*field.second);
|
||||
if (field_type == NULL_TREE || field_type == error_mark_node)
|
||||
{
|
||||
return field_type;
|
||||
}
|
||||
tree field_declaration = build_field(get_location(&field.second->position()),
|
||||
record_type_node, field.first, field_type);
|
||||
TYPE_FIELDS(record_type_node) = chainon(TYPE_FIELDS(record_type_node), field_declaration);
|
||||
}
|
||||
layout_type(record_type_node);
|
||||
|
||||
return record_type_node;
|
||||
}
|
||||
else if (std::shared_ptr<boot::union_type> union_type = type.is_union())
|
||||
{
|
||||
std::set<std::string> field_names;
|
||||
tree union_type_node = make_node(UNION_TYPE);
|
||||
|
||||
for (auto& field : union_type->fields)
|
||||
{
|
||||
if (field_names.find(field.first) != field_names.cend())
|
||||
{
|
||||
error_at(get_location(&field.second->position()), "repeated field name");
|
||||
return error_mark_node;
|
||||
}
|
||||
field_names.insert(field.first);
|
||||
|
||||
tree field_type = build_type(*field.second);
|
||||
if (field_type == NULL_TREE || field_type == error_mark_node)
|
||||
{
|
||||
return field_type;
|
||||
}
|
||||
tree field_declaration = build_field(get_location(&field.second->position()),
|
||||
union_type_node, field.first, field_type);
|
||||
TYPE_FIELDS(union_type_node) = chainon(TYPE_FIELDS(union_type_node), field_declaration);
|
||||
}
|
||||
layout_type(union_type_node);
|
||||
|
||||
return union_type_node;
|
||||
}
|
||||
else if (std::shared_ptr<boot::procedure_type> procedure_type = type.is_procedure())
|
||||
{
|
||||
tree procedure_type_node = build_procedure_type(*procedure_type);
|
||||
return build_pointer_type_for_mode(procedure_type_node, VOIDmode, true);
|
||||
}
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
void generic_visitor::visit(boot::variable_declaration *declaration)
|
||||
{
|
||||
tree declaration_type = build_type(declaration->variable_type());
|
||||
gcc_assert(declaration_type != NULL_TREE);
|
||||
declaration->variable_type().accept(this);
|
||||
|
||||
location_t declaration_location = get_location(&declaration->position());
|
||||
tree declaration_tree = build_decl(declaration_location, VAR_DECL,
|
||||
get_identifier(declaration->identifier.c_str()), declaration_type);
|
||||
get_identifier(declaration->identifier.c_str()), this->current_expression);
|
||||
bool result = this->symbol_map->enter(declaration->identifier, declaration_tree);
|
||||
|
||||
if (is_pointer_type(declaration_type))
|
||||
if (is_pointer_type(this->current_expression))
|
||||
{
|
||||
DECL_INITIAL(declaration_tree) = elna_pointer_nil_node;
|
||||
}
|
||||
this->current_expression = NULL_TREE;
|
||||
if (!result)
|
||||
{
|
||||
error_at(declaration_location, "variable '%s' already declared in this scope",
|
||||
@ -967,28 +875,30 @@ namespace gcc
|
||||
|
||||
void generic_visitor::visit(boot::traits_expression *trait)
|
||||
{
|
||||
tree type_expression = build_type(trait->type());
|
||||
trait->type().accept(this);
|
||||
|
||||
if (trait->name == "size")
|
||||
{
|
||||
this->current_expression = build1(CONVERT_EXPR, elna_word_type_node, size_in_bytes(type_expression));
|
||||
this->current_expression = build1(CONVERT_EXPR, elna_word_type_node,
|
||||
size_in_bytes(this->current_expression));
|
||||
}
|
||||
else if (trait->name == "alignment")
|
||||
{
|
||||
this->current_expression = build_int_cstu(elna_word_type_node, TYPE_ALIGN_UNIT(type_expression));
|
||||
this->current_expression = build_int_cstu(elna_word_type_node,
|
||||
TYPE_ALIGN_UNIT(this->current_expression));
|
||||
}
|
||||
else if (trait->name == "min" && is_integral_type(type_expression))
|
||||
else if (trait->name == "min" && is_integral_type(this->current_expression))
|
||||
{
|
||||
this->current_expression = TYPE_MIN_VALUE(type_expression);
|
||||
this->current_expression = TYPE_MIN_VALUE(this->current_expression);
|
||||
}
|
||||
else if (trait->name == "max" && is_integral_type(type_expression))
|
||||
else if (trait->name == "max" && is_integral_type(this->current_expression))
|
||||
{
|
||||
this->current_expression = TYPE_MAX_VALUE(type_expression);
|
||||
this->current_expression = TYPE_MAX_VALUE(this->current_expression);
|
||||
}
|
||||
else
|
||||
{
|
||||
error_at(get_location(&trait->position()), "type '%s' does not have property '%s'",
|
||||
print_type(type_expression).c_str(), trait->name.c_str());
|
||||
print_type(this->current_expression).c_str(), trait->name.c_str());
|
||||
this->current_expression = error_mark_node;
|
||||
}
|
||||
}
|
||||
@ -1190,5 +1100,111 @@ namespace gcc
|
||||
|
||||
this->current_expression = NULL_TREE;
|
||||
}
|
||||
|
||||
void generic_visitor::visit(boot::basic_type *type)
|
||||
{
|
||||
tree symbol = this->lookup(type->base_name());
|
||||
|
||||
if (symbol == NULL_TREE && TYPE_P(symbol))
|
||||
{
|
||||
error_at(get_location(&type->position()),
|
||||
"type '%s' not declared", type->base_name().c_str());
|
||||
|
||||
this->current_expression = error_mark_node;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->current_expression = symbol;
|
||||
}
|
||||
}
|
||||
|
||||
void generic_visitor::visit(boot::array_type *type)
|
||||
{
|
||||
tree lower_bound = build_int_cst_type(integer_type_node, 0);
|
||||
tree upper_bound = build_int_cst_type(integer_type_node, type->size);
|
||||
type->base().accept(this);
|
||||
|
||||
if (this->current_expression != NULL_TREE && this->current_expression != error_mark_node)
|
||||
{
|
||||
tree range_type = build_range_type(integer_type_node, lower_bound, upper_bound);
|
||||
|
||||
this->current_expression = build_array_type(this->current_expression, range_type);
|
||||
}
|
||||
}
|
||||
|
||||
void generic_visitor::visit(boot::pointer_type *type)
|
||||
{
|
||||
type->base().accept(this);
|
||||
|
||||
if (this->current_expression != NULL_TREE && this->current_expression != error_mark_node)
|
||||
{
|
||||
this->current_expression = build_pointer_type_for_mode(this->current_expression, VOIDmode, true);
|
||||
}
|
||||
}
|
||||
|
||||
void generic_visitor::visit(boot::record_type *type)
|
||||
{
|
||||
std::set<std::string> field_names;
|
||||
tree record_type_node = make_node(RECORD_TYPE);
|
||||
|
||||
for (auto& field : type->fields)
|
||||
{
|
||||
if (field_names.find(field.first) != field_names.cend())
|
||||
{
|
||||
error_at(get_location(&field.second->position()), "repeated field name");
|
||||
this->current_expression = error_mark_node;
|
||||
return;
|
||||
}
|
||||
field_names.insert(field.first);
|
||||
|
||||
field.second->accept(this);
|
||||
if (this->current_expression == NULL_TREE || this->current_expression == error_mark_node)
|
||||
{
|
||||
return;
|
||||
}
|
||||
tree field_declaration = build_field(get_location(&field.second->position()),
|
||||
record_type_node, field.first, this->current_expression);
|
||||
TYPE_FIELDS(record_type_node) = chainon(TYPE_FIELDS(record_type_node), field_declaration);
|
||||
}
|
||||
layout_type(record_type_node);
|
||||
|
||||
this->current_expression = record_type_node;
|
||||
}
|
||||
|
||||
void generic_visitor::visit(boot::union_type *type)
|
||||
{
|
||||
std::set<std::string> field_names;
|
||||
tree union_type_node = make_node(UNION_TYPE);
|
||||
|
||||
for (auto& field : type->fields)
|
||||
{
|
||||
if (field_names.find(field.first) != field_names.cend())
|
||||
{
|
||||
error_at(get_location(&field.second->position()), "repeated field name");
|
||||
this->current_expression = error_mark_node;
|
||||
return;
|
||||
}
|
||||
field_names.insert(field.first);
|
||||
|
||||
field.second->accept(this);
|
||||
if (this->current_expression == NULL_TREE || this->current_expression == error_mark_node)
|
||||
{
|
||||
return;
|
||||
}
|
||||
tree field_declaration = build_field(get_location(&field.second->position()),
|
||||
union_type_node, field.first, this->current_expression);
|
||||
TYPE_FIELDS(union_type_node) = chainon(TYPE_FIELDS(union_type_node), field_declaration);
|
||||
}
|
||||
layout_type(union_type_node);
|
||||
|
||||
this->current_expression = union_type_node;
|
||||
}
|
||||
|
||||
void generic_visitor::visit(boot::procedure_type *type)
|
||||
{
|
||||
tree procedure_type_node = build_procedure_type(*type);
|
||||
this->current_expression = build_pointer_type_for_mode(procedure_type_node, VOIDmode, true);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user