Fix a bunch of stuff back and forth, 39 tests passing
This commit is contained in:
@@ -463,24 +463,24 @@ obj ast_transformation (Object) {
|
|||||||
// may have type, or an expression, or both
|
// may have type, or an expression, or both
|
||||||
var type_syntax_node = get_node("type", node)
|
var type_syntax_node = get_node("type", node)
|
||||||
var expression_syntax_node = get_node("boolean_expression", node)
|
var expression_syntax_node = get_node("boolean_expression", node)
|
||||||
var ident_type = null<type>()
|
|
||||||
var expression = null<ast_node>()
|
var expression = null<ast_node>()
|
||||||
if (type_syntax_node) ident_type = transform_type(type_syntax_node, scope, template_replacements)
|
// we do it early so that if there is a type_syntax_node we can add to scope so that the expression can find this for things like rec closures
|
||||||
|
var identifier = ast_identifier_ptr(name, null<type>(), scope)
|
||||||
|
add_to_scope(name, identifier, scope)
|
||||||
|
if (type_syntax_node) identifier->identifier.type = transform_type(type_syntax_node, scope, template_replacements)
|
||||||
if (expression_syntax_node) {
|
if (expression_syntax_node) {
|
||||||
expression = transform(expression_syntax_node, scope, template_replacements)
|
expression = transform(expression_syntax_node, scope, template_replacements)
|
||||||
if (!type_syntax_node)
|
if (!type_syntax_node)
|
||||||
ident_type = get_ast_type(expression)
|
identifier->identifier.type = get_ast_type(expression)
|
||||||
}
|
}
|
||||||
if (!ident_type) error("declaration statement with no type or expression from which to inference type")
|
if (!identifier->identifier.type) error("declaration statement with no type or expression from which to inference type")
|
||||||
var identifier = ast_identifier_ptr(name, ident_type, scope)
|
|
||||||
var declaration = ast_declaration_statement_ptr(identifier, expression)
|
var declaration = ast_declaration_statement_ptr(identifier, expression)
|
||||||
// ok, deal with the possible init position method call
|
// ok, deal with the possible init position method call
|
||||||
if (identifiers.size == 2) {
|
if (identifiers.size == 2) {
|
||||||
var method = transform(identifiers[1], ident_type->type_def, template_replacements)
|
var method = transform(identifiers[1], identifier->identifier.type->type_def, template_replacements)
|
||||||
var parameters = get_nodes("parameter", node).map(fun(child: *tree<symbol>): *ast_node return transform(get_node("boolean_expression", child), scope, template_replacements);)
|
var parameters = get_nodes("parameter", node).map(fun(child: *tree<symbol>): *ast_node return transform(get_node("boolean_expression", child), scope, template_replacements);)
|
||||||
declaration->declaration_statement.init_method_call = make_method_call(identifier, method, parameters)
|
declaration->declaration_statement.init_method_call = make_method_call(identifier, method, parameters)
|
||||||
}
|
}
|
||||||
add_to_scope(name, identifier, scope)
|
|
||||||
return declaration
|
return declaration
|
||||||
}
|
}
|
||||||
fun transform_assignment_statement(node: *tree<symbol>, scope: *ast_node, template_replacements: map<string, *type>): *ast_node {
|
fun transform_assignment_statement(node: *tree<symbol>, scope: *ast_node, template_replacements: map<string, *type>): *ast_node {
|
||||||
@@ -555,6 +555,7 @@ obj ast_transformation (Object) {
|
|||||||
return function_node
|
return function_node
|
||||||
}
|
}
|
||||||
fun find_closed_variables(func: *ast_node, node: *ast_node): set<*ast_node> {
|
fun find_closed_variables(func: *ast_node, node: *ast_node): set<*ast_node> {
|
||||||
|
if (!node) return set<*ast_node>()
|
||||||
match (*node) {
|
match (*node) {
|
||||||
ast_node::identifier(backing) {
|
ast_node::identifier(backing) {
|
||||||
println("found an identifier")
|
println("found an identifier")
|
||||||
@@ -574,6 +575,7 @@ 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
|
||||||
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
|
||||||
@@ -582,6 +584,41 @@ obj ast_transformation (Object) {
|
|||||||
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)
|
||||||
}
|
}
|
||||||
|
ast_node::if_statement(backing) {
|
||||||
|
println("found an if statement")
|
||||||
|
return find_closed_variables(func, backing.condition) + find_closed_variables(func, backing.then_part) + find_closed_variables(func, backing.else_part)
|
||||||
|
}
|
||||||
|
// match_statement: match_statement,
|
||||||
|
// case_statement: case_statement,
|
||||||
|
ast_node::while_loop(backing) {
|
||||||
|
println("found an while loop")
|
||||||
|
return find_closed_variables(func, backing.condition) + find_closed_variables(func, backing.statement)
|
||||||
|
}
|
||||||
|
ast_node::for_loop(backing) {
|
||||||
|
println("found an for loop")
|
||||||
|
return find_closed_variables(func, backing.init) + find_closed_variables(func, backing.condition) +
|
||||||
|
find_closed_variables(func, backing.update) + find_closed_variables(func, backing.body)
|
||||||
|
}
|
||||||
|
ast_node::return_statement(backing) {
|
||||||
|
println("found a return_statement")
|
||||||
|
return find_closed_variables(func, backing.return_value)
|
||||||
|
}
|
||||||
|
ast_node::defer_statement(backing) {
|
||||||
|
println("found a defer_statement")
|
||||||
|
return find_closed_variables(func, backing.statement)
|
||||||
|
}
|
||||||
|
ast_node::assignment_statement(backing) {
|
||||||
|
println("found an assignment_statement")
|
||||||
|
return find_closed_variables(func, backing.to) + find_closed_variables(func, backing.from)
|
||||||
|
}
|
||||||
|
ast_node::declaration_statement(backing) {
|
||||||
|
println("found an declaration_statement")
|
||||||
|
return find_closed_variables(func, backing.expression) + find_closed_variables(func, backing.init_method_call)
|
||||||
|
}
|
||||||
|
ast_node::if_comp(backing) {
|
||||||
|
println("found an if_comp")
|
||||||
|
return find_closed_variables(func, backing.statement)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return set<*ast_node>()
|
return set<*ast_node>()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -273,7 +273,7 @@ obj c_generator (Object) {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
return make_pair(prequal+plain_typedefs+top_level_c_passthrough+variable_extern_declarations+structs+closure_struct_definitions+function_typedef_string+function_prototypes+variable_declarations+function_definitions + "\n", linker_string)
|
return make_pair(prequal+plain_typedefs+top_level_c_passthrough+variable_extern_declarations+structs+function_typedef_string+closure_struct_definitions+function_prototypes+variable_declarations+function_definitions + "\n", linker_string)
|
||||||
}
|
}
|
||||||
fun get_closure_struct_type(closed_variables: set<*ast_node>): string {
|
fun get_closure_struct_type(closed_variables: set<*ast_node>): string {
|
||||||
if (!closure_struct_map.contains_key(closed_variables)) {
|
if (!closure_struct_map.contains_key(closed_variables)) {
|
||||||
@@ -317,16 +317,29 @@ obj c_generator (Object) {
|
|||||||
// add destruct to defer_stack
|
// add destruct to defer_stack
|
||||||
var identifier = node->declaration_statement.identifier
|
var identifier = node->declaration_statement.identifier
|
||||||
var ident_type = identifier->identifier.type
|
var ident_type = identifier->identifier.type
|
||||||
var to_ret = code_triple() + type_to_c(identifier->identifier.type) + " " + get_name(identifier)
|
// we do the declaration in the pre now so that we can take it's address to close over it for things like recursive closures
|
||||||
|
// we only make it first if it's a function type though, so that global levels still work
|
||||||
|
var to_ret = code_triple(type_to_c(identifier->identifier.type) + " " + get_name(identifier), string(), string())
|
||||||
if (node->declaration_statement.expression) {
|
if (node->declaration_statement.expression) {
|
||||||
if (ident_type->is_object() && has_method(ident_type->type_def, "copy_construct", vector(get_ast_type(node->declaration_statement.expression)->clone_with_increased_indirection()))) {
|
if (ident_type->is_object() && has_method(ident_type->type_def, "copy_construct", vector(get_ast_type(node->declaration_statement.expression)->clone_with_increased_indirection()))) {
|
||||||
to_ret += ";\n";
|
to_ret.pre += ";\n"
|
||||||
to_ret += generate(ast_statement_ptr(make_method_call(identifier, "copy_construct", vector(make_operator_call("&", vector(node->declaration_statement.expression))))), enclosing_object, enclosing_func, defer_stack)
|
to_ret += generate(ast_statement_ptr(make_method_call(identifier, "copy_construct", vector(make_operator_call("&", vector(node->declaration_statement.expression))))), enclosing_object, enclosing_func, defer_stack)
|
||||||
} else {
|
} else {
|
||||||
to_ret += code_triple(" = ") + generate(node->declaration_statement.expression, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>())
|
if (ident_type->is_function()) {
|
||||||
|
to_ret.pre += string(";\n")
|
||||||
|
to_ret += code_triple() + get_name(identifier) + " = " + generate(node->declaration_statement.expression, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>())
|
||||||
|
} else {
|
||||||
|
// some shifting around to get it to work in all cases
|
||||||
|
to_ret.value = to_ret.pre
|
||||||
|
to_ret.pre = ""
|
||||||
|
to_ret += code_triple() + string(" = ") + generate(node->declaration_statement.expression, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>()).one_string()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (node->declaration_statement.init_method_call) to_ret += code_triple(";\n") + generate(node->declaration_statement.init_method_call, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>())
|
}
|
||||||
|
if (node->declaration_statement.init_method_call) {
|
||||||
|
to_ret.pre += ";\n"
|
||||||
|
to_ret += code_triple() + generate(node->declaration_statement.init_method_call, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>())
|
||||||
|
}
|
||||||
if (add_to_defer && ident_type->is_object() && has_method(ident_type->type_def, "destruct", vector<*type>()))
|
if (add_to_defer && ident_type->is_object() && has_method(ident_type->type_def, "destruct", vector<*type>()))
|
||||||
defer_stack->top().second.push(ast_statement_ptr(make_method_call(identifier, "destruct", vector<*ast_node>())))
|
defer_stack->top().second.push(ast_statement_ptr(make_method_call(identifier, "destruct", vector<*ast_node>())))
|
||||||
return to_ret
|
return to_ret
|
||||||
@@ -363,7 +376,7 @@ obj c_generator (Object) {
|
|||||||
}
|
}
|
||||||
fun generate_identifier(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node): code_triple {
|
fun generate_identifier(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node): code_triple {
|
||||||
if (enclosing_func && enclosing_func->function.closed_variables.contains(node))
|
if (enclosing_func && enclosing_func->function.closed_variables.contains(node))
|
||||||
return code_triple(string("*(closure_data->") + get_name(node) + ")")
|
return code_triple(string("(*(closure_data->") + get_name(node) + "))")
|
||||||
if (enclosing_object && get_ast_scope(enclosing_object)->contains_key(node->identifier.name) && get_ast_scope(enclosing_object)->get(node->identifier.name).contains(node))
|
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("(this->") + get_name(node) + ")"
|
return code_triple("(this->") + get_name(node) + ")"
|
||||||
return code_triple(get_name(node))
|
return code_triple(get_name(node))
|
||||||
@@ -481,15 +494,17 @@ obj c_generator (Object) {
|
|||||||
// don't add & if it was ->
|
// don't add & if it was ->
|
||||||
if (node->function_call.func->function_call.func->function.name == ".")
|
if (node->function_call.func->function_call.func->function.name == ".")
|
||||||
call_string += "&"
|
call_string += "&"
|
||||||
// call_string += generate_function(node->function_call.func->function_call.parameters[0], false)
|
|
||||||
call_string += generate_identifier(node->function_call.func->function_call.parameters[0], enclosing_object, enclosing_func)
|
call_string += generate_identifier(node->function_call.func->function_call.parameters[0], enclosing_object, enclosing_func)
|
||||||
} else {
|
} else {
|
||||||
// regular style function name or lambda
|
// regular style function name or lambda
|
||||||
func_name = generate_function(node->function_call.func, false).one_string()
|
// func_name = generate_function(node->function_call.func, false).one_string()
|
||||||
if (!is_function(node->function_call.func)) {
|
if (!is_function(node->function_call.func)) {
|
||||||
// not function, so we must be an identifier or function call return or something
|
// not function, so we must be an identifier or function call return or something
|
||||||
|
func_name = generate(node->function_call.func, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>()).one_string()
|
||||||
call_string += func_name + ".data"
|
call_string += func_name + ".data"
|
||||||
func_name = func_name + ".func"
|
func_name = func_name + ".func"
|
||||||
|
} else {
|
||||||
|
func_name = generate_function(node->function_call.func, false).one_string()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// handle method call from inside method of same object
|
// handle method call from inside method of same object
|
||||||
|
|||||||
@@ -69,6 +69,11 @@ obj set<T> (Object, Serializable) {
|
|||||||
fun operator+=(items: ref set<T>) {
|
fun operator+=(items: ref set<T>) {
|
||||||
add(items)
|
add(items)
|
||||||
}
|
}
|
||||||
|
fun operator+(items: ref set<T>): set<T> {
|
||||||
|
var to_ret.copy_construct(this): set<T>
|
||||||
|
to_ret.add(items)
|
||||||
|
return to_ret
|
||||||
|
}
|
||||||
fun add(item: ref T) {
|
fun add(item: ref T) {
|
||||||
if (!contains(item))
|
if (!contains(item))
|
||||||
data.add(item)
|
data.add(item)
|
||||||
|
|||||||
@@ -166,5 +166,11 @@ obj type (Object) {
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
fun is_function(): bool {
|
||||||
|
match (base) {
|
||||||
|
base_type::function() return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import mem:*;
|
import mem:*;
|
||||||
import io:*;
|
import simple_print:*;
|
||||||
|
|
||||||
obj AnObject {
|
obj AnObject {
|
||||||
var a: int;
|
var a: int;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import io:*
|
import simple_print:*
|
||||||
|
|
||||||
fun main():int {
|
fun main():int {
|
||||||
var message = "thingy: "
|
var message = "thingy: "
|
||||||
|
|||||||
Reference in New Issue
Block a user