Allow declaring type synonyms
This commit is contained in:
@ -282,6 +282,36 @@ namespace gcc
|
||||
this->current_expression = NULL_TREE;
|
||||
}
|
||||
|
||||
void generic_visitor::visit(source::type_definition *definition)
|
||||
{
|
||||
tree tree_type = build_type(definition->body());
|
||||
|
||||
if (tree_type == NULL_TREE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
location_t definition_location = get_location(&definition->position());
|
||||
tree definition_tree = build_decl(definition_location, TYPE_DECL,
|
||||
get_identifier(definition->identifier().c_str()), tree_type);
|
||||
auto result = this->symbol_map.insert({ definition->identifier(), definition_tree });
|
||||
|
||||
if (result.second)
|
||||
{
|
||||
DECL_CONTEXT(definition_tree) = this->main_fndecl;
|
||||
variable_chain.append(definition_tree);
|
||||
|
||||
auto declaration_statement = build1_loc(definition_location, DECL_EXPR,
|
||||
void_type_node, definition_tree);
|
||||
append_to_statement_list(declaration_statement, &this->current_statements);
|
||||
}
|
||||
else
|
||||
{
|
||||
error_at(definition_location,
|
||||
"type '%s' already declared in this scope",
|
||||
definition->identifier().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
tree generic_visitor::build_type(source::type_expression& type)
|
||||
{
|
||||
if (source::basic_type_expression *basic_type = type.is_basic())
|
||||
@ -306,6 +336,12 @@ namespace gcc
|
||||
{
|
||||
return elna_string_type_node;
|
||||
}
|
||||
auto symbol = this->symbol_map.find(basic_type->base_name());
|
||||
|
||||
if (symbol != this->symbol_map.end())
|
||||
{
|
||||
return TREE_TYPE(symbol->second);
|
||||
}
|
||||
}
|
||||
else if (source::array_type_expression *array_type = type.is_array())
|
||||
{
|
||||
@ -371,39 +407,47 @@ namespace gcc
|
||||
this->current_expression = symbol->second;
|
||||
}
|
||||
|
||||
void generic_visitor::visit(source::array_access_expression *expression)
|
||||
{
|
||||
expression->base().accept(this);
|
||||
tree designator = this->current_expression;
|
||||
|
||||
expression->index().accept(this);
|
||||
tree index = this->current_expression;
|
||||
|
||||
tree element_type = TREE_TYPE(TREE_TYPE(designator));
|
||||
|
||||
this->current_expression = build4_loc(get_location(&expression->position()),
|
||||
ARRAY_REF, element_type, designator, index, NULL_TREE, NULL_TREE);
|
||||
}
|
||||
|
||||
void generic_visitor::visit(source::assign_statement *statement)
|
||||
{
|
||||
auto lvalue = this->symbol_map.find(statement->lvalue());
|
||||
statement->lvalue().accept(this);
|
||||
|
||||
auto lvalue = this->current_expression;
|
||||
auto statement_location = get_location(&statement->position());
|
||||
|
||||
if (lvalue == this->symbol_map.end())
|
||||
{
|
||||
error_at(statement_location,
|
||||
"variable '%s' not declared in the current scope",
|
||||
statement->lvalue().c_str());
|
||||
return;
|
||||
}
|
||||
statement->rvalue().accept(this);
|
||||
|
||||
if (TREE_CODE(lvalue->second) == CONST_DECL)
|
||||
if (TREE_CODE(lvalue) == CONST_DECL)
|
||||
{
|
||||
error_at(statement_location, "cannot modify constant '%s'",
|
||||
statement->lvalue().c_str());
|
||||
statement->lvalue().is_variable()->name().c_str());
|
||||
this->current_expression = error_mark_node;
|
||||
return;
|
||||
}
|
||||
if (TREE_TYPE(this->current_expression) != TREE_TYPE(lvalue->second))
|
||||
if (TREE_TYPE(this->current_expression) != TREE_TYPE(lvalue))
|
||||
{
|
||||
error_at(statement_location,
|
||||
"cannot assign value of type %s to variable '%s' of type %s",
|
||||
"cannot assign value of type %s to variable of type %s",
|
||||
print_type(TREE_TYPE(this->current_expression)),
|
||||
statement->lvalue().c_str(),
|
||||
print_type(TREE_TYPE(lvalue->second)));
|
||||
print_type(TREE_TYPE(lvalue)));
|
||||
this->current_expression = error_mark_node;
|
||||
return;
|
||||
}
|
||||
auto assignment = build2_loc(statement_location, MODIFY_EXPR,
|
||||
void_type_node, lvalue->second, this->current_expression);
|
||||
void_type_node, lvalue, this->current_expression);
|
||||
|
||||
append_to_statement_list(assignment, &this->current_statements);
|
||||
this->current_expression = NULL_TREE;
|
||||
|
Reference in New Issue
Block a user