More unification for typechecking:
This commit is contained in:
29
k.krak
29
k.krak
@@ -175,17 +175,28 @@ fun main(argc: int, argv: **char): int {
|
|||||||
println("trying to unify " + t1->bound_to->to_string() + " and " + t2->bound_to->to_string())
|
println("trying to unify " + t1->bound_to->to_string() + " and " + t2->bound_to->to_string())
|
||||||
if (t1->bound_to->equality(t2->bound_to, false) || t1->bound_to->is_unknown())
|
if (t1->bound_to->equality(t2->bound_to, false) || t1->bound_to->is_unknown())
|
||||||
t1->set(t2->bound_to)
|
t1->set(t2->bound_to)
|
||||||
else
|
else if (t2->bound_to->is_unknown())
|
||||||
t2->set(t1->bound_to)
|
t2->set(t1->bound_to)
|
||||||
|
else
|
||||||
|
error("Doesn't typecheck! Attempted to unify " + t1->bound_to->to_string() + " and " + t2->bound_to->to_string())
|
||||||
}
|
}
|
||||||
var traverse_for_unify: fun(*tree<ast>): void = fun(t: *tree<ast>) {
|
var traverse_for_unify: fun(*tree<ast>): void = fun(t: *tree<ast>) {
|
||||||
t->children.for_each(traverse_for_unify)
|
t->children.for_each(traverse_for_unify)
|
||||||
match (t->data) {
|
match (t->data) {
|
||||||
ast::_declaration() if (t->children.size > 1)
|
ast::_declaration() if (t->children.size > 1)
|
||||||
unify(get_type(t->children[0]), get_type(t->children[1]))
|
unify(get_type(t->children[0]), get_type(t->children[1]))
|
||||||
/*ast::_assignment()*/
|
/*ast::_assignment() unify(get_type(t->children[0]), get_type(t->children[1]))*/
|
||||||
/*ast::_call()*/
|
ast::_call() {
|
||||||
/*ast::_return()*/
|
var fun_type = get_type(t->children[0])->bound_to
|
||||||
|
if (!fun_type->is_fun())
|
||||||
|
error("trying to call not a function type: " + fun_type->to_string())
|
||||||
|
if (fun_type->base._fun.first.first.size != (t->children.size - 1))
|
||||||
|
error("trying to call function with type wrong number of params (" + to_string(fun_type->base._fun.first.first.size) + " vs " + to_string(t->children.size - 1) + "): " + fun_type->to_string())
|
||||||
|
for (var i = 1; i < t->children.size; i++;)
|
||||||
|
unify(fun_type->base._fun.first.first[i-1], get_type(t->children[i]))
|
||||||
|
}
|
||||||
|
ast::_return() if (t->children.size > 0)
|
||||||
|
unify(get_type(get_ancestor_satisfying(t, fun(t: *tree<ast>): bool return is_function(t);))->bound_to->base._fun.first.second, get_type(t->children[0]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
traverse_for_unify(item)
|
traverse_for_unify(item)
|
||||||
@@ -590,9 +601,13 @@ fun syntax_to_ast(file_name: str, syntax: *tree<symbol>, import_paths: ref vec<s
|
|||||||
syntax_to_ast_helper(syntax->children[0]),
|
syntax_to_ast_helper(syntax->children[0]),
|
||||||
syntax_to_ast_helper(syntax->children[2])))
|
syntax_to_ast_helper(syntax->children[2])))
|
||||||
}
|
}
|
||||||
} else if (syntax->data.name == "number")
|
} else if (syntax->data.name == "number") {
|
||||||
return _value(concat(syntax), binding(type(base_type::_int(), 0, false)))
|
var number_string = concat(syntax)
|
||||||
else if (syntax->data.name == "bool")
|
if (number_string.contains('.'))
|
||||||
|
return _value(number_string, binding(type(base_type::_double(), 0, false)))
|
||||||
|
else
|
||||||
|
return _value(number_string, binding(type(base_type::_int(), 0, false)))
|
||||||
|
} else if (syntax->data.name == "bool")
|
||||||
return _value(concat(syntax), binding(type(base_type::_bool(), 0, false)))
|
return _value(concat(syntax), binding(type(base_type::_bool(), 0, false)))
|
||||||
else if (syntax->data.name == "scoped_identifier" || syntax->data.name == "identifier")
|
else if (syntax->data.name == "scoped_identifier" || syntax->data.name == "identifier")
|
||||||
return make_ast_binding(concat(syntax))
|
return make_ast_binding(concat(syntax))
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ fun get_type(a: *tree<ast>): *binding<type> {
|
|||||||
ast::_identifier(b) return b.second
|
ast::_identifier(b) return b.second
|
||||||
ast::_binding(b) return get_type(b.second->bound_to)
|
ast::_binding(b) return get_type(b.second->bound_to)
|
||||||
ast::_function(b) return b.second
|
ast::_function(b) return b.second
|
||||||
/*ast::_call() return get_type(a->children[0])->bound_to->base->_fun->second*/
|
ast::_call() return get_type(a->children[0])->bound_to->base._fun.first.second
|
||||||
/*ast::_compiler_intrinsic(b) return str("_compiler_intrinsic(") + b.first + ")"*/
|
/*ast::_compiler_intrinsic(b) return str("_compiler_intrinsic(") + b.first + ")"*/
|
||||||
ast::_cast(b) return b
|
ast::_cast(b) return b
|
||||||
ast::_value(b) return b.second
|
ast::_value(b) return b.second
|
||||||
@@ -249,6 +249,13 @@ fun is_value(i: *tree<ast>): bool { match(i->data) { ast::_value(b) return true;
|
|||||||
|
|
||||||
fun is_top_level_item(i: *tree<ast>): bool { return i->parent != null<tree<ast>>() && is_translation_unit(i->parent); }
|
fun is_top_level_item(i: *tree<ast>): bool { return i->parent != null<tree<ast>>() && is_translation_unit(i->parent); }
|
||||||
|
|
||||||
|
fun get_ancestor_satisfying(t: *tree<ast>, p: fun(*tree<ast>): bool): *tree<ast> {
|
||||||
|
t = t->parent
|
||||||
|
while (t != null<tree<ast>>() && !p(t))
|
||||||
|
t = t->parent
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
var bindings: *vec<*void>
|
var bindings: *vec<*void>
|
||||||
|
|
||||||
|
|||||||
@@ -309,5 +309,8 @@ obj str (Object, Serializable, Hashable) {
|
|||||||
fun for_each(func: fun(char):void) {
|
fun for_each(func: fun(char):void) {
|
||||||
data.for_each(func)
|
data.for_each(func)
|
||||||
}
|
}
|
||||||
|
fun contains(c: char): bool {
|
||||||
|
return data.contains(c)
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user