Finish support for typechecking and translating records. Un-XFAIL rec.rs.

This commit is contained in:
Graydon Hoare 2010-11-30 10:39:35 -08:00
parent 9c426521ee
commit 25b973df1b
3 changed files with 79 additions and 0 deletions

View File

@ -534,6 +534,7 @@ TEST_XFAILS_SELF := $(filter-out \
item-name-overload.rs \
lazy-init.rs \
multiline-comment.rs \
rec.rs \
return-nil.rs \
tup.rs \
u32-decr.rs \

View File

@ -280,6 +280,13 @@ fn type_of_inner(@crate_ctxt cx, @typeck.ty t) -> TypeRef {
}
ret T_struct(tys);
}
case (typeck.ty_rec(?fields)) {
let vec[TypeRef] tys = vec();
for (typeck.field f in fields) {
tys += type_of(cx, f.ty);
}
ret T_struct(tys);
}
case (typeck.ty_fn(?args, ?out)) {
let vec[TypeRef] atys = vec(T_taskptr());
for (typeck.arg arg in args) {
@ -1106,6 +1113,12 @@ fn trans_field(@block_ctxt cx, &ast.span sp, @ast.expr base,
auto v = r.bcx.build.GEP(r.val, vec(C_int(0), C_int(ix as int)));
ret tup(res(r.bcx, v), lv._1);
}
case (typeck.ty_rec(?fields)) {
let uint ix = typeck.field_idx(cx.fcx.ccx.sess, sp,
field, fields);
auto v = r.bcx.build.GEP(r.val, vec(C_int(0), C_int(ix as int)));
ret tup(res(r.bcx, v), lv._1);
}
}
cx.fcx.ccx.sess.unimpl("field variant in trans_field");
fail;
@ -1201,6 +1214,23 @@ impure fn trans_tup(@block_ctxt cx, vec[tup(ast.mutability, @ast.expr)] args,
ret res(r.bcx, tup_val);
}
impure fn trans_rec(@block_ctxt cx, vec[tup(ast.ident, @ast.expr)] args,
&ast.ann ann) -> result {
auto ty = node_type(cx.fcx.ccx, ann);
auto tup_val = cx.build.Alloca(ty);
let int i = 0;
auto r = res(cx, C_nil());
for (tup(ast.ident, @ast.expr) arg in args) {
auto t = typeck.expr_ty(arg._1);
auto src_res = trans_expr(r.bcx, arg._1);
auto dst_elt = r.bcx.build.GEP(tup_val, vec(C_int(0), C_int(i)));
// FIXME: calculate copy init-ness in typestate.
r = copy_ty(src_res.bcx, true, dst_elt, src_res.val, t);
i += 1;
}
ret res(r.bcx, tup_val);
}
impure fn trans_expr(@block_ctxt cx, @ast.expr e) -> result {
@ -1261,6 +1291,10 @@ impure fn trans_expr(@block_ctxt cx, @ast.expr e) -> result {
ret trans_tup(cx, args, ann);
}
case (ast.expr_rec(?args, ?ann)) {
ret trans_rec(cx, args, ann);
}
// lval cases fall through to trans_lval and then
// possibly load the result (if it's non-structural).

View File

@ -474,6 +474,19 @@ fn field_num(session.session sess, &span sp, &ast.ident id) -> uint {
ret accum;
}
fn field_idx(session.session sess, &span sp,
&ast.ident id, vec[field] fields) -> uint {
let uint i = 0u;
for (field f in fields) {
if (_str.eq(f.label, id)) {
ret i;
}
i += 1u;
}
sess.span_err(sp, "unknown field '" + id + "' of record");
fail;
}
// Type utilities
// FIXME: remove me when == works on these tags.
@ -1346,6 +1359,22 @@ fn check_expr(&fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
ast.expr_tup(args_1, ann));
}
case (ast.expr_rec(?args, _)) {
let vec[tup(ast.ident, @ast.expr)] args_1 = vec();
let vec[field] args_t = vec();
for (tup(ast.ident, @ast.expr) arg in args) {
auto expr_1 = check_expr(fcx, arg._1);
args_1 += tup(arg._0, expr_1);
append[field](args_t,rec(label=arg._0,
ty=expr_ty(expr_1)));
}
auto ann = ast.ann_type(plain_ty(ty_rec(args_t)));
ret @fold.respan[ast.expr_](expr.span,
ast.expr_rec(args_1, ann));
}
case (ast.expr_field(?base, ?field, _)) {
auto base_1 = check_expr(fcx, base);
auto base_t = expr_ty(base_1);
@ -1363,6 +1392,21 @@ fn check_expr(&fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
field,
ann));
}
case (ty_rec(?fields)) {
let uint ix = field_idx(fcx.ccx.sess,
expr.span, field, fields);
if (ix >= _vec.len[typeck.field](fields)) {
fcx.ccx.sess.span_err(expr.span,
"bad index on record");
}
auto ann = ast.ann_type(fields.(ix).ty);
ret @fold.respan[ast.expr_](expr.span,
ast.expr_field(base_1,
field,
ann));
}
case (_) {
fcx.ccx.sess.unimpl("base type for expr_field "
+ "in typeck.check_expr: "