66 tests passing! Implemented the extra need_variable parameter to allow references of constants, etc. Need to check a few of the tests still failing.

This commit is contained in:
Nathan Braswell
2016-03-12 03:23:43 -05:00
parent ac8493d7f3
commit 6a1c210b8a

View File

@@ -196,7 +196,7 @@ obj c_generator (Object) {
// start out with one stack on the stack
var defer_stack = stack<pair<bool,stack<*ast_node>>>(make_pair(false, stack<*ast_node>()))
var decorated_name = generate_function(child, enclosing_object, null<ast_node>(), false).one_string()
var decorated_name = generate_function(child, enclosing_object, null<ast_node>(), false, false).one_string()
backing.parameters.for_each(fun(parameter: *ast_node) {
if (parameter_types != "") { parameter_types += ", "; parameters += ", ";}
parameter_types += type_to_c(parameter->identifier.type)
@@ -303,7 +303,7 @@ obj c_generator (Object) {
}
fun generate_if_comp(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, defer_stack: *stack<pair<bool,stack<*ast_node>>>): code_triple {
if (node->if_comp.wanted_generator == "__C__")
return generate(node->if_comp.statement, enclosing_object, enclosing_func, defer_stack)
return generate(node->if_comp.statement, enclosing_object, enclosing_func, defer_stack, false)
return code_triple()
}
fun generate_simple_passthrough(node: *ast_node, is_top_level: bool): string {
@@ -328,7 +328,7 @@ obj c_generator (Object) {
return pre + result + post
return pre + "{" + result + "}" + post
}
fun generate_statement(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, defer_stack: *stack<pair<bool,stack<*ast_node>>>): code_triple return generate(node->statement.child, enclosing_object, enclosing_func, defer_stack) + ";\n";
fun generate_statement(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, defer_stack: *stack<pair<bool,stack<*ast_node>>>): code_triple return generate(node->statement.child, enclosing_object, enclosing_func, defer_stack, false) + ";\n";
fun generate_declaration_statement(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *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
@@ -339,44 +339,43 @@ obj c_generator (Object) {
if (node->declaration_statement.expression) {
if (ident_type->is_object() && has_method(ident_type->type_def, "copy_construct", vector(get_ast_type(node->declaration_statement.expression)->clone_with_increased_indirection()))) {
to_ret.pre += ";\n"
to_ret += generate(ast_statement_ptr(make_method_call(identifier, "copy_construct", vector(make_operator_call("&", vector(node->declaration_statement.expression))))), enclosing_object, enclosing_func, defer_stack)
to_ret += generate(ast_statement_ptr(make_method_call(identifier, "copy_construct", vector(make_operator_call("&", vector(node->declaration_statement.expression))))), enclosing_object, enclosing_func, defer_stack, false)
} else {
if (ident_type->is_function()) {
to_ret.pre += string(";\n")
to_ret += code_triple() + get_name(identifier) + " = " + generate(node->declaration_statement.expression, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>())
to_ret += code_triple() + get_name(identifier) + " = " + generate(node->declaration_statement.expression, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false)
} else {
// some shifting around to get it to work in all cases
// what cases?
to_ret.value = to_ret.pre
to_ret.pre = ""
to_ret += code_triple() + string(" = ") + generate(node->declaration_statement.expression, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>())
// to_ret += code_triple() + string(" = ") + generate(node->declaration_statement.expression, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>()).one_string()
to_ret += code_triple() + string(" = ") + generate(node->declaration_statement.expression, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false)
}
}
}
if (node->declaration_statement.init_method_call) {
to_ret.pre += ";\n"
to_ret += code_triple() + generate(node->declaration_statement.init_method_call, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>())
to_ret += code_triple() + generate(node->declaration_statement.init_method_call, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false)
}
if (add_to_defer && ident_type->is_object() && ident_type->indirection == 0 && 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
}
fun generate_assignment_statement(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node): code_triple {
return generate(node->assignment_statement.to, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>()) + " = " + generate(node->assignment_statement.from, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>())
return generate(node->assignment_statement.to, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false) + " = " + generate(node->assignment_statement.from, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false)
}
fun generate_if_statement(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, defer_stack: *stack<pair<bool,stack<*ast_node>>>): code_triple {
var if_str = code_triple("if (") + generate(node->if_statement.condition, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>()) + ") {\n" + generate(node->if_statement.then_part, enclosing_object, enclosing_func, defer_stack).one_string() + "}"
var if_str = code_triple("if (") + generate(node->if_statement.condition, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false) + ") {\n" + generate(node->if_statement.then_part, enclosing_object, enclosing_func, defer_stack, false).one_string() + "}"
if (node->if_statement.else_part)
if_str += code_triple(" else {\n") + generate(node->if_statement.else_part, enclosing_object, enclosing_func, defer_stack).one_string() + "}"
if_str += code_triple(" else {\n") + generate(node->if_statement.else_part, enclosing_object, enclosing_func, defer_stack, false).one_string() + "}"
return if_str + "\n"
}
fun generate_while_loop(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, defer_stack: *stack<pair<bool,stack<*ast_node>>>): code_triple {
// stick another stack on
defer_stack->push(make_pair(true, stack<*ast_node>()))
var condition = generate(node->while_loop.condition, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>())
var condition = generate(node->while_loop.condition, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false)
var to_ret = code_triple("while (1) {\n") + condition.pre + "if(!" + condition.value + ") {" + condition.post + "break;}" + condition.post
to_ret += generate(node->while_loop.statement, enclosing_object, enclosing_func, defer_stack).one_string()
to_ret += generate(node->while_loop.statement, enclosing_object, enclosing_func, defer_stack, false).one_string()
to_ret += generate_from_defer_stack(defer_stack, 1, enclosing_object, enclosing_func)
defer_stack->pop()
to_ret += "}\n"
@@ -386,14 +385,14 @@ obj c_generator (Object) {
// stick another stack on
defer_stack->push(make_pair(true, stack<*ast_node>()))
// gotta take off last semicolon
var init = generate(node->for_loop.init, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>())
var cond = generate(node->for_loop.condition, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>())
var update = generate(node->for_loop.update, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>())
var init = generate(node->for_loop.init, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false)
var cond = generate(node->for_loop.condition, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false)
var update = generate(node->for_loop.update, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false)
var do_update_name = string("do_update") + get_id()
var to_ret = string("{\n") + init.one_string() + "bool " + do_update_name + " = false;\nfor (;;) {\n"
to_ret += string("if (") + do_update_name + ") {" + update.one_string() + "}\n" + do_update_name + " = true;\n"
to_ret += cond.pre + "if (!" + cond.value + ") {" + cond.post + "break;}" + cond.post
to_ret += generate(node->for_loop.body, enclosing_object, enclosing_func, defer_stack).one_string()
to_ret += generate(node->for_loop.body, enclosing_object, enclosing_func, defer_stack, false).one_string()
to_ret += generate_from_defer_stack(defer_stack, 1, enclosing_object, enclosing_func).one_string()
defer_stack->pop()
to_ret += "}/*end inner for*/}/*end for's enclosing block*/\n"
@@ -420,23 +419,32 @@ obj c_generator (Object) {
var to_ret = code_triple()
if (return_value) {
var return_value_type = get_ast_type(return_value)
// should this happen every time so that we're sure that we don't call a function after we destruct some things it depends on
// always need a return temp so we don't destruct things the return depends on before they're calculated
// if we're returning an object, copy_construct a new one to return
// if we're returning a ref, we need to account for that in the temp type
// note the temp type is a pointer, not a ref so we don't have the deref/ref thing on return
var temp_ident_type = return_value_type
if (function_return_type->is_ref)
temp_ident_type = temp_ident_type->clone_with_increased_indirection()
var temp_ident = ast_identifier_ptr(string("temporary_return")+get_id(), temp_ident_type, null<ast_node>())
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, enclosing_func, defer_stack, false).one_string() + ";\n"
if (return_value_type->is_object() && !function_return_type->is_ref && 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")+get_id(), return_value_type, null<ast_node>())
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, enclosing_func, 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, enclosing_func, defer_stack).one_string()
// make this new identifier the new return value
return_value = temp_ident
} else {
var refamp = string()
if (function_return_type->is_ref)
refamp = "&"
to_ret.pre += (generate(temp_ident, enclosing_object, enclosing_func, defer_stack, false) + " = " + refamp + generate(return_value, enclosing_object, enclosing_func, defer_stack, false) + ";").one_string() + ";\n"
}
// make this new identifier the new return value
return_value = temp_ident
}
to_ret += code_triple("return")
if (function_return_type->is_ref)
to_ret += code_triple(" &")
if (return_value)
to_ret += code_triple(" ") + generate(return_value, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>())
to_ret += code_triple(" ") + generate(return_value, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false)
// generate all in stack by passing -1, make sure added after we calculate the return value
to_ret.pre += generate_from_defer_stack(defer_stack, -1, enclosing_object, enclosing_func).one_string()
@@ -463,43 +471,58 @@ obj c_generator (Object) {
num++
}
for (var i = 0; i < num; i++;)
defer_stack->from_top(i).second.for_each_reverse(fun(node: *ast_node) to_ret += generate(node, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>());)
defer_stack->from_top(i).second.for_each_reverse(fun(node: *ast_node) to_ret += generate(node, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false);)
return to_ret
}
fun generate_defer_statement(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, defer_stack: *stack<pair<bool,stack<*ast_node>>>): code_triple {
defer_stack->top().second.push(node->defer_statement.statement)
return code_triple("/*defer wanna know what*/")
}
fun generate_value(node: *ast_node): code_triple {
fun generate_value(node: *ast_node, need_variable: bool): code_triple {
var value = node->value.string_value
if (value[0] != '"')
return code_triple(value);
var to_ret = string("\"")
if (value.slice(0,3) == "\"\"\"")
value = value.slice(3,-4)
else
value = value.slice(1,-2)
value.for_each(fun(c: char) {
if (c == '\n')
to_ret += "\\n"
else if (c == '"')
to_ret += "\\\""
else
to_ret += c
})
return code_triple(to_ret + "\"")
var to_ret = string()
if (value[0] != '"') {
to_ret = value;
} else {
to_ret = string("\"")
if (value.slice(0,3) == "\"\"\"")
value = value.slice(3,-4)
else
value = value.slice(1,-2)
value.for_each(fun(c: char) {
if (c == '\n')
to_ret += "\\n"
else if (c == '"')
to_ret += "\\\""
else
to_ret += c
})
to_ret += "\""
}
if (need_variable) {
var temp_ident = ast_identifier_ptr(string("temporary_value")+get_id(), get_ast_type(node), null<ast_node>())
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
var trip_ret = code_triple()
// trip_ret.pre += generate_declaration_statement(declaration, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false).one_string() + " = " + to_ret + ";\n"
// trip_ret.value = generate_identifier(temp_ident, enclosing_object, enclosing_func).one_string()
trip_ret.pre += generate_declaration_statement(declaration, null<ast_node>(), null<ast_node>(), null<stack<pair<bool,stack<*ast_node>>>>(), false).one_string() + " = " + to_ret + ";\n"
trip_ret.value = generate_identifier(temp_ident, null<ast_node>(), null<ast_node>()).one_string()
return trip_ret
}
return code_triple(to_ret)
}
fun generate_code_block(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, defer_stack: *stack<pair<bool,stack<*ast_node>>>): code_triple {
var to_ret = code_triple("{\n")
// stick another stack on
defer_stack->push(make_pair(false, stack<*ast_node>()))
node->code_block.children.for_each(fun(child: *ast_node) to_ret += generate(child, enclosing_object, enclosing_func, defer_stack).one_string();)
node->code_block.children.for_each(fun(child: *ast_node) to_ret += generate(child, enclosing_object, enclosing_func, defer_stack, false).one_string();)
to_ret += generate_from_defer_stack(defer_stack, 1, enclosing_object, enclosing_func)
defer_stack->pop()
return to_ret + "}"
}
// this generates the function as a value, not the actual function
fun generate_function(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, as_value: bool): code_triple {
fun generate_function(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, as_value: bool, need_variable: bool): code_triple {
if (as_value) {
var closed_vars = node->function.closed_variables
if (closed_vars.size() == 0)
@@ -510,14 +533,15 @@ obj c_generator (Object) {
to_ret.pre += closure_type_str + " " + temp_closure_struct + " = (" + closure_type_str + "){"
closed_vars.for_each(fun(i: *ast_node) {
// note that we get/have gotten rid of refs here, or maybe more accurately, everything is a ref
to_ret.pre += string(".") + get_name(i) + "=&" + generate(i, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>()).one_string() + ","
// should be a variable anyway?
to_ret.pre += string(".") + get_name(i) + "=&" + generate(i, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), true).one_string() + ","
})
to_ret.pre += "};\n"
return to_ret + string("((") + type_to_c(node->function.type) + "){(void*)&" + temp_closure_struct + ",(void*)" + get_name(node) + "})"
}
return code_triple(get_name(node))
}
fun generate_function_call(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node): code_triple {
fun generate_function_call(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, need_variable: bool): code_triple {
var func_name = string()
var call_string = code_triple()
var func_return_type = get_ast_type(node)
@@ -533,16 +557,18 @@ obj c_generator (Object) {
// should get uglier when we have to figure out if it's just an inside lambda
if (dot_style_method_call) {
func_name = generate_function(node->function_call.func->function_call.parameters[1], enclosing_object, enclosing_func, false).one_string()
func_name = generate_function(node->function_call.func->function_call.parameters[1], enclosing_object, enclosing_func, false, false).one_string()
// don't add & if it was ->
if (node->function_call.func->function_call.func->function.name == ".")
call_string += "&"
// having a null defer stack should be ok, as the only things we should get through here are identifiers and function calls
// XXX should it? wouldn't function calls be a problem?
call_string += generate(node->function_call.func->function_call.parameters[0], enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>())
// should this be true if ref?
call_string += generate(node->function_call.func->function_call.parameters[0], enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), true)
} else if (is_identifier(node->function_call.func) || is_function(node->function_call.func)) {
// we handle the case when it's not this later, i.e. it's a lambda returned from another function or something
func_name = generate_function(node->function_call.func, enclosing_object, enclosing_func, false).one_string()
func_name = generate_function(node->function_call.func, enclosing_object, enclosing_func, false, false).one_string()
}
// handle method call from inside method of same object
if (!dot_style_method_call && enclosing_object) {
@@ -563,10 +589,10 @@ obj c_generator (Object) {
|| func_name == "<" || func_name == ">" || func_name == "<=" || func_name == ">="
|| func_name == "==" || func_name == "!=" || func_name == "%"
))
return code_triple("(") + generate(parameters[0], enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>()) + func_name + generate(parameters[1], enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>()) + string(")")
return code_triple("(") + generate(parameters[0], enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false) + func_name + generate(parameters[1], enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false) + string(")")
if ( parameters.size == 2 && (func_name == "||" || func_name == "&&")) {
var first = generate(parameters[0], enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>())
var second = generate(parameters[1], enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>())
var first = generate(parameters[0], enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false)
var second = generate(parameters[1], enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false)
var result = code_triple()
result.pre += first.pre;
var temp_bool = string("temp_bool") + get_id()
@@ -586,16 +612,17 @@ obj c_generator (Object) {
// don't propegate enclosing function down right of access
// XXX what about enclosing object? should it be the thing on the left?
if (func_name == "." || func_name == "->")
return code_triple("(") + generate(parameters[0], enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>()) + func_name + generate(parameters[1], null<ast_node>(), null<ast_node>(), null<stack<pair<bool,stack<*ast_node>>>>()) + string(")")
return code_triple("(") + generate(parameters[0], enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false) + func_name + generate(parameters[1], null<ast_node>(), null<ast_node>(), null<stack<pair<bool,stack<*ast_node>>>>(), false) + string(")")
if (func_name == "[]")
return code_triple("(") + generate(parameters[0], enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>()) + "[" + generate(parameters[1], enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>()) + string("])")
return code_triple("(") + generate(parameters[0], enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false) + "[" + generate(parameters[1], enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false) + string("])")
// the post ones need to be post-ed specifically, and take the p off
if (func_name == "++p" || func_name == "--p")
return code_triple("(") + generate(parameters[0], enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>()) + ")" + func_name.slice(0,-2)
return code_triple("(") + generate(parameters[0], enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false) + ")" + func_name.slice(0,-2)
// So we don't end up copy_constructing etc, we just handle the unary operators right here
// note also the passing down need_variable for &
if (func_name == "*" || func_name == "&")
return code_triple("(") + func_name + generate(parameters[0], enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>()) + ")"
return code_triple("(") + func_name + generate(parameters[0], enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), func_name == "&") + ")"
// for checking if we pass in a ref
var func_type = get_ast_type(node->function_call.func)
@@ -617,18 +644,20 @@ obj c_generator (Object) {
// have to pass false to the declaration generator, so can't do it through generate_statement
call_string.pre += generate_declaration_statement(declaration, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false).one_string() + ";\n"
call_string.pre += generate_statement(ast_statement_ptr(make_method_call(temp_ident, "copy_construct", vector(make_operator_call("&", vector(param))))), enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>()).one_string()
call_string += generate(temp_ident, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>())
call_string += generate(temp_ident, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false)
} else {
call_string += generate(param, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>())
call_string += generate(param, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), in_function_param_type->is_ref)
}
}
var pre_call = string()
// we now have temporary return variables for all objects, even without destruct so we can do chained method calls
// actually all non-ref returns, for chained any calls
// well, now only if we also pass in true for need_variable
// XXX this should change to only if we know we need it by having an enum or bool passed down to this call...
// if (func_return_type->is_object() && !func_return_type->is_ref && func_return_type->indirection == 0 && has_method(func_return_type->type_def, "destruct", vector<*type>())) {
// if (func_return_type->is_object() && !func_return_type->is_ref && func_return_type->indirection == 0) {
if (!func_return_type->is_ref && !func_return_type->is_void()) {
var needs_temp_for_destruct = func_return_type->is_object() && func_return_type->indirection == 0 && has_method(func_return_type->type_def, "destruct", vector<*type>())
if (!func_return_type->is_ref && (needs_temp_for_destruct || (!func_return_type->is_void() && need_variable)) ) {
// kind of ugly combo here of
var temp_ident = ast_identifier_ptr(string("temporary_return")+get_id(), func_return_type, null<ast_node>())
var declaration = ast_declaration_statement_ptr(temp_ident, null<ast_node>())
@@ -636,7 +665,7 @@ obj c_generator (Object) {
call_string.pre += generate_declaration_statement(declaration, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false).one_string() + ";\n"
pre_call = generate_identifier(temp_ident, enclosing_object, enclosing_func).one_string()
// move destruct condition inside
if (func_return_type->is_object() && func_return_type->indirection == 0 && has_method(func_return_type->type_def, "destruct", vector<*type>()))
if (needs_temp_for_destruct)
call_string.post += generate_statement(ast_statement_ptr(make_method_call(temp_ident, "destruct", vector<*ast_node>())), enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>()).one_string()
}
var ref_pre = string()
@@ -656,7 +685,7 @@ obj c_generator (Object) {
call_string.pre += generate_declaration_statement(declaration, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false).one_string() + ";\n"
pre_call = generate_identifier(temp_ident, enclosing_object, enclosing_func).one_string()
}
var name_temp = generate(node->function_call.func, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>())
var name_temp = generate(node->function_call.func, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false)
call_string.pre += name_temp.pre
call_string.post += name_temp.post
func_name = name_temp.value
@@ -693,7 +722,7 @@ obj c_generator (Object) {
}
// for now, anyway
fun generate(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, defer_stack: *stack<pair<bool,stack<*ast_node>>>): code_triple {
fun generate(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, defer_stack: *stack<pair<bool,stack<*ast_node>>>, need_variable: bool): code_triple {
if (!node) return code_triple("/*NULL*/")
match (*node) {
ast_node::if_comp(backing) return generate_if_comp(node, enclosing_object, enclosing_func, defer_stack)
@@ -704,13 +733,13 @@ obj c_generator (Object) {
ast_node::if_statement(backing) return generate_if_statement(node, enclosing_object, enclosing_func, defer_stack)
ast_node::while_loop(backing) return generate_while_loop(node, enclosing_object, enclosing_func, defer_stack)
ast_node::for_loop(backing) return generate_for_loop(node, enclosing_object, enclosing_func, defer_stack)
ast_node::function(backing) return generate_function(node, enclosing_object, enclosing_func, true)
ast_node::function_call(backing) return generate_function_call(node, enclosing_object, enclosing_func)
ast_node::function(backing) return generate_function(node, enclosing_object, enclosing_func, true, need_variable)
ast_node::function_call(backing) return generate_function_call(node, enclosing_object, enclosing_func, need_variable)
ast_node::code_block(backing) return generate_code_block(node, enclosing_object, enclosing_func, defer_stack)
ast_node::return_statement(backing) return generate_return_statement(node, enclosing_object, enclosing_func, defer_stack)
ast_node::branching_statement(backing) return generate_branching_statement(node, enclosing_object, enclosing_func, defer_stack)
ast_node::defer_statement(backing) return generate_defer_statement(node, enclosing_object, enclosing_func, defer_stack)
ast_node::value(backing) return generate_value(node)
ast_node::value(backing) return generate_value(node, need_variable)
ast_node::identifier(backing) return generate_identifier(node, enclosing_object, enclosing_func)
}
return code_triple("/* COULD NOT GENERATE */")