diff --git a/stdlib/adt_lower.krak b/stdlib/adt_lower.krak index 5239365..6bf7031 100644 --- a/stdlib/adt_lower.krak +++ b/stdlib/adt_lower.krak @@ -147,10 +147,8 @@ fun adt_lower(name_ast_map: *map,*ast_node>>, ast_to_ var second_helper = fun(node: *ast_node, parent_chain: *stack<*ast_node>) { match(*node) { ast_node::match_statement(backing) { - /*println("Match statement!")*/ var block = ast_code_block_ptr() var value = backing.value - /*var holder = ast_identifier_ptr(string("holder"), get_ast_type(value), block)*/ var holder = ast_identifier_ptr(string("holder"), get_ast_type(value)->clone_with_increased_indirection(), block) block->code_block.children.add(ast_statement_ptr(ast_declaration_statement_ptr(holder, null(), false))) // dirty hack @@ -158,10 +156,8 @@ fun adt_lower(name_ast_map: *map,*ast_node>>, ast_to_ block->code_block.children.add(if_hack) var if_block = ast_code_block_ptr() if_hack->if_statement.then_part = if_block - /*block->code_block.children.add(ast_statement_ptr(ast_declaration_statement_ptr(holder, make_operator_call("&", vector(value)), false)))*/ backing.cases.for_each(fun(case_stmt: *ast_node) { var option = case_stmt->case_statement.option - /*println(string("case: ") + get_ast_name(option))*/ var flag = get_from_scope(get_ast_type(value)->type_def, "flag") var data = get_from_scope(get_ast_type(value)->type_def, "data") var option_num = -7 @@ -170,13 +166,11 @@ fun adt_lower(name_ast_map: *map,*ast_node>>, ast_to_ for (var i = 0; i < type_def_option_map[get_ast_type(value)->type_def].size; i++;) if (type_def_option_map[get_ast_type(value)->type_def][i] == option) option_num = i; - /*var condition = make_operator_call("==", vector(make_operator_call(".", vector(holder, flag)), ast_value_ptr(to_string(option_num), type_ptr(base_type::integer()))))*/ var condition = make_operator_call("==", vector(make_operator_call("->", vector(holder, flag)), ast_value_ptr(to_string(option_num), type_ptr(base_type::integer())))) var if_stmt = ast_if_statement_ptr(condition) var inner_block = ast_code_block_ptr() var unpack_ident = case_stmt->case_statement.unpack_ident if (unpack_ident) { - /*var get_option = make_operator_call(".", vector(make_operator_call(".", vector(holder, data)), option))*/ var get_option = make_operator_call(".", vector(make_operator_call("->", vector(holder, data)), option)) get_option = make_operator_call("&", vector(get_option)) unpack_ident->identifier.type = unpack_ident->identifier.type->clone_with_ref() diff --git a/stdlib/ast_transformation.krak b/stdlib/ast_transformation.krak index 951d820..e46a41f 100644 --- a/stdlib/ast_transformation.krak +++ b/stdlib/ast_transformation.krak @@ -241,7 +241,9 @@ obj ast_transformation (Object) { }) var is_variadic = get_node("\"...\"", node) != null>() // figure out function type and make function_node - var function_node = ast_function_ptr(function_name, type_ptr(parameters.map(fun(parameter: *ast_node): *type return parameter->identifier.type;), return_type, 0, false, is_variadic), parameters, get_node("\"ext\"", node) != null>(), is_variadic) + var function_node = ast_function_ptr(function_name, + type_ptr(parameters.map(fun(parameter: *ast_node): *type return parameter->identifier.type;), + return_type, 0, false, is_variadic), parameters, get_node("\"ext\"", node) != null>(), is_variadic) // fix up the enclosing_scope's parameters.for_each(fun(n: *ast_node) n->identifier.enclosing_scope = function_node;) // add to scope diff --git a/stdlib/c_generator.krak b/stdlib/c_generator.krak index ced28d7..bf30985 100644 --- a/stdlib/c_generator.krak +++ b/stdlib/c_generator.krak @@ -423,9 +423,6 @@ obj c_generator (Object) { to_ret.pre += ";\n" to_ret += code_triple() + generate(node->declaration_statement.init_method_call, enclosing_object, enclosing_func, null>>>(), false) } - // reference can happen because some passes generate them (adt_lower right now) - /*if (add_to_defer && !ident_type->is_ref && ident_type->indirection == 0 && (ident_type->is_object() && has_method(ident_type->type_def, "destruct", vector<*type>())))*/ - /*defer_stack->top().second.push(ast_statement_ptr(make_method_call(identifier, "destruct", vector<*ast_node>())))*/ return to_ret } fun generate_assignment_statement(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node): code_triple { @@ -440,12 +437,9 @@ obj c_generator (Object) { 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 condition = generate(node->while_loop.condition, enclosing_object, enclosing_func, null>>>(), false) - var to_ret = code_triple("while (1) {\n") + condition.pre + "if(!" + condition.value + ") {" + condition.post + "break;}" + condition.post - to_ret += generate(node->while_loop.statement, enclosing_object, enclosing_func, defer_stack, false).one_string() - to_ret += generate_from_defer_stack(defer_stack, 1, enclosing_object, enclosing_func) + 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() - to_ret += "}\n" return to_ret } fun generate_for_loop(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, defer_stack: *stack>>): code_triple { @@ -453,17 +447,25 @@ obj c_generator (Object) { defer_stack->push(make_pair(true, stack<*ast_node>())) // gotta take off last semicolon /*var init = generate(node->for_loop.init, enclosing_object, enclosing_func, null>>>(), false)*/ - var init = generate(node->for_loop.init, enclosing_object, enclosing_func, defer_stack, false) - var cond = generate(node->for_loop.condition, enclosing_object, enclosing_func, null>>>(), false) - var 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 - 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() + var init = code_triple(";") + if (node->for_loop.init) + init = generate(node->for_loop.init, enclosing_object, enclosing_func, defer_stack, false) + var cond = code_triple(";") + if (node->for_loop.condition) + cond = generate(node->for_loop.condition, enclosing_object, enclosing_func, null>>>(), 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*/ + 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" + //to_ret += "}/*end inner for*/}/*end for's enclosing block*/\n" return code_triple(to_ret) } fun generate_identifier(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node): code_triple { @@ -526,8 +528,6 @@ obj c_generator (Object) { } fun generate_defer_statement(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, defer_stack: *stack>>): code_triple { error("Unremoved defer!") - defer_stack->top().second.push(node->defer_statement.statement) - return code_triple("/*defer wanna know what*/") } fun generate_match_statement(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, defer_stack: *stack>>): code_triple { var to_ret = code_triple("/* begin match */") diff --git a/stdlib/obj_lower.krak b/stdlib/obj_lower.krak index 167638f..4134fa4 100644 --- a/stdlib/obj_lower.krak +++ b/stdlib/obj_lower.krak @@ -8,9 +8,16 @@ import mem:* import io:* import ast_nodes:* import ast_transformation:* - import pass_common:* +// Here's how we lower objects +// - first, we make sure that all functions, if statments, while loops and for loops have code blocks +// as children, not just statements. +// - then, we "uglify" for loops and while loops so that functions that need pre and post statements always +// have a code block to insert them into that makes sure that they get run. +// - then on the pass up the chain, at function calls we add in they copy_construct in and defer destruct out +// temporaries. +// - this is also when we add in defer destructs for function parameters (inside the function) and declaration statements fun obj_lower(name_ast_map: *map,*ast_node>>, ast_to_syntax: *map<*ast_node, *tree>) { 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>) { @@ -21,8 +28,40 @@ fun obj_lower(name_ast_map: *map,*ast_node>>, ast_to_ 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)) + ast_node::while_loop(backing) { + if (!is_code_block(backing.statement)) backing.statement = ast_code_block_ptr(backing.statement) + var condition = backing.condition + backing.condition = ast_value_ptr(string("true"), type_ptr(base_type::boolean())) + // objects do not coerce to booleans, so it should be ok for this not to be a ref + var condition_ident = ast_identifier_ptr("condition_temp", get_ast_type(condition), backing.statement) + backing.statement->code_block.children.add(0, ast_statement_ptr(ast_declaration_statement_ptr(condition_ident, condition, false))) + var condition_if = ast_if_statement_ptr(make_operator_call("!", vector(condition_ident))) + condition_if->if_statement.then_part = ast_statement_ptr(ast_branching_statement_ptr(branching_type::break_stmt())) + backing.statement->code_block.children.add(1, ast_statement_ptr(condition_if)) + } + ast_node::for_loop(backing) { + if (!is_code_block(backing.body)) backing.body = ast_code_block_ptr(backing.body) + add_before_in(backing.init, parent_chain->top(), parent_chain->from_top(1)) + backing.init = null() + // the do_update goes in the block above the for + var update_ident = ast_identifier_ptr("do_update", type_ptr(base_type::boolean()), parent_chain->from_top(1)) + add_before_in(ast_statement_ptr(ast_declaration_statement_ptr(update_ident, ast_value_ptr(string("false"), type_ptr(base_type::boolean())), false)), + parent_chain->top(), parent_chain->from_top(1)) + var update_if = ast_if_statement_ptr(update_ident) + update_if->if_statement.then_part = ast_statement_ptr(ast_code_block_ptr(backing.update)) + backing.update = null() + backing.body->code_block.children.add(0, ast_statement_ptr(update_if)) + backing.body->code_block.children.add(1, ast_statement_ptr(ast_assignment_statement_ptr(update_ident, ast_value_ptr(string("true"), type_ptr(base_type::boolean()))))) + + var condition = backing.condition + backing.condition = ast_value_ptr(string("true"), type_ptr(base_type::boolean())) + // objects do not coerce to booleans, so it should be ok for this not to be a ref + var condition_ident = ast_identifier_ptr("condition_temp", get_ast_type(condition), backing.body) + backing.body->code_block.children.add(2, ast_statement_ptr(ast_declaration_statement_ptr(condition_ident, condition, false))) + var condition_if = ast_if_statement_ptr(make_operator_call("!", vector(condition_ident))) + condition_if->if_statement.then_part = ast_statement_ptr(ast_branching_statement_ptr(branching_type::break_stmt())) + backing.body->code_block.children.add(3, ast_statement_ptr(condition_if)) + } } } var helper_after = fun(node: *ast_node, parent_chain: *stack<*ast_node>) { @@ -33,8 +72,8 @@ fun obj_lower(name_ast_map: *map,*ast_node>>, ast_to_ 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++) + backing.body_statement->statement.child->code_block.children.add(order++, + ast_statement_ptr(ast_defer_statement_ptr(ast_statement_ptr(make_method_call(param, "destruct", vector<*ast_node>()))))) } }) } @@ -44,7 +83,8 @@ fun obj_lower(name_ast_map: *map,*ast_node>>, ast_to_ 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>())))), parent_chain->top(), parent_chain->from_top(1)) + 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/stdlib/pass_common.krak b/stdlib/pass_common.krak index e81a31c..90045f0 100644 --- a/stdlib/pass_common.krak +++ b/stdlib/pass_common.krak @@ -89,7 +89,7 @@ fun add_before_in(to_add: *ast_node, before: *ast_node, in: *ast_node) { if (bc) { var i = bc->find(before) if (i >= 0) { - bc->add(to_add, i) + bc->add(i, to_add) return } } @@ -102,7 +102,7 @@ fun add_after_in(to_add: *ast_node, before: *ast_node, in: *ast_node) { if (bc) { var i = bc->find(before) if (i >= 0) { - bc->add(to_add, i+1) + bc->add(i+1, to_add) return } } diff --git a/stdlib/vector.krak b/stdlib/vector.krak index 07a74c0..8d54863 100644 --- a/stdlib/vector.krak +++ b/stdlib/vector.krak @@ -225,7 +225,7 @@ obj vector (Object, Serializable) { size++; } - fun add(dataIn: ref T, index: int) { + fun add(index: int, dataIn: ref T) { add(last()) for (var i = size-2; i > index; i--;) { data[i] = data[i-1]