Skip to content

Commit 0655423

Browse files
committed
Teach ty.unify about ty_obj.
1 parent aa1d8d0 commit 0655423

File tree

1 file changed

+83
-0
lines changed

1 file changed

+83
-0
lines changed

src/comp/middle/ty.rs

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ tag type_err {
6060
terr_record_size(uint, uint);
6161
terr_record_mutability;
6262
terr_record_fields(ast.ident,ast.ident);
63+
terr_meth_count;
64+
terr_obj_meths(ast.ident,ast.ident);
6365
terr_arg_count;
6466
}
6567

@@ -724,6 +726,67 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
724726

725727
}
726728

729+
fn unify_obj(&hashmap[int,@ty.t] bindings,
730+
@ty.t expected,
731+
@ty.t actual,
732+
&unify_handler handler,
733+
vec[method] expected_meths,
734+
vec[method] actual_meths) -> unify_result {
735+
let vec[method] result_meths = vec();
736+
let uint i = 0u;
737+
let uint expected_len = _vec.len[method](expected_meths);
738+
let uint actual_len = _vec.len[method](actual_meths);
739+
740+
if (expected_len != actual_len) {
741+
ret ures_err(terr_meth_count, expected, actual);
742+
}
743+
744+
// FIXME: work around buggy typestate logic for 'alt', sigh.
745+
fn is_ok(&unify_result r) -> bool {
746+
alt (r) {
747+
case (ures_ok(?tfn)) {
748+
ret true;
749+
}
750+
case (_) {}
751+
}
752+
ret false;
753+
}
754+
755+
fn append_if_ok(&method e_meth,
756+
&unify_result r, &mutable vec[method] result_meths) {
757+
alt (r) {
758+
case (ures_ok(?tfn)) {
759+
alt (tfn.struct) {
760+
case (ty_fn(?ins, ?out)) {
761+
result_meths += vec(rec(inputs = ins,
762+
output = out
763+
with e_meth));
764+
}
765+
}
766+
}
767+
}
768+
}
769+
770+
while (i < expected_len) {
771+
auto e_meth = expected_meths.(i);
772+
auto a_meth = actual_meths.(i);
773+
if (! _str.eq(e_meth.ident, a_meth.ident)) {
774+
ret ures_err(terr_obj_meths(e_meth.ident, a_meth.ident),
775+
expected, actual);
776+
}
777+
auto r = unify_fn(bindings, expected, actual, handler,
778+
e_meth.inputs, e_meth.output,
779+
a_meth.inputs, a_meth.output);
780+
if (!is_ok(r)) {
781+
ret r;
782+
}
783+
append_if_ok(e_meth, r, result_meths);
784+
i += 1u;
785+
}
786+
auto t = plain_ty(ty_obj(result_meths));
787+
ret ures_ok(t);
788+
}
789+
727790
fn unify_step(&hashmap[int,@ty.t] bindings, @ty.t expected, @ty.t actual,
728791
&unify_handler handler) -> unify_result {
729792
// TODO: rewrite this using tuple pattern matching when available, to
@@ -961,6 +1024,18 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
9611024
}
9621025
}
9631026

1027+
case (ty.ty_obj(?expected_meths)) {
1028+
alt (actual.struct) {
1029+
case (ty.ty_obj(?actual_meths)) {
1030+
ret unify_obj(bindings, expected, actual, handler,
1031+
expected_meths, actual_meths);
1032+
}
1033+
case (_) {
1034+
ret ures_err(terr_mismatch, expected, actual);
1035+
}
1036+
}
1037+
}
1038+
9641039
case (ty.ty_var(?expected_id)) {
9651040
alt (bindings.find(expected_id)) {
9661041
case (some[@ty.t](?expected_ty)) {
@@ -1042,6 +1117,14 @@ fn type_err_to_str(&ty.type_err err) -> str {
10421117
case (terr_arg_count) {
10431118
ret "incorrect number of function parameters";
10441119
}
1120+
case (terr_meth_count) {
1121+
ret "incorrect number of object methods";
1122+
}
1123+
case (terr_obj_meths(?e_meth, ?a_meth)) {
1124+
ret "expected an obj with method '" + e_meth +
1125+
"' but found one with method '" + a_meth +
1126+
"'";
1127+
}
10451128
}
10461129
}
10471130

0 commit comments

Comments
 (0)