working on moving rest of obj stuff into obj_lower
This commit is contained in:
@@ -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))
|
||||
|
||||
Reference in New Issue
Block a user