@@ -26,6 +26,7 @@ type fn_ctxt = rec(@ty ret_ty,
26
26
@crate_ctxt ccx ) ;
27
27
28
28
type arg = rec ( ast. mode mode , @ty ty) ;
29
+ type field = rec ( ast. ident label , @ty ty) ;
29
30
30
31
// NB: If you change this, you'll probably want to change the corresponding
31
32
// AST structure in front/ast.rs as well.
@@ -41,6 +42,7 @@ tag sty {
41
42
ty_box ( @ty) ;
42
43
ty_vec ( @ty) ;
43
44
ty_tup ( vec[ @ty] ) ;
45
+ ty_rec ( vec[ field] ) ;
44
46
ty_fn ( vec[ arg] , @ty) ; // TODO: effect
45
47
ty_var ( int) ; // ephemeral type var
46
48
ty_local ( ast. def_id ) ; // type of a local var
@@ -52,6 +54,9 @@ tag type_err {
52
54
terr_mismatch;
53
55
terr_tuple_size ( uint, uint) ;
54
56
terr_tuple_mutability;
57
+ terr_record_size ( uint, uint) ;
58
+ terr_record_mutability;
59
+ terr_record_fields ( ast. ident , ast. ident ) ;
55
60
terr_arg_count;
56
61
}
57
62
@@ -78,6 +83,10 @@ fn ast_ty_to_str(&@ast.ty ty) -> str {
78
83
ret s + ast_ty_to_str ( input. ty ) ;
79
84
}
80
85
86
+ fn ast_field_to_str ( & tup( ast. ident, @ast. ty) f ) -> str {
87
+ ret ast_ty_to_str ( f. _1 ) + " " + f. _0 ;
88
+ }
89
+
81
90
auto s;
82
91
alt ( ty. node ) {
83
92
case ( ast. ty_nil ) { s = "()" ; }
@@ -97,6 +106,14 @@ fn ast_ty_to_str(&@ast.ty ty) -> str {
97
106
s += ")" ;
98
107
}
99
108
109
+ case ( ast. ty_rec ( ?elems) ) {
110
+ auto f = ast_field_to_str;
111
+ s = "rec(" ;
112
+ s += _str. connect ( _vec. map [ tup ( ast. ident , @ast. ty ) , str]
113
+ ( f, elems) , "," ) ;
114
+ s += ")" ;
115
+ }
116
+
100
117
case ( ast. ty_fn ( ?inputs, ?output) ) {
101
118
auto f = ast_fn_input_to_str;
102
119
s = "fn(" ;
@@ -154,6 +171,10 @@ fn ty_to_str(&@ty typ) -> str {
154
171
ret s + ty_to_str ( input . ty) ;
155
172
}
156
173
174
+ fn field_to_str ( & field f) -> str {
175
+ ret ty_to_str ( f. ty ) + " " + f. label ;
176
+ }
177
+
157
178
auto s = "" ;
158
179
if ( typ. mut == ast. mut ) {
159
180
s += "mutable " ;
@@ -176,6 +197,12 @@ fn ty_to_str(&@ty typ) -> str {
176
197
s = "tup(" + _str. connect ( strs, "," ) + ")" ;
177
198
}
178
199
200
+ case ( ty_rec ( ?elems) ) {
201
+ auto f = field_to_str;
202
+ auto strs = _vec. map [ field, str ] ( f, elems) ;
203
+ s = "rec(" + _str. connect ( strs, "," ) + ")" ;
204
+ }
205
+
179
206
case ( ty_fn ( ?inputs, ?output) ) {
180
207
auto f = fn_input_to_str;
181
208
s = "fn(" + _str. connect ( _vec. map [ arg, str] ( f, inputs) ,
@@ -222,6 +249,14 @@ fn ast_ty_to_ty(ty_getter getter, &@ast.ty ast_ty) -> @ty {
222
249
}
223
250
sty = ty_tup ( flds) ;
224
251
}
252
+ case ( ast. ty_rec ( ?fields) ) {
253
+ let vec[ field] flds = vec ( ) ;
254
+ for ( tup( ast. ident, @ast. ty) f in fields) {
255
+ append[ field] ( flds, rec ( label=f. _0 ,
256
+ ty=ast_ty_to_ty ( getter, f. _1 ) ) ) ;
257
+ }
258
+ sty = ty_rec ( flds) ;
259
+ }
225
260
226
261
case ( ast. ty_fn ( ?inputs, ?output) ) {
227
262
auto f = bind ast_arg_to_arg ( getter, _) ;
@@ -281,6 +316,19 @@ fn type_err_to_str(&type_err err) -> str {
281
316
case ( terr_tuple_mutability) {
282
317
ret "tuple elements differ in mutability" ;
283
318
}
319
+ case ( terr_record_size ( ?e_sz, ?a_sz) ) {
320
+ ret "expected a record with " + _uint. to_str ( e_sz, 10 u) +
321
+ " fields but found one with " + _uint. to_str ( a_sz, 10 u) +
322
+ " fields" ;
323
+ }
324
+ case ( terr_record_mutability) {
325
+ ret "record elements differ in mutability" ;
326
+ }
327
+ case ( terr_record_fields ( ?e_fld, ?a_fld) ) {
328
+ ret "expected a record with field '" + e_fld +
329
+ "' but found one with field '" + a_fld +
330
+ "'" ;
331
+ }
284
332
case ( terr_arg_count) {
285
333
ret "incorrect number of function parameters" ;
286
334
}
@@ -445,8 +493,9 @@ fn type_is_nil(@ty t) -> bool {
445
493
446
494
fn type_is_structural ( @ty t ) -> bool {
447
495
alt ( t. struct ) {
448
- // FIXME: cover rec and tag when we support them .
496
+ // FIXME: cover tag when we support it .
449
497
case ( ty_tup ( _) ) { ret true ; }
498
+ case ( ty_rec ( _) ) { ret true ; }
450
499
}
451
500
ret false;
452
501
}
@@ -726,6 +775,65 @@ fn unify(&fn_ctxt fcx, @ty expected, @ty actual) -> unify_result {
726
775
}
727
776
}
728
777
778
+ case ( ty_rec( ?expected_fields) ) {
779
+ alt ( actual. struct ) {
780
+ case ( ty_rec( ?actual_fields) ) {
781
+ auto expected_len = _vec. len [ field] ( expected_fields) ;
782
+ auto actual_len = _vec. len [ field] ( actual_fields) ;
783
+ if ( expected_len != actual_len) {
784
+ auto err = terr_record_size ( expected_len,
785
+ actual_len) ;
786
+ ret ures_err( err, expected, actual) ;
787
+ }
788
+
789
+ // TODO: implement an iterator that can iterate over
790
+ // two arrays simultaneously.
791
+ let vec[ field] result_fields = vec ( ) ;
792
+ auto i = 0 u;
793
+ while ( i < expected_len) {
794
+ auto expected_field = expected_fields. ( i) ;
795
+ auto actual_field = actual_fields. ( i) ;
796
+ if ( expected_field. ty . mut != actual_field. ty . mut ) {
797
+ auto err = terr_record_mutability;
798
+ ret ures_err( err, expected, actual) ;
799
+ }
800
+
801
+ if ( !_str. eq ( expected_field. label ,
802
+ actual_field. label ) ) {
803
+ auto err =
804
+ terr_record_fields ( expected_field. label ,
805
+ actual_field. label ) ;
806
+ ret ures_err( err, expected, actual) ;
807
+ }
808
+
809
+ auto result = unify_step ( fcx,
810
+ bindings,
811
+ expected_field. ty ,
812
+ actual_field. ty ) ;
813
+ alt ( result) {
814
+ case ( ures_ok ( ?rty) ) {
815
+ append[ field] ( result_fields,
816
+ rec ( ty=rty with expected_field) ) ;
817
+ }
818
+ case ( _) {
819
+ ret result;
820
+ }
821
+ }
822
+
823
+ i += 1 u;
824
+ }
825
+
826
+ ret ures_ok( plain_ty ( ty_rec ( result_fields) ) ) ;
827
+ }
828
+
829
+ // TODO: ty_var
830
+
831
+ case ( _) {
832
+ ret ures_err ( terr_mismatch, expected, actual) ;
833
+ }
834
+ }
835
+ }
836
+
729
837
case ( ty_fn( ?expected_inputs, ?expected_output) ) {
730
838
alt ( actual. struct ) {
731
839
case ( ty_fn( ?actual_inputs, ?actual_output) ) {
0 commit comments