add return temps in most all situations now, fix for and while

This commit is contained in:
Nathan Braswell
2016-03-09 15:21:50 -05:00
parent a6529ab381
commit f28d44df4b
2 changed files with 55 additions and 12 deletions

View File

@@ -360,7 +360,9 @@ obj c_generator (Object) {
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 { 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 // stick another stack on
defer_stack->push(make_pair(true, stack<*ast_node>())) defer_stack->push(make_pair(true, stack<*ast_node>()))
var to_ret = code_triple("while (") + generate(node->while_loop.condition, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>()).one_string() + ") {\n" + generate(node->while_loop.statement, enclosing_object, enclosing_func, defer_stack).one_string() var condition = generate(node->while_loop.condition, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>())
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_from_defer_stack(defer_stack, 1, enclosing_object, enclosing_func) to_ret += generate_from_defer_stack(defer_stack, 1, enclosing_object, enclosing_func)
defer_stack->pop() defer_stack->pop()
to_ret += "}\n" to_ret += "}\n"
@@ -370,13 +372,18 @@ obj c_generator (Object) {
// stick another stack on // stick another stack on
defer_stack->push(make_pair(true, stack<*ast_node>())) defer_stack->push(make_pair(true, stack<*ast_node>()))
// gotta take off last semicolon // gotta take off last semicolon
var to_ret = code_triple("for (") + generate(node->for_loop.init, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>()).one_string() + " " + generate(node->for_loop.condition, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>()).one_string() + "; " + var init = generate(node->for_loop.init, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>())
generate(node->for_loop.update, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>()).one_string().slice(0,-3) + var cond = generate(node->for_loop.condition, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>())
") {\n" + generate(node->for_loop.body, enclosing_object, enclosing_func, defer_stack).one_string() var update = generate(node->for_loop.update, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>())
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_from_defer_stack(defer_stack, 1, enclosing_object, enclosing_func).one_string() to_ret += generate_from_defer_stack(defer_stack, 1, enclosing_object, enclosing_func).one_string()
defer_stack->pop() defer_stack->pop()
to_ret += "}\n" to_ret += "}/*end inner for*/}/*end for's enclosing block*/\n"
return to_ret return code_triple(to_ret)
} }
fun generate_identifier(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node): code_triple { fun generate_identifier(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node): code_triple {
var pre = string() var pre = string()
@@ -518,15 +525,41 @@ obj c_generator (Object) {
func_name = generate_function(node->function_call.func, false).one_string() func_name = generate_function(node->function_call.func, false).one_string()
} }
// handle method call from inside method of same object // handle method call from inside method of same object
if (!dot_style_method_call && enclosing_object && enclosing_object->type_def.methods.contains(node->function_call.func)) if (!dot_style_method_call && enclosing_object) {
call_string += "this" var methods = enclosing_object->type_def.methods
for (var i = 0; i < methods.size; i++;) {
if (methods[i] == node->function_call.func || (is_template(methods[i]) && methods[i]->template.instantiated.contains(node->function_call.func))) {
call_string += "this";
break
}
}
}
var parameters = node->function_call.parameters var parameters = node->function_call.parameters
if ( parameters.size == 2 && (func_name == "+" || func_name == "-" || func_name == "*" || func_name == "/" || func_name == "||" if ( parameters.size == 2 && (func_name == "+" || func_name == "-" || func_name == "*" || func_name == "/"
|| func_name == "&&" || func_name == "<" || func_name == ">" || func_name == "<=" || func_name == ">=" || func_name == "<" || func_name == ">" || func_name == "<=" || 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>>>>()) + func_name + generate(parameters[1], enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>()) + 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 result = code_triple()
result.pre += first.pre;
var temp_bool = string("temp_bool") + get_id()
result.pre += string("bool ") + temp_bool + " = " + first.value + ";\n"
result.pre += first.post;
if (func_name == "||")
result.pre += string("if (!") + temp_bool + ") {"
else
result.pre += string("if (") + temp_bool + ") {"
result.pre += second.pre
result.pre += temp_bool + " = " + second.value + ";\n"
result.pre += second.post
result.pre += "}"
result.value = temp_bool
return result
}
// don't propegate enclosing function down right of access // don't propegate enclosing function down right of access
// XXX what about enclosing object? should it be the thing on the left? // XXX what about enclosing object? should it be the thing on the left?
if (func_name == "." || func_name == "->") if (func_name == "." || func_name == "->")
@@ -568,8 +601,11 @@ obj c_generator (Object) {
} }
var pre_call = string() var pre_call = string()
// we now have temporary return variables for all objects, even without destruct so we can do chained method calls // 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
// 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 && 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_object() && !func_return_type->is_ref && func_return_type->indirection == 0) {
if (!func_return_type->is_ref && !func_return_type->is_void()) {
// kind of ugly combo here of // kind of ugly combo here of
var temp_ident = ast_identifier_ptr(string("temporary_return")+get_id(), func_return_type, null<ast_node>()) 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>()) var declaration = ast_declaration_statement_ptr(temp_ident, null<ast_node>())
@@ -577,7 +613,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" 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() pre_call = generate_identifier(temp_ident, enclosing_object, enclosing_func).one_string()
// move destruct condition inside // move destruct condition inside
if (has_method(func_return_type->type_def, "destruct", vector<*type>())) if (func_return_type->is_object() && func_return_type->indirection == 0 && has_method(func_return_type->type_def, "destruct", vector<*type>()))
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() 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 = code_triple() var ref_pre = code_triple()

7
tests/.gitignore vendored
View File

@@ -1,3 +1,10 @@
tester tester
test_compiler test_compiler
*.results *.results
test_chainedIndirectTemplates
test_functionsValues
test_future
test_grammer
test_set
test_templateFuncInfr
test_util