Implement defer
This commit is contained in:
@ -87,17 +87,18 @@ elna.stagefeedback: stagefeedback-start
|
||||
-mv elna/*$(objext) stagefeedback/elna
|
||||
|
||||
ELNA_INCLUDES = -I $(srcdir)/elna/include -I elna/generated
|
||||
ELNA_CXXFLAGS = -std=c++14
|
||||
|
||||
elna/%.o: elna/boot/%.cc elna/generated/parser.hh elna/generated/location.hh
|
||||
$(COMPILE) $(ELNA_INCLUDES) $<
|
||||
$(COMPILE) $(ELNA_CXXFLAGS) $(ELNA_INCLUDES) $<
|
||||
$(POSTCOMPILE)
|
||||
|
||||
elna/%.o: elna/generated/%.cc elna/generated/parser.hh elna/generated/location.hh
|
||||
$(COMPILE) $(ELNA_INCLUDES) $<
|
||||
$(COMPILE) $(ELNA_CXXFLAGS) $(ELNA_INCLUDES) $<
|
||||
$(POSTCOMPILE)
|
||||
|
||||
elna/%.o: elna/gcc/%.cc elna/generated/parser.hh elna/generated/location.hh
|
||||
$(COMPILE) $(ELNA_INCLUDES) $<
|
||||
$(COMPILE) $(ELNA_CXXFLAGS) $(ELNA_INCLUDES) $<
|
||||
$(POSTCOMPILE)
|
||||
|
||||
elna/generated/parser.cc: elna/boot/parser.yy
|
||||
|
@ -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;
|
||||
@ -214,19 +214,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 +288,9 @@ 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());
|
||||
this->current_expression = build_string_literal(string->number().size() + 1, string->number().c_str());
|
||||
}
|
||||
|
||||
tree generic_visitor::build_arithmetic_operation(boot::binary_expression *expression,
|
||||
@ -433,9 +443,12 @@ namespace gcc
|
||||
TREE_CONSTANT(definition_tree) = 1;
|
||||
TREE_READONLY(definition_tree) = 1;
|
||||
|
||||
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
|
||||
{
|
||||
@ -450,27 +463,9 @@ namespace gcc
|
||||
{
|
||||
tree tree_type = build_type(definition->body());
|
||||
|
||||
if (tree_type == NULL_TREE)
|
||||
if (!this->symbol_map->enter(definition->identifier(), tree_type))
|
||||
{
|
||||
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->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);
|
||||
}
|
||||
else
|
||||
{
|
||||
error_at(definition_location,
|
||||
error_at(get_location(&definition->position()),
|
||||
"type '%s' already declared in this scope",
|
||||
definition->identifier().c_str());
|
||||
}
|
||||
@ -606,11 +601,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 +700,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 +726,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 +758,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 +798,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 +818,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 +843,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 +860,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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -60,6 +60,11 @@ namespace gcc
|
||||
TREE_CHAIN(this->last) = t;
|
||||
}
|
||||
|
||||
void block_chain::chain(tree t)
|
||||
{
|
||||
BLOCK_CHAIN(this->last) = t;
|
||||
}
|
||||
|
||||
tree_symbol_mapping::tree_symbol_mapping(tree bind_expression, tree block)
|
||||
: m_bind_expression(bind_expression), m_block(block)
|
||||
{
|
||||
@ -75,6 +80,47 @@ namespace gcc
|
||||
return m_block;
|
||||
}
|
||||
|
||||
block_scope::block_scope()
|
||||
: m_statement_list(alloc_stmt_list())
|
||||
{
|
||||
}
|
||||
|
||||
void block_scope::append_statement(tree statement_tree)
|
||||
{
|
||||
if (!defers.empty())
|
||||
{
|
||||
append_to_statement_list(statement_tree, &this->defers.front().second);
|
||||
}
|
||||
else
|
||||
{
|
||||
append_to_statement_list(statement_tree, &this->m_statement_list);
|
||||
}
|
||||
}
|
||||
|
||||
void block_scope::defer(tree statement_tree)
|
||||
{
|
||||
defers.push_front({ statement_tree, alloc_stmt_list() });
|
||||
}
|
||||
|
||||
tree block_scope::chain_defer()
|
||||
{
|
||||
if (this->defers.empty())
|
||||
{
|
||||
return m_statement_list;
|
||||
}
|
||||
std::forward_list<std::pair<tree, tree>>::iterator defer_iterator =
|
||||
this->defers.begin();
|
||||
tree defer_tree = build2(TRY_FINALLY_EXPR, void_type_node, defer_iterator->second, defer_iterator->first);
|
||||
|
||||
++defer_iterator;
|
||||
for (; defer_iterator != this->defers.end(); ++defer_iterator)
|
||||
{
|
||||
append_to_statement_list(defer_tree, &defer_iterator->second);
|
||||
defer_tree = build2(TRY_FINALLY_EXPR, void_type_node, defer_iterator->second, defer_iterator->first);
|
||||
}
|
||||
return build2(COMPOUND_EXPR, TREE_TYPE(defer_tree), m_statement_list, defer_tree);
|
||||
}
|
||||
|
||||
std::shared_ptr<boot::symbol_table<tree>> builtin_symbol_table()
|
||||
{
|
||||
std::shared_ptr<boot::symbol_table<tree>> initial_table =
|
||||
|
Reference in New Issue
Block a user