diff --git a/stdlib/ast_transformation.krak b/stdlib/ast_transformation.krak index 3a46d55..9971cd8 100644 --- a/stdlib/ast_transformation.krak +++ b/stdlib/ast_transformation.krak @@ -844,9 +844,25 @@ fun unify_type(template_type: *tree, param_type: *type, new_map: *mapchildren.size == 1) - new_map->set(concat_symbol_tree(template_type), param_type) - else if (get_node("\"\\*\"", template_type)) + if (template_type->children.size == 1) { + if (get_node("function_type", template_type)) { + println("UNIFYING FUNCTION") + var template_function_types = get_nodes("type", get_node("function_type", template_type)) + if (!param_type->is_function() || template_function_types.size -1 != param_type->parameter_types.size) { + println("not combining function because:") + println(param_type->is_function()) + println(template_function_types.size-1) + println(param_type->parameter_types.size) + return; + } + for (var i = 0; i < template_function_types.size; i++;) + unify_type(template_function_types[i], param_type->parameter_types[i], new_map, template_replacements) + unify_type(template_function_types.last(), param_type->return_type, new_map, template_replacements) + } else { + println(string("setting ") + concat_symbol_tree(template_type) + " equal to " + param_type->to_string()) + new_map->set(concat_symbol_tree(template_type), param_type) + } + } else if (get_node("\"\\*\"", template_type)) unify_type(template_type->children[1], param_type->clone_with_decreased_indirection(), new_map, template_replacements) else { println(template_type->children[0]->data.name) diff --git a/stdlib/c_generator.krak b/stdlib/c_generator.krak index 50a95b4..4f1fbc0 100644 --- a/stdlib/c_generator.krak +++ b/stdlib/c_generator.krak @@ -348,9 +348,9 @@ obj c_generator (Object) { return generate(node->assignment_statement.to, enclosing_object, enclosing_func, null>>>()) + " = " + generate(node->assignment_statement.from, enclosing_object, enclosing_func, null>>>()) } fun generate_if_statement(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, defer_stack: *stack>>): code_triple { - var if_str = code_triple("if (") + generate(node->if_statement.condition, enclosing_object, enclosing_func, null>>>()) + ") {\n" + generate(node->if_statement.then_part, enclosing_object, enclosing_func, defer_stack) + "}" + var if_str = code_triple("if (") + generate(node->if_statement.condition, enclosing_object, enclosing_func, null>>>()) + ") {\n" + generate(node->if_statement.then_part, enclosing_object, enclosing_func, defer_stack).one_string() + "}" if (node->if_statement.else_part) - if_str += code_triple(" else {\n") + generate(node->if_statement.else_part, enclosing_object, enclosing_func, defer_stack) + "}" + if_str += code_triple(" else {\n") + generate(node->if_statement.else_part, enclosing_object, enclosing_func, defer_stack).one_string() + "}" return if_str + "\n" } fun generate_while_loop(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, defer_stack: *stack>>): code_triple { @@ -463,7 +463,7 @@ obj c_generator (Object) { if (as_value) { var closed_vars = node->function.closed_variables if (closed_vars.size() == 0) - return code_triple(string("((") + type_to_c(node->function.type) + "){NULL," + get_name(node) + "})") + return code_triple(string("((") + type_to_c(node->function.type) + "){(void*)NULL,(void*)" + get_name(node) + "})") var temp_closure_struct = string("closure_struct_temp") + get_id() var to_ret = code_triple() var closure_type_str = get_closure_struct_type(closed_vars) @@ -475,7 +475,7 @@ obj c_generator (Object) { return code_triple(get_name(node)) } fun generate_function_call(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node): code_triple { - var func_name = string() + var func_name = generate_function(node->function_call.func, false).one_string() var call_string = code_triple() var func_return_type = get_ast_type(node) @@ -495,17 +495,6 @@ obj c_generator (Object) { if (node->function_call.func->function_call.func->function.name == ".") call_string += "&" 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() - 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 if (!dot_style_method_call && enclosing_object && enclosing_object->type_def.methods.contains(node->function_call.func)) @@ -550,18 +539,53 @@ obj c_generator (Object) { call_string += generate(param, enclosing_object, enclosing_func, null>>>()) } }) + var pre_call = string() if (func_return_type->is_object() && func_return_type->indirection == 0 && has_method(func_return_type->type_def, "destruct", vector<*type>())) { // kind of ugly combo here of 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, null>>>(), false).one_string() + ";\n" - call_string.pre += generate_identifier(temp_ident, enclosing_object, enclosing_func).one_string() + " = " + func_name + "(" + call_string.value + ");\n" - call_string.value = generate_identifier(temp_ident, enclosing_object, enclosing_func).one_string() + pre_call = generate_identifier(temp_ident, enclosing_object, enclosing_func).one_string() call_string.post += generate_statement(ast_statement_ptr(make_method_call(temp_ident, "destruct", vector<*ast_node>())), enclosing_object, enclosing_func, null>>>()).one_string() - return call_string } - return code_triple() + func_name + "(" + call_string + ")" + if (!is_function(node->function_call.func)) { + // not function, so we must be an identifier or function call return or something + 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, null>>>(), false).one_string() + ";\n" + pre_call = generate_identifier(temp_ident, enclosing_object, enclosing_func).one_string() + } + func_name = generate(node->function_call.func, enclosing_object, enclosing_func, null>>>()).one_string() + // should not have return var because is void + if (pre_call == "") { + var func_type = get_ast_type(node->function_call.func) + call_string.pre += string("if (")+func_name+".data) ((" + 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 ((") + type_to_c(func_type) + "_without_data) " + func_name+".func)(" + call_string.value + ");\n" + call_string.value = "" + } else { + var func_type = get_ast_type(node->function_call.func) + call_string.pre += string("if (")+func_name+".data) " + pre_call + " = ((" + type_to_c(func_type) + "_with_data) "+func_name+".func)("+func_name +".data," + call_string.value + ");\n" + call_string.pre += string("else ") + pre_call + " = ((" + type_to_c(func_type) + "_without_data) " + func_name+".func)(" + call_string.value + ");\n" + call_string.value = pre_call + } + return call_string + } + } + if (pre_call != "") { + call_string.pre = pre_call + " = " + func_name + "(" + call_string.value + ")" + call_string.value = pre_call + } else { + call_string.value = func_name + "(" + call_string.value + ")" + } + return call_string } // for now, anyway @@ -633,9 +657,13 @@ obj c_generator (Object) { if (function_type_map.contains_key(*type)) return function_type_map[*type] var temp_name = string("function_struct") + get_id() - var temp = string("func)(void*") + var temp = string() type->parameter_types.for_each(fun(parameter_type: *type) temp += string(", ") + type_to_c(parameter_type) + " ";) - function_typedef_string += string("typedef struct {\nvoid* data;\n") + type_to_c(type->return_type) + " (*" + temp + ");\n} " + temp_name + ";" + var with_data = string("typedef ") + type_to_c(type->return_type) + " (*" + temp_name + "_with_data)(void*" + temp + ");\n" + var without_data = string("typedef ") + type_to_c(type->return_type) + " (*" + temp_name + "_without_data)(" + temp.slice(1,-1) + ");\n" + function_typedef_string += with_data + function_typedef_string += without_data + function_typedef_string += string("typedef struct {\nvoid* data;\n") + temp_name + "_with_data func;\n} " + temp_name + ";\n" // again, the indirection function_type_map[*type] = temp_name+indirection return temp_name + indirection diff --git a/stdlib/type.krak b/stdlib/type.krak index 57f164e..76cbb67 100644 --- a/stdlib/type.krak +++ b/stdlib/type.krak @@ -172,5 +172,11 @@ obj type (Object) { } return false } + fun is_void(): bool { + match (base) { + base_type::void_return() return true + } + return false + } }