diff --git a/stdlib/c_generator.krak b/stdlib/c_generator.krak index 0646499..cab8da5 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() + // and also is closure style, so need special call + if (!func_type->is_raw) { + // 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 + } else { + // this is a raw function value + func_name = generate(node->function_call.func, enclosing_object, enclosing_func, false).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 } } if (pre_call != "") { diff --git a/stdlib/function_value_lower.krak b/stdlib/function_value_lower.krak index 9231994..218fc72 100644 --- a/stdlib/function_value_lower.krak +++ b/stdlib/function_value_lower.krak @@ -96,9 +96,11 @@ fun function_value_lower(name_ast_map: *map,*ast_node var lambda_call_type = type_ptr(vector(lambda_struct_type) + t.parameter_types, t.return_type, 0, false, false, true) // create parameters - var lambda_call_parameters = vector<*ast_node>() + var lambda_call_func_param = ast_identifier_ptr("func_struct", lambda_struct_type, null()) + var lambda_call_parameters = vector(lambda_call_func_param) var lambda_call_function = ast_function_ptr(string("lambda_call"), lambda_call_type, lambda_call_parameters, false) lambda_call_function->function.body_statement = ast_code_block_ptr() + lambda_call_function->function.body_statement->code_block.children.add(ast_return_statement_ptr(ast_function_call_ptr(access_expression(lambda_call_func_param, "func"), vector<*ast_node>()))) // create call body with if, etc lambda_type_to_struct_type_and_call_func[t] = make_pair(lambda_struct_type, lambda_call_function) @@ -131,6 +133,7 @@ fun function_value_lower(name_ast_map: *map,*ast_node body->code_block.children.add(ast_declaration_statement_ptr(ident, null())) body->code_block.children.add(ast_assignment_statement_ptr(access_expression(ident, "func"), l)) body->code_block.children.add(ast_assignment_statement_ptr(access_expression(ident, "data"), ast_value_ptr(string("0"), type_ptr(base_type::void_return(), 1)))) + body->code_block.children.add(ast_return_statement_ptr(ident)) lambda_creation_funcs[l]->function.body_statement = body name_ast_map->values.first().second->translation_unit.children.add(lambda_creation_funcs[l]) // after we use it's type to look up the new one... diff --git a/test_function_value.krak b/test_function_value.krak index bdc9e4b..e4de9a8 100644 --- a/test_function_value.krak +++ b/test_function_value.krak @@ -1,7 +1,6 @@ fun main(argc: int, argv: **char): int { - var a = fun(): int { return 1; } - a() - return 0 + var a = fun(): int { return 11; } + return a() }