fixed regex, 61 tests passing
This commit is contained in:
@@ -677,7 +677,7 @@ obj ast_transformation (Object) {
|
||||
ast_node::function_call(backing) {
|
||||
println("found an function_call")
|
||||
// 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())
|
||||
var to_ret = find_closed_variables(func, backing.func)
|
||||
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"
|
||||
|
||||
// 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 parameter_types = string()
|
||||
var parameters = string()
|
||||
// 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) + "*"
|
||||
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
|
||||
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) {
|
||||
if (parameter_types != "") { parameter_types += ", "; parameters += ", ";}
|
||||
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")))
|
||||
enclosing_object_traverse = get_ast_scope(enclosing_object_traverse)->get(string("~enclosing_scope"))[0]
|
||||
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
|
||||
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) {
|
||||
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::function(backing) {
|
||||
// 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) {
|
||||
backing.instantiated.for_each(fun(node: *ast_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) {
|
||||
type_poset.add_vertex(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)
|
||||
vert->type_def.methods.for_each(fun(method: *ast_node) {
|
||||
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
|
||||
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()
|
||||
closure_struct_definitions += "typedef struct {\n"
|
||||
// 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";)
|
||||
closure_struct_definitions += string("} ") + closure_name + ";\n"
|
||||
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 {
|
||||
var pre = 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 += "(*"
|
||||
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))
|
||||
return code_triple(pre + "(this->" + 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()
|
||||
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
|
||||
// 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)))) {
|
||||
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
|
||||
}
|
||||
}
|
||||
// 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")
|
||||
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>>>>())
|
||||
// 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
|
||||
}
|
||||
@@ -494,7 +499,7 @@ obj c_generator (Object) {
|
||||
return to_ret + "}"
|
||||
}
|
||||
// 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) {
|
||||
var closed_vars = node->function.closed_variables
|
||||
if (closed_vars.size() == 0)
|
||||
@@ -503,7 +508,10 @@ obj c_generator (Object) {
|
||||
var to_ret = code_triple()
|
||||
var closure_type_str = get_closure_struct_type(closed_vars)
|
||||
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"
|
||||
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
|
||||
|
||||
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 ->
|
||||
if (node->function_call.func->function_call.func->function.name == ".")
|
||||
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>>>>())
|
||||
} 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, 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
|
||||
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::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,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::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)
|
||||
|
||||
Reference in New Issue
Block a user