60 tests passing
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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,7 +541,10 @@ 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))) {
|
||||
call_string += "this";
|
||||
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
3
tests/.gitignore
vendored
@@ -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
|
||||
|
||||
@@ -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); } )
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user