Add struct access! Uses new translation_unit_generative pass depended on by scope lookups to generate compiler_intrinsics that access members of structs'

This commit is contained in:
Nathan Braswell
2018-10-27 18:00:26 -04:00
parent db3004329d
commit 8177bc7fd0
3 changed files with 99 additions and 31 deletions

125
k.krak
View File

@@ -16,6 +16,11 @@ import tree:*
import symbol:* import symbol:*
import binding:* import binding:*
adt OptionVecAst {
Some: vec<*tree<ast>>,
None
}
fun main(argc: int, argv: **char): int { fun main(argc: int, argv: **char): int {
// delay construction until we either load it or copy construct it // delay construction until we either load it or copy construct it
var gram: grammer var gram: grammer
@@ -190,10 +195,40 @@ fun main(argc: int, argv: **char): int {
), false, false))), vec<*binding<type>>())))) ), false, false))), vec<*binding<type>>()))))
} }
passes[str("translation_unit_generative")] = fun(item: *tree<ast>) {
println("Running translation_unit_generative")
if !is_translation_unit(item) {
error("Running translation_unit_generative on not a translation unit");
}
for (var i = 0; i < item->children.size; i++;) {
var child = item->children[i]
if is_type_def(child)
match (child->data) {
ast::_type_def(name) {
println("Found a type_def! - " + name)
for (var j = 0; j < child->children.size; j++;) {
var grandchild = child->children[j];
if is_declaration(grandchild) {
var ident = grandchild->children[0]
var type_def_binding = make_ast_binding(name)
set_ast_binding(type_def_binding, child)
item->add_child(_compiler_intrinsic(ident->data._identifier.first, binding_p(type::_fun(make_triple(make_pair(vec(
binding_p(type::_obj(type_def_binding))
),
ident->data._identifier.second
), false, false))), vec<*binding<type>>()))
println("adding compiler intrinsic to do " + name + "." + ident->data._identifier.first)
}
}
}
}
}
}
// resolves all binding possibilities for one top level item // resolves all binding possibilities for one top level item
passes[str("name_possibility_resolve")] = fun(item: *tree<ast>) { passes[str("name_possibility_resolve")] = fun(item: *tree<ast>) {
println("Running name possibility resolver?") 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 scope_lookup: fun(*tree<ast>, str, bool): OptionVecAst = fun(scope: *tree<ast>, name: str, is_type: bool): OptionVecAst {
var to_ret = vec<*tree<ast>>() var to_ret = vec<*tree<ast>>()
for (var i = 0; i < scope->children.size; i++;) { for (var i = 0; i < scope->children.size; i++;) {
match(scope->children[i]->data) { match(scope->children[i]->data) {
@@ -211,37 +246,57 @@ fun main(argc: int, argv: **char): int {
} }
set_ast_binding(b.first, name_ast_map[file_path]) set_ast_binding(b.first, name_ast_map[file_path])
} }
to_ret += scope_lookup(get_ast_binding(b.first), name, is_type) var other_top_level = get_ast_binding(b.first)
if !pass_poset.done(make_pair(other_top_level, str("translation_unit_generative"))) {
pass_poset.add_open_dep(make_pair(item, str("name_possibility_resolve")), make_pair(other_top_level, str("translation_unit_generative")))
return OptionVecAst::None()
}
match (scope_lookup(other_top_level, name, is_type)) {
OptionVecAst::None() return OptionVecAst::None()
OptionVecAst::Some(v) {
to_ret += v
}
}
} }
ast::_type_def(b) if (is_type && b == name) ast::_type_def(b) if (is_type && b == name)
to_ret += scope->children[i] to_ret += scope->children[i]
ast::_adt_def(b) if (is_type && b == name) ast::_adt_def(b) if (is_type && b == name)
to_ret += scope->children[i] to_ret += scope->children[i]
ast::_function(b) if (!is_type && b.first == name) ast::_function(b) if (!is_type && b.first == name)
to_ret += scope->children[i] to_ret += scope->children[i]
ast::_template(b) if (!is_type && b.first == name) ast::_compiler_intrinsic(b) if (!is_type && b.first == name)
to_ret += scope->children[i] to_ret += scope->children[i]
ast::_identifier(b) if (!is_type && b.first == name) ast::_template(b) if (!is_type && b.first == name)
to_ret += scope->children[i] to_ret += scope->children[i]
ast::_declaration() if (!is_type && scope->children[i]->children[0]->data._identifier.first == name) ast::_identifier(b) if (!is_type && b.first == name)
to_ret += scope->children[i]->children[0] 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>>()) {
match (scope_lookup(scope->parent, name, is_type)) {
OptionVecAst::None() return OptionVecAst::None()
OptionVecAst::Some(v) return OptionVecAst::Some(to_ret + v)
} }
} }
if (scope->parent != null<tree<ast>>())
return to_ret + scope_lookup(scope->parent, name, is_type)
else if (primitive_ops.contains_key(name)) else if (primitive_ops.contains_key(name))
to_ret += primitive_ops[name] to_ret += primitive_ops[name]
return to_ret return OptionVecAst::Some(to_ret)
} }
var try_binding = fun(binding: *tree<ast>, start_scope: *tree<ast>, type_binding: bool) { var try_binding = fun(binding: *tree<ast>, start_scope: *tree<ast>, type_binding: bool) {
if !ast_bound(binding) { if !ast_bound(binding) && !multiple_binding_options.contains_key(binding) {
var options = scope_lookup(start_scope, ast_binding_str(binding), type_binding) match (scope_lookup(start_scope, ast_binding_str(binding), type_binding)) {
if (options.size == 0) OptionVecAst::None() return;
error("Could not find any options for scope lookup of " + ast_binding_str(binding)) OptionVecAst::Some(options) {
else if (options.size == 1) if (options.size == 0)
set_ast_binding(binding, options[0]) error("Could not find any options for scope lookup of " + ast_binding_str(binding))
else else if (options.size == 1)
multiple_binding_options[binding] = options set_ast_binding(binding, options[0])
else
multiple_binding_options[binding] = options
}
}
} }
} }
var handle_type: fun(*binding<type>, *tree<ast>): void = fun(t: *binding<type>, n: *tree<ast>) { var handle_type: fun(*binding<type>, *tree<ast>): void = fun(t: *binding<type>, n: *tree<ast>) {
@@ -761,9 +816,16 @@ fun main(argc: int, argv: **char): int {
ast::_call() { ast::_call() {
if (is_compiler_intrinsic(get_ast_binding(t->children[0]))) { if (is_compiler_intrinsic(get_ast_binding(t->children[0]))) {
if (t->children.size == 2) { if (t->children.size == 2) {
C_str += idt + "(" + get_ast_binding(t->children[0])->data._compiler_intrinsic.first + "(" var intrinsic_name = get_ast_binding(t->children[0])->data._compiler_intrinsic.first
emit_C(t->children[1], 0) if (intrinsic_name == "&" || intrinsic_name == "*") {
C_str += "))" C_str += idt + "(" + intrinsic_name + "("
emit_C(t->children[1], 0)
C_str += "))"
} else {
C_str += "("
emit_C(t->children[1], 0)
C_str += ")." + intrinsic_name
}
} else if (t->children.size == 3) { } else if (t->children.size == 3) {
C_str += idt + "((" C_str += idt + "(("
emit_C(t->children[1], 0) emit_C(t->children[1], 0)
@@ -1036,8 +1098,7 @@ fun syntax_to_ast(file_name: str, syntax: *tree<symbol>, import_paths: ref vec<s
syntax->data.name == "shiftand" || syntax->data.name == "shiftand" ||
syntax->data.name == "term" || syntax->data.name == "term" ||
syntax->data.name == "factor" || syntax->data.name == "factor" ||
syntax->data.name == "unarad" || syntax->data.name == "unarad") {
syntax->data.name == "access_operation") {
if (syntax->children.size == 1) { if (syntax->children.size == 1) {
return syntax_to_ast_helper(syntax->children[0], declared_template_types) return syntax_to_ast_helper(syntax->children[0], declared_template_types)
} else if (syntax->children.size == 2) { } else if (syntax->children.size == 2) {
@@ -1060,6 +1121,10 @@ fun syntax_to_ast(file_name: str, syntax: *tree<symbol>, import_paths: ref vec<s
syntax_to_ast_helper(syntax->children[0], declared_template_types), syntax_to_ast_helper(syntax->children[0], declared_template_types),
syntax_to_ast_helper(syntax->children[2], declared_template_types))) syntax_to_ast_helper(syntax->children[2], declared_template_types)))
} }
} else if (syntax->data.name == "access_operation") {
// somehow note / do the crazier scope lookup
// also handle . vs ->
return _call(vec(make_ast_binding(concat(syntax->children[2])), syntax_to_ast_helper(syntax->children[0], declared_template_types)))
} else if (syntax->data.name == "cast_expression") { } else if (syntax->data.name == "cast_expression") {
return _cast(parse_type(get_node("type", syntax), declared_template_types), vec(syntax_to_ast_helper(syntax->children[0], declared_template_types))) return _cast(parse_type(get_node("type", syntax), declared_template_types), vec(syntax_to_ast_helper(syntax->children[0], declared_template_types)))
} else if (syntax->data.name == "number") { } else if (syntax->data.name == "number") {

View File

@@ -152,7 +152,7 @@ fun adt_lower(name_ast_map: *map<str, pair<*tree<symbol>,*ast_node>>, ast_to_syn
backing.cases.for_each(fun(case_stmt: *ast_node) { backing.cases.for_each(fun(case_stmt: *ast_node) {
var option = case_stmt->case_statement.option var option = case_stmt->case_statement.option
if (!get_ast_scope(get_ast_type(value)->type_def)->contains_key(str("flag"))) 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? - ") error("trying to get flag from struct without it - are you matching on not an adt? - " + get_ast_type(value)->to_string())
var flag = get_from_scope(get_ast_type(value)->type_def, "flag") 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 data = get_from_scope(get_ast_type(value)->type_def, "data")
var option_num = -7 var option_num = -7

View File

@@ -119,6 +119,9 @@ fun shallow_equality(a: *type, b: *type):bool {
type::_fun(x) { type::_fun(x) {
return is_fun(b) && a->_fun.third == b->_fun.third return is_fun(b) && a->_fun.third == b->_fun.third
} }
type::_obj(x) {
return is_obj(b) && get_ast_binding(x) == get_ast_binding(b->_obj)
}
} }
return *a == *b return *a == *b
} }