Files
kraken/stdlib/defer_lower.krak

92 lines
4.3 KiB
Plaintext
Raw Normal View History

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<string, pair<*tree<symbol>,*ast_node>>, ast_to_syntax: *map<*ast_node, *tree<symbol>>) {
2017-01-21 22:01:47 -05:00
var enclosing_function_stack = stack<*ast_node>()
var visited = set<*ast_node>()
name_ast_map->for_each(fun(name: string, syntax_ast_pair: pair<*tree<symbol>,*ast_node>) {
2017-01-21 22:01:47 -05:00
var defer_triple_stack = stack<stack<stack<*ast_node>>>()
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())) {
remove(node, parent_chain)
2017-01-21 22:01:47 -05:00
defer_triple_stack.top().top().push(backing.statement)
} else {
replace_with_in(node, backing.statement, parent_chain)
}
}
ast_node::code_block(backing) {
2017-01-21 22:01:47 -05:00
defer_triple_stack.top().push(stack<*ast_node>())
}
ast_node::for_loop(backing) {
2017-01-21 22:01:47 -05:00
loop_stack.push(defer_triple_stack.top().size())
}
ast_node::while_loop(backing) {
2017-01-21 22:01:47 -05:00
loop_stack.push(defer_triple_stack.top().size())
}
ast_node::function(backing) {
2017-01-21 22:01:47 -05:00
enclosing_function_stack.push(node)
defer_triple_stack.push(stack<stack<*ast_node>>())
}
}
}
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)
2017-01-21 22:01:47 -05:00
for (var i = 0; i < defer_triple_stack.top().size() - loop_stack.top(); i++;)
block->code_block.children.add_all(defer_triple_stack.top().from_top(i).reverse_vector())
block->code_block.children.add(node)
}
ast_node::return_statement(backing) {
var block = ast_code_block_ptr()
replace_with_in(node, block, parent_chain)
var return_value = node->return_statement.return_value
if (return_value) {
2017-01-21 22:01:47 -05:00
if (get_ast_type(enclosing_function_stack.top())->return_type->is_ref)
return_value = make_operator_call("&", vector(return_value))
var temp_return = ast_identifier_ptr("temp_boom_return", get_ast_type(return_value)->clone_without_ref(), block)
block->code_block.children.add(ast_declaration_statement_ptr(temp_return, null<ast_node>(), false))
block->code_block.children.add(assign_or_copy_construct_statement(temp_return, return_value))
// dereference so that the real ref can take it back
2017-01-21 22:01:47 -05:00
if (get_ast_type(enclosing_function_stack.top())->return_type->is_ref)
temp_return = make_operator_call("*", vector(temp_return))
node->return_statement.return_value = temp_return
}
2017-01-21 22:01:47 -05:00
for (var i = 0; i < defer_triple_stack.top().size(); i++;)
block->code_block.children.add_all(defer_triple_stack.top().from_top(i).reverse_vector())
block->code_block.children.add(node)
}
ast_node::code_block(backing) {
2017-01-21 22:01:47 -05:00
node->code_block.children.add_all(defer_triple_stack.top().pop().reverse_vector())
}
ast_node::for_loop(backing) {
loop_stack.pop()
}
ast_node::while_loop(backing) {
loop_stack.pop()
}
2017-01-21 22:01:47 -05:00
ast_node::function(backing) {
defer_triple_stack.pop()
enclosing_function_stack.pop()
}
}
}
run_on_tree(helper_before, helper_after, syntax_ast_pair.second, &visited)
})
}