Skip to content

Commit 9872963

Browse files
committed
---
yaml --- r: 2102 b: refs/heads/master c: ec5a60d h: refs/heads/master v: v3
1 parent e3aa71d commit 9872963

File tree

3 files changed

+116
-65
lines changed

3 files changed

+116
-65
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
---
2-
refs/heads/master: 99a697b56abba8e4ab94fc14b5b4769bee9702f0
2+
refs/heads/master: ec5a60d5e26c9d38755e66660d7913e42f42a1b3

trunk/src/comp/middle/ty.rs

Lines changed: 103 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import std._str;
22
import std._uint;
33
import std._vec;
4+
import std.UFind;
45
import std.map;
56
import std.map.hashmap;
67
import std.option;
@@ -879,6 +880,10 @@ fn is_lval(@ast.expr expr) -> bool {
879880
//
880881
// http://www.cs.man.ac.uk/~hoderk/ubench/unification_full.pdf
881882

883+
type var_bindings = rec(UFind.ufind sets,
884+
hashmap[int,uint] var_ids,
885+
mutable vec[mutable vec[@t]] types);
886+
882887
fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
883888
-> unify_result {
884889
// Wraps the given type in an appropriate cname.
@@ -917,7 +922,7 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
917922
fn_common_res_ok(vec[arg], @t);
918923
}
919924

920-
fn unify_fn_common(@hashmap[int,@ty.t] bindings,
925+
fn unify_fn_common(&var_bindings bindings,
921926
@ty.t expected,
922927
@ty.t actual,
923928
&unify_handler handler,
@@ -982,7 +987,7 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
982987
}
983988
}
984989

985-
fn unify_fn(@hashmap[int,@ty.t] bindings,
990+
fn unify_fn(&var_bindings bindings,
986991
ast.proto e_proto,
987992
ast.proto a_proto,
988993
@ty.t expected,
@@ -1009,7 +1014,7 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
10091014
}
10101015
}
10111016

1012-
fn unify_native_fn(@hashmap[int,@ty.t] bindings,
1017+
fn unify_native_fn(&var_bindings bindings,
10131018
ast.native_abi e_abi,
10141019
ast.native_abi a_abi,
10151020
@ty.t expected,
@@ -1037,7 +1042,7 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
10371042
}
10381043
}
10391044

1040-
fn unify_obj(@hashmap[int,@ty.t] bindings,
1045+
fn unify_obj(&var_bindings bindings,
10411046
@ty.t expected,
10421047
@ty.t actual,
10431048
&unify_handler handler,
@@ -1084,32 +1089,20 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
10841089
ret ures_ok(t);
10851090
}
10861091

1087-
fn resolve(@hashmap[int,@t] bindings, @t typ) -> @t {
1088-
alt (typ.struct) {
1089-
case (ty_var(?id)) {
1090-
alt (bindings.find(id)) {
1091-
case (some[@t](?typ2)) {
1092-
ret resolve(bindings, typ2);
1093-
}
1094-
case (none[@t]) {
1095-
// fall through
1096-
}
1097-
}
1098-
}
1099-
case (_) {
1100-
// fall through
1101-
}
1092+
fn get_or_create_set(&var_bindings bindings, int id) -> uint {
1093+
auto set_num;
1094+
alt (bindings.var_ids.find(id)) {
1095+
case (none[uint]) {
1096+
set_num = UFind.make_set(bindings.sets);
1097+
bindings.var_ids.insert(id, set_num);
1098+
}
1099+
case (some[uint](?n)) { set_num = n; }
11021100
}
1103-
ret typ;
1101+
ret set_num;
11041102
}
11051103

1106-
fn unify_step(@hashmap[int,@ty.t] bindings, @ty.t in_expected,
1107-
@ty.t in_actual, &unify_handler handler) -> unify_result {
1108-
1109-
// Resolve any bindings.
1110-
auto expected = resolve(bindings, in_expected);
1111-
auto actual = resolve(bindings, in_actual);
1112-
1104+
fn unify_step(&var_bindings bindings, @ty.t expected, @ty.t actual,
1105+
&unify_handler handler) -> unify_result {
11131106
// TODO: rewrite this using tuple pattern matching when available, to
11141107
// avoid all this rightward drift and spikiness.
11151108

@@ -1120,8 +1113,26 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
11201113
// If the RHS is a variable type, then just do the appropriate
11211114
// binding.
11221115
case (ty.ty_var(?actual_id)) {
1123-
bindings.insert(actual_id, expected);
1124-
ret ures_ok(expected);
1116+
auto actual_n = get_or_create_set(bindings, actual_id);
1117+
alt (expected.struct) {
1118+
case (ty.ty_var(?expected_id)) {
1119+
auto expected_n = get_or_create_set(bindings,
1120+
expected_id);
1121+
UFind.union(bindings.sets, expected_n, actual_n);
1122+
}
1123+
1124+
case (_) {
1125+
// Just bind the type variable to the expected type.
1126+
auto vlen = _vec.len[mutable vec[@t]](bindings.types);
1127+
if (actual_n < vlen) {
1128+
bindings.types.(actual_n) += vec(expected);
1129+
} else {
1130+
check (actual_n == vlen);
1131+
bindings.types += vec(mutable vec(expected));
1132+
}
1133+
}
1134+
}
1135+
ret ures_ok(actual);
11251136
}
11261137
case (ty.ty_local(?actual_id)) {
11271138
auto actual_ty = handler.resolve_local(actual_id);
@@ -1487,8 +1498,15 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
14871498

14881499
case (ty.ty_var(?expected_id)) {
14891500
// Add a binding.
1490-
bindings.insert(expected_id, actual);
1491-
ret ures_ok(actual);
1501+
auto expected_n = get_or_create_set(bindings, expected_id);
1502+
auto vlen = _vec.len[mutable vec[@t]](bindings.types);
1503+
if (expected_n < vlen) {
1504+
bindings.types.(expected_n) += vec(actual);
1505+
} else {
1506+
check (expected_n == vlen);
1507+
bindings.types += vec(mutable vec(actual));
1508+
}
1509+
ret ures_ok(expected);
14921510
}
14931511

14941512
case (ty.ty_local(?expected_id)) {
@@ -1517,36 +1535,73 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
15171535
}
15181536

15191537
// Performs type binding substitution.
1520-
fn substitute(@hashmap[int,@t] bindings, @t typ) -> @t {
1521-
state obj folder(@hashmap[int,@t] bindings) {
1538+
fn substitute(var_bindings bindings, vec[@t] set_types, @t typ) -> @t {
1539+
state obj folder(tup(var_bindings, vec[@t]) env) {
15221540
fn fold_simple_ty(@t typ) -> @t {
1541+
auto bindings = env._0;
1542+
auto types = env._1;
15231543
alt (typ.struct) {
1524-
case (ty_var(?id)) {
1525-
alt (bindings.find(id)) {
1526-
case (some[@t](?typ2)) {
1527-
ret substitute(bindings, typ2);
1528-
}
1529-
case (none[@t]) {
1530-
ret typ;
1531-
}
1532-
}
1544+
case (ty_var(?id)) {
1545+
alt (bindings.var_ids.find(id)) {
1546+
case (some[uint](?n)) {
1547+
auto root = UFind.find(bindings.sets, n);
1548+
ret types.(root);
15331549
}
1534-
case (_) {
1535-
ret typ;
1550+
case (none[uint]) { ret typ; }
15361551
}
15371552
}
1553+
case (_) { ret typ; }
1554+
}
15381555
}
15391556
}
15401557

1541-
ret ty.fold_ty(folder(bindings), typ);
1558+
ret ty.fold_ty(folder(tup(bindings, set_types)), typ);
15421559
}
15431560

1544-
auto bindings = @common.new_int_hash[@ty.t]();
1561+
fn unify_sets(&var_bindings bindings) -> vec[@t] {
1562+
let vec[@t] throwaway = vec();
1563+
let vec[mutable vec[@t]] set_types = vec(mutable throwaway);
1564+
_vec.pop[mutable vec[@t]](set_types); // FIXME: botch
1565+
1566+
for (UFind.node node in bindings.sets.nodes) {
1567+
let vec[@t] v = vec();
1568+
set_types += vec(mutable v);
1569+
}
1570+
1571+
auto i = 0u;
1572+
while (i < _vec.len[mutable vec[@t]](set_types)) {
1573+
auto root = UFind.find(bindings.sets, i);
1574+
set_types.(root) += bindings.types.(i);
1575+
i += 1u;
1576+
}
1577+
1578+
let vec[@t] result = vec();
1579+
for (vec[@t] types in set_types) {
1580+
if (_vec.len[@t](types) > 1u) {
1581+
log "unification of > 1 types in a type set is unimplemented";
1582+
fail;
1583+
}
1584+
result += vec(types.(0));
1585+
}
1586+
1587+
ret result;
1588+
}
1589+
1590+
let vec[@t] throwaway = vec();
1591+
let vec[mutable vec[@t]] types = vec(mutable throwaway);
1592+
_vec.pop[mutable vec[@t]](types); // FIXME: botch
1593+
1594+
auto bindings = rec(sets=UFind.make(),
1595+
var_ids=common.new_int_hash[uint](),
1596+
mutable types=types);
15451597

15461598
auto ures = unify_step(bindings, expected, actual, handler);
15471599
alt (ures) {
1548-
case (ures_ok(?t)) { ret ures_ok(substitute(bindings, t)); }
1549-
case (_) { ret ures; }
1600+
case (ures_ok(?t)) {
1601+
auto set_types = unify_sets(bindings);
1602+
ret ures_ok(substitute(bindings, set_types, t));
1603+
}
1604+
case (_) { ret ures; }
15501605
}
15511606
fail; // not reached
15521607
}

trunk/src/lib/UFind.rs

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,39 +3,35 @@ import option.some;
33

44
// A very naive implementation of union-find with unsigned integer nodes.
55

6-
tag node {
7-
elem(uint, option.t[uint]);
8-
}
6+
type node = option.t[uint];
97
type ufind = rec(mutable vec[mutable node] nodes);
108

119
fn make() -> ufind {
12-
let vec[mutable node] v = vec(mutable elem(0u, none[uint]));
10+
let vec[mutable node] v = vec(mutable none[uint]);
1311
_vec.pop[mutable node](v); // FIXME: botch
1412
ret rec(mutable nodes=v);
1513
}
1614

17-
fn make_set(&ufind ufnd, uint n) {
18-
ufnd.nodes += vec(mutable elem(n, none[uint]));
15+
fn make_set(&ufind ufnd) -> uint {
16+
auto idx = _vec.len[mutable node](ufnd.nodes);
17+
ufnd.nodes += vec(mutable none[uint]);
18+
ret idx;
1919
}
2020

2121
fn find(&ufind ufnd, uint n) -> uint {
2222
alt (ufnd.nodes.(n)) {
23-
case (elem(_, ?parent_opt)) {
24-
alt (parent_opt) {
25-
case (none[uint]) { ret n; }
26-
case (some[uint](?m)) {
27-
// TODO: "be"
28-
ret find(ufnd, m);
29-
}
30-
}
31-
}
23+
case (none[uint]) { ret n; }
24+
case (some[uint](?m)) {
25+
// TODO: "be"
26+
ret find(ufnd, m);
27+
}
3228
}
3329
}
3430

3531
fn union(&ufind ufnd, uint m, uint n) {
3632
auto m_root = find(ufnd, m);
3733
auto n_root = find(ufnd, n);
3834
auto ptr = some[uint](n_root);
39-
ufnd.nodes.(m_root) = elem(m_root, ptr);
35+
ufnd.nodes.(m_root) = ptr;
4036
}
4137

0 commit comments

Comments
 (0)