working on moving rest of obj stuff into obj_lower

This commit is contained in:
Nathan Braswell
2017-11-03 00:39:58 -04:00
parent 5b8ef4ce2e
commit cb720e5cd6
9 changed files with 295 additions and 144 deletions

View File

@@ -27,12 +27,76 @@ fun make_function_parent_block(function: *ast_node, parent: *ast_node, parent_bl
result.parent_function = parent_function
return result
}
fun find_closed_variables(func: *ast_node, node: *ast_node): set<*ast_node> {
if (!node) return set<*ast_node>()
match (*node) {
ast_node::identifier(backing) {
if (!in_scope_chain(backing.enclosing_scope, func)) {
if (backing.name == "temporary_return_boomchaka" ||
backing.name == "temp_boom_return")
error("trying to close over temp return")
else
return set(node);
}
}
ast_node::code_block(backing) {
var to_ret = set<*ast_node>()
backing.children.for_each(fun(n: *ast_node) to_ret += find_closed_variables(func, n);)
return to_ret
}
ast_node::function_call(backing) {
if (is_function(backing.func) && (backing.func->function.name == "." || backing.func->function.name == "->"))
return find_closed_variables(func, backing.parameters.first())
var to_ret = find_closed_variables(func, backing.func)
backing.parameters.for_each(fun(n: *ast_node) to_ret += find_closed_variables(func, n);)
return to_ret
}
ast_node::function(backing) {
// if this is a lambda, we need to check all of the things it closes over
var to_ret = set<*ast_node>()
backing.closed_variables.for_each(fun(n: *ast_node) to_ret += find_closed_variables(func, n);)
return to_ret
}
ast_node::return_statement(backing) return find_closed_variables(func, backing.return_value)
ast_node::if_statement(backing) return find_closed_variables(func, backing.condition) + find_closed_variables(func, backing.then_part) + find_closed_variables(func, backing.else_part)
ast_node::match_statement(backing) {
var to_ret = set<*ast_node>()
backing.cases.for_each(fun(n: *ast_node) to_ret += find_closed_variables(func, n);)
return to_ret
}
ast_node::case_statement(backing) return find_closed_variables(func, backing.statement)
ast_node::while_loop(backing) return find_closed_variables(func, backing.condition) + find_closed_variables(func, backing.statement)
ast_node::for_loop(backing) {
return find_closed_variables(func, backing.init) + find_closed_variables(func, backing.condition) +
find_closed_variables(func, backing.update) + find_closed_variables(func, backing.body)
}
ast_node::return_statement(backing) return find_closed_variables(func, backing.return_value)
ast_node::defer_statement(backing) return find_closed_variables(func, backing.statement)
ast_node::assignment_statement(backing) return find_closed_variables(func, backing.to) + find_closed_variables(func, backing.from)
ast_node::declaration_statement(backing) return find_closed_variables(func, backing.expression) + find_closed_variables(func, backing.init_method_call)
ast_node::if_comp(backing) return find_closed_variables(func, backing.statement)
ast_node::cast(backing) return find_closed_variables(func, backing.value)
}
return set<*ast_node>()
}
fun in_scope_chain(node: *ast_node, high_scope: *ast_node): bool {
if (node == high_scope)
return true
if (get_ast_scope(node)->contains_key(string("~enclosing_scope")))
return in_scope_chain(get_ast_scope(node)->get(string("~enclosing_scope"))[0], high_scope)
return false
}
fun function_value_lower(name_ast_map: *map<string, pair<*tree<symbol>,*ast_node>>, ast_to_syntax: *map<*ast_node, *tree<symbol>>) {
var visited = hash_set<*ast_node>()
var lambdas = set<*ast_node>()
name_ast_map->for_each(fun(name: string, syntax_ast_pair: pair<*tree<symbol>,*ast_node>) {
lambdas.add(syntax_ast_pair.second->translation_unit.lambdas)
// do in order so that inner lambdas are done before outer ones, so enclosed
// variables can propegate outwards
syntax_ast_pair.second->translation_unit.lambdas.for_each(fun(n: *ast_node) {
n->function.closed_variables = find_closed_variables(n, n->function.body_statement)
})
})
var all_types = hash_set<*type>()
var function_value_creation_points = vector<function_parent_block>()
@@ -172,13 +236,13 @@ fun function_value_lower(name_ast_map: *map<string, pair<*tree<symbol>,*ast_node
body->code_block.children.add(ast_assignment_statement_ptr(access_expression(ident, "data"), closure_param))
l->function.closed_variables.for_each(fun(v: *ast_node) {
// HACK
if (v->identifier.name == "this") {
// add in an assignment at the beginning of the lambda
if (!is_code_block(l->function.body_statement))
error("lambda body isn't a block in function_value_lower")
l->function.body_statement->code_block.children.add(0, ast_declaration_statement_ptr(ast_identifier_ptr("this", v->identifier.type, l->function.body_statement),
make_operator_call("*", vector(access_expression(closure_lambda_param, v->identifier.name)))))
}
/*if (v->identifier.name == "this") {*/
/*// add in an assignment at the beginning of the lambda*/
/*if (!is_code_block(l->function.body_statement))*/
/*error("lambda body isn't a block in function_value_lower")*/
/*l->function.body_statement->code_block.children.add(0, ast_declaration_statement_ptr(ast_identifier_ptr("this", v->identifier.type, l->function.body_statement),*/
/*make_operator_call("*", vector(access_expression(closure_lambda_param, v->identifier.name)))))*/
/*}*/
// have to make sure to clean here as well
var closed_param_type = v->identifier.type
if (lambda_type_to_struct_type_and_call_func.contains_key(*closed_param_type))