Big changes to k - now all passes are top-level-item focused, does dead simple scope lookup. Added an error message when trying to match on not an ADT
This commit is contained in:
264
k.krak
264
k.krak
@@ -87,32 +87,95 @@ fun main(argc: int, argv: **char): int {
|
||||
var name_ast_map = map<str, *tree<ast>>()
|
||||
var passes = map<str, fun(*tree<ast>): void>()
|
||||
|
||||
// resolves all reachable imports
|
||||
passes[str("import")] = fun(import_binding: *tree<ast>) {
|
||||
var file_path = binding_str(import_binding)
|
||||
println("Running import resolver for " + file_path)
|
||||
if (!name_ast_map.contains_key(file_path)) {
|
||||
printerr(file_path + ", ")
|
||||
var parse_tree = parse.parse_input(read_file(file_path), file_path)
|
||||
trim(parse_tree)
|
||||
name_ast_map[file_path] = syntax_to_ast(file_path, parse_tree, import_paths)
|
||||
}
|
||||
set_bindings(import_binding, name_ast_map[file_path])
|
||||
|
||||
name_ast_map[file_path]->children.for_each(fun(n: *tree<ast>) {
|
||||
match (n->data) {
|
||||
ast::_import(b) {
|
||||
pass_poset.add_close_dep(make_pair(import_binding, str("import")), make_pair(b.first, str("import")))
|
||||
// resolves all binding possibilities for one top level item
|
||||
passes[str("name_possibility_resolve")] = fun(item: *tree<ast>) {
|
||||
println("Running name possibility resolver?")
|
||||
var scope_lookup: fun(*tree<ast>, str, bool): vec<*tree<ast>> = fun(scope: *tree<ast>, name: str, is_type: bool): vec<*tree<ast>> {
|
||||
var to_ret = vec<*tree<ast>>()
|
||||
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) {
|
||||
// Import / parse file if not already
|
||||
var file_path = 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)
|
||||
trim(parse_tree)
|
||||
name_ast_map[file_path] = syntax_to_ast(file_path, parse_tree, import_paths)
|
||||
}
|
||||
set_binding(b.first, name_ast_map[file_path])
|
||||
}
|
||||
to_ret += scope_lookup(get_binding(b.first), name, is_type)
|
||||
}
|
||||
ast::_type_def(b) if (is_type && b == name)
|
||||
to_ret += scope->children[i]
|
||||
ast::_adt_def(b) if (is_type && b == name)
|
||||
to_ret += scope->children[i]
|
||||
ast::_function(b) if (!is_type && b.first == name)
|
||||
to_ret += scope->children[i]
|
||||
ast::_template(b) if (!is_type && b.first == name)
|
||||
to_ret += scope->children[i]
|
||||
ast::_identifier(b) if (!is_type && b.first == name)
|
||||
to_ret += scope->children[i]
|
||||
ast::_declaration() if (!is_type && scope->children[i]->children[0]->data._identifier.first == name)
|
||||
to_ret += scope->children[i]->children[0]
|
||||
}
|
||||
}
|
||||
})
|
||||
if (scope->parent != null<tree<ast>>())
|
||||
return to_ret + scope_lookup(scope->parent, name, is_type)
|
||||
return to_ret
|
||||
}
|
||||
var try_binding = fun(binding: *tree<ast>, start_scope: *tree<ast>, type_binding: bool) {
|
||||
if !bound(binding) {
|
||||
var options = scope_lookup(start_scope, binding->data._binding.first, type_binding)
|
||||
if (options.size != 1)
|
||||
error("Do not have exactly one option for scope lookup of " + binding->data._binding.first)
|
||||
set_binding(binding, options[0])
|
||||
}
|
||||
}
|
||||
var handle_type: fun(*type, *tree<ast>): void = fun(t: *type, n: *tree<ast>) {
|
||||
match(t->base) {
|
||||
base_type::_obj(b) try_binding(b, n, true)
|
||||
base_type::_fun(b) {
|
||||
b.first.first.for_each(fun(it: *type) {
|
||||
handle_type(it, n)
|
||||
})
|
||||
handle_type(b.first.second, n)
|
||||
}
|
||||
}
|
||||
}
|
||||
var traverse_for_bindings: fun(*tree<ast>): void = fun(t: *tree<ast>) {
|
||||
match (t->data) {
|
||||
// TODO: Handle type binding lookup
|
||||
ast::_identifier(b) handle_type(b.second, t)
|
||||
/*_binding: triple<str, vec<*type>, *tree<ast>>,*/
|
||||
ast::_function(b) handle_type(b.second, t)
|
||||
ast::_compiler_intrinsic(b) b.second.for_each(fun(ty: *type) {
|
||||
handle_type(ty, t)
|
||||
})
|
||||
ast::_cast(b) handle_type(b, t)
|
||||
/*_value: pair<str, *type>*/
|
||||
ast::_binding(b) try_binding(t, t, false)
|
||||
}
|
||||
t->children.for_each(traverse_for_bindings)
|
||||
}
|
||||
traverse_for_bindings(item)
|
||||
}
|
||||
|
||||
// resolves all binding possibilities for one top level item
|
||||
passes[str("name_type_resolve")] = fun(item: *tree<ast>) {
|
||||
println("Running name type resolver?")
|
||||
// just temp
|
||||
pass_poset.add_close_dep(make_pair(item, str("name_type_resolve")), make_pair(item, str("name_possibility_resolve")))
|
||||
}
|
||||
|
||||
// emit C
|
||||
var C_str = str()
|
||||
passes[str("emit_C")] = fun(import_binding: *tree<ast>) {
|
||||
if !pass_poset.done(make_pair(import_binding, str("import"))) {
|
||||
pass_poset.add_open_dep(make_pair(import_binding, str("emit_C")), make_pair(import_binding, str("import")))
|
||||
var C_func_declaration_str = str()
|
||||
passes[str("emit_C")] = fun(item: *tree<ast>) {
|
||||
if !pass_poset.done(make_pair(item, str("name_type_resolve"))) {
|
||||
pass_poset.add_open_dep(make_pair(item, str("emit_C")), make_pair(item, str("name_type_resolve")))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -122,25 +185,34 @@ fun main(argc: int, argv: **char): int {
|
||||
error("type is ref in to_c_type")
|
||||
match(t->base) {
|
||||
base_type::_unknown() error("unknown in to_c_type")
|
||||
base_type::_void() return "void" + ind
|
||||
base_type::_void() return "void" + ind
|
||||
base_type::_obj(b) error("ob in to_c_type unimplemented")
|
||||
base_type::_fun(b) error("fun in to_c_type unimplemented")
|
||||
base_type::_template_placeholder() error("template_placeholder in to_c_type")
|
||||
base_type::_bool() return "bool" + ind
|
||||
base_type::_char() return "char" + ind
|
||||
base_type::_uchar() return "usigned char" + ind
|
||||
base_type::_short() return "short" + ind
|
||||
base_type::_ushort() return "unsigned short" + ind
|
||||
base_type::_int() return "int" + ind
|
||||
base_type::_uint() return "unsigned int" + ind
|
||||
base_type::_long() return "long" + ind
|
||||
base_type::_ulong() return "unsigned long" + ind
|
||||
base_type::_float() return "float" + ind
|
||||
base_type::_double() return "double" + ind
|
||||
base_type::_bool() return "bool" + ind
|
||||
base_type::_char() return "char" + ind
|
||||
base_type::_uchar() return "usigned char" + ind
|
||||
base_type::_short() return "short" + ind
|
||||
base_type::_ushort() return "unsigned short" + ind
|
||||
base_type::_int() return "int" + ind
|
||||
base_type::_uint() return "unsigned int" + ind
|
||||
base_type::_long() return "long" + ind
|
||||
base_type::_ulong() return "unsigned long" + ind
|
||||
base_type::_float() return "float" + ind
|
||||
base_type::_double() return "double" + ind
|
||||
}
|
||||
error("fell through to_c_type")
|
||||
}
|
||||
|
||||
var emit_name = fun(x: *tree<ast>): void {
|
||||
match(x->data) {
|
||||
ast::_identifier(b) { C_str += b.first; return; }
|
||||
ast::_type_def(b) { C_str += b; return; }
|
||||
ast::_function(b) { C_str += b.first; return; }
|
||||
}
|
||||
error("cannot emit_name of thing: " + to_string(x->data))
|
||||
}
|
||||
|
||||
var emit_C: fun(*tree<ast>, int): void = fun(t: *tree<ast>, level: int) {
|
||||
var idt = str("\t") * level
|
||||
match (t->data) {
|
||||
@@ -150,41 +222,60 @@ fun main(argc: int, argv: **char): int {
|
||||
C_str += ";\n"
|
||||
})
|
||||
}
|
||||
ast::_import(b) {
|
||||
pass_poset.add_close_dep(make_pair(import_binding, str("emit_C")), make_pair(b.first, str("emit_C")))
|
||||
}
|
||||
ast::_import(b) { }
|
||||
ast::_identifier(b) { C_str += idt + b.first; }
|
||||
ast::_binding(b) { error("binding gen unimplemented"); }
|
||||
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")))
|
||||
emit_name(b.third)
|
||||
}
|
||||
ast::_type_def(b) { error("type_def gen unimplemented"); }
|
||||
ast::_adt_def(b) { error("no adt_def should remain at C emit"); }
|
||||
ast::_function(b) {
|
||||
var fun_name = b.first
|
||||
var fun_type = b.second
|
||||
var is_ext = b.third
|
||||
var return_type = fun_type->base._fun.first.second
|
||||
var parameter_types = fun_type->base._fun.first.first
|
||||
var is_variadic = fun_type->base._fun.second
|
||||
var is_raw = fun_type->base._fun.third
|
||||
C_str += to_c_type(return_type) + " " + fun_name + " ("
|
||||
// TODO check is_ext for name mangling
|
||||
C_str += to_c_type(return_type) + " " + fun_name + "("
|
||||
C_func_declaration_str += to_c_type(return_type) + " " + fun_name + "("
|
||||
for (var i = 0; i < parameter_types.size; i++;) {
|
||||
if (i != 0)
|
||||
C_str += ", "
|
||||
C_str += to_c_type(parameter_types[i]) + " "
|
||||
if (i != 0) {
|
||||
C_str += ", "
|
||||
C_func_declaration_str += ", "
|
||||
}
|
||||
C_str += to_c_type(parameter_types[i]) + " "
|
||||
C_func_declaration_str += to_c_type(parameter_types[i])
|
||||
emit_C(t->children[i], 0)
|
||||
}
|
||||
if (is_variadic) {
|
||||
if (parameter_types.size != 0)
|
||||
if (parameter_types.size != 0) {
|
||||
C_str += ", "
|
||||
C_str += "..."
|
||||
C_func_declaration_str += ", "
|
||||
}
|
||||
C_str += "..."
|
||||
C_func_declaration_str += "..."
|
||||
}
|
||||
C_str += ") {\n"
|
||||
C_str += ") {\n"
|
||||
C_func_declaration_str += ");\n"
|
||||
for (var i = parameter_types.size; i < t->children.size; i++;) {
|
||||
emit_C(t->children[i], level+1)
|
||||
C_str += ";\n"
|
||||
}
|
||||
C_str += "}"
|
||||
C_str += "}\n"
|
||||
}
|
||||
ast::_template(b) { /* template should be ignored */ }
|
||||
ast::_declaration() { error("declaration gen unimplemented"); }
|
||||
ast::_declaration() {
|
||||
C_str += idt + to_c_type(t->children[0]->data._identifier.second) + " "
|
||||
emit_name(t->children[0])
|
||||
if (t->children.size > 1) {
|
||||
C_str += " = "
|
||||
emit_C(t->children[1], 0)
|
||||
}
|
||||
}
|
||||
ast::_assignment() { error("assignment gen unimplemented"); }
|
||||
ast::_block() {
|
||||
C_str += idt + "{\n"
|
||||
@@ -192,7 +283,7 @@ fun main(argc: int, argv: **char): int {
|
||||
emit_C(c, level+1)
|
||||
C_str += ";\n"
|
||||
})
|
||||
C_str += idt + "}\n"
|
||||
C_str += idt + "}"
|
||||
}
|
||||
ast::_if() { error("if gen unimplemented"); }
|
||||
ast::_match() { error("no match should remain at C emit"); }
|
||||
@@ -209,25 +300,54 @@ fun main(argc: int, argv: **char): int {
|
||||
ast::_break() { C_str += idt + "break"; }
|
||||
ast::_continue() { C_str += idt + "continue"; }
|
||||
ast::_defer() { error("no defer should remain at C emit"); }
|
||||
ast::_call() { error("call gen unimplemented"); }
|
||||
ast::_call() {
|
||||
emit_C(t->children[0], level)
|
||||
C_str += "("
|
||||
for (var i = 1; i < t->children.size; i++;) {
|
||||
if (i != 1)
|
||||
C_str += ", "
|
||||
emit_C(t->children[1], level+1)
|
||||
}
|
||||
C_str += ")"
|
||||
}
|
||||
ast::_compiler_intrinsic(b) { error("compiler_intrinsic gen unimplemented"); }
|
||||
ast::_cast(b) { error("cast gen unimplemented"); }
|
||||
ast::_value(b) { C_str += idt + b.first; }
|
||||
}
|
||||
}
|
||||
|
||||
var file_path = binding_str(import_binding)
|
||||
println("Running emit C for " + file_path)
|
||||
emit_C(name_ast_map[file_path], 0)
|
||||
emit_C(item, 0)
|
||||
}
|
||||
|
||||
var top_binding = make_binding(kraken_file_name)
|
||||
pass_poset.add_job(make_pair(top_binding, str("emit_C")))
|
||||
// We construct our real main entry function and add an emit_C pass for it,
|
||||
// starting generation of the entire program
|
||||
var real_main = _function(
|
||||
str("main"),
|
||||
type(base_type::_fun(make_triple(make_pair(vec(
|
||||
type(base_type::_int(), 0, false),
|
||||
type(base_type::_char(), 2, false)
|
||||
),
|
||||
type(base_type::_int(), 0, false)
|
||||
), false, false)), 0, false),
|
||||
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")))))
|
||||
)
|
||||
)
|
||||
var top_unit = _translation_unit(str(), vec(
|
||||
_import(make_binding(kraken_file_name), set(str("*")), vec(
|
||||
_identifier(kraken_file_name, type(base_type::_void(), 0, false))
|
||||
)),
|
||||
real_main
|
||||
))
|
||||
pass_poset.add_job(make_pair(real_main, str("emit_C")))
|
||||
|
||||
pass_poset.run(fun(file_pass: pair<*tree<ast>, str>) {
|
||||
printlnerr("doing pass new style " + file_pass.second + " on " + to_string(file_pass.first->data))
|
||||
passes[file_pass.second](file_pass.first)
|
||||
})
|
||||
C_str = C_func_declaration_str + "\n" + C_str
|
||||
|
||||
println()
|
||||
println()
|
||||
@@ -252,44 +372,6 @@ fun main(argc: int, argv: **char): int {
|
||||
return 0
|
||||
}
|
||||
|
||||
var bindings: *vec<*tree<ast>>
|
||||
fun make_binding(s: str): *tree<ast> {
|
||||
var binding = _binding(s, vec<*type>(), null<tree<ast>>())
|
||||
if (bindings == null<vec<*tree<ast>>>())
|
||||
bindings = new<vec<*tree<ast>>>()->construct()
|
||||
bindings->add(binding)
|
||||
return binding
|
||||
}
|
||||
fun set_bindings(binding: *tree<ast>, to: *tree<ast>) {
|
||||
match(binding->data) {
|
||||
ast::_binding(b) {
|
||||
var from = b.third
|
||||
// don't set null, that will set all unbound ones
|
||||
if (from == null<tree<ast>>()) {
|
||||
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
|
||||
return
|
||||
}
|
||||
}
|
||||
error("trying to set bindings on not a binding")
|
||||
}
|
||||
fun bound(binding: *tree<ast>): bool {
|
||||
match(binding->data) {
|
||||
ast::_binding(b) return b.third != null<tree<ast>>()
|
||||
}
|
||||
error("Trying to check bound for not a binding")
|
||||
}
|
||||
fun binding_str(binding: *tree<ast>): str {
|
||||
match(binding->data) {
|
||||
ast::_binding(b) return b.first
|
||||
}
|
||||
error("Trying to get name for not a binding")
|
||||
}
|
||||
|
||||
fun parse_type(syntax: *tree<symbol>): *type {
|
||||
var is_ref = get_node("\"ref\"", syntax) != null<tree<symbol>>()
|
||||
var indr = 0
|
||||
@@ -373,7 +455,7 @@ fun syntax_to_ast(file_name: str, syntax: *tree<symbol>, import_paths: ref vec<s
|
||||
else
|
||||
return_type = type(base_type::_void(), 0, false)
|
||||
var function_type = type(base_type::_fun(make_triple(make_pair(parameters.map(fun(i: *tree<ast>): *type return i->data._identifier.second;), return_type), false, false)), 0, false)
|
||||
var n = _function(concat(get_node("func_identifier", syntax)), function_type, parameters + body)
|
||||
var n = _function(concat(get_node("func_identifier", syntax)), function_type, false, parameters + body)
|
||||
var template = get_node("template_dec", syntax)
|
||||
if (template == null<tree<symbol>>()) {
|
||||
return n
|
||||
|
||||
@@ -151,6 +151,8 @@ fun adt_lower(name_ast_map: *map<str, pair<*tree<symbol>,*ast_node>>, ast_to_syn
|
||||
block->code_block.children.add(_assign(holder, make_operator_call("&", vec(value))))
|
||||
backing.cases.for_each(fun(case_stmt: *ast_node) {
|
||||
var option = case_stmt->case_statement.option
|
||||
if (!get_ast_scope(get_ast_type(value)->type_def)->contains_key(str("flag")))
|
||||
error("trying to get flag from struct without it - are you matching on not an adt? - ")
|
||||
var flag = get_from_scope(get_ast_type(value)->type_def, "flag")
|
||||
var data = get_from_scope(get_ast_type(value)->type_def, "data")
|
||||
var option_num = -7
|
||||
|
||||
@@ -13,7 +13,7 @@ adt ast {
|
||||
_binding: triple<str, vec<*type>, *tree<ast>>,
|
||||
_type_def: str,
|
||||
_adt_def: str,
|
||||
_function: pair<str, *type>,
|
||||
_function: triple<str, *type, bool>,
|
||||
_template: pair<str, set<str>>,
|
||||
_declaration,
|
||||
_assignment,
|
||||
@@ -40,7 +40,7 @@ fun to_string(a: ref ast): str {
|
||||
ast::_binding(b) return str("_binding(") + b.first + "->" + to_string(b.third) + ")"
|
||||
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) + ")"
|
||||
ast::_function(b) return str("_function(") + b.first + ": " + deref_to_string(b.second) + ", ext?:" + to_string(b.third) + ")"
|
||||
ast::_template(b) return str("_template(") + b.first + "[" + str(",").join(b.second.data) + "])"
|
||||
ast::_declaration() return str("_declaration")
|
||||
ast::_assignment() return str("_assignment")
|
||||
@@ -81,8 +81,8 @@ fun _identifier(p1: str, p2: *type): *tree<ast> {
|
||||
fun _binding(p1: str, p2: vec<*type>, p3: *tree<ast>): *tree<ast> {
|
||||
return new<tree<ast>>()->construct(ast::_binding(make_triple(p1, p2, p3)))
|
||||
}
|
||||
fun _function(p1: str, p2: *type): *tree<ast> {
|
||||
return new<tree<ast>>()->construct(ast::_function(make_pair(p1, p2)))
|
||||
fun _function(p1: str, p2: *type, p3: bool): *tree<ast> {
|
||||
return new<tree<ast>>()->construct(ast::_function(make_triple(p1, p2, p3)))
|
||||
}
|
||||
fun _template(p1: str, p2: set<str>): *tree<ast> {
|
||||
return new<tree<ast>>()->construct(ast::_template(make_pair(p1, p2)))
|
||||
@@ -156,8 +156,8 @@ fun _identifier(p1: str, p2: *type, c: ref vec<*tree<ast>>): *tree<ast> {
|
||||
fun _binding(p1: str, p2: vec<*type>, p3: *tree<ast>, c: ref vec<*tree<ast>>): *tree<ast> {
|
||||
return new<tree<ast>>()->construct(ast::_binding(make_triple(p1, p2, p3)), c)
|
||||
}
|
||||
fun _function(p1: str, p2: *type, c: ref vec<*tree<ast>>): *tree<ast> {
|
||||
return new<tree<ast>>()->construct(ast::_function(make_pair(p1, p2)), c)
|
||||
fun _function(p1: str, p2: *type, p3: bool, c: ref vec<*tree<ast>>): *tree<ast> {
|
||||
return new<tree<ast>>()->construct(ast::_function(make_triple(p1, p2, p3)), c)
|
||||
}
|
||||
fun _template(p1: str, p2: set<str>, c: ref vec<*tree<ast>>): *tree<ast> {
|
||||
return new<tree<ast>>()->construct(ast::_template(make_pair(p1, p2)), c)
|
||||
@@ -207,3 +207,81 @@ fun _defer(c: ref vec<*tree<ast>>): *tree<ast> {
|
||||
fun _call(c: ref vec<*tree<ast>>): *tree<ast> {
|
||||
return new<tree<ast>>()->construct(ast::_call(), c)
|
||||
}
|
||||
|
||||
|
||||
|
||||
fun is_translation_unit(i: *tree<ast>): bool { match(i->data) { ast::_translation_unit(b) return true; } return false; }
|
||||
fun is_import(i: *tree<ast>): bool { match(i->data) { ast::_import(b) return true; } return false; }
|
||||
fun is_identifier(i: *tree<ast>): bool { match(i->data) { ast::_identifier(b) return true; } return false; }
|
||||
fun is_binding(i: *tree<ast>): bool { match(i->data) { ast::_binding(b) return true; } return false; }
|
||||
fun is_type_def(i: *tree<ast>): bool { match(i->data) { ast::_type_def(b) return true; } return false; }
|
||||
fun is_adt_def(i: *tree<ast>): bool { match(i->data) { ast::_adt_def(b) return true; } return false; }
|
||||
fun is_function(i: *tree<ast>): bool { match(i->data) { ast::_function(b) return true; } return false; }
|
||||
fun is_template(i: *tree<ast>): bool { match(i->data) { ast::_template(b) return true; } return false; }
|
||||
fun is_declaration(i: *tree<ast>): bool { match(i->data) { ast::_declaration() return true; } return false; }
|
||||
fun is_assignment(i: *tree<ast>): bool { match(i->data) { ast::_assignment() return true; } return false; }
|
||||
fun is_block(i: *tree<ast>): bool { match(i->data) { ast::_block() return true; } return false; }
|
||||
fun is_if(i: *tree<ast>): bool { match(i->data) { ast::_if() return true; } return false; }
|
||||
fun is_match(i: *tree<ast>): bool { match(i->data) { ast::_match() return true; } return false; }
|
||||
fun is_case(i: *tree<ast>): bool { match(i->data) { ast::_case() return true; } return false; }
|
||||
fun is_while(i: *tree<ast>): bool { match(i->data) { ast::_while() return true; } return false; }
|
||||
fun is_for(i: *tree<ast>): bool { match(i->data) { ast::_for() return true; } return false; }
|
||||
fun is_return(i: *tree<ast>): bool { match(i->data) { ast::_return() return true; } return false; }
|
||||
fun is_break(i: *tree<ast>): bool { match(i->data) { ast::_break() return true; } return false; }
|
||||
fun is_continue(i: *tree<ast>): bool { match(i->data) { ast::_continue() return true; } return false; }
|
||||
fun is_defer(i: *tree<ast>): bool { match(i->data) { ast::_defer() return true; } return false; }
|
||||
fun is_call(i: *tree<ast>): bool { match(i->data) { ast::_call() return true; } return false; }
|
||||
fun is_compiler_intrinsic(i: *tree<ast>): bool { match(i->data) { ast::_compiler_intrinsic(b) return true; } return false; }
|
||||
fun is_cast(i: *tree<ast>): bool { match(i->data) { ast::_cast(b) return true; } return false; }
|
||||
fun is_value(i: *tree<ast>): bool { match(i->data) { ast::_value(b) return true; } return false; }
|
||||
|
||||
fun is_top_level_item(i: *tree<ast>): bool { return i->parent != null<tree<ast>>() && is_translation_unit(i->parent); }
|
||||
|
||||
var bindings: *vec<*tree<ast>>
|
||||
fun make_binding(s: *char): *tree<ast> {
|
||||
return make_binding(str(s))
|
||||
}
|
||||
fun make_binding(s: str): *tree<ast> {
|
||||
var binding = _binding(s, vec<*type>(), null<tree<ast>>())
|
||||
if (bindings == null<vec<*tree<ast>>>())
|
||||
bindings = new<vec<*tree<ast>>>()->construct()
|
||||
bindings->add(binding)
|
||||
return binding
|
||||
}
|
||||
fun get_binding(binding: *tree<ast>): *tree<ast> {
|
||||
match(binding->data) {
|
||||
ast::_binding(b) {
|
||||
return b.third
|
||||
}
|
||||
}
|
||||
error("trying to get binding on not a binding")
|
||||
}
|
||||
fun set_binding(binding: *tree<ast>, to: *tree<ast>) {
|
||||
match(binding->data) {
|
||||
ast::_binding(b) {
|
||||
var from = b.third
|
||||
// don't set null, that will set all unbound ones
|
||||
if (from == null<tree<ast>>()) {
|
||||
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
|
||||
return
|
||||
}
|
||||
}
|
||||
error("trying to set binding on not a binding")
|
||||
}
|
||||
fun bound(binding: *tree<ast>): bool {
|
||||
match(binding->data) {
|
||||
ast::_binding(b) return b.third != null<tree<ast>>()
|
||||
}
|
||||
error("Trying to check bound for not a binding")
|
||||
}
|
||||
fun binding_str(binding: *tree<ast>): str {
|
||||
match(binding->data) {
|
||||
ast::_binding(b) return b.first
|
||||
}
|
||||
error("Trying to get name for not a binding")
|
||||
}
|
||||
|
||||
@@ -3,21 +3,28 @@ import vec
|
||||
|
||||
obj tree<T> (Object) {
|
||||
var data: T
|
||||
var parent: *tree<T>
|
||||
var children: vec::vec<*tree<T>>
|
||||
fun construct(dataIn: T): *tree<T> {
|
||||
mem::maybe_copy_construct(&data, &dataIn)
|
||||
parent = mem::null<tree<T>>()
|
||||
children.construct()
|
||||
return this
|
||||
}
|
||||
fun construct(dataIn: T, c: ref vec::vec<*tree<T>>): *tree<T> {
|
||||
mem::maybe_copy_construct(&data, &dataIn)
|
||||
parent = mem::null<tree<T>>()
|
||||
children.copy_construct(&c)
|
||||
children.for_each(fun(i: *tree<T>) {
|
||||
i->parent = this
|
||||
})
|
||||
return this
|
||||
}
|
||||
// Some of these don't really make much sense considering this tree is all about
|
||||
// heap allocated pointers. Best to have it for saftey, though
|
||||
fun copy_construct(old: *tree<T>) {
|
||||
mem::maybe_copy_construct(&data, &old->data)
|
||||
parent = old->parent
|
||||
children.copy_construct(&old->children)
|
||||
}
|
||||
// ditto
|
||||
|
||||
Reference in New Issue
Block a user