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))
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<symbol>, 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<symbol>, 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 {

View File

@@ -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<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) {
// 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<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"
// 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<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
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<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>())))
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<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
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<stack<pair<bool,stack<*ast_node>>>>())
to_ret += generate_from_defer_stack(defer_stack, -1, enclosing_object)
to_ret += code_triple("return ") + generate(return_value, enclosing_object, null<stack<pair<bool,stack<*ast_node>>>>())
return to_ret
}
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::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)

View File

@@ -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<type>()
to_ret->copy_construct(this)