diff --git a/captain.sh b/captain.sh index e88077f..eec662a 100755 --- a/captain.sh +++ b/captain.sh @@ -1,7 +1,7 @@ #!/bin/bash kraken="kraken" -bootstrap_commits=(cf46fb13afe66ba475db9725e9269c9c1cd3bbc3 2cd43e5a217318c70097334b3598d2924f64b362 2051f54b559ac5edf67277d4f1134aca2cb9215d ecbbcb4eda56e2467efb0a04e7d668b95856aa4b d126cbf24ba8b26e3814e2260d555ecaee86508c 947384cced5397a517a71963edc8f47e668d734f cfcaff7887a804fe77dadaf2ebb0251d6e8ae8e2 12dfa837e31bf09adb1335219473b9a7e6db9eac) +bootstrap_commits=(cf46fb13afe66ba475db9725e9269c9c1cd3bbc3 2cd43e5a217318c70097334b3598d2924f64b362 2051f54b559ac5edf67277d4f1134aca2cb9215d ecbbcb4eda56e2467efb0a04e7d668b95856aa4b d126cbf24ba8b26e3814e2260d555ecaee86508c 947384cced5397a517a71963edc8f47e668d734f cfcaff7887a804fe77dadaf2ebb0251d6e8ae8e2 12dfa837e31bf09adb1335219473b9a7e6db9eac acb0e48324f353d30d148eb11d1bf2843d83b51a) # Echo version string to a file included by kraken.krak diff --git a/kraken.krak b/kraken.krak index 0ebf125..4d43de4 100644 --- a/kraken.krak +++ b/kraken.krak @@ -1,16 +1,17 @@ import io:* import grammer:* import parser:* -import ast_transformation:* import string:* import util:* import symbol:* import tree:* import serialize:* -import c_generator:* -import c_line_control:* import interpreter:* import os:* +import ast_transformation:* +import defer_lower:* +import c_line_control:* +import c_generator:* import compiler_version @@ -97,6 +98,9 @@ fun main(argc: int, argv: **char):int { /*var parsers = vector(parse1,parse2,parse3,parse4,parse5,parse6,parse7,parse8)*/ var importer.construct(parsers, ast_pass, vector(string(), base_dir + "/stdlib/")): importer importer.import(kraken_file_name) + // Passes + printlnerr("Lowering Defer") + defer_lower(&importer.name_ast_map, &importer.ast_pass.ast_to_syntax) if (interpret_instead) { printlnerr("Interpreting!") var interpret.construct(importer.name_ast_map, importer.ast_pass.ast_to_syntax): interpreter diff --git a/stdlib/c_generator.krak b/stdlib/c_generator.krak index ab62008..d2032b3 100644 --- a/stdlib/c_generator.krak +++ b/stdlib/c_generator.krak @@ -688,6 +688,7 @@ obj c_generator (Object) { return to_ret } 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*/") } diff --git a/stdlib/c_line_control.krak b/stdlib/c_line_control.krak index 4aa7c8c..e9210a1 100644 --- a/stdlib/c_line_control.krak +++ b/stdlib/c_line_control.krak @@ -9,66 +9,30 @@ import io:* import ast_nodes:* import ast_transformation:* +import pass_common:* + fun get_line(node: *tree, name: string): *ast_node { var to_ret = ast_simple_passthrough_ptr() to_ret->simple_passthrough.passthrough_str = string("\n#line ") + get_first_terminal(node)->data.position + " \"" + name + "\"\n" return to_ret } -fun add_before_in(to_add: *ast_node, before: *ast_node, in: *ast_node) { - var bc = null>() - match(*in) { - ast_node::translation_unit(backing) bc = &in->translation_unit.children - ast_node::code_block(backing) bc = &in->code_block.children - } - if (bc) { - for (var i = 0; i < bc->size; i++;) { - if ((*bc)[i] == before) { - /*println("\nbefore\n")*/ - /*(*bc).for_each(fun(n:*ast_node) println(get_ast_name(n));)*/ - /*(*bc).for_each(fun(n:*ast_node) println(n);)*/ - (*bc).add(to_add, i) - /*println("\nafter\n")*/ - /*(*bc).for_each(fun(n:*ast_node) println(get_ast_name(n));)*/ - /*(*bc).for_each(fun(n:*ast_node) println(n);)*/ - /*println("\n")*/ - return - } - } - } - error(string("cannot add_before_in to ") + get_ast_name(in)) -} - fun c_line_control(name_ast_map: *map,*ast_node>>, ast_to_syntax: *map<*ast_node, *tree>) { var first = true name_ast_map->for_each(fun(name: string, syntax_ast_pair: pair<*tree,*ast_node>) { - var helper: fun(*ast_node, *ast_node):void = fun(node: *ast_node, parent: *ast_node) { - if (!node) return + var helper_after = fun(node: *ast_node, parent_chain: *stack<*ast_node>) {} + var helper = fun(node: *ast_node, parent_chain: *stack<*ast_node>) { match(*node) { - ast_node::translation_unit(backing) get_ast_children(node).for_each(fun(n: *ast_node) helper(n, node);) - ast_node::type_def(backing) { - /*println(string("adding ") + get_ast_name(node) + " to " + get_ast_name(parent))*/ - /*add_before_in(get_line(), node, parent)*/ - /*get_ast_children(node).for_each(fun(n: *ast_node) helper(n, node);)*/ - } - ast_node::function(backing) get_ast_children(node).for_each(fun(n: *ast_node) helper(n, node);) - ast_node::code_block(backing) get_ast_children(node).for_each(fun(n: *ast_node) helper(n, node);) ast_node::statement(backing) { - if (is_code_block(parent) && ast_to_syntax->contains_key(node)) { + if (is_code_block(parent_chain->top()) && ast_to_syntax->contains_key(node)) { /*println(string("adding ") + get_ast_name(node) + " to " + get_ast_name(parent))*/ - add_before_in(get_line(ast_to_syntax->get(node), name), node, parent) + add_before_in(get_line(ast_to_syntax->get(node), name), node, parent_chain->top()) } - get_ast_children(node).for_each(fun(n: *ast_node) helper(n, node);) } - ast_node::if_statement(backing) get_ast_children(node).for_each(fun(n: *ast_node) helper(n, node);) - ast_node::match_statement(backing) get_ast_children(node).for_each(fun(n: *ast_node) helper(n, node);) - ast_node::case_statement(backing) get_ast_children(node).for_each(fun(n: *ast_node) helper(n, node);) - ast_node::while_loop(backing) get_ast_children(node).for_each(fun(n: *ast_node) helper(n, node);) - ast_node::for_loop(backing) get_ast_children(node).for_each(fun(n: *ast_node) helper(n, node);) } } if (first) - helper(syntax_ast_pair.second, null()) + run_on_tree(helper, helper_after, syntax_ast_pair.second) first = false }) } diff --git a/stdlib/defer_lower.krak b/stdlib/defer_lower.krak new file mode 100644 index 0000000..ace5dd3 --- /dev/null +++ b/stdlib/defer_lower.krak @@ -0,0 +1,64 @@ +import symbol:* +import tree:* +import vector:* +import map:* +import util:* +import string:* +import mem:* +import io:* +import ast_nodes:* +import ast_transformation:* + +import pass_common:* + +fun defer_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 defer_double_stack = stack>() + var loop_stack = stack(-1) + var helper_before = fun(node: *ast_node, parent_chain: *stack<*ast_node>) { + 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) + } + } + ast_node::code_block(backing) { + defer_double_stack.push(stack<*ast_node>()) + } + ast_node::for_loop(backing) { + loop_stack.push(defer_double_stack.size()) + } + ast_node::while_loop(backing) { + loop_stack.push(defer_double_stack.size()) + } + } + } + var helper_after = fun(node: *ast_node, parent_chain: *stack<*ast_node>) { + match(*node) { + ast_node::branching_statement(backing) { + var block = ast_code_block_ptr() + replace_with_in(node, block, parent_chain) + for (var i = 0; i < defer_double_stack.size() - loop_stack.top(); i++;) + block->code_block.children.add_all(defer_double_stack.from_top(i).reverse_vector()) + block->code_block.children.add(ast_statement_ptr(node)) + } + ast_node::code_block(backing) { + node->code_block.children.add_all(defer_double_stack.pop().reverse_vector()) + } + ast_node::for_loop(backing) { + loop_stack.pop() + } + ast_node::while_loop(backing) { + loop_stack.pop() + } + } + } + run_on_tree(helper_before, helper_after, syntax_ast_pair.second) + }) +} + diff --git a/stdlib/pass_common.krak b/stdlib/pass_common.krak new file mode 100644 index 0000000..26a76d6 --- /dev/null +++ b/stdlib/pass_common.krak @@ -0,0 +1,94 @@ +import ast_nodes:* +import mem:* +import util:* +import vector:* +import stack:* +import string:* + +fun get_children_pointer(node: *ast_node): *vector<*ast_node> { + var bc = null>() + match(*node) { + ast_node::translation_unit(backing) bc = &node->translation_unit.children + ast_node::code_block(backing) bc = &node->code_block.children + } + return bc +} + +fun remove_full_statement(node: *ast_node, parent_chain: *stack<*ast_node>): *ast_node { + if (is_statement(node)) + return remove(node, parent_chain) + if (is_statement(parent_chain->top())) + return remove(parent_chain->top(), parent_chain->from_top(1)) + error(string("cannot remove full statement in ") + get_ast_name(parent_chain->top())) +} + +fun remove(orig: *ast_node, in: *stack<*ast_node>): *ast_node + return remove(orig, in->top()) +fun remove(orig: *ast_node, in: *ast_node): *ast_node { + var bc = get_children_pointer(in) + if (bc) { + var i = bc->find(orig) + if (i >= 0) { + var temp = bc->at(i) + bc->remove(i) + return temp + } + } + error(string("cannot remove inside ") + get_ast_name(in)) +} +fun replace_with_in(orig: *ast_node, new: *ast_node, in: *stack<*ast_node>) + replace_with_in(orig, new, in->top()) +fun replace_with_in(orig: *ast_node, new: *ast_node, in: *ast_node) { + if (is_statement(in)) { + in->statement.child = new + } else { + var bc = get_children_pointer(in) + if (bc) { + var i = bc->find(orig) + if (i >= 0) { + bc->set(i, new) + return + } + } + error(string("cannot replace_with_in inside ") + get_ast_name(in)) + } +} + +fun add_before_in(to_add: *ast_node, before: *ast_node, in: *stack<*ast_node>) + add_before_in(to_add, before, in->top()) +fun add_before_in(to_add: *ast_node, before: *ast_node, in: *ast_node) { + var bc = get_children_pointer(in) + if (bc) { + var i = bc->find(before) + if (i >= 0) { + bc->add(to_add, i) + return + } + } + error(string("cannot add_before_in to ") + get_ast_name(in)) +} + +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>() + run_on_tree_helper(func_before, func_after, tree, &parent_stack) +} +fun run_on_tree_helper(func_before: fun(*ast_node,*stack<*ast_node>):void, func_after: fun(*ast_node,*stack<*ast_node>):void, node: *ast_node, parent_chain: *stack<*ast_node>) { + if (!node) return + func_before(node, parent_chain) + parent_chain->push(node) + match(*node) { + ast_node::translation_unit(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain);) + ast_node::type_def(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain);) + ast_node::function(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain);) + ast_node::code_block(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain);) + ast_node::statement(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain);) + ast_node::if_statement(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain);) + ast_node::match_statement(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain);) + ast_node::case_statement(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain);) + ast_node::while_loop(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain);) + ast_node::for_loop(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain);) + } + parent_chain->pop() + func_after(node, parent_chain) +} + diff --git a/stdlib/stack.krak b/stdlib/stack.krak index 1da8944..1b498ea 100644 --- a/stdlib/stack.krak +++ b/stdlib/stack.krak @@ -71,4 +71,6 @@ obj stack (Object, Serializable) { fun for_each_reverse(func: fun(T):void) { data.for_each_reverse(func) } + fun reverse_vector(): vector::vector + return data.reverse() } diff --git a/tests/test_break_continue_defer.expected_results b/tests/test_break_continue_defer.expected_results index c2e76b0..25d3ff5 100644 --- a/tests/test_break_continue_defer.expected_results +++ b/tests/test_break_continue_defer.expected_results @@ -7,10 +7,11 @@ happens every time, even when breaking or continueing 5 happens every time, even when breaking or continueing happens every time, even when breaking or continueing -7 +only happens once before breaking 7 happens every time, even when breaking or continueing happens every time, even when breaking or continueing happens every time, even when breaking or continueing +block outside for first last deferred diff --git a/tests/test_break_continue_defer.krak b/tests/test_break_continue_defer.krak index c143c8a..237e71e 100644 --- a/tests/test_break_continue_defer.krak +++ b/tests/test_break_continue_defer.krak @@ -1,14 +1,21 @@ import io:* fun main():int { - for (var i = 1; i < 10; i++;) { - { - defer println("happens every time, even when breaking or continueing") - if (i % 2 == 0) - continue - if (i == 9) - break - println(i) + { + defer println("block outside for") + for (var i = 1; i < 10; i++;) { + { + defer println("happens every time, even when breaking or continueing") + if (i % 2 == 0) + continue + if (i == 9) + break + if (i == 7) { + defer println("only happens once before breaking 7") + continue + } + println(i) + } } } {