Added copy_constructing when returning

This commit is contained in:
Nathan Braswell
2016-01-30 22:04:37 -05:00
parent a64e01e828
commit 83450aa833
4 changed files with 46 additions and 25 deletions

View File

@@ -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)) 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) 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(func: *char, params: vector<*ast_node>): *ast_node return make_operator_call(string(func), params);
fun make_operator_call(left: *ast_node, func: string, right: *ast_node): *ast_node { fun make_operator_call(func: string, params: vector<*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)) 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<symbol>, scope: *ast_node): *ast_node { fun transform_assignment_statement(node: *tree<symbol>, scope: *ast_node): *ast_node {
var assign_to = transform(get_node("factor", node), scope) var assign_to = transform(get_node("factor", node), scope)
var to_assign = transform(get_node("boolean_expression", 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) if (get_node("\"\\+=\"", node)) to_assign = make_operator_call("+", vector(to_assign, 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("-", vector(to_assign, 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("*", vector(to_assign, 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("/", vector(to_assign, to_assign))
var assignment = ast_assignment_statement_ptr(assign_to, to_assign) var assignment = ast_assignment_statement_ptr(assign_to, to_assign)
return assignment return assignment
} }
@@ -451,6 +451,10 @@ fun transform_expression(node: *tree<symbol>, scope: *ast_node, searching_for: s
fun get_builtin_function(name: string, param_types: vector<*type>): *ast_node { fun get_builtin_function(name: string, param_types: vector<*type>): *ast_node {
if (name == "." || name == "->") if (name == "." || name == "->")
return ast_function_ptr(name, type_ptr(param_types, param_types[1]), vector<*ast_node>()) 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>()) 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 { fun function_lookup(name: string, scope: *ast_node, param_types: vector<*type>): *ast_node {

View File

@@ -139,7 +139,7 @@ obj c_generator (Object) {
top_level_c_passthrough += generate_simple_passthrough(backing.statement->statement.child) 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::simple_passthrough(backing) top_level_c_passthrough += generate_simple_passthrough(child)
ast_node::declaration_statement(backing) variable_declarations += generate_declaration_statement(child, null<ast_node>(), null<stack<pair<bool,stack<*ast_node>>>>()).one_string() + ";\n" ast_node::declaration_statement(backing) variable_declarations += generate_declaration_statement(child, null<ast_node>(), null<stack<pair<bool,stack<*ast_node>>>>(), true).one_string() + ";\n"
ast_node::function(backing) { ast_node::function(backing) {
// make sure not a template // make sure not a template
// or a passthrough // or a passthrough
@@ -155,7 +155,7 @@ obj c_generator (Object) {
type_poset.get_sorted().for_each(fun(vert: *ast_node) { 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" plain_typedefs += string("typedef struct ") + vert->type_def.name + "_dummy " + vert->type_def.name + ";\n"
structs += string("struct ") + vert->type_def.name + "_dummy {\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<ast_node>(), null<stack<pair<bool,stack<*ast_node>>>>()).one_string() + ";\n";) vert->type_def.variables.for_each(fun(variable_declaration: *ast_node) structs += generate_declaration_statement(variable_declaration, null<ast_node>(), null<stack<pair<bool,stack<*ast_node>>>>(), true).one_string() + ";\n";)
structs += "};\n" structs += "};\n"
// generate the methods // generate the methods
vert->type_def.methods.for_each(fun(method: *ast_node) generate_function_definition(method, vert);) 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 return node->simple_passthrough.passthrough_str
} }
fun generate_statement(node: *ast_node, enclosing_object: *ast_node, defer_stack: *stack<pair<bool,stack<*ast_node>>>): code_triple return generate(node->statement.child, enclosing_object, defer_stack) + ";\n"; fun generate_statement(node: *ast_node, enclosing_object: *ast_node, defer_stack: *stack<pair<bool,stack<*ast_node>>>): 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<pair<bool,stack<*ast_node>>>): code_triple { fun generate_declaration_statement(node: *ast_node, enclosing_object: *ast_node, defer_stack: *stack<pair<bool,stack<*ast_node>>>, add_to_defer: bool): code_triple {
// add destruct to defer_stack // add destruct to defer_stack
var identifier = node->declaration_statement.identifier var identifier = node->declaration_statement.identifier
var ident_type = identifier->identifier.type 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) + " " + identifier->identifier.name
if (node->declaration_statement.expression) to_ret += code_triple(" = ") + generate(node->declaration_statement.expression, enclosing_object, null<stack<pair<bool,stack<*ast_node>>>>()) if (node->declaration_statement.expression) to_ret += code_triple(" = ") + generate(node->declaration_statement.expression, enclosing_object, null<stack<pair<bool,stack<*ast_node>>>>())
if (node->declaration_statement.init_method_call) to_ret += code_triple(";\n") + generate(node->declaration_statement.init_method_call, enclosing_object, null<stack<pair<bool,stack<*ast_node>>>>()) if (node->declaration_statement.init_method_call) to_ret += code_triple(";\n") + generate(node->declaration_statement.init_method_call, enclosing_object, null<stack<pair<bool,stack<*ast_node>>>>())
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>()))) defer_stack->top().second.push(ast_statement_ptr(make_method_call(identifier, "destruct", vector<*ast_node>())))
return to_ret return to_ret
} }
@@ -220,9 +220,22 @@ obj c_generator (Object) {
return code_triple(node->identifier.name) return code_triple(node->identifier.name)
} }
fun generate_return_statement(node: *ast_node, enclosing_object: *ast_node, defer_stack: *stack<pair<bool,stack<*ast_node>>>): code_triple { fun generate_return_statement(node: *ast_node, enclosing_object: *ast_node, defer_stack: *stack<pair<bool,stack<*ast_node>>>): 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<ast_node>())
// 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 // generate all in stack by passing -1
var to_ret = generate_from_defer_stack(defer_stack, -1, enclosing_object) 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<stack<pair<bool,stack<*ast_node>>>>()) to_ret += code_triple("return ") + generate(return_value, enclosing_object, null<stack<pair<bool,stack<*ast_node>>>>())
return to_ret return to_ret
} }
fun generate_branching_statement(node: *ast_node, enclosing_object: *ast_node, defer_stack: *stack<pair<bool,stack<*ast_node>>>): code_triple { fun generate_branching_statement(node: *ast_node, enclosing_object: *ast_node, defer_stack: *stack<pair<bool,stack<*ast_node>>>): code_triple {
@@ -323,7 +336,7 @@ obj c_generator (Object) {
ast_node::if_comp(backing) return generate_if_comp(node) ast_node::if_comp(backing) return generate_if_comp(node)
ast_node::simple_passthrough(backing) return code_triple() + generate_simple_passthrough(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::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::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::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) ast_node::while_loop(backing) return generate_while_loop(node, enclosing_object, defer_stack)

View File

@@ -115,6 +115,8 @@ obj type (Object) {
} }
return string("impossible type, indirection:") + indirection 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 { fun clone_with_indirection(ind: int): *type {
var to_ret = new<type>() var to_ret = new<type>()
to_ret->copy_construct(this) to_ret->copy_construct(this)

View File

@@ -1,5 +1,9 @@
import to_import: simple_print, simple_println, a, b, string_id 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) { obj Something (ObjectTrait) {
var member: int var member: int
fun construct(): *Something { fun construct(): *Something {
@@ -35,6 +39,15 @@ fun some_other_function(in: bool): float {
} }
*/ */
fun main(): int { 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 var a_declaration:int
simple_print(1 + 2) simple_print(1 + 2)
@@ -99,16 +112,5 @@ fun main(): int {
return 0 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
} }