diff --git a/stdlib/c_generator.krak b/stdlib/c_generator.krak index f61e1c5..2c1f05f 100644 --- a/stdlib/c_generator.krak +++ b/stdlib/c_generator.krak @@ -236,17 +236,71 @@ obj c_generator (Object) { function_definitions += "}\n" } else { // this is one of the other functions instead - function_definitions += "{" + var param = backing.parameters[0] + var adt_this = ast_identifier_ptr("this", enclosing_object->type_def.self_type->clone_with_indirection(1), enclosing_object) + function_definitions += "{\n" if (backing.name == "operator==") { function_definitions += "/*operator==*/" + function_definitions += string("if (this->flag != ") + generate_identifier(param, null(), null()).one_string() + ".flag) return false;\n" + enclosing_object->adt_def.options.for_each(fun(option: *ast_node) { + var option_type = option->identifier.type + function_definitions += string("if (this->flag == ") + string("enum_opt_") + generate_identifier(option, null(), null()).one_string() + ") {\n" + if (option_type->is_empty_adt_option()) { + 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 + 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" + function_definitions += equals_res.one_string() + "return result;\n" + } else { + var option_name = generate_identifier(option, null(), null()).one_string() + var param_name = generate_identifier(param, null(), null()).one_string() + function_definitions += string("return this->data.") + option_name + " == " + param_name + ".data." + option_name + ";\n" + } + } + function_definitions += "}\n" + }) } else if (backing.name == "operator!=") { function_definitions += "/*operator!=*/" + 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" + function_definitions += equals_res.one_string() + "return result;\n" } else if (backing.name == "copy_construct") { function_definitions += "/*copy_construct*/" + function_definitions += string("this->flag = ") + generate_identifier(param, null(), null()).one_string() + "->flag;\n" + enclosing_object->adt_def.options.for_each(fun(option: *ast_node) { + var option_type = option->identifier.type + function_definitions += string("if (this->flag == ") + string("enum_opt_") + generate_identifier(option, null(), null()).one_string() + ") {\n" + if (option_type->is_empty_adt_option()) { + function_definitions += "/*no data to copy*/;" + } else { + if (option_type->is_adt() || (option_type->is_object() && has_method(option_type->type_def, "copy_construct", vector(option_type->clone_with_increased_indirection())))) { + // don't really need the defer_stack + function_definitions += generate(ast_statement_ptr(make_method_call(make_operator_call("->", vector(adt_this, option)), "copy_construct", vector(make_operator_call("&", vector(make_operator_call("->", vector(param, option))))))), null(), null(), &defer_stack, false).one_string() + } else { + var option_name = generate_identifier(option, null(), null()).one_string() + var param_name = generate_identifier(param, null(), null()).one_string() + function_definitions += string("this->data.") + option_name + " = " + param_name + "->data." + option_name + ";\n" + } + } + function_definitions += "}\n" + }) } else if (backing.name == "operator=") { function_definitions += "/*operator=*/" + 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() } else if (backing.name == "destruct") { function_definitions += "/*destruct*/" + enclosing_object->adt_def.options.for_each(fun(option: *ast_node) { + var option_type = option->identifier.type + function_definitions += string("if (this->flag == ") + string("enum_opt_") + generate_identifier(option, null(), null()).one_string() + ") {\n" + if (option_type->is_adt() || (option_type->is_object() && has_method(option_type->type_def, "destruct", vector<*type>()))) { + // don't really need the defer_stack + function_definitions += generate(ast_statement_ptr(make_method_call(make_operator_call("->", vector(adt_this, option)), "destruct", vector<*ast_node>())), null(), null(), &defer_stack, false).one_string() + } + function_definitions += "}\n" + }) } function_definitions += "}\n" }