diff --git a/stdlib/c_generator.krak b/stdlib/c_generator.krak index 4f20c73..1eb6ea7 100644 --- a/stdlib/c_generator.krak +++ b/stdlib/c_generator.krak @@ -77,12 +77,14 @@ obj c_generator (Object) { var id_counter: int var ast_name_map: map<*ast_node, string> var closure_struct_map: map, string> + var function_type_map: map var function_typedef_string: string var closure_struct_definitions: string fun construct(): *c_generator { id_counter = 0 ast_name_map.construct() closure_struct_map.construct() + function_type_map.construct() function_typedef_string.construct() closure_struct_definitions.construct() return this @@ -90,6 +92,10 @@ obj c_generator (Object) { fun copy_construct(old: *c_generator) { id_counter = old->id_counter ast_name_map.copy_construct(&old->ast_name_map) + closure_struct_map.copy_construct(&old->closure_struct_map) + function_type_map.copy_construct(&old->function_type_map) + function_typedef_string.copy_construct(&old->function_typedef_string) + closure_struct_definitions.copy_construct(&old->closure_struct_definitions) } fun operator=(other: ref c_generator) { destruct() @@ -97,6 +103,10 @@ obj c_generator (Object) { } fun destruct() { ast_name_map.destruct() + closure_struct_map.destruct() + function_type_map.destruct() + function_typedef_string.destruct() + closure_struct_definitions.destruct() } fun get_id(): string return to_string(id_counter++); fun generate_c(name_ast_map: map,*ast_node>>): pair { @@ -134,7 +144,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).one_string() + var decorated_name = generate_function(child, 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) @@ -146,9 +156,9 @@ obj c_generator (Object) { defer_stack.top().second.push(ast_statement_ptr(make_method_call(parameter, "destruct", vector<*ast_node>()))) }) function_prototypes += type_to_c(backing.type->return_type) + " " + decorated_name + "(" + parameter_types + ");\n" - function_definitions += type_to_c(backing.type->return_type) + " " + decorated_name + "(" + parameters + ") {\n" + generate_statement(backing.body_statement, enclosing_object, &defer_stack).one_string() + function_definitions += type_to_c(backing.type->return_type) + " " + decorated_name + "(" + parameters + ") {\n" + generate_statement(backing.body_statement, enclosing_object, child, &defer_stack).one_string() // emit parameter destructors? - function_definitions += generate_from_defer_stack(&defer_stack, -1, enclosing_object).one_string() + function_definitions += generate_from_defer_stack(&defer_stack, -1, enclosing_object, child).one_string() function_definitions += "}\n" } @@ -165,7 +175,7 @@ obj c_generator (Object) { top_level_c_passthrough += generate_simple_passthrough(backing.statement->statement.child, true) } ast_node::simple_passthrough(backing) top_level_c_passthrough += generate_simple_passthrough(child, true) - ast_node::declaration_statement(backing) variable_declarations += generate_declaration_statement(child, null(), null>>>(), true).one_string() + ";\n" + ast_node::declaration_statement(backing) variable_declarations += generate_declaration_statement(child, null(), null(), null>>>(), true).one_string() + ";\n" ast_node::function(backing) { // check for and add to parameters if a closure generate_function_definition(child, null()) @@ -201,7 +211,7 @@ obj c_generator (Object) { var base_name = get_name(vert) plain_typedefs += string("typedef struct ") + base_name + "_dummy " + base_name + ";\n" structs += string("struct ") + base_name + "_dummy {\n" - vert->type_def.variables.for_each(fun(variable_declaration: *ast_node) structs += generate_declaration_statement(variable_declaration, null(), null>>>(), true).one_string() + ";\n";) + vert->type_def.variables.for_each(fun(variable_declaration: *ast_node) structs += generate_declaration_statement(variable_declaration, null(), null(), null>>>(), true).one_string() + ";\n";) structs += "};\n" // generate the methods (note some of these may be templates) vert->type_def.methods.for_each(fun(method: *ast_node) { @@ -216,14 +226,17 @@ obj c_generator (Object) { } fun get_closure_struct_type(closed_variables: set<*ast_node>): string { if (!closure_struct_map.contains_key(closed_variables)) { - closure_struct_definitions += "typedef struct {} random_closure_type;\n" - closure_struct_map[closed_variables] = string("random_closure_type") + var closure_name = string("closure_data_type") + get_id() + closure_struct_definitions += "typedef struct {\n" + closed_variables.for_each(fun(i: *ast_node) closure_struct_definitions += type_to_c(i->identifier.type->clone_with_increased_indirection()) + " " + i->identifier.name + ";\n";) + closure_struct_definitions += string("} ") + closure_name + ";\n" + closure_struct_map[closed_variables] = closure_name } return closure_struct_map[closed_variables] } - fun generate_if_comp(node: *ast_node, enclosing_object: *ast_node, defer_stack: *stack>>): code_triple { + fun generate_if_comp(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, defer_stack: *stack>>): code_triple { if (node->if_comp.wanted_generator == "__C__") - return generate(node->if_comp.statement, enclosing_object, defer_stack) + return generate(node->if_comp.statement, enclosing_object, enclosing_func, defer_stack) return code_triple() } fun generate_simple_passthrough(node: *ast_node, is_top_level: bool): string { @@ -233,7 +246,7 @@ obj c_generator (Object) { var post = string() node->simple_passthrough.in_params.for_each(fun(i: pair<*ast_node, string>) { var wanted_name = i.second - var current_name = generate_identifier(i.first, null()).one_string() + var current_name = generate_identifier(i.first, null(), null()).one_string() if (wanted_name != current_name) result += type_to_c(i.first->identifier.type) + " " + wanted_name + " = " + current_name + ";\n" }) @@ -242,14 +255,14 @@ obj c_generator (Object) { var temp_name = string("out_temp") + get_id() pre += type_to_c(i.first->identifier.type) + " " + temp_name + ";\n" result += temp_name + " = " + i.second + ";\n" - post += generate_identifier(i.first, null()).one_string() + " = " + temp_name + ";\n" + post += generate_identifier(i.first, null(), null()).one_string() + " = " + temp_name + ";\n" }) if (is_top_level) return pre + result + post return pre + "{" + result + "}" + post } - fun generate_statement(node: *ast_node, enclosing_object: *ast_node, defer_stack: *stack>>): code_triple return generate(node->statement.child, enclosing_object, defer_stack) + ";\n"; - fun generate_declaration_statement(node: *ast_node, enclosing_object: *ast_node, defer_stack: *stack>>, add_to_defer: bool): code_triple { + fun generate_statement(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, defer_stack: *stack>>): code_triple return generate(node->statement.child, enclosing_object, enclosing_func, defer_stack) + ";\n"; + fun generate_declaration_statement(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, defer_stack: *stack>>, add_to_defer: bool): code_triple { // add destruct to defer_stack var identifier = node->declaration_statement.identifier var ident_type = identifier->identifier.type @@ -257,52 +270,54 @@ obj c_generator (Object) { 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 += generate(ast_statement_ptr(make_method_call(identifier, "copy_construct", vector(make_operator_call("&", vector(node->declaration_statement.expression))))), enclosing_object, defer_stack) + 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, null>>>()) + to_ret += code_triple(" = ") + generate(node->declaration_statement.expression, enclosing_object, enclosing_func, null>>>()) } } - if (node->declaration_statement.init_method_call) to_ret += code_triple(";\n") + generate(node->declaration_statement.init_method_call, enclosing_object, null>>>()) + 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 (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 } - fun generate_assignment_statement(node: *ast_node, enclosing_object: *ast_node): code_triple { - return generate(node->assignment_statement.to, enclosing_object, null>>>()) + " = " + generate(node->assignment_statement.from, enclosing_object, null>>>()) + fun generate_assignment_statement(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node): code_triple { + 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, defer_stack: *stack>>): code_triple { - var if_str = code_triple("if (") + generate(node->if_statement.condition, enclosing_object, null>>>()) + ") {\n" + generate(node->if_statement.then_part, enclosing_object, defer_stack) + "}" + 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) + "}" if (node->if_statement.else_part) - if_str += code_triple(" else {\n") + generate(node->if_statement.else_part, enclosing_object, defer_stack) + "}" + if_str += code_triple(" else {\n") + generate(node->if_statement.else_part, enclosing_object, enclosing_func, defer_stack) + "}" return if_str + "\n" } - fun generate_while_loop(node: *ast_node, enclosing_object: *ast_node, defer_stack: *stack>>): code_triple { + fun generate_while_loop(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, defer_stack: *stack>>): code_triple { // stick another stack on defer_stack->push(make_pair(true, stack<*ast_node>())) - var to_ret = code_triple("while (") + generate(node->while_loop.condition, enclosing_object, null>>>()).one_string() + ") {\n" + generate(node->while_loop.statement, enclosing_object, defer_stack).one_string() - to_ret += generate_from_defer_stack(defer_stack, 1, enclosing_object) + var to_ret = code_triple("while (") + generate(node->while_loop.condition, enclosing_object, enclosing_func, null>>>()).one_string() + ") {\n" + generate(node->while_loop.statement, enclosing_object, enclosing_func, defer_stack).one_string() + to_ret += generate_from_defer_stack(defer_stack, 1, enclosing_object, enclosing_func) defer_stack->pop() to_ret += "}\n" return to_ret } - fun generate_for_loop(node: *ast_node, enclosing_object: *ast_node, defer_stack: *stack>>): code_triple { + fun generate_for_loop(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, defer_stack: *stack>>): code_triple { // stick another stack on defer_stack->push(make_pair(true, stack<*ast_node>())) // gotta take off last semicolon - var to_ret = code_triple("for (") + generate(node->for_loop.init, enclosing_object, null>>>()).one_string() + " " + generate(node->for_loop.condition, enclosing_object, null>>>()).one_string() + "; " + - generate(node->for_loop.update, enclosing_object, null>>>()).one_string().slice(0,-3) + - ") {\n" + generate(node->for_loop.body, enclosing_object, defer_stack).one_string() - to_ret += generate_from_defer_stack(defer_stack, 1, enclosing_object).one_string() + var to_ret = code_triple("for (") + generate(node->for_loop.init, enclosing_object, enclosing_func, null>>>()).one_string() + " " + generate(node->for_loop.condition, enclosing_object, enclosing_func, null>>>()).one_string() + "; " + + generate(node->for_loop.update, enclosing_object, enclosing_func, null>>>()).one_string().slice(0,-3) + + ") {\n" + generate(node->for_loop.body, enclosing_object, enclosing_func, defer_stack).one_string() + to_ret += generate_from_defer_stack(defer_stack, 1, enclosing_object, enclosing_func).one_string() defer_stack->pop() to_ret += "}\n" return to_ret } - fun generate_identifier(node: *ast_node, enclosing_object: *ast_node): code_triple { + 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) + ")") 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)) } - fun generate_return_statement(node: *ast_node, enclosing_object: *ast_node, defer_stack: *stack>>): code_triple { + fun generate_return_statement(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, defer_stack: *stack>>): code_triple { var return_value = node->return_statement.return_value if (!return_value) return code_triple("return") @@ -313,25 +328,25 @@ obj c_generator (Object) { var temp_ident = ast_identifier_ptr(string("temporary_return")+get_id(), return_value_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 - to_ret.pre = generate_declaration_statement(declaration, enclosing_object, defer_stack, false).one_string() + ";\n" - to_ret.pre += generate_statement(ast_statement_ptr(make_method_call(temp_ident, "copy_construct", vector(make_operator_call("&", vector(return_value))))), enclosing_object, defer_stack).one_string() + to_ret.pre = generate_declaration_statement(declaration, enclosing_object, enclosing_func, defer_stack, false).one_string() + ";\n" + to_ret.pre += generate_statement(ast_statement_ptr(make_method_call(temp_ident, "copy_construct", vector(make_operator_call("&", vector(return_value))))), enclosing_object, enclosing_func, defer_stack).one_string() // make this new identifier the new return value return_value = temp_ident } // generate all in stack by passing -1 - to_ret += generate_from_defer_stack(defer_stack, -1, enclosing_object) - to_ret += code_triple("return ") + generate(return_value, enclosing_object, null>>>()) + to_ret += generate_from_defer_stack(defer_stack, -1, enclosing_object, enclosing_func) + to_ret += code_triple("return ") + generate(return_value, enclosing_object, enclosing_func, null>>>()) return to_ret } - fun generate_branching_statement(node: *ast_node, enclosing_object: *ast_node, defer_stack: *stack>>): code_triple { + fun generate_branching_statement(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, defer_stack: *stack>>): code_triple { // -2 means generate up through loop - var to_ret = generate_from_defer_stack(defer_stack, -2, enclosing_object) + var to_ret = generate_from_defer_stack(defer_stack, -2, enclosing_object, enclosing_func) match(node->branching_statement.b_type) { branching_type::break_stmt() return to_ret + string("break") branching_type::continue_stmt() return to_ret + string("continue") } } - fun generate_from_defer_stack(defer_stack: *stack>>, num: int, enclosing_object: *ast_node): code_triple { + fun generate_from_defer_stack(defer_stack: *stack>>, num: int, enclosing_object: *ast_node, enclosing_func: *ast_node): code_triple { var to_ret = code_triple() if (num == -1) num = defer_stack->size() @@ -344,10 +359,10 @@ obj c_generator (Object) { num++ } for (var i = 0; i < num; i++;) - defer_stack->from_top(i).second.for_each(fun(node: *ast_node) to_ret += generate(node, enclosing_object, null>>>());) + defer_stack->from_top(i).second.for_each(fun(node: *ast_node) to_ret += generate(node, enclosing_object, enclosing_func, null>>>());) return to_ret } - fun generate_defer_statement(node: *ast_node, enclosing_object: *ast_node, defer_stack: *stack>>): code_triple { + fun generate_defer_statement(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, defer_stack: *stack>>): code_triple { defer_stack->top().second.push(node->defer_statement.statement) return code_triple("/*defer wanna know what*/") } @@ -370,20 +385,32 @@ obj c_generator (Object) { }) return code_triple(to_ret + "\"") } - fun generate_code_block(node: *ast_node, enclosing_object: *ast_node, defer_stack: *stack>>): code_triple { + fun generate_code_block(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, defer_stack: *stack>>): code_triple { var to_ret = code_triple("{\n") // stick another stack on defer_stack->push(make_pair(false, stack<*ast_node>())) - node->code_block.children.for_each(fun(child: *ast_node) to_ret += generate(child, enclosing_object, defer_stack).one_string();) - to_ret += generate_from_defer_stack(defer_stack, 1, enclosing_object) + node->code_block.children.for_each(fun(child: *ast_node) to_ret += generate(child, enclosing_object, enclosing_func, defer_stack).one_string();) + to_ret += generate_from_defer_stack(defer_stack, 1, enclosing_object, enclosing_func) defer_stack->pop() return to_ret + "}" } // this generates the function as a value, not the actual function - fun generate_function(node: *ast_node): code_triple { + fun generate_function(node: *ast_node, as_value: bool): code_triple { + 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) + "})") + 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) + 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) + ",";) + to_ret.pre += "};\n" + return to_ret + string("((") + type_to_c(node->function.type) + "){(void*)&" + temp_closure_struct + ",(void*)" + get_name(node) + "})" + } return code_triple(get_name(node)) } - fun generate_function_call(node: *ast_node, enclosing_object: *ast_node): code_triple { + fun generate_function_call(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node): code_triple { var func_name = string() var call_string = code_triple() var func_return_type = get_ast_type(node) @@ -396,15 +423,22 @@ obj c_generator (Object) { (is_type_def(get_ast_scope(node->function_call.func->function_call.parameters[1])->get(string("~enclosing_scope"))[0]) || // or if it's a templated method (yes, this has gotten uuuuugly) is_type_def(get_ast_scope(get_ast_scope(node->function_call.func->function_call.parameters[1])->get(string("~enclosing_scope"))[0])->get(string("~enclosing_scope"))[0])) + // should get uglier when we have to figure out if it's just an inside lambda if (dot_style_method_call) { - func_name = generate(node->function_call.func->function_call.parameters[1], enclosing_object, null>>>()).one_string() + func_name = generate_function(node->function_call.func->function_call.parameters[1], false).one_string() // don't add & if it was -> if (node->function_call.func->function_call.func->function.name == ".") call_string += "&" - call_string += generate(node->function_call.func->function_call.parameters[0], enclosing_object, null>>>()) - } else { // regular style function name - func_name = generate(node->function_call.func, enclosing_object, null>>>()).one_string() + call_string += generate_function(node->function_call.func->function_call.parameters[0], false) + } 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 + call_string += func_name + ".data" + func_name = func_name + ".func" + } } // 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)) @@ -415,19 +449,19 @@ obj c_generator (Object) { || func_name == "&&" || func_name == "<" || func_name == ">" || func_name == "<=" || func_name == ">=" || func_name == "==" || func_name == "!=" || func_name == "%" )) - return code_triple("(") + generate(parameters[0], enclosing_object, null>>>()) + func_name + generate(parameters[1], enclosing_object, null>>>()) + string(")") + return code_triple("(") + generate(parameters[0], enclosing_object, enclosing_func, null>>>()) + func_name + generate(parameters[1], enclosing_object, enclosing_func, null>>>()) + string(")") // don't propegate enclosing function down right of access if (func_name == "." || func_name == "->") - return code_triple("(") + generate(parameters[0], enclosing_object, null>>>()) + func_name + generate(parameters[1], null(), null>>>()) + string(")") + return code_triple("(") + generate(parameters[0], enclosing_object, enclosing_func, null>>>()) + func_name + generate(parameters[1], null(), null(), null>>>()) + string(")") if (func_name == "[") - return code_triple("(") + generate(parameters[0], enclosing_object, null>>>()) + "[" + generate(parameters[1], null(), null>>>()) + string("])") + return code_triple("(") + generate(parameters[0], enclosing_object, enclosing_func, null>>>()) + "[" + generate(parameters[1], null(), null(), null>>>()) + string("])") // the post ones need to be post-ed specifically, and take the p off if (func_name == "++p" || func_name == "--p") - return code_triple("(") + generate(parameters[0], enclosing_object, null>>>()) + ")" + func_name.slice(0,-2) + return code_triple("(") + generate(parameters[0], enclosing_object, enclosing_func, null>>>()) + ")" + func_name.slice(0,-2) // So we don't end up copy_constructing etc, we just handle the unary operators right here if (func_name == "*" || func_name == "&") - return code_triple("(") + func_name + generate(parameters[0], enclosing_object, null>>>()) + ")" + return code_triple("(") + func_name + generate(parameters[0], enclosing_object, enclosing_func, null>>>()) + ")" // regular parameter generation parameters.for_each(fun(param: *ast_node) { @@ -439,14 +473,14 @@ obj c_generator (Object) { var temp_ident = ast_identifier_ptr(string("temporary_param")+get_id(), param_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, null>>>(), false).one_string() + ";\n" - call_string.pre += generate_statement(ast_statement_ptr(make_method_call(temp_ident, "copy_construct", vector(make_operator_call("&", vector(param))))), enclosing_object, null>>>()).one_string() - call_string += generate(temp_ident, enclosing_object, null>>>()) + call_string.pre += generate_declaration_statement(declaration, enclosing_object, enclosing_func, null>>>(), false).one_string() + ";\n" + call_string.pre += generate_statement(ast_statement_ptr(make_method_call(temp_ident, "copy_construct", vector(make_operator_call("&", vector(param))))), enclosing_object, enclosing_func, null>>>()).one_string() + call_string += generate(temp_ident, enclosing_object, enclosing_func, null>>>()) if (has_method(param_type->type_def, "destruct", vector<*type>())) { - call_string.post += generate_statement(ast_statement_ptr(make_method_call(temp_ident, "destruct", vector<*ast_node>())), enclosing_object, null>>>()).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() } } else { - call_string += generate(param, enclosing_object, null>>>()) + call_string += generate(param, enclosing_object, enclosing_func, null>>>()) } }) if (func_return_type->is_object() && func_return_type->indirection == 0 && has_method(func_return_type->type_def, "destruct", vector<*type>())) { @@ -454,35 +488,35 @@ obj c_generator (Object) { 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, null>>>(), false).one_string() + ";\n" - call_string.pre += generate_identifier(temp_ident, enclosing_object).one_string() + " = " + func_name + "(" + call_string.value + ");\n" - call_string.value = generate_identifier(temp_ident, enclosing_object).one_string() - call_string.post += generate_statement(ast_statement_ptr(make_method_call(temp_ident, "destruct", vector<*ast_node>())), enclosing_object, null>>>()).one_string() + 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() + 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 + ")" } // for now, anyway - fun generate(node: *ast_node, enclosing_object: *ast_node, defer_stack: *stack>>): code_triple { + fun generate(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, defer_stack: *stack>>): code_triple { if (!node) return code_triple("/*NULL*/") match (*node) { - ast_node::if_comp(backing) return generate_if_comp(node, enclosing_object, defer_stack) + ast_node::if_comp(backing) return generate_if_comp(node, enclosing_object, enclosing_func, defer_stack) ast_node::simple_passthrough(backing) return code_triple() + generate_simple_passthrough(node, false) - ast_node::statement(backing) return generate_statement(node, enclosing_object, defer_stack) - ast_node::declaration_statement(backing) return generate_declaration_statement(node, enclosing_object, defer_stack, true) - ast_node::assignment_statement(backing) return generate_assignment_statement(node, enclosing_object) - ast_node::if_statement(backing) return generate_if_statement(node, enclosing_object, defer_stack) - ast_node::while_loop(backing) return generate_while_loop(node, enclosing_object, defer_stack) - ast_node::for_loop(backing) return generate_for_loop(node, enclosing_object, defer_stack) - ast_node::function(backing) return generate_function(node) - ast_node::function_call(backing) return generate_function_call(node, enclosing_object) - ast_node::code_block(backing) return generate_code_block(node, enclosing_object, defer_stack) - ast_node::return_statement(backing) return generate_return_statement(node, enclosing_object, defer_stack) - ast_node::branching_statement(backing) return generate_branching_statement(node, enclosing_object, defer_stack) - ast_node::defer_statement(backing) return generate_defer_statement(node, enclosing_object, defer_stack) + ast_node::statement(backing) return generate_statement(node, enclosing_object, enclosing_func, defer_stack) + ast_node::declaration_statement(backing) return generate_declaration_statement(node, enclosing_object, enclosing_func, defer_stack, true) + ast_node::assignment_statement(backing) return generate_assignment_statement(node, enclosing_object, enclosing_func) + 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_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) + ast_node::branching_statement(backing) return generate_branching_statement(node, enclosing_object, enclosing_func, defer_stack) + ast_node::defer_statement(backing) return generate_defer_statement(node, enclosing_object, enclosing_func, defer_stack) ast_node::value(backing) return generate_value(node) - ast_node::identifier(backing) return generate_identifier(node, enclosing_object) + ast_node::identifier(backing) return generate_identifier(node, enclosing_object, enclosing_func) } return code_triple("/* COULD NOT GENERATE */") } @@ -528,17 +562,15 @@ obj c_generator (Object) { return get_name(type->type_def) + indirection } base_type::function() { - var temp_name = string("temp") + get_id() - var temp = temp_name + ")(" - var first = true - type->parameter_types.for_each(fun(parameter_type: *type) { - if (!first) { - temp += ", " - } - first = false - temp += type_to_c(parameter_type) + " " - }) - function_typedef_string += string("typedef ") + type_to_c(type->return_type) + " (*" + temp + ");" + // maybe disregard indirection in the future? + 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*") + 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 + ";" + // again, the indirection + function_type_map[*type] = temp_name+indirection return temp_name + indirection } }