Skip to content

Commit 57f4d54

Browse files
committed
---
yaml --- r: 978 b: refs/heads/master c: a94046f h: refs/heads/master v: v3
1 parent 02ccf5b commit 57f4d54

File tree

2 files changed

+110
-2
lines changed

2 files changed

+110
-2
lines changed

[refs]

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
---
2-
refs/heads/master: 6c5a05b819c4dc7e3c47056a61a27fa4f11a364f
2+
refs/heads/master: a94046f5d2d22389113c8954e87d63e29f9b6625

trunk/src/comp/middle/typeck.rs

+109-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ type fn_ctxt = rec(@ty ret_ty,
2626
@crate_ctxt ccx);
2727

2828
type arg = rec(ast.mode mode, @ty ty);
29+
type field = rec(ast.ident label, @ty ty);
2930

3031
// NB: If you change this, you'll probably want to change the corresponding
3132
// AST structure in front/ast.rs as well.
@@ -41,6 +42,7 @@ tag sty {
4142
ty_box(@ty);
4243
ty_vec(@ty);
4344
ty_tup(vec[@ty]);
45+
ty_rec(vec[field]);
4446
ty_fn(vec[arg], @ty); // TODO: effect
4547
ty_var(int); // ephemeral type var
4648
ty_local(ast.def_id); // type of a local var
@@ -52,6 +54,9 @@ tag type_err {
5254
terr_mismatch;
5355
terr_tuple_size(uint, uint);
5456
terr_tuple_mutability;
57+
terr_record_size(uint, uint);
58+
terr_record_mutability;
59+
terr_record_fields(ast.ident,ast.ident);
5560
terr_arg_count;
5661
}
5762

@@ -78,6 +83,10 @@ fn ast_ty_to_str(&@ast.ty ty) -> str {
7883
ret s + ast_ty_to_str(input.ty);
7984
}
8085

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+
8190
auto s;
8291
alt (ty.node) {
8392
case (ast.ty_nil) { s = "()"; }
@@ -97,6 +106,14 @@ fn ast_ty_to_str(&@ast.ty ty) -> str {
97106
s += ")";
98107
}
99108

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+
100117
case (ast.ty_fn(?inputs, ?output)) {
101118
auto f = ast_fn_input_to_str;
102119
s = "fn(";
@@ -154,6 +171,10 @@ fn ty_to_str(&@ty typ) -> str {
154171
ret s + ty_to_str(input.ty);
155172
}
156173

174+
fn field_to_str(&field f) -> str {
175+
ret ty_to_str(f.ty) + " " + f.label;
176+
}
177+
157178
auto s = "";
158179
if (typ.mut == ast.mut) {
159180
s += "mutable ";
@@ -176,6 +197,12 @@ fn ty_to_str(&@ty typ) -> str {
176197
s = "tup(" + _str.connect(strs, ",") + ")";
177198
}
178199

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+
179206
case (ty_fn(?inputs, ?output)) {
180207
auto f = fn_input_to_str;
181208
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 {
222249
}
223250
sty = ty_tup(flds);
224251
}
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+
}
225260

226261
case (ast.ty_fn(?inputs, ?output)) {
227262
auto f = bind ast_arg_to_arg(getter, _);
@@ -281,6 +316,19 @@ fn type_err_to_str(&type_err err) -> str {
281316
case (terr_tuple_mutability) {
282317
ret "tuple elements differ in mutability";
283318
}
319+
case (terr_record_size(?e_sz, ?a_sz)) {
320+
ret "expected a record with " + _uint.to_str(e_sz, 10u) +
321+
" fields but found one with " + _uint.to_str(a_sz, 10u) +
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+
}
284332
case (terr_arg_count) {
285333
ret "incorrect number of function parameters";
286334
}
@@ -445,8 +493,9 @@ fn type_is_nil(@ty t) -> bool {
445493

446494
fn type_is_structural(@ty t) -> bool {
447495
alt (t.struct) {
448-
// FIXME: cover rec and tag when we support them.
496+
// FIXME: cover tag when we support it.
449497
case (ty_tup(_)) { ret true; }
498+
case (ty_rec(_)) { ret true; }
450499
}
451500
ret false;
452501
}
@@ -726,6 +775,65 @@ fn unify(&fn_ctxt fcx, @ty expected, @ty actual) -> unify_result {
726775
}
727776
}
728777

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 = 0u;
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 += 1u;
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+
729837
case (ty_fn(?expected_inputs, ?expected_output)) {
730838
alt (actual.struct) {
731839
case (ty_fn(?actual_inputs, ?actual_output)) {

0 commit comments

Comments
 (0)