fixed regex, 61 tests passing

This commit is contained in:
Nathan Braswell
2016-03-10 14:08:56 -05:00
parent 7543b95529
commit 40d630f348
2 changed files with 29 additions and 21 deletions

View File

@@ -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);)

View File

@@ -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)