Fix defer_lower to handle return statements, starting on obj_lower which has now taken over calling destruct for declared varaibles. Some of the code from the c_generator has been commented out or bypassed to use the new system - it should be removed when it's complete.
This commit is contained in:
@@ -10,6 +10,7 @@ import interpreter:*
|
|||||||
import os:*
|
import os:*
|
||||||
import ast_transformation:*
|
import ast_transformation:*
|
||||||
import adt_lower:*
|
import adt_lower:*
|
||||||
|
import obj_lower:*
|
||||||
import defer_lower:*
|
import defer_lower:*
|
||||||
import c_line_control:*
|
import c_line_control:*
|
||||||
import c_generator:*
|
import c_generator:*
|
||||||
@@ -102,6 +103,8 @@ fun main(argc: int, argv: **char):int {
|
|||||||
// Passes
|
// Passes
|
||||||
printlnerr("Lowering ADTs")
|
printlnerr("Lowering ADTs")
|
||||||
adt_lower(&importer.name_ast_map, &importer.ast_pass.ast_to_syntax)
|
adt_lower(&importer.name_ast_map, &importer.ast_pass.ast_to_syntax)
|
||||||
|
printlnerr("Lowering Objects")
|
||||||
|
obj_lower(&importer.name_ast_map, &importer.ast_pass.ast_to_syntax)
|
||||||
printlnerr("Lowering Defer")
|
printlnerr("Lowering Defer")
|
||||||
defer_lower(&importer.name_ast_map, &importer.ast_pass.ast_to_syntax)
|
defer_lower(&importer.name_ast_map, &importer.ast_pass.ast_to_syntax)
|
||||||
if (interpret_instead) {
|
if (interpret_instead) {
|
||||||
|
|||||||
@@ -417,6 +417,11 @@ obj template (Object) {
|
|||||||
instantiated_map == other.instantiated_map && is_function == other.is_function
|
instantiated_map == other.instantiated_map && is_function == other.is_function
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fun ast_code_block_ptr(stmt: *ast_node): *ast_node {
|
||||||
|
var to_ret = ast_code_block_ptr()
|
||||||
|
to_ret->code_block.children.add(stmt)
|
||||||
|
return to_ret
|
||||||
|
}
|
||||||
fun ast_code_block_ptr(): *ast_node {
|
fun ast_code_block_ptr(): *ast_node {
|
||||||
var to_ret.construct(): code_block
|
var to_ret.construct(): code_block
|
||||||
var ptr = new<ast_node>()
|
var ptr = new<ast_node>()
|
||||||
|
|||||||
@@ -431,8 +431,8 @@ obj c_generator (Object) {
|
|||||||
to_ret += code_triple() + generate(node->declaration_statement.init_method_call, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false)
|
to_ret += code_triple() + generate(node->declaration_statement.init_method_call, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false)
|
||||||
}
|
}
|
||||||
// reference can happen because some passes generate them (adt_lower right now)
|
// 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>())))
|
/*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>())))
|
/*defer_stack->top().second.push(ast_statement_ptr(make_method_call(identifier, "destruct", vector<*ast_node>())))*/
|
||||||
return to_ret
|
return to_ret
|
||||||
}
|
}
|
||||||
fun generate_assignment_statement(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node): code_triple {
|
fun generate_assignment_statement(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node): code_triple {
|
||||||
@@ -492,6 +492,18 @@ obj c_generator (Object) {
|
|||||||
var return_value = node->return_statement.return_value
|
var return_value = node->return_statement.return_value
|
||||||
var function_return_type = get_ast_type(enclosing_func)->return_type
|
var function_return_type = get_ast_type(enclosing_func)->return_type
|
||||||
var to_ret = code_triple()
|
var to_ret = code_triple()
|
||||||
|
|
||||||
|
// new one
|
||||||
|
to_ret += code_triple("return")
|
||||||
|
var refamp = string()
|
||||||
|
if (function_return_type->is_ref)
|
||||||
|
refamp = "&"
|
||||||
|
if (return_value)
|
||||||
|
to_ret += code_triple(" ") + refamp + generate(return_value, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false)
|
||||||
|
to_ret.pre += generate_from_defer_stack(defer_stack, -1, enclosing_object, enclosing_func).one_string()
|
||||||
|
return to_ret
|
||||||
|
|
||||||
|
|
||||||
if (return_value) {
|
if (return_value) {
|
||||||
var return_value_type = get_ast_type(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
|
// always need a return temp so we don't destruct things the return depends on before they're calculated
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import ast_transformation:*
|
|||||||
import pass_common:*
|
import pass_common:*
|
||||||
|
|
||||||
fun defer_lower(name_ast_map: *map<string, pair<*tree<symbol>,*ast_node>>, ast_to_syntax: *map<*ast_node, *tree<symbol>>) {
|
fun defer_lower(name_ast_map: *map<string, pair<*tree<symbol>,*ast_node>>, ast_to_syntax: *map<*ast_node, *tree<symbol>>) {
|
||||||
|
var enclosing_function = null<ast_node>()
|
||||||
name_ast_map->for_each(fun(name: string, syntax_ast_pair: pair<*tree<symbol>,*ast_node>) {
|
name_ast_map->for_each(fun(name: string, syntax_ast_pair: pair<*tree<symbol>,*ast_node>) {
|
||||||
var defer_double_stack = stack<stack<*ast_node>>()
|
var defer_double_stack = stack<stack<*ast_node>>()
|
||||||
var loop_stack = stack(-1)
|
var loop_stack = stack(-1)
|
||||||
@@ -36,6 +37,9 @@ fun defer_lower(name_ast_map: *map<string, pair<*tree<symbol>,*ast_node>>, ast_t
|
|||||||
ast_node::while_loop(backing) {
|
ast_node::while_loop(backing) {
|
||||||
loop_stack.push(defer_double_stack.size())
|
loop_stack.push(defer_double_stack.size())
|
||||||
}
|
}
|
||||||
|
ast_node::function(backing) {
|
||||||
|
enclosing_function = node
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var helper_after = fun(node: *ast_node, parent_chain: *stack<*ast_node>) {
|
var helper_after = fun(node: *ast_node, parent_chain: *stack<*ast_node>) {
|
||||||
@@ -47,6 +51,25 @@ fun defer_lower(name_ast_map: *map<string, pair<*tree<symbol>,*ast_node>>, ast_t
|
|||||||
block->code_block.children.add_all(defer_double_stack.from_top(i).reverse_vector())
|
block->code_block.children.add_all(defer_double_stack.from_top(i).reverse_vector())
|
||||||
block->code_block.children.add(ast_statement_ptr(node))
|
block->code_block.children.add(ast_statement_ptr(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) {
|
||||||
|
if (get_ast_type(enclosing_function)->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_statement_ptr(ast_declaration_statement_ptr(temp_return, null<ast_node>(), false)))
|
||||||
|
block->code_block.children.add(ast_statement_ptr(assign_or_copy_construct_statement(temp_return, return_value)))
|
||||||
|
// dereference so that the real ref can take it back
|
||||||
|
if (get_ast_type(enclosing_function)->return_type->is_ref)
|
||||||
|
temp_return = make_operator_call("*", vector(temp_return))
|
||||||
|
node->return_statement.return_value = temp_return
|
||||||
|
}
|
||||||
|
for (var i = 0; i < defer_double_stack.size(); 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) {
|
ast_node::code_block(backing) {
|
||||||
node->code_block.children.add_all(defer_double_stack.pop().reverse_vector())
|
node->code_block.children.add_all(defer_double_stack.pop().reverse_vector())
|
||||||
}
|
}
|
||||||
|
|||||||
44
stdlib/obj_lower.krak
Normal file
44
stdlib/obj_lower.krak
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
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 obj_lower(name_ast_map: *map<string, pair<*tree<symbol>,*ast_node>>, ast_to_syntax: *map<*ast_node, *tree<symbol>>) {
|
||||||
|
name_ast_map->for_each(fun(name: string, syntax_ast_pair: pair<*tree<symbol>,*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")*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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::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")*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
run_on_tree(helper_before, helper_after, syntax_ast_pair.second)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
@@ -95,42 +95,98 @@ fun add_before_in(to_add: *ast_node, before: *ast_node, in: *ast_node) {
|
|||||||
}
|
}
|
||||||
error(string("cannot add_before_in to ") + get_ast_name(in))
|
error(string("cannot add_before_in to ") + get_ast_name(in))
|
||||||
}
|
}
|
||||||
|
fun add_after_in(to_add: *ast_node, before: *ast_node, in: *stack<*ast_node>)
|
||||||
|
add_after_in(to_add, before, in->top())
|
||||||
|
fun add_after_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+1)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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 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) {
|
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>()
|
var parent_stack = stack<*ast_node>()
|
||||||
run_on_tree_helper(func_before, func_after, tree, &parent_stack)
|
run_on_tree_helper(func_before, func_after, tree, &parent_stack, false)
|
||||||
}
|
}
|
||||||
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>) {
|
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>, do_func: bool) {
|
||||||
if (!node) return
|
if (!node || (!do_func && is_function(node))) return
|
||||||
func_before(node, parent_chain)
|
func_before(node, parent_chain)
|
||||||
parent_chain->push(node)
|
parent_chain->push(node)
|
||||||
match(*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::translation_unit(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain, true);)
|
||||||
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::type_def(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain, true);)
|
||||||
ast_node::adt_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::adt_def(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain, true);)
|
||||||
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::function(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain, false);)
|
||||||
ast_node::template(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain);)
|
ast_node::template(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain, true);)
|
||||||
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::code_block(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain, false);)
|
||||||
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::statement(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain, false);)
|
||||||
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::if_statement(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain, false);)
|
||||||
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::match_statement(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain, false);)
|
||||||
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::case_statement(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain, false);)
|
||||||
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::while_loop(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain, false);)
|
||||||
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);)
|
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, false);)
|
||||||
ast_node::return_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::return_statement(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain, false);)
|
||||||
ast_node::defer_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::defer_statement(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain, false);)
|
||||||
ast_node::assignment_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::assignment_statement(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain, false);)
|
||||||
ast_node::declaration_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::declaration_statement(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain, false);)
|
||||||
ast_node::if_comp(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_comp(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain, true);)
|
||||||
ast_node::function_call(backing) {
|
ast_node::function_call(backing) {
|
||||||
if (!is_function(backing.func))
|
if (!is_function(backing.func))
|
||||||
run_on_tree_helper(func_before, func_after, backing.func, parent_chain)
|
run_on_tree_helper(func_before, func_after, backing.func, parent_chain, false)
|
||||||
node->function_call.parameters.for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain);)
|
node->function_call.parameters.for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain, false);)
|
||||||
}
|
}
|
||||||
ast_node::cast(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain);)
|
ast_node::cast(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain, false);)
|
||||||
}
|
}
|
||||||
parent_chain->pop()
|
// function may have messed with the parent chain
|
||||||
|
if (parent_chain->data.contains(node))
|
||||||
|
while(parent_chain->pop() != node){}
|
||||||
func_after(node, parent_chain)
|
func_after(node, parent_chain)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user