From 15fe2aeba47c2fcdae96c10dd5005f5d969580bf Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Sun, 26 Jun 2016 04:44:54 -0700 Subject: [PATCH] Moved copy_constructing into functions and destructing the results into obj_lower. Removed all defer_stack from c_generator. The last thing should be to move ref handling into obj_lower or maybe a pass after, then the rest of c_generator can be cleaned up and fixing interpreter (except for closures) should be easy. --- stdlib/c_generator.krak | 213 ++++++------------ stdlib/hash_map.krak | 32 +-- stdlib/obj_lower.krak | 56 ++++- tests/test_adt.expected_results | 12 +- ...structor_copy_constructor.expected_results | 2 +- tests/test_util.expected_results | 4 +- tests/test_vectorTest.expected_results | 6 +- 7 files changed, 140 insertions(+), 185 deletions(-) diff --git a/stdlib/c_generator.krak b/stdlib/c_generator.krak index 8972a00..dd5decc 100644 --- a/stdlib/c_generator.krak +++ b/stdlib/c_generator.krak @@ -193,7 +193,7 @@ obj c_generator (Object) { linker_string.destruct() } fun get_id(): string return to_string(id_counter++); - fun generate_function_prototype_and_header(child: *ast_node, enclosing_object: *ast_node, is_lambda: bool, defer_stack: *stack>>):pair { + fun generate_function_prototype_and_header(child: *ast_node, enclosing_object: *ast_node, is_lambda: bool):pair { var backing = child->function var parameter_types = string() @@ -245,14 +245,12 @@ obj c_generator (Object) { var backing = child->function // stack-stack thing // this could be a stack of strings too, maybe // start out with one stack on the stack - var defer_stack = stack>>(make_pair(false, stack<*ast_node>())) - var prototype_and_header = generate_function_prototype_and_header(child, enclosing_object, is_lambda, &defer_stack) + var prototype_and_header = generate_function_prototype_and_header(child, enclosing_object, is_lambda) function_prototypes += prototype_and_header.first if (!backing.is_extern) function_definitions += prototype_and_header.second if (backing.body_statement) { - function_definitions += string(" {\n") + generate_statement(backing.body_statement, enclosing_object, child, &defer_stack).one_string() - function_definitions += generate_from_defer_stack(&defer_stack, -1, enclosing_object, child).one_string() + function_definitions += string(" {\n") + generate_statement(backing.body_statement, enclosing_object, child).one_string() function_definitions += "}\n" } else if (!backing.is_extern) { error("Empty function statement and not extern - no ADTs anymore!") @@ -283,7 +281,7 @@ obj c_generator (Object) { top_level_c_passthrough += generate_simple_passthrough(backing.statement->statement.child, true) } ast_node::simple_passthrough(backing) top_level_c_passthrough += generate_simple_passthrough(child, true) - ast_node::declaration_statement(backing) variable_declarations += generate_declaration_statement(child, null(), null(), null>>>(), false).one_string() + ";\n" // false - don't do defer + ast_node::declaration_statement(backing) variable_declarations += generate_declaration_statement(child, null(), null(), false).one_string() + ";\n" // false - don't do defer // shouldn't need to do anything with return, as the intrinsic should be something like link ast_node::compiler_intrinsic(backing) generate_compiler_intrinsic(child) ast_node::function(backing) { @@ -332,7 +330,7 @@ obj c_generator (Object) { plain_typedefs += base_name + "_dummy " + base_name + ";\n" structs += base_name + "_dummy {\n" if (is_type_def(vert)) { - vert->type_def.variables.for_each(fun(variable_declaration: *ast_node) structs += generate_declaration_statement(variable_declaration, null(), null(), null>>>(), false).one_string() + ";\n";) // also no defer stack + vert->type_def.variables.for_each(fun(variable_declaration: *ast_node) structs += generate_declaration_statement(variable_declaration, null(), null(), false).one_string() + ";\n";) // also no defer stack // generate the methods (note some of these may be templates) vert->type_def.methods.for_each(fun(method: *ast_node) { if (is_template(method)) @@ -362,9 +360,9 @@ obj c_generator (Object) { } return closure_struct_map[closed_variables] } - fun generate_if_comp(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, defer_stack: *stack>>): code_triple { + fun generate_if_comp(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node): code_triple { if (node->if_comp.wanted_generator == "__C__") - return generate(node->if_comp.statement, enclosing_object, enclosing_func, defer_stack, false) + return generate(node->if_comp.statement, enclosing_object, enclosing_func, false) return code_triple() } fun generate_simple_passthrough(node: *ast_node, is_top_level: bool): string { @@ -391,9 +389,8 @@ obj c_generator (Object) { return pre + result + post return pre + "{" + result + "}" + post } - fun generate_statement(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, defer_stack: *stack>>): code_triple return generate(node->statement.child, enclosing_object, enclosing_func, defer_stack, false) + ";\n"; - fun generate_declaration_statement(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, defer_stack: *stack>>, add_to_defer: bool): code_triple { - // add destruct to defer_stack + fun generate_statement(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node): code_triple return generate(node->statement.child, enclosing_object, enclosing_func, false) + ";\n"; + fun generate_declaration_statement(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, add_to_defer: bool): code_triple { var identifier = node->declaration_statement.identifier var ident_type = identifier->identifier.type // we do the declaration in the pre now so that we can take it's address to close over it for things like recursive closures @@ -403,69 +400,50 @@ obj c_generator (Object) { pre_stuff = string("extern ") + pre_stuff var to_ret = code_triple(pre_stuff, string(), string()) if (node->declaration_statement.expression) { - if (ident_type->indirection == 0 && (ident_type->is_object() && has_method(ident_type->type_def, "copy_construct", vector(get_ast_type(node->declaration_statement.expression)->clone_with_increased_indirection())))) { - to_ret.pre += ";\n" - to_ret += generate(ast_statement_ptr(make_method_call(identifier, "copy_construct", vector(make_operator_call("&", vector(node->declaration_statement.expression))))), enclosing_object, enclosing_func, defer_stack, false) + if (ident_type->is_function()) { + to_ret.pre += string(";\n") + to_ret += code_triple() + get_name(identifier) + " = " + generate(node->declaration_statement.expression, enclosing_object, enclosing_func, false) } else { - if (ident_type->is_function()) { - to_ret.pre += string(";\n") - to_ret += code_triple() + get_name(identifier) + " = " + generate(node->declaration_statement.expression, enclosing_object, enclosing_func, null>>>(), false) - } else { - // some shifting around to get it to work in all cases - // what cases? - to_ret.value = to_ret.pre - to_ret.pre = "" - to_ret += code_triple() + string(" = ") + generate(node->declaration_statement.expression, enclosing_object, enclosing_func, null>>>(), false) - } + // some shifting around to get it to work in all cases + // what cases? + to_ret.value = to_ret.pre + to_ret.pre = "" + to_ret += code_triple() + string(" = ") + generate(node->declaration_statement.expression, enclosing_object, enclosing_func, false) } } if (node->declaration_statement.init_method_call) { to_ret.pre += ";\n" - to_ret += code_triple() + generate(node->declaration_statement.init_method_call, enclosing_object, enclosing_func, null>>>(), false) + to_ret += code_triple() + generate(node->declaration_statement.init_method_call, enclosing_object, enclosing_func, false) } return to_ret } fun generate_assignment_statement(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node): code_triple { - return generate(node->assignment_statement.to, enclosing_object, enclosing_func, null>>>(), false) + " = " + generate(node->assignment_statement.from, enclosing_object, enclosing_func, null>>>(), false) + return generate(node->assignment_statement.to, enclosing_object, enclosing_func, false) + " = " + generate(node->assignment_statement.from, enclosing_object, enclosing_func, false) } - fun generate_if_statement(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, defer_stack: *stack>>): code_triple { - var if_str = code_triple("if (") + generate(node->if_statement.condition, enclosing_object, enclosing_func, null>>>(), false) + ") {\n" + generate(node->if_statement.then_part, enclosing_object, enclosing_func, defer_stack, false).one_string() + "}" + fun generate_if_statement(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node): code_triple { + var if_str = code_triple("if (") + generate(node->if_statement.condition, enclosing_object, enclosing_func, false) + ") {\n" + generate(node->if_statement.then_part, enclosing_object, enclosing_func, false).one_string() + "}" if (node->if_statement.else_part) - if_str += code_triple(" else {\n") + generate(node->if_statement.else_part, enclosing_object, enclosing_func, defer_stack, false).one_string() + "}" + if_str += code_triple(" else {\n") + generate(node->if_statement.else_part, enclosing_object, enclosing_func, false).one_string() + "}" return if_str + "\n" } - fun generate_while_loop(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, defer_stack: *stack>>): code_triple { - // stick another stack on - defer_stack->push(make_pair(true, stack<*ast_node>())) - var to_ret = code_triple("while (" + generate(node->while_loop.condition, enclosing_object, enclosing_func, null>>>(), false).one_string() + ")\n" - + generate(node->while_loop.statement, enclosing_object, enclosing_func, defer_stack, false).one_string()) - defer_stack->pop() + fun generate_while_loop(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node): code_triple { + var to_ret = code_triple("while (" + generate(node->while_loop.condition, enclosing_object, enclosing_func, false).one_string() + ")\n" + + generate(node->while_loop.statement, enclosing_object, enclosing_func, false).one_string()) return to_ret } - fun generate_for_loop(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, defer_stack: *stack>>): code_triple { - // stick another stack on - defer_stack->push(make_pair(true, stack<*ast_node>())) + fun generate_for_loop(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node): code_triple { // gotta take off last semicolon - /*var init = generate(node->for_loop.init, enclosing_object, enclosing_func, null>>>(), false)*/ var init = code_triple(";") if (node->for_loop.init) - init = generate(node->for_loop.init, enclosing_object, enclosing_func, defer_stack, false) + init = generate(node->for_loop.init, enclosing_object, enclosing_func, false) var cond = code_triple(";") if (node->for_loop.condition) - cond = generate(node->for_loop.condition, enclosing_object, enclosing_func, null>>>(), false) + cond = generate(node->for_loop.condition, enclosing_object, enclosing_func, false) var update = code_triple() if (node->for_loop.update) - update = generate(node->for_loop.update, enclosing_object, enclosing_func, null>>>(), false) - /*var do_update_name = string("do_update") + get_id()*/ - /*var to_ret = string("{\n") + init.one_string() + "bool " + do_update_name + " = false;\nfor (;;) {\n"*/ - /*to_ret += string("if (") + do_update_name + ") {" + update.one_string() + "}\n" + do_update_name + " = true;\n"*/ - /*to_ret += cond.pre + "if (!" + cond.value + ") {" + cond.post + "break;}" + cond.post*/ + update = generate(node->for_loop.update, enclosing_object, enclosing_func, false) var to_ret = string("for (") + init.one_string() + cond.one_string() + "; " + update.one_string().slice(0,-2) + ")\n" + - generate(node->for_loop.body, enclosing_object, enclosing_func, defer_stack, false).one_string() - /*to_ret += generate(node->for_loop.body, enclosing_object, enclosing_func, defer_stack, false).one_string()*/ - /*to_ret += generate_from_defer_stack(defer_stack, 1, enclosing_object, enclosing_func).one_string()*/ - defer_stack->pop() - //to_ret += "}/*end inner for*/}/*end for's enclosing block*/\n" + generate(node->for_loop.body, enclosing_object, enclosing_func, false).one_string() return code_triple(to_ret) } fun generate_identifier(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node): code_triple { @@ -483,7 +461,7 @@ obj c_generator (Object) { return code_triple(pre + "(this->" + get_name(node) + ")" + post) return code_triple(pre + get_name(node) + post) } - fun generate_return_statement(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, defer_stack: *stack>>): code_triple { + fun generate_return_statement(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node): code_triple { var return_value = node->return_statement.return_value var function_return_type = get_ast_type(enclosing_func)->return_type var to_ret = code_triple() @@ -493,63 +471,25 @@ obj c_generator (Object) { if (function_return_type->is_ref) refamp = "&" if (return_value) - 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() + to_ret += code_triple(" ") + refamp + generate(return_value, enclosing_object, enclosing_func, false) 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 - var to_ret = generate_from_defer_stack(defer_stack, -2, enclosing_object, enclosing_func) + fun generate_branching_statement(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node): code_triple { match(node->branching_statement.b_type) { - branching_type::break_stmt() return to_ret + string("break") - branching_type::continue_stmt() return to_ret + string("continue") + branching_type::break_stmt() return code_triple("break") + branching_type::continue_stmt() return code_triple("continue") } } - fun generate_from_defer_stack(defer_stack: *stack>>, num: int, enclosing_object: *ast_node, enclosing_func: *ast_node): code_triple { - var to_ret = code_triple() - if (num == -1) - num = defer_stack->size() - if (num == -2) { - num = 1 - for (var i = 0; i < defer_stack->size(); i++;) - if (defer_stack->from_top(i).first) - break - else - num++ - } - 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, defer_stack, false);) - if (defer_stack->top().second.size()) - to_ret += generate_from_defer_stack(defer_stack, 1, enclosing_object, enclosing_func); - defer_stack->pop() - } - return to_ret - } - fun generate_defer_statement(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, defer_stack: *stack>>): code_triple { + fun generate_defer_statement(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node): code_triple { error("Unremoved defer!") } - fun generate_match_statement(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, defer_stack: *stack>>): code_triple { + fun generate_match_statement(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node): code_triple { + error("remaining match") var to_ret = code_triple("/* begin match */") - var matching_value = generate(node->match_statement.value, enclosing_object, enclosing_func, defer_stack, true) - to_ret.pre += matching_value.pre - to_ret.post += matching_value.post - node->match_statement.cases.for_each(fun(case_node: *ast_node) { - var option_str = generate(case_node->case_statement.option, enclosing_object, enclosing_func, defer_stack, false).one_string() - var to_ret_case = code_triple("/*case ") + option_str + "*/ if(" + matching_value.value + ".flag == " + string("enum_opt_") + option_str + ") {\n" - if (case_node->case_statement.unpack_ident) { - to_ret_case += generate_declaration_statement(ast_declaration_statement_ptr(case_node->case_statement.unpack_ident, null(), false), null(), null(), null>>>(), false).one_string() - to_ret_case += string(" = ") + matching_value.value + ".data." + option_str + ";\n" - } else { - to_ret_case += "/*no unpack_ident*/\n" - } - to_ret_case += generate(case_node->case_statement.statement, enclosing_object, enclosing_func, defer_stack, false).one_string() + "\n}\n" - to_ret += to_ret_case.one_string() - }) return to_ret } - fun generate_cast(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, defer_stack: *stack>>, need_variable: bool): code_triple { - return code_triple("((") + type_to_c(node->cast.to_type) + ")(" + generate(node->cast.value, enclosing_object, enclosing_func, defer_stack, false) + "))" + fun generate_cast(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node): code_triple { + return code_triple("((") + type_to_c(node->cast.to_type) + ")(" + generate(node->cast.value, enclosing_object, enclosing_func, false) + "))" } fun generate_value(node: *ast_node, need_variable: bool): code_triple { var value = node->value.string_value @@ -578,19 +518,15 @@ 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, null(), null(), null>>>(), false).one_string() + " = " + to_ret + ";\n" + trip_ret.pre += generate_declaration_statement(declaration, null(), null(), false).one_string() + " = " + to_ret + ";\n" trip_ret.value = generate_identifier(temp_ident, null(), null()).one_string() return trip_ret } return code_triple(to_ret) } - fun generate_code_block(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, defer_stack: *stack>>): code_triple { + fun generate_code_block(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node): code_triple { var to_ret = code_triple("{\n") - // stick another stack on - defer_stack->push(make_pair(false, stack<*ast_node>())) - node->code_block.children.for_each(fun(child: *ast_node) to_ret += generate(child, enclosing_object, enclosing_func, defer_stack, false).one_string();) - to_ret += generate_from_defer_stack(defer_stack, 1, enclosing_object, enclosing_func) - defer_stack->pop() + node->code_block.children.for_each(fun(child: *ast_node) to_ret += generate(child, enclosing_object, enclosing_func, false).one_string();) return to_ret + "}" } // this generates the function as a value, not the actual function @@ -606,7 +542,7 @@ obj c_generator (Object) { closed_vars.for_each(fun(i: *ast_node) { // note that we get/have gotten rid of refs here, or maybe more accurately, everything is a ref // should be a variable anyway? - to_ret.pre += string(".") + get_name(i) + "=(void*)&" + generate(i, enclosing_object, enclosing_func, null>>>(), true).one_string() + "," + to_ret.pre += string(".") + get_name(i) + "=(void*)&" + generate(i, enclosing_object, enclosing_func, true).one_string() + "," }) to_ret.pre += "};\n" return to_ret + string("((") + type_to_c(node->function.type) + "){(void*)&" + temp_closure_struct + ",(void*)" + get_name(node) + "})" @@ -634,7 +570,7 @@ obj c_generator (Object) { // XXX should it? wouldn't function calls be a problem? // should this be true if ref? - call_string += generate(node->function_call.func->function_call.parameters[0], enclosing_object, enclosing_func, null>>>(), true) + call_string += generate(node->function_call.func->function_call.parameters[0], enclosing_object, enclosing_func, true) } else if (is_identifier(node->function_call.func) || is_function(node->function_call.func)) { // we handle the case when it's not this later, i.e. it's a lambda returned from another function or something func_name = generate_function(node->function_call.func, enclosing_object, enclosing_func, false, false).one_string() @@ -655,25 +591,25 @@ obj c_generator (Object) { || func_name == "==" || func_name == "!=" || func_name == "%" || func_name == "^" || func_name == "|" || func_name == "&" )) - return code_triple("(") + generate(parameters[0], enclosing_object, enclosing_func, null>>>(), false) + func_name + generate(parameters[1], enclosing_object, enclosing_func, null>>>(), false) + string(")") + return code_triple("(") + generate(parameters[0], enclosing_object, enclosing_func, false) + func_name + generate(parameters[1], enclosing_object, enclosing_func, false) + string(")") if ( parameters.size == 2 && (func_name == "||" || func_name == "&&")) { error("Remaining || or &&") } // don't propegate enclosing function down right of access // XXX what about enclosing object? should it be the thing on the left? if (func_name == "." || func_name == "->") { - return code_triple("(") + generate(parameters[0], enclosing_object, enclosing_func, null>>>(), false) + func_name + generate(parameters[1], null(), null(), null>>>(), false) + string(")") + return code_triple("(") + generate(parameters[0], enclosing_object, enclosing_func, false) + func_name + generate(parameters[1], null(), null(), false) + string(")") } if (func_name == "[]") - return code_triple("(") + generate(parameters[0], enclosing_object, enclosing_func, null>>>(), false) + "[" + generate(parameters[1], enclosing_object, enclosing_func, null>>>(), false) + string("])") + return code_triple("(") + generate(parameters[0], enclosing_object, enclosing_func, false) + "[" + generate(parameters[1], enclosing_object, enclosing_func, false) + string("])") // the post ones need to be post-ed specifically, and take the p off if (func_name == "++p" || func_name == "--p") - return code_triple("(") + generate(parameters[0], enclosing_object, enclosing_func, null>>>(), false) + ")" + func_name.slice(0,-2) + return code_triple("(") + generate(parameters[0], enclosing_object, enclosing_func, false) + ")" + func_name.slice(0,-2) // So we don't end up copy_constructing etc, we just handle the unary operators right here // note also the passing down need_variable for & if (func_name == "*" || func_name == "&") - return code_triple("(") + func_name + generate(parameters[0], enclosing_object, enclosing_func, null>>>(), func_name == "&") + ")" + return code_triple("(") + func_name + generate(parameters[0], enclosing_object, enclosing_func, func_name == "&") + ")" // for checking if we pass in a ref var func_type = get_ast_type(node->function_call.func) @@ -694,30 +630,17 @@ obj c_generator (Object) { call_string += "&" var param_type = get_ast_type(param) - if (!in_function_param_type->is_ref && param_type->indirection == 0 && (param_type->is_object() && has_method(param_type->type_def, "copy_construct", vector(param_type->clone_with_indirection(1))))) { - var temp_ident = ast_identifier_ptr(string("temporary_param")+get_id(), param_type->clone_without_ref(), 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 - call_string.pre += generate_declaration_statement(declaration, enclosing_object, enclosing_func, null>>>(), false).one_string() + ";\n" - call_string.pre += generate_statement(ast_statement_ptr(make_method_call(temp_ident, "copy_construct", vector(make_operator_call("&", vector(param))))), enclosing_object, enclosing_func, null>>>()).one_string() - call_string += generate(temp_ident, enclosing_object, enclosing_func, null>>>(), false) - } else { - call_string += generate(param, enclosing_object, enclosing_func, null>>>(), in_function_param_type->is_ref) - } + call_string += generate(param, enclosing_object, enclosing_func, in_function_param_type->is_ref) } var pre_call = string() // temporary returns if we're asked for them or we need them for destruct - var needs_temp_for_destruct = func_return_type->indirection == 0 && (func_return_type->is_object() && has_method(func_return_type->type_def, "destruct", vector<*type>())) - if (!func_return_type->is_ref && (needs_temp_for_destruct || (!func_return_type->is_void() && need_variable)) ) { + if (!func_return_type->is_ref && !func_return_type->is_void() && need_variable) { // kind of ugly combo here of var temp_ident = ast_identifier_ptr(string("temporary_return")+get_id(), func_return_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 - call_string.pre += generate_declaration_statement(declaration, enclosing_object, enclosing_func, null>>>(), false).one_string() + ";\n" + call_string.pre += generate_declaration_statement(declaration, enclosing_object, enclosing_func, false).one_string() + ";\n" pre_call = generate_identifier(temp_ident, enclosing_object, enclosing_func).one_string() - // move destruct condition inside - if (needs_temp_for_destruct) - call_string.post += generate_statement(ast_statement_ptr(make_method_call(temp_ident, "destruct", vector<*ast_node>())), enclosing_object, enclosing_func, null>>>()).one_string() } var ref_pre = string() var ref_post = string() @@ -733,10 +656,10 @@ obj c_generator (Object) { var temp_ident = ast_identifier_ptr(string("temporary_return")+get_id(), func_return_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 - call_string.pre += generate_declaration_statement(declaration, enclosing_object, enclosing_func, null>>>(), false).one_string() + ";\n" + call_string.pre += generate_declaration_statement(declaration, enclosing_object, enclosing_func, false).one_string() + ";\n" pre_call = generate_identifier(temp_ident, enclosing_object, enclosing_func).one_string() } - var name_temp = generate(node->function_call.func, enclosing_object, enclosing_func, null>>>(), false) + var name_temp = generate(node->function_call.func, enclosing_object, enclosing_func, false) call_string.pre += name_temp.pre call_string.post += name_temp.post func_name = name_temp.value @@ -787,26 +710,26 @@ obj c_generator (Object) { } // for now, anyway - fun generate(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, defer_stack: *stack>>, need_variable: bool): code_triple { + fun generate(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, need_variable: bool): code_triple { if (!node) return code_triple("/*NULL*/") match (*node) { - ast_node::if_comp(backing) return generate_if_comp(node, enclosing_object, enclosing_func, defer_stack) + ast_node::if_comp(backing) return generate_if_comp(node, enclosing_object, enclosing_func) ast_node::simple_passthrough(backing) return code_triple() + generate_simple_passthrough(node, false) - ast_node::statement(backing) return generate_statement(node, enclosing_object, enclosing_func, defer_stack) - ast_node::declaration_statement(backing) return generate_declaration_statement(node, enclosing_object, enclosing_func, defer_stack, true) + ast_node::statement(backing) return generate_statement(node, enclosing_object, enclosing_func) + ast_node::declaration_statement(backing) return generate_declaration_statement(node, enclosing_object, enclosing_func, true) ast_node::assignment_statement(backing) return generate_assignment_statement(node, enclosing_object, enclosing_func) - ast_node::if_statement(backing) return generate_if_statement(node, enclosing_object, enclosing_func, defer_stack) - ast_node::while_loop(backing) return generate_while_loop(node, enclosing_object, enclosing_func, defer_stack) - ast_node::for_loop(backing) return generate_for_loop(node, enclosing_object, enclosing_func, defer_stack) + ast_node::if_statement(backing) return generate_if_statement(node, enclosing_object, enclosing_func) + ast_node::while_loop(backing) return generate_while_loop(node, enclosing_object, enclosing_func) + ast_node::for_loop(backing) return generate_for_loop(node, enclosing_object, enclosing_func) ast_node::function(backing) return generate_function(node, enclosing_object, enclosing_func, true, need_variable) ast_node::function_call(backing) return generate_function_call(node, enclosing_object, enclosing_func, need_variable) ast_node::compiler_intrinsic(backing) return generate_compiler_intrinsic(node) - ast_node::code_block(backing) return generate_code_block(node, enclosing_object, enclosing_func, defer_stack) - ast_node::return_statement(backing) return generate_return_statement(node, enclosing_object, enclosing_func, defer_stack) - ast_node::branching_statement(backing) return generate_branching_statement(node, enclosing_object, enclosing_func, defer_stack) - ast_node::defer_statement(backing) return generate_defer_statement(node, enclosing_object, enclosing_func, defer_stack) - ast_node::match_statement(backing) return generate_match_statement(node, enclosing_object, enclosing_func, defer_stack) - ast_node::cast(backing) return generate_cast(node, enclosing_object, enclosing_func, defer_stack, need_variable) + ast_node::code_block(backing) return generate_code_block(node, enclosing_object, enclosing_func) + ast_node::return_statement(backing) return generate_return_statement(node, enclosing_object, enclosing_func) + ast_node::branching_statement(backing) return generate_branching_statement(node, enclosing_object, enclosing_func) + ast_node::defer_statement(backing) return generate_defer_statement(node, enclosing_object, enclosing_func) + ast_node::match_statement(backing) return generate_match_statement(node, enclosing_object, enclosing_func) + ast_node::cast(backing) return generate_cast(node, enclosing_object, enclosing_func) ast_node::value(backing) return generate_value(node, need_variable) ast_node::identifier(backing) return generate_identifier(node, enclosing_object, enclosing_func) } diff --git a/stdlib/hash_map.krak b/stdlib/hash_map.krak index 2c5ef60..a2876cd 100644 --- a/stdlib/hash_map.krak +++ b/stdlib/hash_map.krak @@ -22,29 +22,17 @@ obj hash_map (Object, Serializable) { data.construct() data.add(map::map()) size = 0 - /*io::print("Constructed hash_map, this: ")*/ - /*io::println((this) cast int)*/ - /*io::print("size of data:")*/ - /*io::println(data.size)*/ return this } fun copy_construct(old: *hash_map) { data.copy_construct(&old->data) size = old->size - /*io::print("Copy constructed hash_map, this: ")*/ - /*io::println((this) cast int)*/ - /*io::print("new size of data:")*/ - /*io::println(data.size)*/ - /*io::print("old size of data:")*/ - /*io::println(old->data.size)*/ } fun operator=(rhs: ref hash_map) { data = rhs.data size = rhs.size } fun destruct() { - /*io::print("destructed hash_map, this: ")*/ - /*io::println((this) cast int)*/ data.destruct() } fun serialize(): vector::vector { @@ -61,32 +49,26 @@ obj hash_map (Object, Serializable) { return data == other.data } fun set(key: ref T, value: ref U) { - /*io::print("doing set! this:")*/ - /*io::println((this) cast int)*/ - /*io::print("size of data:")*/ - /*io::println(data.size)*/ - var key_hash = (util::hash(key)) cast int - if (!data[key_hash%data.size].contains_key(key)) { + var key_hash = util::hash(key) + if (!data[(key_hash%data.size) cast int].contains_key(key)) { size++ if (size > data.size) { - /*io::print("rehashing to: ")*/ - /*io::println(size*2)*/ var new_data = vector::vector>() for (var i = 0; i < size*2; i++;) new_data.addEnd(map::map()) for_each(fun(key: T, value: U) { - new_data[(util::hash(key)) cast int%new_data.size].set(key, value) + new_data[(util::hash(key)%new_data.size) cast int].set(key, value) }) data = new_data } } - data[key_hash%data.size].set(key, value) + data[(key_hash%data.size) cast int].set(key, value) } fun get(key: ref T): ref U { - return data[(util::hash(key)) cast int%data.size].get(key) + return data[(util::hash(key)%data.size) cast int].get(key) } fun contains_key(key: ref T): bool { - return data[(util::hash(key)) cast int%data.size].contains_key(key) + return data[(util::hash(key)%data.size) cast int].contains_key(key) } fun contains_value(value: ref U): bool { for (var i = 0; i < data.size; i++;) { @@ -103,7 +85,7 @@ obj hash_map (Object, Serializable) { io::println("trying to reverse get a value that is not in the hash_map") } fun remove(key: ref T) { - data[(util::hash(key)) cast int%data.size].remove(key) + data[(util::hash(key)%data.size) cast int].remove(key) } fun for_each(func: fun(T, U):void) { for (var i = 0; i < data.size; i++;) diff --git a/stdlib/obj_lower.krak b/stdlib/obj_lower.krak index a689a29..6a0e515 100644 --- a/stdlib/obj_lower.krak +++ b/stdlib/obj_lower.krak @@ -110,6 +110,49 @@ fun obj_lower(name_ast_map: *map,*ast_node>>, ast_to_ // Pass 3 var construct_in_destruct_out = fun(node: *ast_node, parent_chain: *stack<*ast_node>) { match(*node) { + ast_node::function_call(backing) { + if (is_function(backing.func)) { + var func_name = backing.func->function.name + if (func_name == "+" || func_name == "-" || func_name == "*" || func_name == "/" + || func_name == "<" || func_name == ">" || func_name == "<=" || func_name == ">=" + || func_name == "==" || func_name == "!=" || func_name == "%" || func_name == "^" + || func_name == "|" || func_name == "&" || func_name == "." || func_name == "->" + || func_name == "." || func_name == "->" || func_name == "[]" || func_name == "++p" || func_name == "--p" + || func_name == "*" || func_name == "&" || func_name == "||" || func_name == "&&" + || func_name == "!" + ) + return + } + var enclosing_block_idx = parent_chain->index_from_top_satisfying(fun(i: *ast_node): bool return is_code_block(i);) + var func_type = get_ast_type(backing.func) + for (var i = 0; i < backing.parameters.size; i++;) { + var param = backing.parameters[i] + var in_function_param_type = null() + // grab type from param itself if we're out of param types (because variadic function) + if (i < func_type->parameter_types.size) + in_function_param_type = func_type->parameter_types[i] + else + in_function_param_type = get_ast_type(param)->clone_without_ref() + var param_type = get_ast_type(param) + if (!in_function_param_type->is_ref && param_type->indirection == 0 && (param_type->is_object() && has_method(param_type->type_def, "copy_construct", vector(param_type->clone_with_indirection(1))))) { + var temp_ident = ast_identifier_ptr("temporary_param_boom", param_type->clone_without_ref(), null()) + var declaration = ast_statement_ptr(ast_declaration_statement_ptr(temp_ident, null(), false)) + var copy_in = ast_statement_ptr(make_method_call(temp_ident, "copy_construct", vector(make_operator_call("&", vector(param))))) + add_before_in(declaration, parent_chain->from_top(enclosing_block_idx-1), parent_chain->from_top(enclosing_block_idx)) + add_before_in(copy_in, parent_chain->from_top(enclosing_block_idx-1), parent_chain->from_top(enclosing_block_idx)) + backing.parameters[i] = temp_ident + } + } + var func_return_type = func_type->return_type + if (!func_return_type->is_ref && func_return_type->indirection == 0 && (func_return_type->is_object() && has_method(func_return_type->type_def, "destruct", vector<*type>()))) { + var temp_return = ast_identifier_ptr("temporary_return_boomchaka", func_return_type, null()) + var declaration = ast_statement_ptr(ast_declaration_statement_ptr(temp_return, node, false)) + add_before_in(declaration, parent_chain->from_top(enclosing_block_idx-1), parent_chain->from_top(enclosing_block_idx)) + add_before_in(ast_statement_ptr(ast_defer_statement_ptr(ast_statement_ptr(make_method_call(temp_return, "destruct", vector<*ast_node>())))), + parent_chain->from_top(enclosing_block_idx-1), parent_chain->from_top(enclosing_block_idx)) + replace_with_in(node, temp_return, parent_chain) + } + } ast_node::function(backing) { var order = 0; backing.parameters.for_each(fun(param: *ast_node) { @@ -125,10 +168,17 @@ fun obj_lower(name_ast_map: *map,*ast_node>>, ast_to_ 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>()))) { - // 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>())))), + if (!ident_type->is_ref && ident_type->indirection == 0 && ident_type->is_object()) { + if (backing.expression && has_method(ident_type->type_def, "copy_construct", vector(get_ast_type(backing.expression)->clone_with_increased_indirection()))) { + add_after_in(ast_statement_ptr(make_method_call(backing.identifier, "copy_construct", vector(make_operator_call("&", vector(backing.expression))))), parent_chain->top(), parent_chain->from_top(1)) + backing.expression = null() + } + if (has_method(ident_type->type_def, "destruct", vector<*type>())) { + // 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)) + } } } } diff --git a/tests/test_adt.expected_results b/tests/test_adt.expected_results index 64fe7bc..5661c1e 100644 --- a/tests/test_adt.expected_results +++ b/tests/test_adt.expected_results @@ -12,13 +12,11 @@ constructed object 100 : 100 copy constructed object 100 : 200 from 100 : 100 destructed object 100 : 100 copy constructed object 100 : 300 from 100 : 200 -destructed object 100 : 200 copy constructed object 100 : 400 from 100 : 300 copy constructed object 100 : 500 from 100 : 400 destructed object 100 : 400 destructed object 100 : 300 copy constructed object 100 : 600 from 100 : 500 -destructed object 100 : 500 done assignment to old variable matched an_obj correctly 100 : 600 int assignment to old var @@ -31,7 +29,6 @@ constructed object 110 : 110 copy constructed object 110 : 210 from 110 : 110 destructed object 110 : 110 copy constructed object 110 : 310 from 110 : 210 -destructed object 110 : 210 copy constructed object 110 : 410 from 110 : 310 copy constructed object 110 : 510 from 110 : 410 destructed object 110 : 410 @@ -41,7 +38,6 @@ constructed object 110 : 110 copy constructed object 110 : 210 from 110 : 110 destructed object 110 : 110 copy constructed object 110 : 310 from 110 : 210 -destructed object 110 : 210 copy constructed object 110 : 410 from 110 : 310 copy constructed object 110 : 510 from 110 : 410 destructed object 110 : 410 @@ -49,7 +45,11 @@ destructed object 110 : 310 copy constructed object 110 : 610 from 110 : 510 destructed object 110 : 610 equality an_obj correctly -destructed object 110 : 510 -destructed object 110 : 510 done test copy_construct for non ref equality 10 +destructed object 110 : 510 +destructed object 110 : 210 +destructed object 110 : 510 +destructed object 110 : 210 +destructed object 100 : 500 +destructed object 100 : 200 diff --git a/tests/test_destructor_copy_constructor.expected_results b/tests/test_destructor_copy_constructor.expected_results index 6001961..371aa95 100644 --- a/tests/test_destructor_copy_constructor.expected_results +++ b/tests/test_destructor_copy_constructor.expected_results @@ -39,9 +39,9 @@ copy_construct outFunc : 1! destroyed outFunc : 0! destroyed inFunc : 1! copy_construct outFunc : 2! -destroyed outFunc : 1! time for the end destroyed outFunc : 2! +destroyed outFunc : 1! destroyed inFunc : 0! destroyed a2 : 0! destroyed a : 0! diff --git a/tests/test_util.expected_results b/tests/test_util.expected_results index 76aead1..7ac022f 100644 --- a/tests/test_util.expected_results +++ b/tests/test_util.expected_results @@ -24,10 +24,10 @@ destruct with 101 destruct with 1 copy construct from 3 to 4 copy construct from 103 to 104 -destruct with 3 -destruct with 103 done destruct with 4 destruct with 104 +destruct with 3 +destruct with 103 destruct with 100 destruct with 0 diff --git a/tests/test_vectorTest.expected_results b/tests/test_vectorTest.expected_results index 52b6c58..d9150a1 100644 --- a/tests/test_vectorTest.expected_results +++ b/tests/test_vectorTest.expected_results @@ -65,15 +65,15 @@ Destroyed: 101 Copied: 103 to 104 Copied: 203 to 204 Copied: 303 to 304 -Destroyed: 103 -Destroyed: 203 -Destroyed: 303 Destroyed: 204 Copied: 304 to 305 Destroyed: 304 done Destroyed: 104 Destroyed: 305 +Destroyed: 103 +Destroyed: 203 +Destroyed: 303 Destroyed: 300 Destroyed: 200 Destroyed: 100