60 tests passing

This commit is contained in:
Nathan Braswell
2016-03-10 04:49:38 -05:00
parent f28d44df4b
commit 7543b95529
4 changed files with 52 additions and 8 deletions

View File

@@ -19,14 +19,17 @@ adt search_type {
obj ast_transformation (Object) {
var ast_to_syntax: map<*ast_node, *tree<symbol>>
var type_def_to_this: map<*ast_node, *ast_node>
var fourth_pass_worklist: queue<*ast_node>
fun construct(): *ast_transformation {
ast_to_syntax.construct()
type_def_to_this.construct()
fourth_pass_worklist.construct()
return this
}
fun copy_construct(old: *ast_transformation) {
ast_to_syntax.copy_construct(&old->ast_to_syntax)
type_def_to_this.copy_construct(&old->type_def_to_this)
fourth_pass_worklist.copy_construct(&old->fourth_pass_worklist)
}
fun operator=(old: ref ast_transformation) {
@@ -35,6 +38,7 @@ obj ast_transformation (Object) {
}
fun destruct() {
ast_to_syntax.destruct()
type_def_to_this.destruct()
fourth_pass_worklist.destruct()
}
// first pass defines all type_defs (objects and aliases), ADTs, and top-level if-comps/passthroughs
@@ -396,12 +400,17 @@ obj ast_transformation (Object) {
fun transform_all(nodes: vector<*tree<symbol>>, scope: *ast_node, template_replacements: map<string, *type>): vector<*ast_node> {
return nodes.map(fun(node: *tree<symbol>): *ast_node return transform(node, scope, template_replacements);)
}
fun make_this(object: *ast_node): *ast_node {
if (!type_def_to_this.contains_key(object))
type_def_to_this[object] = ast_identifier_ptr("this", object->type_def.self_type->clone_with_indirection(1), object)
return type_def_to_this[object]
}
fun transform_identifier(node: *tree<symbol>, scope: *ast_node, searching_for: search_type): *ast_node {
// first, we check for and generate this
var name = concat_symbol_tree(node)
if (name == "this") {
while (!is_type_def(scope)) scope = get_ast_scope(scope)->get(string("~enclosing_scope"))[0]
return ast_identifier_ptr("this", scope->type_def.self_type->clone_with_indirection(1), scope)
return make_this(scope)
}
match (searching_for) {
search_type::none() return identifier_lookup(name, scope)
@@ -431,6 +440,8 @@ obj ast_transformation (Object) {
value_type = type_ptr(base_type::character(), 1)
else if (value_str[0] == '\'') //'// lol, comment hack for vim syntax highlighting (my fault, of course)
value_type = type_ptr(base_type::character())
else if (value_str == "true" || value_str == "false")
value_type = type_ptr(base_type::boolean())
else {
// should differentiate between float and double...
var contains_dot = false
@@ -666,10 +677,25 @@ 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 == "."))
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);)
return to_ret
}
ast_node::function(backing) {
// now if this is a method, it is called without an access operator because we are in a lambda inside another method
// this is because we don't look at the right side of access operators, note the above function_call case
if (backing.scope.contains_key(string("~enclosing_scope"))) {
var enclosing = backing.scope[string("~enclosing_scope")][0]
if (is_type_def(enclosing))
return set(make_this(enclosing))
if (is_template(enclosing) && is_type_def(enclosing->template.scope[string("~enclosing_scope")][0]))
return set(make_this(enclosing->template.scope[string("~enclosing_scope")][0]))
}
// we don't close over actual functions
return set<*ast_node>()
}
ast_node::return_statement(backing) {
println("found an return_statement")
return find_closed_variables(func, backing.return_value)

View File

@@ -179,7 +179,8 @@ obj c_generator (Object) {
var parameter_types = string()
var parameters = string()
if (enclosing_object) {
// lambdas can have the enclosing object too, if it's needed (lambda in a method)
if (enclosing_object && backing.closed_variables.size() == 0) {
parameter_types = type_to_c(enclosing_object->type_def.self_type) + "*"
parameters = type_to_c(enclosing_object->type_def.self_type) + "* this"
}
@@ -218,7 +219,18 @@ obj c_generator (Object) {
name_ast_map.for_each(fun(name: string, tree_pair: pair<*tree<symbol>,*ast_node>) {
// iterate through children for each ast
// assert translation_unit?
(tree_pair.second->translation_unit.children + tree_pair.second->translation_unit.lambdas).for_each(fun(child: *ast_node) {
// do lambdas seperatly, so we can reconstitute the enclosing object if it has one
tree_pair.second->translation_unit.lambdas.for_each(fun(child: *ast_node) {
var enclosing_object_traverse = child
while(enclosing_object_traverse && !is_type_def(enclosing_object_traverse) &&
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)
else
generate_function_definition(child, null<ast_node>())
})
tree_pair.second->translation_unit.children.for_each(fun(child: *ast_node) {
match (*child) {
// should really check the genrator
ast_node::if_comp(backing) {
@@ -281,7 +293,7 @@ obj c_generator (Object) {
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)) +
" " + i->identifier.name + ";\n";)
" " + get_name(i) + ";\n";)
closure_struct_definitions += string("} ") + closure_name + ";\n"
closure_struct_map[closed_variables] = closure_name
}
@@ -529,6 +541,9 @@ obj c_generator (Object) {
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))) {
if (enclosing_func && enclosing_func->function.closed_variables.size())
call_string += "(*(closure_data->this))";
else
call_string += "this";
break
}
@@ -589,7 +604,7 @@ obj c_generator (Object) {
var param_type = get_ast_type(param)
if (param_type->is_object() && !in_function_param_type->is_ref && param_type->indirection == 0 && has_method(param_type->type_def, "copy_construct", vector(param_type->clone_with_indirection(1)))) {
var temp_ident = ast_identifier_ptr(string("temporary_param")+get_id(), param_type, null<ast_node>())
var temp_ident = ast_identifier_ptr(string("temporary_param")+get_id(), param_type->clone_without_ref(), 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
call_string.pre += generate_declaration_statement(declaration, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false).one_string() + ";\n"

3
tests/.gitignore vendored
View File

@@ -1,6 +1,7 @@
tester
test_compiler
*.results
*.c
test_chainedIndirectTemplates
test_functionsValues
test_future
@@ -8,3 +9,5 @@ test_grammer
test_set
test_templateFuncInfr
test_util
test_close_over_members
test_string

View File

@@ -1,6 +1,6 @@
import io:*
import set
import mem
import util
fun runFunc(func: fun():void) {
func()
@@ -26,7 +26,7 @@ obj One (Object) {
}
fun destruct() {
var a:One
mem::safe_recursive_delete(&a, fun(it: *One): set::set<*One> { return set::set(it); } )
util::safe_recursive_delete(&a, fun(it: *One): set::set<*One> { return set::set(it); } )
}
}