60 tests passing
This commit is contained in:
@@ -19,14 +19,17 @@ adt search_type {
|
|||||||
|
|
||||||
obj ast_transformation (Object) {
|
obj ast_transformation (Object) {
|
||||||
var ast_to_syntax: map<*ast_node, *tree<symbol>>
|
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>
|
var fourth_pass_worklist: queue<*ast_node>
|
||||||
fun construct(): *ast_transformation {
|
fun construct(): *ast_transformation {
|
||||||
ast_to_syntax.construct()
|
ast_to_syntax.construct()
|
||||||
|
type_def_to_this.construct()
|
||||||
fourth_pass_worklist.construct()
|
fourth_pass_worklist.construct()
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
fun copy_construct(old: *ast_transformation) {
|
fun copy_construct(old: *ast_transformation) {
|
||||||
ast_to_syntax.copy_construct(&old->ast_to_syntax)
|
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)
|
fourth_pass_worklist.copy_construct(&old->fourth_pass_worklist)
|
||||||
}
|
}
|
||||||
fun operator=(old: ref ast_transformation) {
|
fun operator=(old: ref ast_transformation) {
|
||||||
@@ -35,6 +38,7 @@ obj ast_transformation (Object) {
|
|||||||
}
|
}
|
||||||
fun destruct() {
|
fun destruct() {
|
||||||
ast_to_syntax.destruct()
|
ast_to_syntax.destruct()
|
||||||
|
type_def_to_this.destruct()
|
||||||
fourth_pass_worklist.destruct()
|
fourth_pass_worklist.destruct()
|
||||||
}
|
}
|
||||||
// first pass defines all type_defs (objects and aliases), ADTs, and top-level if-comps/passthroughs
|
// 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> {
|
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);)
|
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 {
|
fun transform_identifier(node: *tree<symbol>, scope: *ast_node, searching_for: search_type): *ast_node {
|
||||||
// first, we check for and generate this
|
// first, we check for and generate this
|
||||||
var name = concat_symbol_tree(node)
|
var name = concat_symbol_tree(node)
|
||||||
if (name == "this") {
|
if (name == "this") {
|
||||||
while (!is_type_def(scope)) scope = get_ast_scope(scope)->get(string("~enclosing_scope"))[0]
|
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) {
|
match (searching_for) {
|
||||||
search_type::none() return identifier_lookup(name, scope)
|
search_type::none() return identifier_lookup(name, scope)
|
||||||
@@ -431,6 +440,8 @@ obj ast_transformation (Object) {
|
|||||||
value_type = type_ptr(base_type::character(), 1)
|
value_type = type_ptr(base_type::character(), 1)
|
||||||
else if (value_str[0] == '\'') //'// lol, comment hack for vim syntax highlighting (my fault, of course)
|
else if (value_str[0] == '\'') //'// lol, comment hack for vim syntax highlighting (my fault, of course)
|
||||||
value_type = type_ptr(base_type::character())
|
value_type = type_ptr(base_type::character())
|
||||||
|
else if (value_str == "true" || value_str == "false")
|
||||||
|
value_type = type_ptr(base_type::boolean())
|
||||||
else {
|
else {
|
||||||
// should differentiate between float and double...
|
// should differentiate between float and double...
|
||||||
var contains_dot = false
|
var contains_dot = false
|
||||||
@@ -666,10 +677,25 @@ 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 == "."))
|
||||||
|
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);)
|
||||||
return to_ret
|
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) {
|
ast_node::return_statement(backing) {
|
||||||
println("found an return_statement")
|
println("found an return_statement")
|
||||||
return find_closed_variables(func, backing.return_value)
|
return find_closed_variables(func, backing.return_value)
|
||||||
|
|||||||
@@ -179,7 +179,8 @@ obj c_generator (Object) {
|
|||||||
|
|
||||||
var parameter_types = string()
|
var parameter_types = string()
|
||||||
var parameters = 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) + "*"
|
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"
|
||||||
}
|
}
|
||||||
@@ -218,7 +219,18 @@ obj c_generator (Object) {
|
|||||||
name_ast_map.for_each(fun(name: string, tree_pair: pair<*tree<symbol>,*ast_node>) {
|
name_ast_map.for_each(fun(name: string, tree_pair: pair<*tree<symbol>,*ast_node>) {
|
||||||
// iterate through children for each ast
|
// iterate through children for each ast
|
||||||
// assert translation_unit?
|
// 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) {
|
match (*child) {
|
||||||
// should really check the genrator
|
// should really check the genrator
|
||||||
ast_node::if_comp(backing) {
|
ast_node::if_comp(backing) {
|
||||||
@@ -281,7 +293,7 @@ obj c_generator (Object) {
|
|||||||
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)) +
|
||||||
" " + i->identifier.name + ";\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
|
||||||
}
|
}
|
||||||
@@ -529,7 +541,10 @@ obj c_generator (Object) {
|
|||||||
var methods = enclosing_object->type_def.methods
|
var methods = enclosing_object->type_def.methods
|
||||||
for (var i = 0; i < methods.size; i++;) {
|
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 (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
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -589,7 +604,7 @@ obj c_generator (Object) {
|
|||||||
|
|
||||||
var param_type = get_ast_type(param)
|
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)))) {
|
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>())
|
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
|
// 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"
|
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
|
tester
|
||||||
test_compiler
|
test_compiler
|
||||||
*.results
|
*.results
|
||||||
|
*.c
|
||||||
test_chainedIndirectTemplates
|
test_chainedIndirectTemplates
|
||||||
test_functionsValues
|
test_functionsValues
|
||||||
test_future
|
test_future
|
||||||
@@ -8,3 +9,5 @@ test_grammer
|
|||||||
test_set
|
test_set
|
||||||
test_templateFuncInfr
|
test_templateFuncInfr
|
||||||
test_util
|
test_util
|
||||||
|
test_close_over_members
|
||||||
|
test_string
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import io:*
|
import io:*
|
||||||
import set
|
import set
|
||||||
import mem
|
import util
|
||||||
|
|
||||||
fun runFunc(func: fun():void) {
|
fun runFunc(func: fun():void) {
|
||||||
func()
|
func()
|
||||||
@@ -26,7 +26,7 @@ obj One (Object) {
|
|||||||
}
|
}
|
||||||
fun destruct() {
|
fun destruct() {
|
||||||
var a:One
|
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