From 40d630f348cf41e06d7a40c81a1be264c570080b Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Thu, 10 Mar 2016 14:08:56 -0500 Subject: [PATCH] fixed regex, 61 tests passing --- stdlib/ast_transformation.krak | 2 +- stdlib/c_generator.krak | 48 ++++++++++++++++++++-------------- 2 files changed, 29 insertions(+), 21 deletions(-) diff --git a/stdlib/ast_transformation.krak b/stdlib/ast_transformation.krak index ea3bbbd..915c52a 100644 --- a/stdlib/ast_transformation.krak +++ b/stdlib/ast_transformation.krak @@ -677,7 +677,7 @@ obj ast_transformation (Object) { ast_node::function_call(backing) { println("found an function_call") // XXX should special case . and ->, I think - if (is_function(backing.func) && (backing.func->function.name == "." || backing.func->function.name == ".")) + 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);) diff --git a/stdlib/c_generator.krak b/stdlib/c_generator.krak index d02914c..7407d3b 100644 --- a/stdlib/c_generator.krak +++ b/stdlib/c_generator.krak @@ -174,13 +174,13 @@ obj c_generator (Object) { var variable_declarations: string = "\n/**Variable Declarations**/\n" // moved out from below so that it can be used for methods as well as regular functions (and eventually lambdas...) - var generate_function_definition = fun(child: *ast_node, enclosing_object: *ast_node) { + var generate_function_definition = fun(child: *ast_node, enclosing_object: *ast_node, is_lambda: bool) { var backing = child->function var parameter_types = string() var parameters = string() // lambdas can have the enclosing object too, if it's needed (lambda in a method) - if (enclosing_object && backing.closed_variables.size() == 0) { + if (enclosing_object && !is_lambda) { parameter_types = type_to_c(enclosing_object->type_def.self_type) + "*" parameters = type_to_c(enclosing_object->type_def.self_type) + "* this" } @@ -196,7 +196,7 @@ obj c_generator (Object) { // start out with one stack on the stack var defer_stack = stack>>(make_pair(false, stack<*ast_node>())) - var decorated_name = generate_function(child, false).one_string() + var decorated_name = generate_function(child, enclosing_object, null(), false).one_string() backing.parameters.for_each(fun(parameter: *ast_node) { if (parameter_types != "") { parameter_types += ", "; parameters += ", ";} parameter_types += type_to_c(parameter->identifier.type) @@ -226,9 +226,9 @@ obj c_generator (Object) { get_ast_scope(enclosing_object_traverse) && get_ast_scope(enclosing_object_traverse)->contains_key(string("~enclosing_scope"))) enclosing_object_traverse = get_ast_scope(enclosing_object_traverse)->get(string("~enclosing_scope"))[0] if (enclosing_object_traverse && is_type_def(enclosing_object_traverse)) - generate_function_definition(child, enclosing_object_traverse) + generate_function_definition(child, enclosing_object_traverse, true) else - generate_function_definition(child, null()) + generate_function_definition(child, null(), true) }) tree_pair.second->translation_unit.children.for_each(fun(child: *ast_node) { match (*child) { @@ -241,12 +241,12 @@ obj c_generator (Object) { ast_node::declaration_statement(backing) variable_declarations += generate_declaration_statement(child, null(), null(), null>>>(), false).one_string() + ";\n" // false - don't do defer ast_node::function(backing) { // check for and add to parameters if a closure - generate_function_definition(child, null()) + generate_function_definition(child, null(), false) } ast_node::template(backing) { backing.instantiated.for_each(fun(node: *ast_node) { match (*node) { - ast_node::function(backing) generate_function_definition(node, null()) + ast_node::function(backing) generate_function_definition(node, null(), false) ast_node::type_def(backing) { type_poset.add_vertex(node) backing.variables.for_each(fun(i: *ast_node) { @@ -279,9 +279,9 @@ obj c_generator (Object) { // generate the methods (note some of these may be templates) vert->type_def.methods.for_each(fun(method: *ast_node) { if (is_template(method)) - method->template.instantiated.for_each(fun(m: *ast_node) generate_function_definition(m, vert);) + method->template.instantiated.for_each(fun(m: *ast_node) generate_function_definition(m, vert, false);) else - generate_function_definition(method, vert); + generate_function_definition(method, vert, false); }) }) @@ -292,7 +292,9 @@ obj c_generator (Object) { var closure_name = string("closure_data_type") + get_id() closure_struct_definitions += "typedef struct {\n" // note that we keep our is_ref, which would not normally happen on a clone with increased indirection - closed_variables.for_each(fun(i: *ast_node) closure_struct_definitions += type_to_c(i->identifier.type->clone_with_increased_indirection(1,i->identifier.type->is_ref)) + + // closed_variables.for_each(fun(i: *ast_node) closure_struct_definitions += type_to_c(i->identifier.type->clone_with_increased_indirection(1,i->identifier.type->is_ref)) + + // NO, now we don't keep our ref. Too hard to make, as &(&*i) isn't legal C + closed_variables.for_each(fun(i: *ast_node) closure_struct_definitions += type_to_c(i->identifier.type->clone_with_increased_indirection()) + " " + get_name(i) + ";\n";) closure_struct_definitions += string("} ") + closure_name + ";\n" closure_struct_map[closed_variables] = closure_name @@ -400,12 +402,14 @@ obj c_generator (Object) { fun generate_identifier(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node): code_triple { var pre = string() var post = string() - if (get_ast_type(node)->is_ref) { + // note that we get rid of references on closing over, (or maybe everything's kind of a reference) + // so we do else if here + if (enclosing_func && enclosing_func->function.closed_variables.contains(node)) + return code_triple(pre + string("(*(closure_data->") + get_name(node) + "))" + post) + else if (get_ast_type(node)->is_ref) { pre += "(*" post += ")" } - if (enclosing_func && enclosing_func->function.closed_variables.contains(node)) - return code_triple(pre + string("(*(closure_data->") + get_name(node) + "))" + post) 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(pre + "(this->" + get_name(node) + ")" + post) return code_triple(pre + get_name(node) + post) @@ -416,6 +420,7 @@ obj c_generator (Object) { var to_ret = code_triple() if (return_value) { var return_value_type = get_ast_type(return_value) + // should this happen every time so that we're sure that we don't call a function after we destruct some things it depends on // if we're returning an object, copy_construct a new one to return if (return_value_type->is_object() && !function_return_type->is_ref && return_value_type->indirection == 0 && has_method(return_value_type->type_def, "copy_construct", vector(return_value_type->clone_with_indirection(1)))) { var temp_ident = ast_identifier_ptr(string("temporary_return")+get_id(), return_value_type, null()) @@ -427,13 +432,13 @@ obj c_generator (Object) { return_value = temp_ident } } - // generate all in stack by passing -1 - to_ret.pre += generate_from_defer_stack(defer_stack, -1, enclosing_object, enclosing_func).one_string() to_ret += code_triple("return") if (function_return_type->is_ref) to_ret += code_triple(" &") if (return_value) to_ret += code_triple(" ") + generate(return_value, enclosing_object, enclosing_func, null>>>()) + // generate all in stack by passing -1, make sure added after we calculate the return value + to_ret.pre += generate_from_defer_stack(defer_stack, -1, enclosing_object, enclosing_func).one_string() return to_ret } @@ -494,7 +499,7 @@ obj c_generator (Object) { return to_ret + "}" } // this generates the function as a value, not the actual function - fun generate_function(node: *ast_node, as_value: bool): code_triple { + fun generate_function(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, as_value: bool): code_triple { if (as_value) { var closed_vars = node->function.closed_variables if (closed_vars.size() == 0) @@ -503,7 +508,10 @@ obj c_generator (Object) { var to_ret = code_triple() var closure_type_str = get_closure_struct_type(closed_vars) to_ret.pre += closure_type_str + " " + temp_closure_struct + " = (" + closure_type_str + "){" - closed_vars.for_each(fun(i: *ast_node) to_ret.pre += string(".") + get_name(i) + "=&" + get_name(i) + ",";) + closed_vars.for_each(fun(i: *ast_node) { + // note that we get/have gotten rid of refs here, or maybe more accurately, everything is a ref + to_ret.pre += string(".") + get_name(i) + "=&" + generate(i, enclosing_object, enclosing_func, null>>>()).one_string() + "," + }) to_ret.pre += "};\n" return to_ret + string("((") + type_to_c(node->function.type) + "){(void*)&" + temp_closure_struct + ",(void*)" + get_name(node) + "})" } @@ -525,7 +533,7 @@ obj c_generator (Object) { // should get uglier when we have to figure out if it's just an inside lambda if (dot_style_method_call) { - func_name = generate_function(node->function_call.func->function_call.parameters[1], false).one_string() + func_name = generate_function(node->function_call.func->function_call.parameters[1], enclosing_object, enclosing_func, false).one_string() // don't add & if it was -> if (node->function_call.func->function_call.func->function.name == ".") call_string += "&" @@ -534,7 +542,7 @@ obj c_generator (Object) { call_string += generate(node->function_call.func->function_call.parameters[0], enclosing_object, enclosing_func, null>>>()) } else if (is_identifier(node->function_call.func) || is_function(node->function_call.func)) { // we handle the case when it's not this later, i.e. it's a lambda returned from another function or something - func_name = generate_function(node->function_call.func, false).one_string() + func_name = generate_function(node->function_call.func, enclosing_object, enclosing_func, false).one_string() } // handle method call from inside method of same object if (!dot_style_method_call && enclosing_object) { @@ -691,7 +699,7 @@ obj c_generator (Object) { ast_node::if_statement(backing) return generate_if_statement(node, enclosing_object, enclosing_func, defer_stack) ast_node::while_loop(backing) return generate_while_loop(node, enclosing_object, enclosing_func, defer_stack) ast_node::for_loop(backing) return generate_for_loop(node, enclosing_object, enclosing_func, defer_stack) - ast_node::function(backing) return generate_function(node,true) + ast_node::function(backing) return generate_function(node, enclosing_object, enclosing_func, true) ast_node::function_call(backing) return generate_function_call(node, enclosing_object, enclosing_func) ast_node::code_block(backing) return generate_code_block(node, enclosing_object, enclosing_func, defer_stack) ast_node::return_statement(backing) return generate_return_statement(node, enclosing_object, enclosing_func, defer_stack)