diff --git a/.gitignore b/.gitignore index d34dc85..7b5bbd2 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ stats *.swm *.swn *.swo +*.swl *.png *krakout* kraklist.txt diff --git a/k.krak b/k.krak index 68cf301..39065fc 100644 --- a/k.krak +++ b/k.krak @@ -95,9 +95,9 @@ fun main(argc: int, argv: **char): int { for (var i = 0; i < scope->children.size; i++;) { match(scope->children[i]->data) { ast::_import(b) if b.second.contains(name) || b.second.contains(str("*")) { - if !bound(b.first) { + if !ast_bound(b.first) { // Import / parse file if not already - var file_path = binding_str(b.first) + var file_path = ast_binding_str(b.first) if (!name_ast_map.contains_key(file_path)) { printerr(file_path + ", ") var parse_tree = parse.parse_input(read_file(file_path), file_path) @@ -106,9 +106,9 @@ fun main(argc: int, argv: **char): int { printlnerr("syntax_to_ast " + file_path + ":") print_tree(name_ast_map[file_path], 1) } - set_binding(b.first, name_ast_map[file_path]) + set_ast_binding(b.first, name_ast_map[file_path]) } - to_ret += scope_lookup(get_binding(b.first), name, is_type) + to_ret += scope_lookup(get_ast_binding(b.first), name, is_type) } ast::_type_def(b) if (is_type && b == name) to_ret += scope->children[i] @@ -129,11 +129,11 @@ fun main(argc: int, argv: **char): int { return to_ret } var try_binding = fun(binding: *tree, start_scope: *tree, type_binding: bool) { - if !bound(binding) { + if !ast_bound(binding) { var options = scope_lookup(start_scope, binding->data._binding.first, type_binding) if (options.size < 1) error("Could not find any options for scope lookup of " + binding->data._binding.first) - set_binding(binding, options[0]) + set_ast_binding(binding, options[0]) } } var handle_type: fun(*type, *tree): void = fun(t: *type, n: *tree) { @@ -227,11 +227,12 @@ fun main(argc: int, argv: **char): int { ast::_import(b) { } ast::_identifier(b) { C_str += idt + b.first; } ast::_binding(b) { - if (is_top_level_item(b.third)) - pass_poset.add_close_dep(make_pair(item, str("emit_C")), make_pair(b.third, str("emit_C"))) - else if (is_identifier(b.third) && is_declaration(b.third->parent) && is_top_level_item(b.third->parent)) - pass_poset.add_close_dep(make_pair(item, str("emit_C")), make_pair(b.third->parent, str("emit_C"))) - C_str += idt + get_c_name(b.third) + var bound_to = b.second->bound_to + if (is_top_level_item(bound_to)) + pass_poset.add_close_dep(make_pair(item, str("emit_C")), make_pair(bound_to, str("emit_C"))) + else if (is_identifier(bound_to) && is_declaration(bound_to->parent) && is_top_level_item(bound_to->parent)) + pass_poset.add_close_dep(make_pair(item, str("emit_C")), make_pair(bound_to->parent, str("emit_C"))) + C_str += get_c_name(bound_to) } ast::_type_def(b) { error("type_def gen unimplemented"); } ast::_adt_def(b) { error("no adt_def should remain at C emit"); } @@ -350,11 +351,11 @@ fun main(argc: int, argv: **char): int { true, vec( _identifier(str("argc"), type(base_type::_int(), 0, false)), _identifier(str("argv"), type(base_type::_char(), 2, false)), - _return(vec(_call(vec(make_binding("fmain"), make_binding("argc"), make_binding("argv"))))) + _return(vec(_call(vec(make_ast_binding("fmain"), make_ast_binding("argc"), make_ast_binding("argv"))))) ) ) var top_unit = _translation_unit(str(), vec( - _import(make_binding(kraken_file_name), set(str("*")), vec( + _import(make_ast_binding(kraken_file_name), set(str("*")), vec( _identifier(kraken_file_name, type(base_type::_void(), 0, false)) )), real_main @@ -406,9 +407,9 @@ fun parse_type(syntax: *tree): *type { if (ident != null>()) { var template_inst = get_node("template_inst", syntax) if (template_inst != null>()) { - return type(base_type::_obj(make_binding(concat(ident) + "")), indr, is_ref) + return type(base_type::_obj(make_ast_binding(concat(ident) + "")), indr, is_ref) } else { - return type(base_type::_obj(make_binding(concat(ident))), indr, is_ref) + return type(base_type::_obj(make_ast_binding(concat(ident))), indr, is_ref) } } else if (func != null>()) { var param_types = vec<*type>() @@ -460,7 +461,7 @@ fun syntax_to_ast(file_name: str, syntax: *tree, import_paths: ref vec): *tree = fun(syntax: *tree): *tree { if (syntax->data.name == "import") { - return _import(make_binding(resolve_import_file(concat(syntax->children[1]) + ".krak")), from_vector(syntax->children.slice(2,-1).filter(fun(s:*tree):bool { + return _import(make_ast_binding(resolve_import_file(concat(syntax->children[1]) + ".krak")), from_vector(syntax->children.slice(2,-1).filter(fun(s:*tree):bool { return s->data.name == "identifier" || s->data.data == "*" }).map(concat)), vec(syntax_to_ast_helper(syntax->children[1]))) } else if (syntax->data.name == "function") { @@ -530,7 +531,7 @@ fun syntax_to_ast(file_name: str, syntax: *tree, import_paths: ref vecdata.name == "assignment_statement") - return _assignment(vec(make_binding(concat(syntax->children[1])), + return _assignment(vec(make_ast_binding(concat(syntax->children[1])), syntax_to_ast_helper(syntax->children[0]), syntax_to_ast_helper(syntax->children[2]))) else if (syntax->data.name == "function_call") @@ -556,16 +557,16 @@ fun syntax_to_ast(file_name: str, syntax: *tree, import_paths: ref vec>()) { if (syntax->children[0]->data.name != "scoped_identifier") error(syntax, "Unexpected template instantiation (not on an identifier)") - return make_binding(concat(syntax->children[0]) + "") + return make_ast_binding(concat(syntax->children[0]) + "") } else if (syntax->children[0]->data.terminal) { - return _call(vec(make_binding(concat(syntax->children[0])), + return _call(vec(make_ast_binding(concat(syntax->children[0])), syntax_to_ast_helper(syntax->children[1]))) } else { - return _call(vec(make_binding(concat(syntax->children[1])), + return _call(vec(make_ast_binding(concat(syntax->children[1])), syntax_to_ast_helper(syntax->children[0]))) } } else { - return _call(vec(make_binding(concat(syntax->children[1])), + return _call(vec(make_ast_binding(concat(syntax->children[1])), syntax_to_ast_helper(syntax->children[0]), syntax_to_ast_helper(syntax->children[2]))) } @@ -574,7 +575,7 @@ fun syntax_to_ast(file_name: str, syntax: *tree, import_paths: ref vecdata.name == "bool") return _value(concat(syntax), type(base_type::_bool(), 0, false)) else if (syntax->data.name == "scoped_identifier" || syntax->data.name == "identifier") - return make_binding(concat(syntax)) + return make_ast_binding(concat(syntax)) else { error(syntax, "Cannot transform") return null>() diff --git a/stdlib/ast.krak b/stdlib/ast.krak index 286253a..0960af1 100644 --- a/stdlib/ast.krak +++ b/stdlib/ast.krak @@ -10,7 +10,7 @@ adt ast { _translation_unit: str, _import: pair<*tree, set>, _identifier: pair, - _binding: triple, *tree>, + _binding: pair>>, _type_def: str, _adt_def: str, _function: triple, @@ -37,7 +37,7 @@ fun to_string(a: ref ast): str { ast::_translation_unit(b) return str("_translation_unit(") + b + ")" ast::_import(b) return str("_import(") + to_string(b.first->data) + ")[" + str(",").join(b.second.data) + "]" ast::_identifier(b) return str("_identifier(") + b.first + ": " + deref_to_string(b.second) + ")" - ast::_binding(b) return str("_binding(") + b.first + "->" + to_string(b.third) + ")" + ast::_binding(b) return str("_binding(") + b.first + "->" + to_string(b.second->bound_to) + ")" ast::_type_def(b) return str("_type_def(") + b + ")" ast::_adt_def(b) return str("_adt_def(") + b + ")" ast::_function(b) return str("_function(") + b.first + ": " + deref_to_string(b.second) + ", ext?:" + to_string(b.third) + ")" @@ -78,8 +78,8 @@ fun _cast(p: *type): *tree { fun _identifier(p1: str, p2: *type): *tree { return new>()->construct(ast::_identifier(make_pair(p1, p2))) } -fun _binding(p1: str, p2: vec<*type>, p3: *tree): *tree { - return new>()->construct(ast::_binding(make_triple(p1, p2, p3))) +fun _binding(p1: str, p2: *binding>): *tree { + return new>()->construct(ast::_binding(make_pair(p1, p2))) } fun _function(p1: str, p2: *type, p3: bool): *tree { return new>()->construct(ast::_function(make_triple(p1, p2, p3))) @@ -153,8 +153,8 @@ fun _cast(p: *type, c: ref vec<*tree>): *tree { fun _identifier(p1: str, p2: *type, c: ref vec<*tree>): *tree { return new>()->construct(ast::_identifier(make_pair(p1, p2)), c) } -fun _binding(p1: str, p2: vec<*type>, p3: *tree, c: ref vec<*tree>): *tree { - return new>()->construct(ast::_binding(make_triple(p1, p2, p3)), c) +fun _binding(p1: str, p2: *binding>, c: ref vec<*tree>): *tree { + return new>()->construct(ast::_binding(make_pair(p1, p2)), c) } fun _function(p1: str, p2: *type, p3: bool, c: ref vec<*tree>): *tree { return new>()->construct(ast::_function(make_triple(p1, p2, p3)), c) @@ -237,49 +237,78 @@ fun is_value(i: *tree): bool { match(i->data) { ast::_value(b) return true; fun is_top_level_item(i: *tree): bool { return i->parent != null>() && is_translation_unit(i->parent); } -var bindings: *vec<*tree> -fun make_binding(s: *char): *tree { - return make_binding(str(s)) + +var bindings: *vec<*void> + +fun binding(): *binding { + var to_ret = new>()->construct() + if (bindings == null>()) + bindings = new>()->construct() + bindings->add( (to_ret) cast *void ) + return to_ret } -fun make_binding(s: str): *tree { - var binding = _binding(s, vec<*type>(), null>()) - if (bindings == null>>()) - bindings = new>>()->construct() - bindings->add(binding) - return binding + +obj binding (Object) { + var bound_to: *T + fun construct(): *binding { + bound_to = null() + return this + } + fun copy_construct(old: *binding): void { + bound_to = old->bound_to + } + fun destruct() { + bound_to = null() + } + fun bound(): bool { + return bound_to != null() + } + fun set(to: *T) { + // don't set null, that will set all unbound ones + if (bound_to == null>()) { + bound_to = to + return + } + var from = bound_to + for (var i = 0; i < bindings->size; i++;) + if ( ((bindings->get(i)) cast *binding)->bound_to == from) + ((bindings->get(i)) cast *binding)->bound_to = to + } } -fun get_binding(binding: *tree): *tree { + + + + +fun make_ast_binding(s: *char): *tree { + return make_ast_binding(str(s)) +} +fun make_ast_binding(s: str): *tree { + return _binding(s, binding>()) +} +fun get_ast_binding(binding: *tree): *tree { match(binding->data) { ast::_binding(b) { - return b.third + return b.second->bound_to } } error("trying to get binding on not a binding") } -fun set_binding(binding: *tree, to: *tree) { +fun set_ast_binding(binding: *tree, to: *tree) { match(binding->data) { ast::_binding(b) { - var from = b.third - // don't set null, that will set all unbound ones - if (from == null>()) { - b.third = to - return - } - for (var i = 0; i < bindings->size; i++;) - if (bindings->get(i)->data._binding.third == from) - bindings->get(i)->data._binding.third = to + b.second->set(to) return } } error("trying to set binding on not a binding") } -fun bound(binding: *tree): bool { +fun ast_bound(binding: *tree): bool { match(binding->data) { - ast::_binding(b) return b.third != null>() + ast::_binding(b) return b.second->bound() } error("Trying to check bound for not a binding") } -fun binding_str(binding: *tree): str { +fun ast_binding_str(binding: *tree): str { match(binding->data) { ast::_binding(b) return b.first }