diff --git a/src/Makefile b/src/Makefile index c965f7b6689..f41ea356943 100644 --- a/src/Makefile +++ b/src/Makefile @@ -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 \ diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 8caaf5f7309..d5b738264f0 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -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). diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 25a42e9a6bb..78dff420ab7 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -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: "