From e3607beabe33eaf6097c26a340f7a0307ddf8c91 Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Fri, 24 Jun 2016 01:42:48 -0700 Subject: [PATCH] Refactor parameter destruction into obj_lower --- stdlib/c_generator.krak | 56 +---------------------------------------- stdlib/defer_lower.krak | 2 -- stdlib/obj_lower.krak | 23 ++++++++++++----- stdlib/pass_common.krak | 41 ------------------------------ 4 files changed, 18 insertions(+), 104 deletions(-) diff --git a/stdlib/c_generator.krak b/stdlib/c_generator.krak index 91bbade..ced28d7 100644 --- a/stdlib/c_generator.krak +++ b/stdlib/c_generator.krak @@ -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>>>(), 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()) - var declaration = ast_declaration_statement_ptr(temp_ident, null(), 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>>>(), 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>>): 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>>>(), 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(), 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>>>(), 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(), null(), null>>>(), false).one_string() + " = " + to_ret + ";\n" trip_ret.value = generate_identifier(temp_ident, null(), null()).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) { } } - diff --git a/stdlib/defer_lower.krak b/stdlib/defer_lower.krak index c79b426..372d229 100644 --- a/stdlib/defer_lower.krak +++ b/stdlib/defer_lower.krak @@ -20,11 +20,9 @@ fun defer_lower(name_ast_map: *map,*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) } } diff --git a/stdlib/obj_lower.krak b/stdlib/obj_lower.krak index e6dd1ae..167638f 100644 --- a/stdlib/obj_lower.krak +++ b/stdlib/obj_lower.krak @@ -15,26 +15,37 @@ fun obj_lower(name_ast_map: *map,*ast_node>>, ast_to_ name_ast_map->for_each(fun(name: string, syntax_ast_pair: pair<*tree,*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")*/ } } } diff --git a/stdlib/pass_common.krak b/stdlib/pass_common.krak index bbb5007..e81a31c 100644 --- a/stdlib/pass_common.krak +++ b/stdlib/pass_common.krak @@ -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>()