import tree:* import type2:* import vec:* import set:* import util:* import str:* import mem:* import binding:* adt ast { _translation_unit: str, _import: pair<*tree, set>, _identifier: pair>, _binding: triple>, *binding>>, _type_def: str, _adt_def: str, _function: triple, bool>, // needs to be a map that retains order _template: pair>>, _declaration, _block, _if, _match, _case, _while, _for, _return, _break, _continue, _defer, _call: bool, _compiler_intrinsic: triple, vec<*binding>>, _cast: *binding, _value: pair> } fun deref_to_string(in: *T): str if (in == mem::null()) return str("null") else return to_string(in) fun deref_to_string(in: *T, ts: fun(*T): str): str if (in == mem::null()) return str("null") else return ts(in) fun binding_deref_to_string(b: *binding): str { var pre = b->get_bound_to(binding_epoch::pre_ref()) var post = b->get_bound_to(binding_epoch::post_ref()) if pre == post { return deref_to_string(pre) } else { return "pre_ref:" + deref_to_string(pre) + "/post_ref:" + deref_to_string(post) } } fun binding_deref_to_string(b: *binding, ts: fun(*T): str): str { var pre = b->get_bound_to(binding_epoch::pre_ref()) var post = b->get_bound_to(binding_epoch::post_ref()) if pre == post { return deref_to_string(pre, ts) } else { return "pre_ref:" + deref_to_string(pre, ts) + "/post_ref:" + deref_to_string(post, ts) } } fun to_string(a: ref ast): str { match(a) { 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 + ": " + binding_deref_to_string(b.second) + ")" ast::_binding(b) return str("_binding(") + b.first + "[" + str(",").join(b.second.map(fun(x:*binding): str { return binding_deref_to_string(x); })) + "]" + "-> " + binding_deref_to_string(b.third, fun(t: *tree): str return to_string(t->data);) + ")" 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 + ": " + binding_deref_to_string(b.second) + ", ext?:" + to_string(b.third) + ")" ast::_template(b) return str("_template(") + b.first + "[" + str(",").join(b.second.keys) + "])" ast::_declaration() return str("_declaration") ast::_block() return str("_block") ast::_if() return str("_if") ast::_match() return str("_match") ast::_case() return str("_case") ast::_while() return str("_while") ast::_for() return str("_for") ast::_return() return str("_return") ast::_break() return str("_break") ast::_continue() return str("_continue") ast::_defer() return str("_defer") ast::_call(b) return "_call(add_scope: " + to_string(b) + ")" ast::_compiler_intrinsic(b) return str("_compiler_intrinsic(") + b.first + ": " + binding_deref_to_string(b.second) + ")" ast::_cast(b) return str("_cast") ast::_value(b) return str("_value(") + b.first + ": " + binding_deref_to_string(b.second) + ")" } } fun _translation_unit(p: str): *tree { return new>()->construct(ast::_translation_unit(p)) } fun _import(p1: *tree, p2: set): *tree { return new>()->construct(ast::_import(make_pair(p1,p2))) } fun _type_def(p: str): *tree { return new>()->construct(ast::_type_def(p)) } fun _adt_def(p: str): *tree { return new>()->construct(ast::_adt_def(p)) } fun _cast(p: *binding): *tree { return new>()->construct(ast::_cast(p)) } fun _identifier(p1: str, p2: *binding): *tree { return new>()->construct(ast::_identifier(make_pair(p1, p2))) } fun _binding(p1: str, p2: vec<*binding>, p3: *binding>): *tree { return new>()->construct(ast::_binding(make_triple(p1, p2, p3))) } fun _function(p1: str, p2: *binding, p3: bool): *tree { return new>()->construct(ast::_function(make_triple(p1, p2, p3))) } fun _template(p1: str, p2: map>): *tree { return new>()->construct(ast::_template(make_pair(p1, p2))) } fun _compiler_intrinsic(p1: str, p2: *binding, p3: vec<*binding>): *tree { return new>()->construct(ast::_compiler_intrinsic(make_triple(p1, p2, p3))) } fun _value(p1: str, p2: *binding): *tree { return new>()->construct(ast::_value(make_pair(p1, p2))) } fun _declaration(): *tree { return new>()->construct(ast::_declaration()) } fun _block(): *tree { return new>()->construct(ast::_block()) } fun _if(): *tree { return new>()->construct(ast::_if()) } fun _match(): *tree { return new>()->construct(ast::_match()) } fun _case(): *tree { return new>()->construct(ast::_case()) } fun _while(): *tree { return new>()->construct(ast::_while()) } fun _for(): *tree { return new>()->construct(ast::_for()) } fun _return(): *tree { return new>()->construct(ast::_return()) } fun _break(): *tree { return new>()->construct(ast::_break()) } fun _continue(): *tree { return new>()->construct(ast::_continue()) } fun _defer(): *tree { return new>()->construct(ast::_defer()) } fun _call(add_scope: bool): *tree { return new>()->construct(ast::_call(add_scope)) } fun _translation_unit(p: str, c: ref vec<*tree>): *tree { return new>()->construct(ast::_translation_unit(p), c) } fun _import(p1: *tree, p2: set, c: ref vec<*tree>): *tree { return new>()->construct(ast::_import(make_pair(p1,p2)), c) } fun _type_def(p: str, c: ref vec<*tree>): *tree { return new>()->construct(ast::_type_def(p), c) } fun _adt_def(p: str, c: ref vec<*tree>): *tree { return new>()->construct(ast::_adt_def(p), c) } fun _cast(p: *binding, c: ref vec<*tree>): *tree { return new>()->construct(ast::_cast(p), c) } fun _identifier(p1: str, p2: *binding, c: ref vec<*tree>): *tree { return new>()->construct(ast::_identifier(make_pair(p1, p2)), c) } fun _binding(p1: str, p2: vec<*binding>, p3: *binding>, c: ref vec<*tree>): *tree { return new>()->construct(ast::_binding(make_triple(p1, p2, p3)), c) } fun _function(p1: str, p2: *binding, p3: bool, c: ref vec<*tree>): *tree { return new>()->construct(ast::_function(make_triple(p1, p2, p3)), c) } fun _template(p1: str, p2: map>, c: ref vec<*tree>): *tree { return new>()->construct(ast::_template(make_pair(p1, p2)), c) } fun _compiler_intrinsic(p1: str, p2: *binding, p3: vec<*binding>, c: ref vec<*tree>): *tree { return new>()->construct(ast::_compiler_intrinsic(make_triple(p1, p2, p3)), c) } fun _value(p1: str, p2: *binding, c: ref vec<*tree>): *tree { return new>()->construct(ast::_value(make_pair(p1, p2)), c) } fun _declaration(c: ref vec<*tree>): *tree { return new>()->construct(ast::_declaration(), c) } fun _block(c: ref vec<*tree>): *tree { return new>()->construct(ast::_block(), c) } fun _if(c: ref vec<*tree>): *tree { return new>()->construct(ast::_if(), c) } fun _match(c: ref vec<*tree>): *tree { return new>()->construct(ast::_match(), c) } fun _case(c: ref vec<*tree>): *tree { return new>()->construct(ast::_case(), c) } fun _while(c: ref vec<*tree>): *tree { return new>()->construct(ast::_while(), c) } fun _for(c: ref vec<*tree>): *tree { return new>()->construct(ast::_for(), c) } fun _return(c: ref vec<*tree>): *tree { return new>()->construct(ast::_return(), c) } fun _defer(c: ref vec<*tree>): *tree { return new>()->construct(ast::_defer(), c) } fun _call(add_scope: bool, c: ref vec<*tree>): *tree { return new>()->construct(ast::_call(add_scope), c) } fun is_translation_unit(i: *tree): bool { match(i->data) { ast::_translation_unit(b) return true; } return false; } fun is_import(i: *tree): bool { match(i->data) { ast::_import(b) return true; } return false; } fun is_identifier(i: *tree): bool { match(i->data) { ast::_identifier(b) return true; } return false; } fun is_binding(i: *tree): bool { match(i->data) { ast::_binding(b) return true; } return false; } fun is_type_def(i: *tree): bool { match(i->data) { ast::_type_def(b) return true; } return false; } fun is_adt_def(i: *tree): bool { match(i->data) { ast::_adt_def(b) return true; } return false; } fun is_function(i: *tree): bool { match(i->data) { ast::_function(b) return true; } return false; } fun is_template(i: *tree): bool { match(i->data) { ast::_template(b) return true; } return false; } fun is_declaration(i: *tree): bool { match(i->data) { ast::_declaration() return true; } return false; } fun is_block(i: *tree): bool { match(i->data) { ast::_block() return true; } return false; } fun is_if(i: *tree): bool { match(i->data) { ast::_if() return true; } return false; } fun is_match(i: *tree): bool { match(i->data) { ast::_match() return true; } return false; } fun is_case(i: *tree): bool { match(i->data) { ast::_case() return true; } return false; } fun is_while(i: *tree): bool { match(i->data) { ast::_while() return true; } return false; } fun is_for(i: *tree): bool { match(i->data) { ast::_for() return true; } return false; } fun is_return(i: *tree): bool { match(i->data) { ast::_return() return true; } return false; } fun is_break(i: *tree): bool { match(i->data) { ast::_break() return true; } return false; } fun is_continue(i: *tree): bool { match(i->data) { ast::_continue() return true; } return false; } fun is_defer(i: *tree): bool { match(i->data) { ast::_defer() return true; } return false; } fun is_call(i: *tree): bool { match(i->data) { ast::_call(b) return true; } return false; } fun is_compiler_intrinsic(i: *tree): bool { match(i->data) { ast::_compiler_intrinsic(b) return true; } return false; } fun is_cast(i: *tree): bool { match(i->data) { ast::_cast(b) return true; } return false; } fun is_value(i: *tree): bool { match(i->data) { ast::_value(b) return true; } return false; } fun is_top_level_item(i: *tree): bool { return i->parent == null>() || is_translation_unit(i->parent); } fun get_ancestor_satisfying(t: *tree, p: fun(*tree): bool): *tree { t = t->parent while (t != null>() && !p(t)) t = t->parent return t } fun make_ast_binding(s: *char): *tree { return make_ast_binding(str(s)) } fun make_ast_binding(s: str): *tree { return make_ast_binding(s, vec<*binding>()) } fun make_ast_binding(s: str, v: vec<*binding>): *tree { return _binding(s, v, binding>()) } fun clone_ast_binding(binding: *tree): *tree { match(binding->data) { ast::_binding(b) { return _binding(b.first, b.second, b.third) } } error("trying to get binding on not a binding") } fun get_ast_binding_inst_types(binding: *tree): ref vec<*binding> { match(binding->data) { ast::_binding(b) { return b.second } } error("trying to get binding on not a binding") } fun get_ast_binding(binding: *tree, epoch: binding_epoch): *tree { match(binding->data) { ast::_binding(b) { return b.third->get_bound_to(epoch) } } error("trying to get binding on not a binding") } fun set_ast_binding(binding: *tree, to: *tree, epoch: binding_epoch) { match(binding->data) { ast::_binding(b) { b.third->set(to, epoch) return } } error("trying to set binding on not a binding") } fun set_single_ast_binding(binding: *tree, to: *tree, epoch: binding_epoch) { match(binding->data) { ast::_binding(b) { b.third->set_single(to, epoch) return } } error("trying to set binding on not a binding") } fun ast_bound(binding: *tree): bool { match(binding->data) { ast::_binding(b) return b.third->bound() } error("Trying to check bound for not a binding") } fun ast_binding_str(binding: *tree): str { match(binding->data) { ast::_binding(b) return b.first } error("Trying to get name for not a binding") }