From 6f659ece49debe79b9f1a0b272ab7cce14d84c85 Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Tue, 13 Jun 2017 00:40:29 -0400 Subject: [PATCH] Fix closing over raw function pointers --- stdlib/c_generator.krak | 59 ++++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 27 deletions(-) diff --git a/stdlib/c_generator.krak b/stdlib/c_generator.krak index fa02632..3a92294 100644 --- a/stdlib/c_generator.krak +++ b/stdlib/c_generator.krak @@ -645,37 +645,42 @@ obj c_generator (Object) { ref_pre += "(*" ref_post += ")" } - if (!func_type->is_raw && (!is_function(node->function_call.func) || node->function_call.func->function.closed_variables.size())) { + if (!is_function(node->function_call.func) || node->function_call.func->function.closed_variables.size()) { // not function, so we must be an identifier or function call return or something // and also is closure style, so need special call if (!dot_style_method_call) { - // lambda - if (pre_call == "" && (!func_return_type->is_void() || func_return_type->indirection)) { - var temp_ident = ast_identifier_ptr(string("temporary_return") + get_id(), func_return_type, null()) - var declaration = ast_declaration_statement_ptr(temp_ident, null()) - // have to pass false to the declaration generator, so can't do it through generate_statement - call_string.pre += generate_declaration_statement(declaration, enclosing_object, enclosing_func, false).one_string() + ";\n" - pre_call = generate_identifier(temp_ident, enclosing_object, enclosing_func).one_string() + // if is a raw function pointer closed over (or something) + if (func_type->is_raw) { + func_name = generate(node->function_call.func, enclosing_object, enclosing_func, false).one_string() + } else { + // lambda + if (pre_call == "" && (!func_return_type->is_void() || func_return_type->indirection)) { + var temp_ident = ast_identifier_ptr(string("temporary_return") + get_id(), func_return_type, null()) + var declaration = ast_declaration_statement_ptr(temp_ident, null()) + // have to pass false to the declaration generator, so can't do it through generate_statement + call_string.pre += generate_declaration_statement(declaration, enclosing_object, enclosing_func, false).one_string() + ";\n" + pre_call = generate_identifier(temp_ident, enclosing_object, enclosing_func).one_string() + } + var name_temp = generate(node->function_call.func, enclosing_object, enclosing_func, false) + call_string.pre += name_temp.pre + call_string.post += name_temp.post + func_name = name_temp.value + // should not have return var because is void + var pre_call_plus = pre_call + if (pre_call_plus != "") + pre_call_plus += " = " + + var func_type = get_ast_type(node->function_call.func) + call_string.pre += string("if (")+func_name+".data) " + pre_call_plus + " ((" + type_to_c(func_type) + "_with_data) "+func_name+".func)("+func_name +".data" + if (call_string.value != "") + call_string.pre += string(",") + call_string.value + call_string.pre += ");\n" + call_string.pre += string("else ") + pre_call_plus + " ((" + type_to_c(func_type) + "_without_data) " + func_name+".func)(" + call_string.value + ");\n" + call_string.value = pre_call + + call_string.value = ref_pre + call_string.value + ref_post + return call_string } - var name_temp = generate(node->function_call.func, enclosing_object, enclosing_func, false) - call_string.pre += name_temp.pre - call_string.post += name_temp.post - func_name = name_temp.value - // should not have return var because is void - var pre_call_plus = pre_call - if (pre_call_plus != "") - pre_call_plus += " = " - - var func_type = get_ast_type(node->function_call.func) - call_string.pre += string("if (")+func_name+".data) " + pre_call_plus + " ((" + type_to_c(func_type) + "_with_data) "+func_name+".func)("+func_name +".data" - if (call_string.value != "") - call_string.pre += string(",") + call_string.value - call_string.pre += ");\n" - call_string.pre += string("else ") + pre_call_plus + " ((" + type_to_c(func_type) + "_without_data) " + func_name+".func)(" + call_string.value + ");\n" - call_string.value = pre_call - - call_string.value = ref_pre + call_string.value + ref_post - return call_string } } if (pre_call != "") {