Refactor parameter destruction into obj_lower

This commit is contained in:
Nathan Braswell
2016-06-24 01:42:48 -07:00
parent 29eff2a23e
commit e3607beabe
4 changed files with 18 additions and 104 deletions

View File

@@ -204,7 +204,6 @@ obj c_generator (Object) {
parameters = type_to_c(enclosing_object->type_def.self_type) + "* this"
}
if (backing.closed_variables.size()) {
/*println("HAS CLOSED VARIABLES")*/
if (parameter_types != "") { parameter_types += ", "; parameters += ", ";}
var closed_type_name = get_closure_struct_type(backing.closed_variables)
parameter_types += closed_type_name + "*"
@@ -220,11 +219,6 @@ obj c_generator (Object) {
if (parameter_types != "") { parameter_types += ", "; parameters += ", ";}
parameter_types += type_to_c(parameter->identifier.type)
parameters += type_to_c(parameter->identifier.type) + " " + get_name(parameter)
// add parameters to destructor thingy (for returns)? Or should that be a different pass?
var parameter_type = parameter->identifier.type
if (!parameter_type->is_ref && parameter_type->indirection == 0 && (parameter_type->is_object() && has_method(parameter_type->type_def, "destruct", vector<*type>())))
defer_stack->top().second.push(ast_statement_ptr(make_method_call(parameter, "destruct", vector<*ast_node>())))
})
if (backing.is_variadic) {
parameter_types += ", ..."
@@ -352,7 +346,6 @@ obj c_generator (Object) {
structs += "};\n"
})
/*return make_pair(prequal+plain_typedefs+top_level_c_passthrough+variable_extern_declarations+structs+function_typedef_string+closure_struct_definitions+function_prototypes+variable_declarations+function_definitions + "\n", linker_string)*/
return make_pair(prequal+plain_typedefs+function_typedef_string+top_level_c_passthrough+variable_extern_declarations+structs+closure_struct_definitions+function_prototypes+variable_declarations+function_definitions + "\n", linker_string)
}
fun get_closure_struct_type(closed_variables: set<*ast_node>): string {
@@ -493,8 +486,7 @@ obj c_generator (Object) {
var function_return_type = get_ast_type(enclosing_func)->return_type
var to_ret = code_triple()
// new one
to_ret += code_triple("return")
to_ret += "return"
var refamp = string()
if (function_return_type->is_ref)
refamp = "&"
@@ -502,46 +494,6 @@ obj c_generator (Object) {
to_ret += code_triple(" ") + refamp + generate(return_value, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false)
to_ret.pre += generate_from_defer_stack(defer_stack, -1, enclosing_object, enclosing_func).one_string()
return to_ret
if (return_value) {
var return_value_type = get_ast_type(return_value)
// always need a return temp so we don't destruct things the return depends on before they're calculated
// if we're returning an object, copy_construct a new one to return
// if we're returning a ref, we need to account for that in the temp type
// note the temp type is a pointer, not a ref so we don't have the deref/ref thing on return
// now use the function_return_type instead so we don't make a ref
// var temp_ident_type = return_value_type
var temp_ident_type = function_return_type
if (function_return_type->is_ref)
temp_ident_type = temp_ident_type->clone_with_increased_indirection()
var temp_ident = ast_identifier_ptr(string("temporary_return")+get_id(), temp_ident_type, null<ast_node>())
var declaration = ast_declaration_statement_ptr(temp_ident, null<ast_node>(), false)
// have to pass false to the declaration generator, so can't do it through generate_statement
to_ret.pre = generate_declaration_statement(declaration, enclosing_object, enclosing_func, defer_stack, false).one_string() + ";\n"
if ((function_return_type->is_object() || return_value_type->is_object()) && !function_return_type->equality(return_value_type, false))
// note the clone with decreased indirection because of the clone with increased indirection above
error(ast_to_syntax[node], string("return type does not match: ") + function_return_type->to_string() + ", " + return_value_type->to_string());
if (!function_return_type->is_ref && return_value_type->indirection == 0 && (return_value_type->is_object() && has_method(return_value_type->type_def, "copy_construct", vector(return_value_type->clone_with_indirection(1))))) {
to_ret.pre += generate_statement(ast_statement_ptr(make_method_call(temp_ident, "copy_construct", vector(make_operator_call("&", vector(return_value))))), enclosing_object, enclosing_func, defer_stack).one_string()
} else {
var refamp = string()
if (function_return_type->is_ref)
refamp = "&"
to_ret.pre += (generate(temp_ident, enclosing_object, enclosing_func, defer_stack, false) + " = " + refamp + generate(return_value, enclosing_object, enclosing_func, defer_stack, false) + ";").one_string() + ";\n"
}
// make this new identifier the new return value
return_value = temp_ident
}
to_ret += code_triple("return")
if (return_value)
to_ret += code_triple(" ") + generate(return_value, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false)
// generate all in stack by passing -1, make sure added after we calculate the return value
to_ret.pre += generate_from_defer_stack(defer_stack, -1, enclosing_object, enclosing_func).one_string()
return to_ret
}
fun generate_branching_statement(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, defer_stack: *stack<pair<bool,stack<*ast_node>>>): code_triple {
// -2 means generate up through loop
@@ -565,7 +517,6 @@ obj c_generator (Object) {
}
for (var i = 0; i < num; i++;) {
defer_stack->push(make_pair(false, stack<*ast_node>()))
/*defer_stack->from_top(i+1).second.for_each_reverse(fun(node: *ast_node) to_ret += generate(node, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false);)*/
defer_stack->from_top(i+1).second.for_each_reverse(fun(node: *ast_node) to_ret += generate(node, enclosing_object, enclosing_func, defer_stack, false);)
if (defer_stack->top().second.size())
to_ret += generate_from_defer_stack(defer_stack, 1, enclosing_object, enclosing_func);
@@ -627,8 +578,6 @@ obj c_generator (Object) {
var declaration = ast_declaration_statement_ptr(temp_ident, null<ast_node>(), false)
// have to pass false to the declaration generator, so can't do it through generate_statement
var trip_ret = code_triple()
// trip_ret.pre += generate_declaration_statement(declaration, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false).one_string() + " = " + to_ret + ";\n"
// trip_ret.value = generate_identifier(temp_ident, enclosing_object, enclosing_func).one_string()
trip_ret.pre += generate_declaration_statement(declaration, null<ast_node>(), null<ast_node>(), null<stack<pair<bool,stack<*ast_node>>>>(), false).one_string() + " = " + to_ret + ";\n"
trip_ret.value = generate_identifier(temp_ident, null<ast_node>(), null<ast_node>()).one_string()
return trip_ret
@@ -794,7 +743,6 @@ obj c_generator (Object) {
}
if (!is_function(node->function_call.func) || node->function_call.func->function.closed_variables.size()) {
// not function, so we must be an identifier or function call return or something
/*println(get_ast_name(node->function_call.func) + " is not a function! must be a lambda or something")*/
if (!dot_style_method_call) {
// lambda
if (pre_call == "" && (!func_return_type->is_void() || func_return_type->indirection)) {
@@ -994,7 +942,6 @@ obj c_generator (Object) {
// TODO keyword avoid seems not to work
if (make_unique && (ast_name_map.contains_value(result) || c_keyword_avoid.contains(result)))
result += get_id()
/*println("HERE: " + result)*/
ast_name_map.set(node, result)
return result
}
@@ -1017,4 +964,3 @@ obj c_generator (Object) {
}
}

View File

@@ -20,11 +20,9 @@ fun defer_lower(name_ast_map: *map<string, pair<*tree<symbol>,*ast_node>>, ast_t
match(*node) {
ast_node::defer_statement(backing) {
if (is_code_block(parent_chain->top()) || (is_statement(parent_chain->top()) && is_code_block(parent_chain->from_top(1)))) {
/*println("defer in codeblock, gonna add at the end")*/
remove_full_statement(node, parent_chain)
defer_double_stack.top().push(backing.statement)
} else {
/*println("defer not in codeblock, so just removing defer part")*/
replace_with_in(node, backing.statement, parent_chain)
}
}

View File

@@ -15,26 +15,37 @@ fun obj_lower(name_ast_map: *map<string, pair<*tree<symbol>,*ast_node>>, ast_to_
name_ast_map->for_each(fun(name: string, syntax_ast_pair: pair<*tree<symbol>,*ast_node>) {
var helper_before = fun(node: *ast_node, parent_chain: *stack<*ast_node>) {
match(*node) {
ast_node::type_def(backing) {
/*println(backing.name + ": enter")*/
ast_node::function(backing) if (backing.body_statement && !is_code_block(backing.body_statement)) backing.body_statement = ast_statement_ptr(ast_code_block_ptr(backing.body_statement))
ast_node::if_statement(backing) {
if (!is_code_block(backing.then_part)) backing.then_part = ast_statement_ptr(ast_code_block_ptr(backing.then_part))
if (backing.else_part && !is_code_block(backing.else_part)) backing.else_part = ast_statement_ptr(ast_code_block_ptr(backing.else_part))
}
// no need for case because it's already been lowered
ast_node::while_loop(backing) if (!is_code_block(backing.statement)) backing.statement = ast_statement_ptr(ast_code_block_ptr(backing.statement))
ast_node::for_loop(backing) if (!is_code_block(backing.body)) backing.body = ast_statement_ptr(ast_code_block_ptr(backing.body))
}
}
var helper_after = fun(node: *ast_node, parent_chain: *stack<*ast_node>) {
match(*node) {
ast_node::type_def(backing) {
/*println(backing.name + ": exit")*/
ast_node::function(backing) {
var order = 0;
backing.parameters.for_each(fun(param: *ast_node) {
var param_type = get_ast_type(param)
if (!param_type->is_ref && param_type->indirection == 0 && (param_type->is_object() && has_method(param_type->type_def, "destruct", vector<*type>()))) {
// the first pass ensures a code_block child
backing.body_statement->statement.child->code_block.children.add(
ast_statement_ptr(ast_defer_statement_ptr(ast_statement_ptr(make_method_call(param, "destruct", vector<*ast_node>())))), order++)
}
})
}
ast_node::declaration_statement(backing) {
var ident_type = get_ast_type(backing.identifier)
if (is_translation_unit(parent_chain->top()) || is_type_def(parent_chain->top()))
return;
if (!ident_type->is_ref && ident_type->indirection == 0 && (ident_type->is_object() && has_method(ident_type->type_def, "destruct", vector<*type>()))) {
ensure_enclosing_statement_scope_is_block(parent_chain)
// have to go up one because our parent is a statement
add_after_in(ast_statement_ptr(ast_defer_statement_ptr(ast_statement_ptr(make_method_call(backing.identifier, "destruct", vector<*ast_node>())))), parent_chain->top(), parent_chain->from_top(1))
}
/*println(backing.name + ": exit")*/
}
}
}

View File

@@ -109,47 +109,6 @@ fun add_after_in(to_add: *ast_node, before: *ast_node, in: *ast_node) {
error(string("cannot add_after_in to ") + get_ast_name(in))
}
// only works for statements (not for loop init, etc)
fun ensure_enclosing_statement_scope_is_block(parent_chain: *stack<*ast_node>) {
var node = parent_chain->top()
match (*node) {
ast_node::for_loop(backing) {
var old = backing.body
if (!is_statement(old))
error("for loop body is not statement")
if (!is_code_block(old->statement.child)) {
var block = ast_code_block_ptr(old)
var stmt = ast_statement_ptr(block);
parent_chain->push(stmt)
parent_chain->push(block)
node->for_loop.body = stmt
}
return
}
ast_node::while_loop(backing) {
var old = backing.statement
if (!is_statement(old))
error("while loop body is not statement")
if (!is_code_block(old->statement.child)) {
var block = ast_code_block_ptr(old)
var stmt = ast_statement_ptr(block);
parent_chain->push(stmt)
parent_chain->push(block)
node->while_loop.statement = stmt
}
return
}
ast_node::code_block(backing) return
ast_node::if_statement(backing) error("ensure enclosing statment can't do if_statement yet")
ast_node::function(backing) error("ensure enclosing statment can't do function yet")
}
var old = parent_chain->pop()
if (parent_chain->empty())
error("hit top of parent chain in ensure_enclosing_statement_scope_is_block")
ensure_enclosing_statement_scope_is_block(parent_chain)
parent_chain->push(old)
}
fun empty_pass_half(node: *ast_node, parent_chain: *stack<*ast_node>) {}
fun run_on_tree(func_before: fun(*ast_node,*stack<*ast_node>):void, func_after: fun(*ast_node,*stack<*ast_node>):void, tree: *ast_node) {
var parent_stack = stack<*ast_node>()