1
1
import std. _str ;
2
2
import std. _uint ;
3
3
import std. _vec ;
4
+ import std. UFind ;
4
5
import std. map ;
5
6
import std. map . hashmap ;
6
7
import std. option ;
@@ -879,6 +880,10 @@ fn is_lval(@ast.expr expr) -> bool {
879
880
//
880
881
// http://www.cs.man.ac.uk/~hoderk/ubench/unification_full.pdf
881
882
883
+ type var_bindings = rec( UFind . ufind sets,
884
+ hashmap[ int, uint] var_ids,
885
+ mutable vec[ mutable vec[ @t] ] types) ;
886
+
882
887
fn unify( @ty. t expected, @ty. t actual, & unify_handler handler)
883
888
-> unify_result {
884
889
// Wraps the given type in an appropriate cname.
@@ -917,7 +922,7 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
917
922
fn_common_res_ok( vec[ arg] , @t) ;
918
923
}
919
924
920
- fn unify_fn_common( @hashmap [ int , @ty . t ] bindings,
925
+ fn unify_fn_common( & var_bindings bindings,
921
926
@ty. t expected,
922
927
@ty. t actual,
923
928
& unify_handler handler,
@@ -982,7 +987,7 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
982
987
}
983
988
}
984
989
985
- fn unify_fn( @hashmap [ int , @ty . t ] bindings,
990
+ fn unify_fn( & var_bindings bindings,
986
991
ast. proto e_proto,
987
992
ast. proto a_proto,
988
993
@ty. t expected,
@@ -1009,7 +1014,7 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
1009
1014
}
1010
1015
}
1011
1016
1012
- fn unify_native_fn( @hashmap [ int , @ty . t ] bindings,
1017
+ fn unify_native_fn( & var_bindings bindings,
1013
1018
ast. native_abi e_abi,
1014
1019
ast. native_abi a_abi,
1015
1020
@ty. t expected,
@@ -1037,7 +1042,7 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
1037
1042
}
1038
1043
}
1039
1044
1040
- fn unify_obj( @hashmap [ int , @ty . t ] bindings,
1045
+ fn unify_obj( & var_bindings bindings,
1041
1046
@ty. t expected,
1042
1047
@ty. t actual,
1043
1048
& unify_handler handler,
@@ -1084,32 +1089,20 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
1084
1089
ret ures_ok( t) ;
1085
1090
}
1086
1091
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; }
1102
1100
}
1103
- ret typ ;
1101
+ ret set_num ;
1104
1102
}
1105
1103
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 {
1113
1106
// TODO: rewrite this using tuple pattern matching when available, to
1114
1107
// avoid all this rightward drift and spikiness.
1115
1108
@@ -1120,8 +1113,26 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
1120
1113
// If the RHS is a variable type, then just do the appropriate
1121
1114
// binding.
1122
1115
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) ;
1125
1136
}
1126
1137
case ( ty. ty_local( ?actual_id) ) {
1127
1138
auto actual_ty = handler. resolve_local( actual_id) ;
@@ -1487,8 +1498,15 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
1487
1498
1488
1499
case ( ty. ty_var( ?expected_id) ) {
1489
1500
// 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) ;
1492
1510
}
1493
1511
1494
1512
case ( ty. ty_local( ?expected_id) ) {
@@ -1517,36 +1535,73 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
1517
1535
}
1518
1536
1519
1537
// 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 ) {
1522
1540
fn fold_simple_ty( @t typ) -> @t {
1541
+ auto bindings = env. _0;
1542
+ auto types = env. _1;
1523
1543
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) ;
1533
1549
}
1534
- case ( _) {
1535
- ret typ;
1550
+ case ( none[ uint] ) { ret typ; }
1536
1551
}
1537
1552
}
1553
+ case ( _) { ret typ; }
1554
+ }
1538
1555
}
1539
1556
}
1540
1557
1541
- ret ty. fold_ty( folder( bindings) , typ) ;
1558
+ ret ty. fold_ty( folder( tup ( bindings, set_types ) ) , typ) ;
1542
1559
}
1543
1560
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 = 0 u;
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 += 1 u;
1576
+ }
1577
+
1578
+ let vec[ @t] result = vec( ) ;
1579
+ for ( vec[ @t] types in set_types) {
1580
+ if ( _vec. len[ @t] ( types) > 1 u) {
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) ;
1545
1597
1546
1598
auto ures = unify_step( bindings, expected, actual, handler) ;
1547
1599
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; }
1550
1605
}
1551
1606
fail; // not reached
1552
1607
}
0 commit comments