From b073d5806b3dd36766c5efea326b7e0e2bec68cc Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Sat, 20 Feb 2016 02:36:35 -0500 Subject: [PATCH] Templated methods work now, even explicit instantiation (along with implicit) --- stdlib/ast_transformation.krak | 39 +++++- stdlib/c_generator.krak | 47 ++++--- stdlib/mem.krak | 29 ---- stdlib/regex.krak | 2 +- stdlib/util.krak | 27 ++++ tests/test_comparison_overload.krak | 2 +- tests/test_simpleObjectTemplateTest.krak | 14 +- tests/to_parse.krak | 164 +++-------------------- 8 files changed, 112 insertions(+), 212 deletions(-) diff --git a/stdlib/ast_transformation.krak b/stdlib/ast_transformation.krak index 81098b2..2b5ad0a 100644 --- a/stdlib/ast_transformation.krak +++ b/stdlib/ast_transformation.krak @@ -204,6 +204,9 @@ obj ast_transformation (Object) { while (!fourth_pass_worklist.empty()) { var partially_inst_type_def = fourth_pass_worklist.pop() partially_inst_type_def->type_def.methods.for_each(fun(method: *ast_node) { + // if this is a templated method, we've either instantiatedit if we need it or not if we didn't, so we don't do anything with it here + if (is_template(method)) + return var template = partially_inst_type_def->type_def.scope[string("~enclosing_scope")][0] var template_types = template->template.template_types var real_types = template->template.instantiated_map.reverse_get(partially_inst_type_def) @@ -263,6 +266,7 @@ obj ast_transformation (Object) { // add to instantiated_map so we only instantiate with a paticular set of types once // put in map first for recursive purposes results[i]->template.instantiated_map.set(real_types_deref, inst_type) + results[i]->template.instantiated.add(inst_type) second_pass_type_def(results[i]->template.syntax_node, inst_type, results[i], template_type_replacements) fourth_pass_worklist.push(inst_type) } @@ -528,14 +532,12 @@ obj ast_transformation (Object) { } fun transform_expression(node: *tree, scope: *ast_node, template_replacements: map): *ast_node return transform_expression(node, scope, search_type::none(), template_replacements) fun transform_expression(node: *tree, scope: *ast_node, searching_for: search_type, template_replacements: map): *ast_node { - // figure out what the expression is, handle overloads, or you know - // ignore everything and do a passthrough var func_name = string() var parameters = vector<*ast_node>() if (node->children.size == 1) { var possible_func = transform(node->children[0], scope, searching_for, template_replacements) if (!possible_func) match (searching_for) { - search_type::function(type_vec) possible_func = find_or_instantiate_template_function(node->children[0], null>(), scope, type_vec, template_replacements); + search_type::function(type_vec) possible_func = find_or_instantiate_template_function(node->children[0], null>(), scope, type_vec, template_replacements, map()); } if (!possible_func) println(concat_symbol_tree(node) + ": HAS NO POSSIBLE FUNCTION OR FUNCTION TEMPLATE SOLUTIONS") @@ -550,7 +552,7 @@ obj ast_transformation (Object) { println("TE() } - search_type::function(type_vec) return find_or_instantiate_template_function(identifier, template_inst, scope, type_vec, template_replacements) + search_type::function(type_vec) return find_or_instantiate_template_function(identifier, template_inst, scope, type_vec, template_replacements, map()) } println("NEVER EVER HAPPEN") } @@ -569,6 +571,23 @@ obj ast_transformation (Object) { var second_param = null() if (func_name == "." || func_name == "->") { second_param = transform(node->children[2], get_ast_type(first_param)->type_def, searching_for, template_replacements) + // template member functions + // XXX add in template inst if it exists + if (!second_param) match (searching_for) { + search_type::function(type_vec) { + var template_inst = get_node("template_inst", node) + var inherited_replacements = map() + var parent = get_ast_scope(get_ast_type(first_param)->type_def)->get(string("~enclosing_scope"))[0] + if (is_template(parent)) { + for (var i = 0; i < parent->template.template_types.size; i++;) + inherited_replacements[parent->template.template_types[i]] = parent->template.instantiated_map.reverse_get(get_ast_type(first_param)->type_def)[i].clone() + } + if (template_inst) + second_param = find_or_instantiate_template_function(node->children[2], template_inst, get_ast_type(first_param)->type_def, type_vec, template_replacements, inherited_replacements); + else + second_param = find_or_instantiate_template_function(node->children[2], null>(), get_ast_type(first_param)->type_def, type_vec, template_replacements, inherited_replacements); + } + } } else { second_param = transform(node->children[2], scope, template_replacements) } @@ -577,7 +596,8 @@ obj ast_transformation (Object) { var parameter_types = parameters.map(fun(param: *ast_node): *type return get_ast_type(param);) return ast_function_call_ptr(get_builtin_function(func_name, parameter_types), parameters) } - fun find_or_instantiate_template_function(identifier: *tree, template_inst: *tree, scope: *ast_node, param_types: vector<*type>, template_replacements: map): *ast_node { + fun find_or_instantiate_template_function(identifier: *tree, template_inst: *tree, scope: *ast_node, param_types: vector<*type>, template_replacements: map, replacements_base: map): *ast_node { + // replacments base is for templated methods starting off with the replacements of their parent (possibly templated) object var name = concat_symbol_tree(identifier) println(string("trying to instantiate a template function: ") + name) var results = scope_lookup(name, scope) @@ -627,7 +647,13 @@ obj ast_transformation (Object) { println("equal to") println(real_types[j]->to_string()) } - + replacements_base.for_each(fun(key: string, value: *type) { + template_type_replacements[key] = value + println("Just Inherited") + println(key) + println("equal to") + println(value->to_string()) + }) println("FOR FIND OR INSTATINTATE") template_type_replacements.for_each(fun(key: string, value: *type) println(string("MAP: ") + key + " : " + value->to_string());) println("MAP DONE") @@ -636,6 +662,7 @@ obj ast_transformation (Object) { // add to instantiated_map so we only instantiate with a paticular set of types once // put in map first for recursive purposes results[i]->template.instantiated_map.set(real_types_deref, inst_func) + results[i]->template.instantiated.add(inst_func) // and fully instantiate it inst_func->function.body_statement = transform_statement(get_node("statement", results[i]->template.syntax_node), inst_func, template_type_replacements) } diff --git a/stdlib/c_generator.krak b/stdlib/c_generator.krak index 3860f4a..bfcc020 100644 --- a/stdlib/c_generator.krak +++ b/stdlib/c_generator.krak @@ -149,29 +149,27 @@ obj c_generator (Object) { // should really check the genrator ast_node::if_comp(backing) { if (is_simple_passthrough(backing.statement->statement.child)) - top_level_c_passthrough += generate_simple_passthrough(backing.statement->statement.child) + 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) + 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::function(backing) { // check for and add to parameters if a closure generate_function_definition(child, null()) } ast_node::template(backing) { - backing.scope.for_each(fun(key: string, value: vector<*ast_node>) { - value.for_each(fun(node: *ast_node) { - match (*node) { - ast_node::function(backing) generate_function_definition(node, null()) - ast_node::type_def(backing) { - type_poset.add_vertex(node) - backing.variables.for_each(fun(i: *ast_node) { - var var_type = get_ast_type(i->declaration_statement.identifier) - if (!var_type->indirection && var_type->type_def) - type_poset.add_relationship(node, var_type->type_def) - }) - } + backing.instantiated.for_each(fun(node: *ast_node) { + match (*node) { + ast_node::function(backing) generate_function_definition(node, null()) + ast_node::type_def(backing) { + type_poset.add_vertex(node) + backing.variables.for_each(fun(i: *ast_node) { + var var_type = get_ast_type(i->declaration_statement.identifier) + if (!var_type->indirection && var_type->type_def) + type_poset.add_relationship(node, var_type->type_def) + }) } - }) + } }) } ast_node::type_def(backing) { @@ -192,8 +190,13 @@ obj c_generator (Object) { 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";) structs += "};\n" - // generate the methods - vert->type_def.methods.for_each(fun(method: *ast_node) generate_function_definition(method, vert);) + // generate the methods (note some of these may be templates) + vert->type_def.methods.for_each(fun(method: *ast_node) { + if (is_template(method)) + method->template.instantiated.for_each(fun(m: *ast_node) generate_function_definition(m, vert);) + else + generate_function_definition(method, vert); + }) }) 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) @@ -203,7 +206,7 @@ obj c_generator (Object) { return generate(node->if_comp.statement, enclosing_object, defer_stack) return code_triple() } - fun generate_simple_passthrough(node: *ast_node): string { + fun generate_simple_passthrough(node: *ast_node, is_top_level: bool): string { // deal with all the passthrough params var result = string() var pre = string() @@ -221,6 +224,8 @@ obj c_generator (Object) { result += temp_name + " = " + i.second + ";\n" post += generate_identifier(i.first, 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"; @@ -368,7 +373,9 @@ obj c_generator (Object) { is_function(node->function_call.func->function_call.func) && (node->function_call.func->function_call.func->function.name == "->" || node->function_call.func->function_call.func->function.name == ".") && is_function(node->function_call.func->function_call.parameters[1]) && - is_type_def(get_ast_scope(node->function_call.func->function_call.parameters[1])->get(string("~enclosing_scope"))[0]) + (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])) if (dot_style_method_call) { func_name = generate(node->function_call.func->function_call.parameters[1], enclosing_object, null>>>()).one_string() @@ -441,7 +448,7 @@ obj c_generator (Object) { if (!node) return code_triple("/*NULL*/") match (*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::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) diff --git a/stdlib/mem.krak b/stdlib/mem.krak index 8deec61..c3ed1c8 100644 --- a/stdlib/mem.krak +++ b/stdlib/mem.krak @@ -1,6 +1,3 @@ -import set -import map - __if_comp__ __C__ simple_passthrough """ #include """ @@ -103,31 +100,6 @@ fun maybe_destruct(it:*T):void { it->destruct() } -// a function that allows the safe deletion of recursive and complicated data structures -fun safe_recursive_delete(first: *T, addingFunc: fun(*T): set::set<*T>) { - var toDelete = set::set<*T>() - var next = set::set(first) - while (toDelete != next) { - toDelete = next - toDelete.for_each( fun(it: *T) next.add(addingFunc(it)); ) - } - toDelete.for_each( fun(it: *T) delete(it); ) -} - -// a function that allows the safe cloning of recursive and complicated data structures -// cloneing func is the func that does the cloning, it takes in a recursive clone function and -// a register clone function -fun safe_recursive_clone(first: *T, cloningFunc: fun(*T, fun(*T):*T, fun(*T):void): void): *T { - var rec_map = map::map<*T,*T>() - // can't do type infrence if you need the type inside the expression... - var rec_it: fun(*T):*T = fun(it: *T): *T { - if (!rec_map.contains_key(it)) - cloningFunc(it, rec_it, fun(cloned: *T) { rec_map[it] = cloned; }) - return rec_map[it] - } - return rec_it(first) -} - obj shared_ptr (Object){ var data: *T; var refCount: int; @@ -191,4 +163,3 @@ obj shared_ptr (Object){ }; //end shared_ptr class - diff --git a/stdlib/regex.krak b/stdlib/regex.krak index afc8f41..d0f1eda 100644 --- a/stdlib/regex.krak +++ b/stdlib/regex.krak @@ -82,7 +82,7 @@ obj regex (Object, Serializable) { regexString.destruct() *referenceCounter -= 1 if (*referenceCounter == 0) { - mem::safe_recursive_delete(begin, fun(it: *regexState): set::set<*regexState> { return it->next_states; } ) + util::safe_recursive_delete(begin, fun(it: *regexState): set::set<*regexState> { return it->next_states; } ) mem::delete(referenceCounter) } } diff --git a/stdlib/util.krak b/stdlib/util.krak index 7e4bfd5..4b9970c 100644 --- a/stdlib/util.krak +++ b/stdlib/util.krak @@ -1,4 +1,6 @@ import mem +import set +import map import vector import serialize @@ -129,3 +131,28 @@ obj range { } } +// a function that allows the safe deletion of recursive and complicated data structures +fun safe_recursive_delete(first: *T, addingFunc: fun(*T): set::set<*T>) { + var toDelete = set::set<*T>() + var next = set::set(first) + while (toDelete != next) { + toDelete = next + toDelete.for_each( fun(it: *T) next.add(addingFunc(it)); ) + } + toDelete.for_each( fun(it: *T) mem::delete(it); ) +} + +// a function that allows the safe cloning of recursive and complicated data structures +// cloneing func is the func that does the cloning, it takes in a recursive clone function and +// a register clone function +fun safe_recursive_clone(first: *T, cloningFunc: fun(*T, fun(*T):*T, fun(*T):void): void): *T { + var rec_map = map::map<*T,*T>() + // can't do type infrence if you need the type inside the expression... + var rec_it: fun(*T):*T = fun(it: *T): *T { + if (!rec_map.contains_key(it)) + cloningFunc(it, rec_it, fun(cloned: *T) { rec_map[it] = cloned; }) + return rec_map[it] + } + return rec_it(first) +} + diff --git a/tests/test_comparison_overload.krak b/tests/test_comparison_overload.krak index 885fc8b..85f5b4a 100644 --- a/tests/test_comparison_overload.krak +++ b/tests/test_comparison_overload.krak @@ -1,4 +1,4 @@ -import io:* +import simple_print:* fun Comparable(): Comparable { var toRet : Comparable diff --git a/tests/test_simpleObjectTemplateTest.krak b/tests/test_simpleObjectTemplateTest.krak index e052ffc..75e926d 100644 --- a/tests/test_simpleObjectTemplateTest.krak +++ b/tests/test_simpleObjectTemplateTest.krak @@ -1,16 +1,16 @@ -import io; +import simple_print; obj TemplateTest { var a: int; var b: T; fun print(): void { - io::print("a: "); - io::print(a); - io::print("\n"); - io::print("b: "); - io::print(b); - io::print("\n"); + simple_print::print("a: "); + simple_print::print(a); + simple_print::print("\n"); + simple_print::print("b: "); + simple_print::print(b); + simple_print::print("\n"); } }; diff --git a/tests/to_parse.krak b/tests/to_parse.krak index 5d649df..1bc3dfb 100644 --- a/tests/to_parse.krak +++ b/tests/to_parse.krak @@ -1,59 +1,5 @@ import simple_print: * -/* -fun something(param: int): Something { - var to_ret.construct_with_param(param): Something - return to_ret -} -obj Something (ObjectTrait) { - var member: int - fun construct(): *Something { - println("Constructing a Something") - member = 1337 - return this - } - fun construct_with_param(param: int): *Something { - println("Constructing a Something with a param") - member = param - return this - } - fun copy_construct(old: *Something) { - println("Copy Constructing a Something") - member = old->member - } - fun destruct() { - print("Destructing a Something: ") - println(member) - } - fun method(a: int):int { - return 5+a+member + other_method() - } - fun other_method(): int return 7; - fun return_this(): *Something { - return this; - } -} -fun return_something_p_1(it: Something): Something { - it.member += 11 - return it -} -*/ -/*fun id(in: *T): *T return in;*/ -/*fun id(in: T): T return in;*/ -/* -fun other_id(in: T): T { - var a: T - a = in - println(id(in)) - println(id(in)) - return in; -} -*/ -/* -fun some_function(): int return 0; -fun some_other_function(in: bool): float { - return 0.0 -} -*/ + obj SimpleContainer { var data: T fun print_data() { @@ -61,101 +7,23 @@ obj SimpleContainer { indirection = data println(indirection) } + fun with_other(other: U) { + var indirection: U + indirection = other + println(data) + println(other) + } + fun return_as(): U { + var indirection: T + indirection = data + return data + } fun construct(dataIn: T) data = dataIn } fun main(): int { - var it: SimpleContainer<*char> - it.data = "Wooo object template" - println(it.data) - it.data = "Wooo object template methods" - it.print_data() - var it2.construct(3): SimpleContainer - it2.print_data() - /*println(other_id("Wooo function template inference"))*/ - /*var a = id(7)*/ - /*println(a)*/ - /*var b = id(8)*/ - /*var b = id<*char>("Double down time")*/ - /*println(b)*/ - /*println(id("Double down time"))*/ - /*println(other_id<*char>("Triple down time"))*/ - - - - /*var test_methods = something(77)*/ - /*var test_methods_param.construct_with_param(10090): Something*/ - /*println("Constructing an object and printint its member, copy-constructing it, and printing that out, then letting both be destructed")*/ - /*println(test_methods.member)*/ - /*println(test_methods_param.member)*/ - /*var second_obj = test_methods*/ - /*second_obj.member += 5*/ - /*println(second_obj.member)*/ - /*[>var some = return_something_p_1(second_obj)<]*/ - /*println(return_something_p_1(second_obj).member)*/ - return 0 - /* - var a_declaration:int - print(1 + 2) - var again = 2 + 4 - 1 * 400 - print(again) - again = 2 + (4 - 1) * 400 - print(again) - var another_declaration: int = 8.0 - print(another_declaration) - var yet_another_declaration = "Hello Marcus\n" - print(yet_another_declaration) - print("Hello World!\n") - print(1337) - if (1 + 2 && false) print("its true!") - else print("its false!") - var counter = 10 - counter-- - --counter - while (counter) print(counter--) - print("\n") - counter = 8 - while (counter) { - print(--counter) - if (counter == 2) - break - } - print("\n") - for (var j = 0; j < 10; j++;) - if (j%2) continue - else print(j) - var an_obj: Something - an_obj.member = 20 - print(an_obj.member) - print("here is thing") - print(123) - print("\n") - print(an_obj.method(1)) - print("\n") - print(string_id("WoooopsEee\n")) - var with_ptr = an_obj.return_this() - print(with_ptr->method(2)) - print("\n") - { - defer print("should_be_third\n") - defer print("should_be_second\n") - print("should be first\n") - } - for (var i = 1; i < 10; i++;) { - defer println("OUTER:happens every time, even when breaking or continueing") - { - defer println("INNER:happens every time, even when breaking or continueing") - if (i % 2 == 0) - continue - if (i == 9) - break - println(i) - } - } - defer println("Here is a return defer outer") - { - defer println("Here is a return defer inner") - return 0 - } - */ + var it: SimpleContainer + it.data = 8 + it.with_other("Wooo object template") + println(it.return_as()) }