Refactor parameter destruction into obj_lower
This commit is contained in:
@@ -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) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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")*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>()
|
||||
|
||||
Reference in New Issue
Block a user