From 83450aa8332c8c1b91f2f0eb0b81260e8dfa8483 Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Sat, 30 Jan 2016 22:04:37 -0500 Subject: [PATCH] Added copy_constructing when returning --- stdlib/ast_transformation.krak | 18 +++++++++++------- stdlib/c_generator.krak | 27 ++++++++++++++++++++------- stdlib/type.krak | 2 ++ tests/to_parse.krak | 24 +++++++++++++----------- 4 files changed, 46 insertions(+), 25 deletions(-) diff --git a/stdlib/ast_transformation.krak b/stdlib/ast_transformation.krak index 840f98a..69df507 100644 --- a/stdlib/ast_transformation.krak +++ b/stdlib/ast_transformation.krak @@ -351,17 +351,17 @@ fun make_method_call(object_ident: *ast_node, method: *ast_node, parameters: vec var method_access = ast_function_call_ptr(get_builtin_function(string("."), vector(get_ast_type(object_ident), get_ast_type(method))), vector(object_ident, method)) return ast_function_call_ptr(method_access, parameters) } -fun make_operator_call(left: *ast_node, func: *char, right: *ast_node): *ast_node return make_operator_call(left, string(func), right); -fun make_operator_call(left: *ast_node, func: string, right: *ast_node): *ast_node { - return ast_function_call_ptr(get_builtin_function(func, vector(get_ast_type(left), get_ast_type(right))), vector(left, right)) +fun make_operator_call(func: *char, params: vector<*ast_node>): *ast_node return make_operator_call(string(func), params); +fun make_operator_call(func: string, params: vector<*ast_node>): *ast_node { + return ast_function_call_ptr(get_builtin_function(func, params.map(fun(p:*ast_node): *type return get_ast_type(p);)), params) } fun transform_assignment_statement(node: *tree, scope: *ast_node): *ast_node { var assign_to = transform(get_node("factor", node), scope) var to_assign = transform(get_node("boolean_expression", node), scope) - if (get_node("\"\\+=\"", node)) to_assign = make_operator_call(assign_to, "+", to_assign) - else if (get_node("\"-=\"", node)) to_assign = make_operator_call(assign_to, "-", to_assign) - else if (get_node("\"\\*=\"", node)) to_assign = make_operator_call(assign_to, "*", to_assign) - else if (get_node("\"/=\"", node)) to_assign = make_operator_call(assign_to, "/", to_assign) + if (get_node("\"\\+=\"", node)) to_assign = make_operator_call("+", vector(to_assign, to_assign)) + else if (get_node("\"-=\"", node)) to_assign = make_operator_call("-", vector(to_assign, to_assign)) + else if (get_node("\"\\*=\"", node)) to_assign = make_operator_call("*", vector(to_assign, to_assign)) + else if (get_node("\"/=\"", node)) to_assign = make_operator_call("/", vector(to_assign, to_assign)) var assignment = ast_assignment_statement_ptr(assign_to, to_assign) return assignment } @@ -451,6 +451,10 @@ fun transform_expression(node: *tree, scope: *ast_node, searching_for: s fun get_builtin_function(name: string, param_types: vector<*type>): *ast_node { if (name == "." || name == "->") return ast_function_ptr(name, type_ptr(param_types, param_types[1]), vector<*ast_node>()) + if (name == "&") + return ast_function_ptr(name, type_ptr(param_types, param_types[0]->clone_with_increased_indirection()), vector<*ast_node>()) + if (name == "\\*") + return ast_function_ptr(name, type_ptr(param_types, param_types[0]->clone_with_decreased_indirection()), vector<*ast_node>()) return ast_function_ptr(name, type_ptr(param_types, param_types[0]), vector<*ast_node>()) } fun function_lookup(name: string, scope: *ast_node, param_types: vector<*type>): *ast_node { diff --git a/stdlib/c_generator.krak b/stdlib/c_generator.krak index 0b796a9..cba7aa9 100644 --- a/stdlib/c_generator.krak +++ b/stdlib/c_generator.krak @@ -139,7 +139,7 @@ obj c_generator (Object) { top_level_c_passthrough += generate_simple_passthrough(backing.statement->statement.child) } ast_node::simple_passthrough(backing) top_level_c_passthrough += generate_simple_passthrough(child) - ast_node::declaration_statement(backing) variable_declarations += generate_declaration_statement(child, null(), null>>>()).one_string() + ";\n" + ast_node::declaration_statement(backing) variable_declarations += generate_declaration_statement(child, null(), null>>>(), true).one_string() + ";\n" ast_node::function(backing) { // make sure not a template // or a passthrough @@ -155,7 +155,7 @@ obj c_generator (Object) { type_poset.get_sorted().for_each(fun(vert: *ast_node) { plain_typedefs += string("typedef struct ") + vert->type_def.name + "_dummy " + vert->type_def.name + ";\n" structs += string("struct ") + vert->type_def.name + "_dummy {\n" - vert->type_def.variables.for_each(fun(variable_declaration: *ast_node) structs += generate_declaration_statement(variable_declaration, null(), null>>>()).one_string() + ";\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);) @@ -173,14 +173,14 @@ obj c_generator (Object) { return node->simple_passthrough.passthrough_str } 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>>): code_triple { + 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 if (node->declaration_statement.expression) to_ret += code_triple(" = ") + generate(node->declaration_statement.expression, enclosing_object, null>>>()) if (node->declaration_statement.init_method_call) to_ret += code_triple(";\n") + generate(node->declaration_statement.init_method_call, enclosing_object, null>>>()) - if (ident_type->is_object() && has_method(ident_type->type_def, "destruct", vector<*type>())) + 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 } @@ -220,9 +220,22 @@ obj c_generator (Object) { return code_triple(node->identifier.name) } fun generate_return_statement(node: *ast_node, enclosing_object: *ast_node, defer_stack: *stack>>): code_triple { + var return_value = node->return_statement.return_value + var return_value_type = get_ast_type(return_value) + var to_ret = code_triple() + // if we're returning an object, copy_construct a new one to return + if (return_value_type->is_object() && return_value_type->indirection == 0 && has_method(return_value_type->type_def, "copy_construct", vector(return_value_type->clone_with_indirection(1)))) { + var temp_ident = ast_identifier_ptr(string("temporary"), return_value_type) + 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() + // make this new identifier the new return value + return_value = temp_ident + } // generate all in stack by passing -1 - var to_ret = generate_from_defer_stack(defer_stack, -1, enclosing_object) - to_ret += code_triple("return ") + generate(node->return_statement.return_value, enclosing_object, null>>>()) + to_ret += generate_from_defer_stack(defer_stack, -1, enclosing_object) + to_ret += code_triple("return ") + generate(return_value, enclosing_object, null>>>()) return to_ret } fun generate_branching_statement(node: *ast_node, enclosing_object: *ast_node, defer_stack: *stack>>): code_triple { @@ -323,7 +336,7 @@ obj c_generator (Object) { ast_node::if_comp(backing) return generate_if_comp(node) 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) + 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) diff --git a/stdlib/type.krak b/stdlib/type.krak index c43420a..48034e0 100644 --- a/stdlib/type.krak +++ b/stdlib/type.krak @@ -115,6 +115,8 @@ obj type (Object) { } return string("impossible type, indirection:") + indirection } + fun clone_with_increased_indirection(): *type return clone_with_indirection(indirection+1); + fun clone_with_decreased_indirection(): *type return clone_with_indirection(indirection-1); fun clone_with_indirection(ind: int): *type { var to_ret = new() to_ret->copy_construct(this) diff --git a/tests/to_parse.krak b/tests/to_parse.krak index 46754ea..398fc35 100644 --- a/tests/to_parse.krak +++ b/tests/to_parse.krak @@ -1,5 +1,9 @@ import to_import: simple_print, simple_println, a, b, string_id +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 { @@ -35,6 +39,15 @@ fun some_other_function(in: bool): float { } */ fun main(): int { + var test_methods = something(77) + var test_methods_param.construct_with_param(10090): Something + simple_println("Constructing an object and printint its member, copy-constructing it, and printing that out, then letting both be destructed") + simple_println(test_methods.member) + simple_println(test_methods_param.member) + var second_obj = test_methods + second_obj.member += 5 + simple_println(second_obj.member) + return 0 /* var a_declaration:int simple_print(1 + 2) @@ -99,16 +112,5 @@ fun main(): int { return 0 } */ - var test_methods.construct(): Something - var test_methods_param.construct_with_param(10090): Something - /*var test_methods: Something*/ - test_methods.member = 10 - simple_println("Constructing an object and printint its member, copy-constructing it, and printing that out, then letting both be destructed") - simple_println(test_methods.member) - simple_println(test_methods_param.member) - var second_obj = test_methods - second_obj.member += 5 - simple_println(second_obj.member) - return 0 }