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:
@@ -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 */")
|
||||
|
||||
Reference in New Issue
Block a user