From 8ce464eb0a4f3c5019655df3ce5930938221b467 Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Thu, 25 Feb 2016 14:24:55 -0500 Subject: [PATCH] Fix a bunch of stuff back and forth, 39 tests passing --- stdlib/ast_transformation.krak | 51 +++++++++++++++++++++++++++++----- stdlib/c_generator.krak | 31 +++++++++++++++------ stdlib/set.krak | 5 ++++ stdlib/type.krak | 6 ++++ tests/test_memTest.krak | 2 +- tests/test_rec_closure.krak | 2 +- 6 files changed, 80 insertions(+), 17 deletions(-) diff --git a/stdlib/ast_transformation.krak b/stdlib/ast_transformation.krak index 0b6bd4a..3a46d55 100644 --- a/stdlib/ast_transformation.krak +++ b/stdlib/ast_transformation.krak @@ -463,24 +463,24 @@ obj ast_transformation (Object) { // may have type, or an expression, or both var type_syntax_node = get_node("type", node) var expression_syntax_node = get_node("boolean_expression", node) - var ident_type = null() var expression = null() - if (type_syntax_node) ident_type = transform_type(type_syntax_node, scope, template_replacements) + // we do it early so that if there is a type_syntax_node we can add to scope so that the expression can find this for things like rec closures + var identifier = ast_identifier_ptr(name, null(), scope) + add_to_scope(name, identifier, scope) + if (type_syntax_node) identifier->identifier.type = transform_type(type_syntax_node, scope, template_replacements) if (expression_syntax_node) { expression = transform(expression_syntax_node, scope, template_replacements) if (!type_syntax_node) - ident_type = get_ast_type(expression) + identifier->identifier.type = get_ast_type(expression) } - if (!ident_type) error("declaration statement with no type or expression from which to inference type") - var identifier = ast_identifier_ptr(name, ident_type, scope) + if (!identifier->identifier.type) error("declaration statement with no type or expression from which to inference type") var declaration = ast_declaration_statement_ptr(identifier, expression) // ok, deal with the possible init position method call if (identifiers.size == 2) { - var method = transform(identifiers[1], ident_type->type_def, template_replacements) + var method = transform(identifiers[1], identifier->identifier.type->type_def, template_replacements) var parameters = get_nodes("parameter", node).map(fun(child: *tree): *ast_node return transform(get_node("boolean_expression", child), scope, template_replacements);) declaration->declaration_statement.init_method_call = make_method_call(identifier, method, parameters) } - add_to_scope(name, identifier, scope) return declaration } fun transform_assignment_statement(node: *tree, scope: *ast_node, template_replacements: map): *ast_node { @@ -555,6 +555,7 @@ obj ast_transformation (Object) { return function_node } 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) { println("found an identifier") @@ -574,6 +575,7 @@ obj ast_transformation (Object) { } ast_node::function_call(backing) { println("found an function_call") + // XXX should special case . and ->, I think 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 @@ -582,6 +584,41 @@ obj ast_transformation (Object) { println("found an return_statement") return find_closed_variables(func, backing.return_value) } + ast_node::if_statement(backing) { + println("found an if statement") + return find_closed_variables(func, backing.condition) + find_closed_variables(func, backing.then_part) + find_closed_variables(func, backing.else_part) + } + // match_statement: match_statement, + // case_statement: case_statement, + ast_node::while_loop(backing) { + println("found an while loop") + return find_closed_variables(func, backing.condition) + find_closed_variables(func, backing.statement) + } + ast_node::for_loop(backing) { + println("found an for loop") + 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) { + println("found a return_statement") + return find_closed_variables(func, backing.return_value) + } + ast_node::defer_statement(backing) { + println("found a defer_statement") + return find_closed_variables(func, backing.statement) + } + ast_node::assignment_statement(backing) { + println("found an assignment_statement") + return find_closed_variables(func, backing.to) + find_closed_variables(func, backing.from) + } + ast_node::declaration_statement(backing) { + println("found an declaration_statement") + return find_closed_variables(func, backing.expression) + find_closed_variables(func, backing.init_method_call) + } + ast_node::if_comp(backing) { + println("found an if_comp") + return find_closed_variables(func, backing.statement) + } } return set<*ast_node>() } diff --git a/stdlib/c_generator.krak b/stdlib/c_generator.krak index 271830d..50a95b4 100644 --- a/stdlib/c_generator.krak +++ b/stdlib/c_generator.krak @@ -273,7 +273,7 @@ obj c_generator (Object) { }) }) - return make_pair(prequal+plain_typedefs+top_level_c_passthrough+variable_extern_declarations+structs+closure_struct_definitions+function_typedef_string+function_prototypes+variable_declarations+function_definitions + "\n", linker_string) + return make_pair(prequal+plain_typedefs+top_level_c_passthrough+variable_extern_declarations+structs+function_typedef_string+closure_struct_definitions+function_prototypes+variable_declarations+function_definitions + "\n", linker_string) } fun get_closure_struct_type(closed_variables: set<*ast_node>): string { if (!closure_struct_map.contains_key(closed_variables)) { @@ -317,16 +317,29 @@ obj c_generator (Object) { // add destruct to defer_stack var identifier = node->declaration_statement.identifier var ident_type = identifier->identifier.type - var to_ret = code_triple() + type_to_c(identifier->identifier.type) + " " + get_name(identifier) + // we do the declaration in the pre now so that we can take it's address to close over it for things like recursive closures + // we only make it first if it's a function type though, so that global levels still work + var to_ret = code_triple(type_to_c(identifier->identifier.type) + " " + get_name(identifier), string(), string()) if (node->declaration_statement.expression) { if (ident_type->is_object() && has_method(ident_type->type_def, "copy_construct", vector(get_ast_type(node->declaration_statement.expression)->clone_with_increased_indirection()))) { - to_ret += ";\n"; + to_ret.pre += ";\n" to_ret += generate(ast_statement_ptr(make_method_call(identifier, "copy_construct", vector(make_operator_call("&", vector(node->declaration_statement.expression))))), enclosing_object, enclosing_func, defer_stack) } else { - to_ret += code_triple(" = ") + generate(node->declaration_statement.expression, enclosing_object, enclosing_func, null>>>()) + if (ident_type->is_function()) { + to_ret.pre += string(";\n") + to_ret += code_triple() + get_name(identifier) + " = " + generate(node->declaration_statement.expression, enclosing_object, enclosing_func, null>>>()) + } else { + // some shifting around to get it to work in all cases + to_ret.value = to_ret.pre + to_ret.pre = "" + to_ret += code_triple() + string(" = ") + generate(node->declaration_statement.expression, enclosing_object, enclosing_func, null>>>()).one_string() + } } } - if (node->declaration_statement.init_method_call) to_ret += code_triple(";\n") + generate(node->declaration_statement.init_method_call, enclosing_object, enclosing_func, null>>>()) + if (node->declaration_statement.init_method_call) { + to_ret.pre += ";\n" + to_ret += code_triple() + generate(node->declaration_statement.init_method_call, enclosing_object, enclosing_func, null>>>()) + } if (add_to_defer && 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>()))) return to_ret @@ -363,7 +376,7 @@ obj c_generator (Object) { } fun generate_identifier(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node): code_triple { if (enclosing_func && enclosing_func->function.closed_variables.contains(node)) - return code_triple(string("*(closure_data->") + get_name(node) + ")") + return code_triple(string("(*(closure_data->") + get_name(node) + "))") if (enclosing_object && get_ast_scope(enclosing_object)->contains_key(node->identifier.name) && get_ast_scope(enclosing_object)->get(node->identifier.name).contains(node)) return code_triple("(this->") + get_name(node) + ")" return code_triple(get_name(node)) @@ -481,15 +494,17 @@ obj c_generator (Object) { // don't add & if it was -> if (node->function_call.func->function_call.func->function.name == ".") call_string += "&" - // call_string += generate_function(node->function_call.func->function_call.parameters[0], false) call_string += generate_identifier(node->function_call.func->function_call.parameters[0], enclosing_object, enclosing_func) } else { // regular style function name or lambda - func_name = generate_function(node->function_call.func, false).one_string() + // func_name = generate_function(node->function_call.func, false).one_string() if (!is_function(node->function_call.func)) { // not function, so we must be an identifier or function call return or something + func_name = generate(node->function_call.func, enclosing_object, enclosing_func, null>>>()).one_string() call_string += func_name + ".data" func_name = func_name + ".func" + } else { + func_name = generate_function(node->function_call.func, false).one_string() } } // handle method call from inside method of same object diff --git a/stdlib/set.krak b/stdlib/set.krak index 3d04ea9..f04b6ad 100644 --- a/stdlib/set.krak +++ b/stdlib/set.krak @@ -69,6 +69,11 @@ obj set (Object, Serializable) { fun operator+=(items: ref set) { add(items) } + fun operator+(items: ref set): set { + var to_ret.copy_construct(this): set + to_ret.add(items) + return to_ret + } fun add(item: ref T) { if (!contains(item)) data.add(item) diff --git a/stdlib/type.krak b/stdlib/type.krak index a424b2f..57f164e 100644 --- a/stdlib/type.krak +++ b/stdlib/type.krak @@ -166,5 +166,11 @@ obj type (Object) { } return false } + fun is_function(): bool { + match (base) { + base_type::function() return true + } + return false + } } diff --git a/tests/test_memTest.krak b/tests/test_memTest.krak index 42a734d..1f75592 100644 --- a/tests/test_memTest.krak +++ b/tests/test_memTest.krak @@ -1,5 +1,5 @@ import mem:*; -import io:*; +import simple_print:*; obj AnObject { var a: int; diff --git a/tests/test_rec_closure.krak b/tests/test_rec_closure.krak index b33ad1c..eac15a8 100644 --- a/tests/test_rec_closure.krak +++ b/tests/test_rec_closure.krak @@ -1,4 +1,4 @@ -import io:* +import simple_print:* fun main():int { var message = "thingy: "