fixed regex, 61 tests passing
This commit is contained in:
@@ -677,7 +677,7 @@ obj ast_transformation (Object) {
|
|||||||
ast_node::function_call(backing) {
|
ast_node::function_call(backing) {
|
||||||
println("found an function_call")
|
println("found an function_call")
|
||||||
// XXX should special case . and ->, I think
|
// XXX should special case . and ->, I think
|
||||||
if (is_function(backing.func) && (backing.func->function.name == "." || backing.func->function.name == "."))
|
if (is_function(backing.func) && (backing.func->function.name == "." || backing.func->function.name == "->"))
|
||||||
return find_closed_variables(func, backing.parameters.first())
|
return find_closed_variables(func, backing.parameters.first())
|
||||||
var to_ret = find_closed_variables(func, backing.func)
|
var to_ret = find_closed_variables(func, backing.func)
|
||||||
backing.parameters.for_each(fun(n: *ast_node) to_ret += find_closed_variables(func, n);)
|
backing.parameters.for_each(fun(n: *ast_node) to_ret += find_closed_variables(func, n);)
|
||||||
|
|||||||
@@ -174,13 +174,13 @@ obj c_generator (Object) {
|
|||||||
var variable_declarations: string = "\n/**Variable Declarations**/\n"
|
var variable_declarations: string = "\n/**Variable Declarations**/\n"
|
||||||
|
|
||||||
// moved out from below so that it can be used for methods as well as regular functions (and eventually lambdas...)
|
// moved out from below so that it can be used for methods as well as regular functions (and eventually lambdas...)
|
||||||
var generate_function_definition = fun(child: *ast_node, enclosing_object: *ast_node) {
|
var generate_function_definition = fun(child: *ast_node, enclosing_object: *ast_node, is_lambda: bool) {
|
||||||
var backing = child->function
|
var backing = child->function
|
||||||
|
|
||||||
var parameter_types = string()
|
var parameter_types = string()
|
||||||
var parameters = string()
|
var parameters = string()
|
||||||
// lambdas can have the enclosing object too, if it's needed (lambda in a method)
|
// lambdas can have the enclosing object too, if it's needed (lambda in a method)
|
||||||
if (enclosing_object && backing.closed_variables.size() == 0) {
|
if (enclosing_object && !is_lambda) {
|
||||||
parameter_types = type_to_c(enclosing_object->type_def.self_type) + "*"
|
parameter_types = type_to_c(enclosing_object->type_def.self_type) + "*"
|
||||||
parameters = type_to_c(enclosing_object->type_def.self_type) + "* this"
|
parameters = type_to_c(enclosing_object->type_def.self_type) + "* this"
|
||||||
}
|
}
|
||||||
@@ -196,7 +196,7 @@ obj c_generator (Object) {
|
|||||||
// start out with one stack on the stack
|
// start out with one stack on the stack
|
||||||
var defer_stack = stack<pair<bool,stack<*ast_node>>>(make_pair(false, stack<*ast_node>()))
|
var defer_stack = stack<pair<bool,stack<*ast_node>>>(make_pair(false, stack<*ast_node>()))
|
||||||
|
|
||||||
var decorated_name = generate_function(child, false).one_string()
|
var decorated_name = generate_function(child, enclosing_object, null<ast_node>(), false).one_string()
|
||||||
backing.parameters.for_each(fun(parameter: *ast_node) {
|
backing.parameters.for_each(fun(parameter: *ast_node) {
|
||||||
if (parameter_types != "") { parameter_types += ", "; parameters += ", ";}
|
if (parameter_types != "") { parameter_types += ", "; parameters += ", ";}
|
||||||
parameter_types += type_to_c(parameter->identifier.type)
|
parameter_types += type_to_c(parameter->identifier.type)
|
||||||
@@ -226,9 +226,9 @@ obj c_generator (Object) {
|
|||||||
get_ast_scope(enclosing_object_traverse) && get_ast_scope(enclosing_object_traverse)->contains_key(string("~enclosing_scope")))
|
get_ast_scope(enclosing_object_traverse) && get_ast_scope(enclosing_object_traverse)->contains_key(string("~enclosing_scope")))
|
||||||
enclosing_object_traverse = get_ast_scope(enclosing_object_traverse)->get(string("~enclosing_scope"))[0]
|
enclosing_object_traverse = get_ast_scope(enclosing_object_traverse)->get(string("~enclosing_scope"))[0]
|
||||||
if (enclosing_object_traverse && is_type_def(enclosing_object_traverse))
|
if (enclosing_object_traverse && is_type_def(enclosing_object_traverse))
|
||||||
generate_function_definition(child, enclosing_object_traverse)
|
generate_function_definition(child, enclosing_object_traverse, true)
|
||||||
else
|
else
|
||||||
generate_function_definition(child, null<ast_node>())
|
generate_function_definition(child, null<ast_node>(), true)
|
||||||
})
|
})
|
||||||
tree_pair.second->translation_unit.children.for_each(fun(child: *ast_node) {
|
tree_pair.second->translation_unit.children.for_each(fun(child: *ast_node) {
|
||||||
match (*child) {
|
match (*child) {
|
||||||
@@ -241,12 +241,12 @@ obj c_generator (Object) {
|
|||||||
ast_node::declaration_statement(backing) variable_declarations += generate_declaration_statement(child, null<ast_node>(), null<ast_node>(), null<stack<pair<bool,stack<*ast_node>>>>(), false).one_string() + ";\n" // false - don't do defer
|
ast_node::declaration_statement(backing) variable_declarations += generate_declaration_statement(child, null<ast_node>(), null<ast_node>(), null<stack<pair<bool,stack<*ast_node>>>>(), false).one_string() + ";\n" // false - don't do defer
|
||||||
ast_node::function(backing) {
|
ast_node::function(backing) {
|
||||||
// check for and add to parameters if a closure
|
// check for and add to parameters if a closure
|
||||||
generate_function_definition(child, null<ast_node>())
|
generate_function_definition(child, null<ast_node>(), false)
|
||||||
}
|
}
|
||||||
ast_node::template(backing) {
|
ast_node::template(backing) {
|
||||||
backing.instantiated.for_each(fun(node: *ast_node) {
|
backing.instantiated.for_each(fun(node: *ast_node) {
|
||||||
match (*node) {
|
match (*node) {
|
||||||
ast_node::function(backing) generate_function_definition(node, null<ast_node>())
|
ast_node::function(backing) generate_function_definition(node, null<ast_node>(), false)
|
||||||
ast_node::type_def(backing) {
|
ast_node::type_def(backing) {
|
||||||
type_poset.add_vertex(node)
|
type_poset.add_vertex(node)
|
||||||
backing.variables.for_each(fun(i: *ast_node) {
|
backing.variables.for_each(fun(i: *ast_node) {
|
||||||
@@ -279,9 +279,9 @@ obj c_generator (Object) {
|
|||||||
// generate the methods (note some of these may be templates)
|
// generate the methods (note some of these may be templates)
|
||||||
vert->type_def.methods.for_each(fun(method: *ast_node) {
|
vert->type_def.methods.for_each(fun(method: *ast_node) {
|
||||||
if (is_template(method))
|
if (is_template(method))
|
||||||
method->template.instantiated.for_each(fun(m: *ast_node) generate_function_definition(m, vert);)
|
method->template.instantiated.for_each(fun(m: *ast_node) generate_function_definition(m, vert, false);)
|
||||||
else
|
else
|
||||||
generate_function_definition(method, vert);
|
generate_function_definition(method, vert, false);
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -292,7 +292,9 @@ obj c_generator (Object) {
|
|||||||
var closure_name = string("closure_data_type") + get_id()
|
var closure_name = string("closure_data_type") + get_id()
|
||||||
closure_struct_definitions += "typedef struct {\n"
|
closure_struct_definitions += "typedef struct {\n"
|
||||||
// note that we keep our is_ref, which would not normally happen on a clone with increased indirection
|
// note that we keep our is_ref, which would not normally happen on a clone with increased indirection
|
||||||
closed_variables.for_each(fun(i: *ast_node) closure_struct_definitions += type_to_c(i->identifier.type->clone_with_increased_indirection(1,i->identifier.type->is_ref)) +
|
// closed_variables.for_each(fun(i: *ast_node) closure_struct_definitions += type_to_c(i->identifier.type->clone_with_increased_indirection(1,i->identifier.type->is_ref)) +
|
||||||
|
// NO, now we don't keep our ref. Too hard to make, as &(&*i) isn't legal C
|
||||||
|
closed_variables.for_each(fun(i: *ast_node) closure_struct_definitions += type_to_c(i->identifier.type->clone_with_increased_indirection()) +
|
||||||
" " + get_name(i) + ";\n";)
|
" " + get_name(i) + ";\n";)
|
||||||
closure_struct_definitions += string("} ") + closure_name + ";\n"
|
closure_struct_definitions += string("} ") + closure_name + ";\n"
|
||||||
closure_struct_map[closed_variables] = closure_name
|
closure_struct_map[closed_variables] = closure_name
|
||||||
@@ -400,12 +402,14 @@ obj c_generator (Object) {
|
|||||||
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()
|
||||||
var post = string()
|
var post = string()
|
||||||
if (get_ast_type(node)->is_ref) {
|
// note that we get rid of references on closing over, (or maybe everything's kind of a reference)
|
||||||
|
// so we do else if here
|
||||||
|
if (enclosing_func && enclosing_func->function.closed_variables.contains(node))
|
||||||
|
return code_triple(pre + string("(*(closure_data->") + get_name(node) + "))" + post)
|
||||||
|
else if (get_ast_type(node)->is_ref) {
|
||||||
pre += "(*"
|
pre += "(*"
|
||||||
post += ")"
|
post += ")"
|
||||||
}
|
}
|
||||||
if (enclosing_func && enclosing_func->function.closed_variables.contains(node))
|
|
||||||
return code_triple(pre + string("(*(closure_data->") + get_name(node) + "))" + post)
|
|
||||||
if (enclosing_object && get_ast_scope(enclosing_object)->contains_key(node->identifier.name) && get_ast_scope(enclosing_object)->get(node->identifier.name).contains(node))
|
if (enclosing_object && get_ast_scope(enclosing_object)->contains_key(node->identifier.name) && get_ast_scope(enclosing_object)->get(node->identifier.name).contains(node))
|
||||||
return code_triple(pre + "(this->" + get_name(node) + ")" + post)
|
return code_triple(pre + "(this->" + get_name(node) + ")" + post)
|
||||||
return code_triple(pre + get_name(node) + post)
|
return code_triple(pre + get_name(node) + post)
|
||||||
@@ -416,6 +420,7 @@ obj c_generator (Object) {
|
|||||||
var to_ret = code_triple()
|
var to_ret = code_triple()
|
||||||
if (return_value) {
|
if (return_value) {
|
||||||
var return_value_type = get_ast_type(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
|
||||||
// if we're returning an object, copy_construct a new one to return
|
// if we're returning an object, copy_construct a new one to return
|
||||||
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)))) {
|
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 temp_ident = ast_identifier_ptr(string("temporary_return")+get_id(), return_value_type, null<ast_node>())
|
||||||
@@ -427,13 +432,13 @@ obj c_generator (Object) {
|
|||||||
return_value = temp_ident
|
return_value = temp_ident
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// generate all in stack by passing -1
|
|
||||||
to_ret.pre += generate_from_defer_stack(defer_stack, -1, enclosing_object, enclosing_func).one_string()
|
|
||||||
to_ret += code_triple("return")
|
to_ret += code_triple("return")
|
||||||
if (function_return_type->is_ref)
|
if (function_return_type->is_ref)
|
||||||
to_ret += code_triple(" &")
|
to_ret += code_triple(" &")
|
||||||
if (return_value)
|
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>>>>())
|
||||||
|
// 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()
|
||||||
|
|
||||||
return to_ret
|
return to_ret
|
||||||
}
|
}
|
||||||
@@ -494,7 +499,7 @@ obj c_generator (Object) {
|
|||||||
return to_ret + "}"
|
return to_ret + "}"
|
||||||
}
|
}
|
||||||
// this generates the function as a value, not the actual function
|
// this generates the function as a value, not the actual function
|
||||||
fun generate_function(node: *ast_node, as_value: bool): code_triple {
|
fun generate_function(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, as_value: bool): code_triple {
|
||||||
if (as_value) {
|
if (as_value) {
|
||||||
var closed_vars = node->function.closed_variables
|
var closed_vars = node->function.closed_variables
|
||||||
if (closed_vars.size() == 0)
|
if (closed_vars.size() == 0)
|
||||||
@@ -503,7 +508,10 @@ obj c_generator (Object) {
|
|||||||
var to_ret = code_triple()
|
var to_ret = code_triple()
|
||||||
var closure_type_str = get_closure_struct_type(closed_vars)
|
var closure_type_str = get_closure_struct_type(closed_vars)
|
||||||
to_ret.pre += closure_type_str + " " + temp_closure_struct + " = (" + closure_type_str + "){"
|
to_ret.pre += closure_type_str + " " + temp_closure_struct + " = (" + closure_type_str + "){"
|
||||||
closed_vars.for_each(fun(i: *ast_node) to_ret.pre += string(".") + get_name(i) + "=&" + get_name(i) + ",";)
|
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() + ","
|
||||||
|
})
|
||||||
to_ret.pre += "};\n"
|
to_ret.pre += "};\n"
|
||||||
return to_ret + string("((") + type_to_c(node->function.type) + "){(void*)&" + temp_closure_struct + ",(void*)" + get_name(node) + "})"
|
return to_ret + string("((") + type_to_c(node->function.type) + "){(void*)&" + temp_closure_struct + ",(void*)" + get_name(node) + "})"
|
||||||
}
|
}
|
||||||
@@ -525,7 +533,7 @@ obj c_generator (Object) {
|
|||||||
// should get uglier when we have to figure out if it's just an inside lambda
|
// should get uglier when we have to figure out if it's just an inside lambda
|
||||||
|
|
||||||
if (dot_style_method_call) {
|
if (dot_style_method_call) {
|
||||||
func_name = generate_function(node->function_call.func->function_call.parameters[1], false).one_string()
|
func_name = generate_function(node->function_call.func->function_call.parameters[1], enclosing_object, enclosing_func, false).one_string()
|
||||||
// don't add & if it was ->
|
// don't add & if it was ->
|
||||||
if (node->function_call.func->function_call.func->function.name == ".")
|
if (node->function_call.func->function_call.func->function.name == ".")
|
||||||
call_string += "&"
|
call_string += "&"
|
||||||
@@ -534,7 +542,7 @@ obj c_generator (Object) {
|
|||||||
call_string += generate(node->function_call.func->function_call.parameters[0], enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>())
|
call_string += generate(node->function_call.func->function_call.parameters[0], enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>())
|
||||||
} else if (is_identifier(node->function_call.func) || is_function(node->function_call.func)) {
|
} 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
|
// 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, false).one_string()
|
func_name = generate_function(node->function_call.func, enclosing_object, enclosing_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) {
|
if (!dot_style_method_call && enclosing_object) {
|
||||||
@@ -691,7 +699,7 @@ obj c_generator (Object) {
|
|||||||
ast_node::if_statement(backing) return generate_if_statement(node, enclosing_object, enclosing_func, defer_stack)
|
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::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::for_loop(backing) return generate_for_loop(node, enclosing_object, enclosing_func, defer_stack)
|
||||||
ast_node::function(backing) return generate_function(node,true)
|
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_call(backing) return generate_function_call(node, enclosing_object, enclosing_func)
|
||||||
ast_node::code_block(backing) return generate_code_block(node, enclosing_object, enclosing_func, defer_stack)
|
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::return_statement(backing) return generate_return_statement(node, enclosing_object, enclosing_func, defer_stack)
|
||||||
|
|||||||
Reference in New Issue
Block a user