Implement defer
This commit is contained in:
@ -50,7 +50,7 @@ namespace gcc
|
||||
|
||||
if (return_type == void_type_node)
|
||||
{
|
||||
append_to_statement_list(stmt, &this->current_statements);
|
||||
this->scope.front().append_statement(stmt);
|
||||
this->current_expression = NULL_TREE;
|
||||
}
|
||||
else
|
||||
@ -133,7 +133,7 @@ namespace gcc
|
||||
tree set_result = build2(INIT_EXPR, void_type_node, DECL_RESULT(main_fndecl),
|
||||
build_int_cst_type(integer_type_node, 0));
|
||||
tree return_stmt = build1(RETURN_EXPR, void_type_node, set_result);
|
||||
append_to_statement_list(return_stmt, &this->current_statements);
|
||||
this->scope.front().append_statement(return_stmt);
|
||||
tree_symbol_mapping mapping = leave_scope();
|
||||
|
||||
BLOCK_SUPERCONTEXT(mapping.block()) = this->main_fndecl;
|
||||
@ -161,8 +161,8 @@ namespace gcc
|
||||
: build_type(*definition->return_type());
|
||||
tree declaration_type = build_function_type_array(return_type,
|
||||
definition->parameters.size(), parameter_types.data());
|
||||
this->main_fndecl = build_fn_decl(definition->identifier().c_str(), declaration_type);
|
||||
this->symbol_map->enter(definition->identifier(), this->main_fndecl);
|
||||
this->main_fndecl = build_fn_decl(definition->identifier.c_str(), declaration_type);
|
||||
this->symbol_map->enter(definition->identifier, this->main_fndecl);
|
||||
|
||||
if (definition->body() != nullptr)
|
||||
{
|
||||
@ -178,17 +178,18 @@ namespace gcc
|
||||
auto parameter = definition->parameters.at(i);
|
||||
|
||||
tree declaration_tree = build_decl(get_location(¶meter->position()), PARM_DECL,
|
||||
get_identifier(parameter->identifier().c_str()), parameter_types[i]);
|
||||
get_identifier(parameter->identifier.c_str()), parameter_types[i]);
|
||||
DECL_CONTEXT(declaration_tree) = this->main_fndecl;
|
||||
DECL_ARG_TYPE(declaration_tree) = parameter_types[i];
|
||||
|
||||
if (definition->body() != nullptr)
|
||||
{
|
||||
this->symbol_map->enter(parameter->identifier(), declaration_tree);
|
||||
this->symbol_map->enter(parameter->identifier, declaration_tree);
|
||||
}
|
||||
argument_chain.append(declaration_tree);
|
||||
}
|
||||
DECL_ARGUMENTS(this->main_fndecl) = argument_chain.head();
|
||||
TREE_PUBLIC(this->main_fndecl) = definition->exported;
|
||||
|
||||
if (definition->body() != nullptr)
|
||||
{
|
||||
@ -214,19 +215,29 @@ namespace gcc
|
||||
|
||||
void generic_visitor::enter_scope()
|
||||
{
|
||||
this->current_statements = alloc_stmt_list();
|
||||
this->variable_chain = tree_chain();
|
||||
scope.emplace_front();
|
||||
this->symbol_map = std::make_shared<boot::symbol_table<tree>>(this->symbol_map);
|
||||
}
|
||||
|
||||
tree_symbol_mapping generic_visitor::leave_scope()
|
||||
{
|
||||
tree new_block = build_block(variable_chain.head(),
|
||||
NULL_TREE, NULL_TREE, NULL_TREE);
|
||||
tree bind_expr = build3(BIND_EXPR, void_type_node, variable_chain.head(),
|
||||
this->current_statements, new_block);
|
||||
tree new_block = build_block(this->scope.front().variables.head(),
|
||||
this->scope.front().blocks.head(), NULL_TREE, NULL_TREE);
|
||||
|
||||
for (tree it = this->scope.front().blocks.head(); it != NULL_TREE; it = BLOCK_CHAIN(it))
|
||||
{
|
||||
BLOCK_SUPERCONTEXT(it) = new_block;
|
||||
}
|
||||
tree bind_expr = build3(BIND_EXPR, void_type_node, this->scope.front().variables.head(),
|
||||
this->scope.front().chain_defer(), new_block);
|
||||
this->symbol_map = this->symbol_map->scope();
|
||||
|
||||
scope.pop_front();
|
||||
|
||||
if (!scope.empty())
|
||||
{
|
||||
scope.front().blocks.append(new_block);
|
||||
}
|
||||
return tree_symbol_mapping{ bind_expr, new_block };
|
||||
}
|
||||
|
||||
@ -278,9 +289,29 @@ namespace gcc
|
||||
this->current_expression = null_pointer_node;
|
||||
}
|
||||
|
||||
void generic_visitor::visit(boot::string_literal *string)
|
||||
void generic_visitor::visit(boot::number_literal<std::string> *string)
|
||||
{
|
||||
this->current_expression = build_string_literal(string->string().size() + 1, string->string().c_str());
|
||||
tree index_type = this->symbol_map->lookup("Word");
|
||||
tree index_constant = build_int_cstu(index_type, string->number().size());
|
||||
tree element_type = this->symbol_map->lookup("Char");
|
||||
tree string_type = build_array_type(element_type, build_index_type(index_constant));
|
||||
|
||||
tree string_literal = build_string(string->number().size(), string->number().c_str());
|
||||
TREE_TYPE(string_literal) = string_type;
|
||||
TREE_CONSTANT(string_literal) = 1;
|
||||
TREE_READONLY(string_literal) = 1;
|
||||
TREE_STATIC(string_literal) = 1;
|
||||
|
||||
string_type = build_pointer_type(element_type);
|
||||
string_literal = build4(ARRAY_REF, element_type, string_literal, integer_zero_node, NULL_TREE, NULL_TREE);
|
||||
string_literal = build1(ADDR_EXPR, string_type, string_literal);
|
||||
|
||||
vec<constructor_elt, va_gc> *elms = NULL;
|
||||
tree string_record = this->symbol_map->lookup("String");
|
||||
CONSTRUCTOR_APPEND_ELT(elms, TYPE_FIELDS(string_record), index_constant);
|
||||
CONSTRUCTOR_APPEND_ELT(elms, TREE_CHAIN(TYPE_FIELDS(string_record)), string_literal);
|
||||
|
||||
this->current_expression = build_constructor(string_record, elms);
|
||||
}
|
||||
|
||||
tree generic_visitor::build_arithmetic_operation(boot::binary_expression *expression,
|
||||
@ -424,55 +455,49 @@ namespace gcc
|
||||
definition->body().accept(this);
|
||||
|
||||
tree definition_tree = build_decl(definition_location, CONST_DECL,
|
||||
get_identifier(definition->identifier().c_str()), TREE_TYPE(this->current_expression));
|
||||
auto result = this->symbol_map->enter(definition->identifier(), definition_tree);
|
||||
get_identifier(definition->identifier.c_str()), TREE_TYPE(this->current_expression));
|
||||
auto result = this->symbol_map->enter(definition->identifier, definition_tree);
|
||||
|
||||
if (result)
|
||||
{
|
||||
DECL_INITIAL(definition_tree) = this->current_expression;
|
||||
TREE_CONSTANT(definition_tree) = 1;
|
||||
TREE_READONLY(definition_tree) = 1;
|
||||
TREE_PUBLIC(definition_tree) = definition->exported;
|
||||
|
||||
auto declaration_statement = build1_loc(definition_location, DECL_EXPR,
|
||||
void_type_node, definition_tree);
|
||||
append_to_statement_list(declaration_statement, &this->current_statements);
|
||||
if (!scope.empty())
|
||||
{
|
||||
auto declaration_statement = build1_loc(definition_location, DECL_EXPR,
|
||||
void_type_node, definition_tree);
|
||||
this->scope.front().append_statement(declaration_statement);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
error_at(definition_location,
|
||||
"variable '%s' already declared in this scope",
|
||||
definition->identifier().c_str());
|
||||
definition->identifier.c_str());
|
||||
}
|
||||
this->current_expression = NULL_TREE;
|
||||
}
|
||||
|
||||
void generic_visitor::visit(boot::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 tree_type = build_type(definition->body());
|
||||
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()), tree_type);
|
||||
auto result = this->symbol_map->enter(definition->identifier, tree_type);
|
||||
|
||||
if (result)
|
||||
{
|
||||
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);
|
||||
TREE_PUBLIC(definition_tree) = definition->exported;
|
||||
}
|
||||
else
|
||||
{
|
||||
error_at(definition_location,
|
||||
error_at(get_location(&definition->position()),
|
||||
"type '%s' already declared in this scope",
|
||||
definition->identifier().c_str());
|
||||
definition->identifier.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
@ -535,11 +560,8 @@ namespace gcc
|
||||
{
|
||||
return field_type;
|
||||
}
|
||||
tree field_declaration = build_decl(get_location(&field.second->position()),
|
||||
FIELD_DECL, get_identifier(field.first.c_str()), field_type);
|
||||
TREE_ADDRESSABLE(field_declaration) = 1;
|
||||
DECL_CONTEXT(field_declaration) = record_type_node;
|
||||
|
||||
tree field_declaration = build_field(get_location(&field.second->position()),
|
||||
record_type_node, field.first, field_type);
|
||||
record_chain.append(field_declaration);
|
||||
}
|
||||
TYPE_FIELDS(record_type_node) = record_chain.head();
|
||||
@ -567,11 +589,8 @@ namespace gcc
|
||||
{
|
||||
return field_type;
|
||||
}
|
||||
tree field_declaration = build_decl(get_location(&field.second->position()),
|
||||
FIELD_DECL, get_identifier(field.first.c_str()), field_type);
|
||||
TREE_ADDRESSABLE(field_declaration) = 1;
|
||||
DECL_CONTEXT(field_declaration) = union_type_node;
|
||||
|
||||
tree field_declaration = build_field(get_location(&field.second->position()),
|
||||
union_type_node, field.first, field_type);
|
||||
union_chain.append(field_declaration);
|
||||
}
|
||||
TYPE_FIELDS(union_type_node) = union_chain.head();
|
||||
@ -589,13 +608,13 @@ namespace gcc
|
||||
|
||||
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);
|
||||
bool result = this->symbol_map->enter(declaration->identifier(), declaration_tree);
|
||||
get_identifier(declaration->identifier.c_str()), declaration_type);
|
||||
bool result = this->symbol_map->enter(declaration->identifier, declaration_tree);
|
||||
|
||||
if (!result)
|
||||
{
|
||||
error_at(declaration_location, "variable '%s' already declared in this scope",
|
||||
declaration->identifier().c_str());
|
||||
declaration->identifier.c_str());
|
||||
}
|
||||
else if (this->main_fndecl == NULL_TREE)
|
||||
{
|
||||
@ -606,11 +625,11 @@ namespace gcc
|
||||
else
|
||||
{
|
||||
DECL_CONTEXT(declaration_tree) = this->main_fndecl;
|
||||
variable_chain.append(declaration_tree);
|
||||
this->scope.front().variables.append(declaration_tree);
|
||||
|
||||
auto declaration_statement = build1_loc(declaration_location, DECL_EXPR,
|
||||
void_type_node, declaration_tree);
|
||||
append_to_statement_list(declaration_statement, &this->current_statements);
|
||||
this->scope.front().append_statement(declaration_statement);
|
||||
}
|
||||
}
|
||||
|
||||
@ -705,7 +724,7 @@ namespace gcc
|
||||
tree assignment = build2_loc(statement_location, MODIFY_EXPR,
|
||||
void_type_node, lvalue, this->current_expression);
|
||||
|
||||
append_to_statement_list(assignment, &this->current_statements);
|
||||
this->scope.front().append_statement(assignment);
|
||||
this->current_expression = NULL_TREE;
|
||||
}
|
||||
else
|
||||
@ -731,14 +750,16 @@ namespace gcc
|
||||
}
|
||||
if (statement->alternative() != nullptr)
|
||||
{
|
||||
enter_scope();
|
||||
for (const auto body_statement : *statement->alternative())
|
||||
{
|
||||
body_statement->accept(this);
|
||||
}
|
||||
tree_symbol_mapping mapping = leave_scope();
|
||||
scope.front().append_statement(mapping.bind_expression());
|
||||
}
|
||||
|
||||
tree endif_label_expr = build1(LABEL_EXPR, void_type_node, endif_label_decl);
|
||||
append_to_statement_list(endif_label_expr, &this->current_statements);
|
||||
this->scope.front().append_statement(endif_label_expr);
|
||||
this->current_expression = NULL_TREE;
|
||||
}
|
||||
|
||||
@ -761,19 +782,22 @@ namespace gcc
|
||||
tree goto_else = build1(GOTO_EXPR, void_type_node, else_label_decl);
|
||||
|
||||
auto cond_expr = build3(COND_EXPR, void_type_node, this->current_expression, goto_then, goto_else);
|
||||
append_to_statement_list(cond_expr, &this->current_statements);
|
||||
this->scope.front().append_statement(cond_expr);
|
||||
|
||||
tree then_label_expr = build1(LABEL_EXPR, void_type_node, then_label_decl);
|
||||
append_to_statement_list(then_label_expr, &this->current_statements);
|
||||
this->scope.front().append_statement(then_label_expr);
|
||||
enter_scope();
|
||||
|
||||
for (const auto body_statement : branch.statements)
|
||||
{
|
||||
body_statement->accept(this);
|
||||
}
|
||||
append_to_statement_list(goto_endif, &this->current_statements);
|
||||
tree_symbol_mapping mapping = leave_scope();
|
||||
this->scope.front().append_statement(mapping.bind_expression());
|
||||
this->scope.front().append_statement(goto_endif);
|
||||
|
||||
tree else_label_expr = build1(LABEL_EXPR, void_type_node, else_label_decl);
|
||||
append_to_statement_list(else_label_expr, &this->current_statements);
|
||||
this->scope.front().append_statement(else_label_expr);
|
||||
}
|
||||
|
||||
tree generic_visitor::build_label_decl(const char *name, location_t loc)
|
||||
@ -798,13 +822,15 @@ namespace gcc
|
||||
this->current_expression = error_mark_node;
|
||||
return;
|
||||
}
|
||||
enter_scope();
|
||||
|
||||
auto prerequisite_location = get_location(&statement->body().prerequisite().position());
|
||||
auto body_location = get_location(&statement->position());
|
||||
|
||||
auto prerequisite_label_decl = build_label_decl("while_check", prerequisite_location);
|
||||
auto prerequisite_label_expr = build1_loc(prerequisite_location, LABEL_EXPR,
|
||||
void_type_node, prerequisite_label_decl);
|
||||
append_to_statement_list(prerequisite_label_expr, &this->current_statements);
|
||||
this->scope.front().append_statement(prerequisite_label_expr);
|
||||
|
||||
auto body_label_decl = build_label_decl("while_body", body_location);
|
||||
auto end_label_decl = build_label_decl("end_while", UNKNOWN_LOCATION);
|
||||
@ -816,21 +842,24 @@ namespace gcc
|
||||
|
||||
auto cond_expr = build3_loc(prerequisite_location, COND_EXPR,
|
||||
void_type_node, this->current_expression, goto_body, goto_end);
|
||||
append_to_statement_list(cond_expr, &this->current_statements);
|
||||
this->scope.front().append_statement(cond_expr);
|
||||
|
||||
auto body_label_expr = build1_loc(body_location, LABEL_EXPR,
|
||||
void_type_node, body_label_decl);
|
||||
append_to_statement_list(body_label_expr, &this->current_statements);
|
||||
this->scope.front().append_statement(body_label_expr);
|
||||
|
||||
for (const auto body_statement : statement->body().statements)
|
||||
{
|
||||
body_statement->accept(this);
|
||||
}
|
||||
tree_symbol_mapping mapping = leave_scope();
|
||||
this->scope.front().append_statement(mapping.bind_expression());
|
||||
|
||||
auto goto_check = build1(GOTO_EXPR, void_type_node, prerequisite_label_decl);
|
||||
append_to_statement_list(goto_check, &this->current_statements);
|
||||
this->scope.front().append_statement(goto_check);
|
||||
|
||||
auto endif_label_expr = build1(LABEL_EXPR, void_type_node, end_label_decl);
|
||||
append_to_statement_list(endif_label_expr, &this->current_statements);
|
||||
this->scope.front().append_statement(endif_label_expr);
|
||||
|
||||
this->current_expression = NULL_TREE;
|
||||
}
|
||||
@ -838,7 +867,8 @@ namespace gcc
|
||||
void generic_visitor::visit(boot::call_statement *statement)
|
||||
{
|
||||
statement->body().accept(this);
|
||||
append_to_statement_list(this->current_expression, &this->current_statements);
|
||||
this->scope.front().append_statement(this->current_expression);
|
||||
this->current_expression = NULL_TREE;
|
||||
}
|
||||
|
||||
void generic_visitor::visit(boot::return_statement *statement)
|
||||
@ -854,7 +884,18 @@ namespace gcc
|
||||
tree set_result = build2(INIT_EXPR, void_type_node, DECL_RESULT(main_fndecl),
|
||||
this->current_expression);
|
||||
tree return_stmt = build1(RETURN_EXPR, void_type_node, set_result);
|
||||
append_to_statement_list(return_stmt, &this->current_statements);
|
||||
this->scope.front().append_statement(return_stmt);
|
||||
}
|
||||
|
||||
void generic_visitor::visit(boot::defer_statement *statement)
|
||||
{
|
||||
enter_scope();
|
||||
for (boot::statement *const body_statement : statement->statements)
|
||||
{
|
||||
body_statement->accept(this);
|
||||
}
|
||||
tree_symbol_mapping mapping = leave_scope();
|
||||
scope.front().defer(mapping.bind_expression());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user