diff --git a/stdlib/ast_transformation.krak b/stdlib/ast_transformation.krak index b58c81c..1362db6 100644 --- a/stdlib/ast_transformation.krak +++ b/stdlib/ast_transformation.krak @@ -165,10 +165,12 @@ obj ast_transformation (Object) { ast_to_syntax.set(identifier, adt_option) var function_node = null() - if (type_syntax) - function_node = ast_function_ptr(option_name, type_ptr(vector(get_ast_type(identifier)), node->adt_def.self_type), vector(identifier)) - else + if (type_syntax) { + var identifier_param = ast_identifier_ptr(option_name, ident_type, node) + function_node = ast_function_ptr(option_name, type_ptr(vector(get_ast_type(identifier_param)), node->adt_def.self_type), vector(identifier_param)) + } else { function_node = ast_function_ptr(option_name, type_ptr(vector<*type>(), node->adt_def.self_type), vector<*ast_node>()) + } add_to_scope(option_name, function_node, node) add_to_scope("~enclosing_scope", node, function_node) node->adt_def.option_funcs.add(function_node) diff --git a/stdlib/c_generator.krak b/stdlib/c_generator.krak index 2c1f05f..7ed54c6 100644 --- a/stdlib/c_generator.krak +++ b/stdlib/c_generator.krak @@ -225,14 +225,23 @@ obj c_generator (Object) { // if this is an option constructor if (enclosing_object->adt_def.options.any_true(fun(opt: *ast_node): bool return opt->identifier.name == backing.name;)) { var option_ident = enclosing_object->adt_def.options.find_first_satisfying(fun(opt: *ast_node): bool return opt->identifier.name == backing.name;) + var option_type = option_ident->identifier.type function_definitions += " { \n" - function_definitions += type_to_c(enclosing_object->adt_def.self_type) + " to_ret;\n" - function_definitions += string("to_ret.flag = ") + string("enum_opt_") + get_name(option_ident) + ";\n" - if (option_ident->identifier.type->is_empty_adt_option()) + var to_ret_ident = ast_identifier_ptr("to_ret", enclosing_object->type_def.self_type, enclosing_object) + function_definitions += type_to_c(enclosing_object->adt_def.self_type) + " "+ get_name(to_ret_ident) + ";\n" + function_definitions += get_name(to_ret_ident) + ".flag = " + string("enum_opt_") + get_name(option_ident) + ";\n" + if (option_type->is_empty_adt_option()) function_definitions += "/*no inner data*/\n" - else - function_definitions += string("to_ret.data.") + get_name(option_ident) + " = " + get_name(option_ident) + ";\n" - function_definitions += "return to_ret;\n" + else { + var param = backing.parameters[0] + if (option_type->is_adt() || (option_type->is_object() && has_method(option_type->type_def, "copy_construct", vector(option_type->clone_with_increased_indirection())))) { + function_definitions += generate(ast_statement_ptr(make_method_call(make_operator_call(".", vector(to_ret_ident, option_ident)), "copy_construct", vector(make_operator_call("&", vector(param))))), null(), null(), &defer_stack, false).one_string() + function_definitions += generate_from_defer_stack(&defer_stack, -1, enclosing_object, child).one_string() + } else { + function_definitions += get_name(to_ret_ident) +".data." + get_name(option_ident) + " = " + get_name(param) + ";\n" + } + } + function_definitions += "return " + get_name(to_ret_ident) + ";\n" function_definitions += "}\n" } else { // this is one of the other functions instead @@ -249,9 +258,11 @@ obj c_generator (Object) { function_definitions += "return true;" } else { if (option_type->is_adt() || (option_type->is_object() && has_method(option_type->type_def, "operator==", vector(option_type)))) { - // don't really need the defer_stack + defer_stack.push(make_pair(false, stack<*ast_node>())) var equals_res = generate(ast_statement_ptr(make_method_call(make_operator_call("->", vector(adt_this, option)), "operator==", vector(make_operator_call(".", vector(param, option))))), null(), null(), &defer_stack, false) equals_res.value = string("bool result = ") + equals_res.value + ";\n" + equals_res.post += generate_from_defer_stack(&defer_stack, -1, enclosing_object, child).one_string() + defer_stack.pop() function_definitions += equals_res.one_string() + "return result;\n" } else { var option_name = generate_identifier(option, null(), null()).one_string() @@ -263,8 +274,11 @@ obj c_generator (Object) { }) } else if (backing.name == "operator!=") { function_definitions += "/*operator!=*/" + defer_stack.push(make_pair(false, stack<*ast_node>())) var equals_res = generate(ast_statement_ptr(make_method_call(make_operator_call("*", vector(adt_this)), "operator==", vector(param))), null(), null(), &defer_stack, false) equals_res.value = string("bool result = !") + equals_res.value + ";\n" + equals_res.post += generate_from_defer_stack(&defer_stack, -1, enclosing_object, child).one_string() + defer_stack.pop() function_definitions += equals_res.one_string() + "return result;\n" } else if (backing.name == "copy_construct") { function_definitions += "/*copy_construct*/" @@ -288,8 +302,11 @@ obj c_generator (Object) { }) } else if (backing.name == "operator=") { function_definitions += "/*operator=*/" + defer_stack.push(make_pair(false, stack<*ast_node>())) function_definitions += generate(ast_statement_ptr(make_method_call(make_operator_call("*", vector(adt_this)), "destruct", vector<*ast_node>())), null(), null(), &defer_stack, false).one_string() function_definitions += generate(ast_statement_ptr(make_method_call(make_operator_call("*", vector(adt_this)), "copy_construct", vector(make_operator_call("&", vector(param))))), null(), null(), &defer_stack, false).one_string() + function_definitions += generate_from_defer_stack(&defer_stack, -1, enclosing_object, child).one_string() + defer_stack.pop() } else if (backing.name == "destruct") { function_definitions += "/*destruct*/" enclosing_object->adt_def.options.for_each(fun(option: *ast_node) { diff --git a/stdlib/string.krak b/stdlib/string.krak index eae4a64..7d568b3 100644 --- a/stdlib/string.krak +++ b/stdlib/string.krak @@ -15,6 +15,10 @@ fun to_string(in: int): string { return ret } +fun operator+(first: *char, second: ref string): string { + return string(first) + second +} + fun string(in:*char):string { var out.construct(in):string return out diff --git a/tests/test_adt.expected_results b/tests/test_adt.expected_results index f6fd947..bdcae97 100644 --- a/tests/test_adt.expected_results +++ b/tests/test_adt.expected_results @@ -12,11 +12,11 @@ constructed object 100 : 100 copy constructed object 100 : 200 from 100 : 100 destructed object 100 : 100 copy constructed object 100 : 300 from 100 : 200 +destructed object 100 : 200 copy constructed object 100 : 400 from 100 : 300 destructed object 100 : 300 copy constructed object 100 : 500 from 100 : 400 destructed object 100 : 400 -destructed object 100 : 200 done assignment to old variable matched an_obj correctly 100 : 500 int assignment to old var @@ -29,6 +29,7 @@ constructed object 110 : 110 copy constructed object 110 : 210 from 110 : 110 destructed object 110 : 110 copy constructed object 110 : 310 from 110 : 210 +destructed object 110 : 210 copy constructed object 110 : 410 from 110 : 310 destructed object 110 : 310 gonna make object in function 110 @@ -36,13 +37,12 @@ constructed object 110 : 110 copy constructed object 110 : 210 from 110 : 110 destructed object 110 : 110 copy constructed object 110 : 310 from 110 : 210 +destructed object 110 : 210 copy constructed object 110 : 410 from 110 : 310 destructed object 110 : 310 copy constructed object 110 : 510 from 110 : 410 destructed object 110 : 510 equality an_obj correctly destructed object 110 : 410 -destructed object 110 : 210 destructed object 110 : 410 -destructed object 110 : 210 done test copy_construct for non ref equality