diff --git a/stdlib/ast_nodes.krak b/stdlib/ast_nodes.krak index 995f7d8..1295318 100644 --- a/stdlib/ast_nodes.krak +++ b/stdlib/ast_nodes.krak @@ -848,25 +848,38 @@ fun is_simple_passthrough(node: *ast_node): bool { obj simple_passthrough (Object) { var scope: map> var passthrough_str: string + var in_params: vector> + var out_params: vector> + var linker_str: string fun construct(): *simple_passthrough { scope.construct() passthrough_str.construct() + in_params.construct() + out_params.construct() + linker_str.construct() return this } fun copy_construct(old: *simple_passthrough) { scope.copy_construct(&old->scope) passthrough_str.copy_construct(&old->passthrough_str) + in_params.copy_construct(&old->in_params) + out_params.copy_construct(&old->out_params) + linker_str.copy_construct(&old->linker_str) } fun destruct() { scope.destruct() passthrough_str.destruct() + in_params.destruct() + out_params.destruct() + linker_str.destruct() } fun operator=(other: ref simple_passthrough) { destruct() copy_construct(&other) } fun operator==(other: ref simple_passthrough): bool { - return scope == other.scope && passthrough_str == other.passthrough_str + return scope == other.scope && passthrough_str == other.passthrough_str && in_params == other.in_params && + out_params == other.out_params && linker_str == other.linker_str } } fun ast_function_call_ptr(func: *ast_node, parameters: vector<*ast_node>): *ast_node { diff --git a/stdlib/ast_transformation.krak b/stdlib/ast_transformation.krak index 5f13c4c..81098b2 100644 --- a/stdlib/ast_transformation.krak +++ b/stdlib/ast_transformation.krak @@ -411,8 +411,29 @@ obj ast_transformation (Object) { } fun transform_simple_passthrough(node: *tree, scope: *ast_node): *ast_node { var new_passthrough = ast_simple_passthrough_ptr() - // setup passthrough params and string new_passthrough->simple_passthrough.passthrough_str = concat_symbol_tree(get_node("triple_quoted_string", node)).slice(3,-4) + // setup passthrough params and string + var passthrough_params = get_node("passthrough_params", node) + if (!passthrough_params) + return new_passthrough + var in_passthrough_params = get_node("in_passthrough_params", passthrough_params) + var out_passthrough_params = get_node("out_passthrough_params", passthrough_params) + if (in_passthrough_params) + get_nodes("param_assign", in_passthrough_params).for_each(fun(p: *tree) { + var idents = get_nodes("identifier", p) + if (idents.size == 2) + new_passthrough->simple_passthrough.in_params.add(make_pair(transform_identifier(idents[0], scope, search_type::none()), concat_symbol_tree(idents[1]))) + else + new_passthrough->simple_passthrough.in_params.add(make_pair(transform_identifier(idents[0], scope, search_type::none()), concat_symbol_tree(idents[0]))) + }) + if (out_passthrough_params) + get_nodes("param_assign", out_passthrough_params).for_each(fun(p: *tree) { + var idents = get_nodes("identifier", p) + if (idents.size == 2) + new_passthrough->simple_passthrough.out_params.add(make_pair(transform_identifier(idents[0], scope, search_type::none()), concat_symbol_tree(idents[1]))) + else + new_passthrough->simple_passthrough.out_params.add(make_pair(transform_identifier(idents[0], scope, search_type::none()), concat_symbol_tree(idents[0]))) + }) return new_passthrough } fun transform_statement(node: *tree, scope: *ast_node, template_replacements: map): *ast_node return ast_statement_ptr(transform(node->children[0], scope, template_replacements)); diff --git a/stdlib/c_generator.krak b/stdlib/c_generator.krak index 43a15ab..4c257d3 100644 --- a/stdlib/c_generator.krak +++ b/stdlib/c_generator.krak @@ -75,18 +75,22 @@ obj code_triple (Object) { obj c_generator (Object) { var id_counter: int + var ast_name_map: map<*ast_node, string> fun construct(): *c_generator { id_counter = 0 + ast_name_map.construct() return this } fun copy_construct(old: *c_generator) { id_counter = old->id_counter + ast_name_map.copy_construct(&old->ast_name_map) } fun operator=(other: ref c_generator) { destruct() copy_construct(&other) } fun destruct() { + ast_name_map.destruct() } fun get_id(): string return to_string(id_counter++); fun generate_c(name_ast_map: map,*ast_node>>): pair { @@ -121,7 +125,7 @@ obj c_generator (Object) { backing.parameters.for_each(fun(parameter: *ast_node) { if (parameter_types != "") { parameter_types += ", "; parameters += ", ";} parameter_types += type_to_c(parameter->identifier.type) - parameters += type_to_c(parameter->identifier.type) + " " + parameter->identifier.name + parameters += type_to_c(parameter->identifier.type) + " " + get_name(parameter) // add parameters to destructor thingy (for returns)? Or should that be a different pass? var parameter_type = parameter->identifier.type @@ -194,21 +198,37 @@ obj c_generator (Object) { return make_pair(prequal+plain_typedefs+top_level_c_passthrough+variable_extern_declarations+structs+function_typedef_string_pre+function_typedef_string+function_prototypes+variable_declarations+function_definitions + "\n", linker_string) } - fun generate_if_comp(node: *ast_node): code_triple { + fun generate_if_comp(node: *ast_node, enclosing_object: *ast_node, defer_stack: *stack>>): code_triple { if (node->if_comp.wanted_generator == "__C__") - return generate(node->if_comp.statement, null(), null>>>()) + return generate(node->if_comp.statement, enclosing_object, defer_stack) return code_triple() } fun generate_simple_passthrough(node: *ast_node): string { // deal with all the passthrough params - return node->simple_passthrough.passthrough_str + var result = string() + var pre = string() + 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() + if (wanted_name != current_name) + result += type_to_c(i.first->identifier.type) + " " + wanted_name + " = " + current_name + ";\n" + }) + result += node->simple_passthrough.passthrough_str + node->simple_passthrough.out_params.for_each(fun(i: pair<*ast_node, string>) { + 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" + }) + 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 { // add destruct to defer_stack var identifier = node->declaration_statement.identifier var ident_type = identifier->identifier.type - var to_ret = code_triple() + type_to_c(identifier->identifier.type) + " " + identifier->identifier.name + var to_ret = code_triple() + type_to_c(identifier->identifier.type) + " " + get_name(identifier) 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"; @@ -254,8 +274,8 @@ obj c_generator (Object) { } fun generate_identifier(node: *ast_node, enclosing_object: *ast_node): code_triple { 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->") + node->identifier.name + ")" - return code_triple(node->identifier.name) + 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 { var return_value = node->return_statement.return_value @@ -360,7 +380,6 @@ obj c_generator (Object) { func_name = generate(node->function_call.func, enclosing_object, null>>>()).one_string() } // handle method call from inside method of same object - /*if (!dot_style_method_call && enclosing_object && get_ast_scope(enclosing_object)->contains_key(func_name))*/ if (!dot_style_method_call && enclosing_object && enclosing_object->type_def.methods.contains(node->function_call.func)) call_string += "this" @@ -421,7 +440,7 @@ obj c_generator (Object) { fun generate(node: *ast_node, enclosing_object: *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) + ast_node::if_comp(backing) return generate_if_comp(node, enclosing_object, defer_stack) ast_node::simple_passthrough(backing) return code_triple() + generate_simple_passthrough(node) 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) @@ -490,26 +509,35 @@ obj c_generator (Object) { return string("impossible type") + indirection } fun get_name(node: *ast_node): string { + if (ast_name_map.contains_key(node)) + return ast_name_map[node] + var result = string("impossible name") match (*node) { ast_node::type_def(backing) { var upper = backing.scope[string("~enclosing_scope")][0] - var result = backing.name + result = backing.name if (is_template(upper)) upper->template.instantiated_map.reverse_get(node).for_each(fun(t: ref type) result += string("_") + type_decoration(&t);) - return result } ast_node::function(backing) { // be careful, operators like . come through this + if (!backing.body_statement) + return backing.name + result = "" var upper = backing.scope.get_with_default(string("~enclosing_scope"), vector(null()))[0] - var str = string() if (upper && is_type_def(upper)) - str += get_name(upper) - str += node->function.name - node->function.parameters.for_each(fun(param: *ast_node) str += string("_") + type_decoration(param->identifier.type);) - return str + result += get_name(upper) + "_" + result += node->function.name + node->function.parameters.for_each(fun(param: *ast_node) result += string("_") + type_decoration(param->identifier.type);) } + ast_node::identifier(backing) result = backing.name } - return string("impossible name") + if (result == "impossible name") + println("HUGE PROBLEMS") + if (ast_name_map.contains_value(result)) + result += get_id() + ast_name_map.set(node, result) + return result } } diff --git a/stdlib/map.krak b/stdlib/map.krak index 798b76d..597016e 100644 --- a/stdlib/map.krak +++ b/stdlib/map.krak @@ -65,6 +65,9 @@ obj map (Object, Serializable) { fun contains_key(key: T): bool { return keys.contains(key) } + fun contains_value(value: U): bool { + return values.contains(value) + } fun get(key: T): ref U { /*return values.get(keys.find(key))*/ var key_loc = keys.find(key)