diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index 6aac7b5056d..3aec322600e 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -146,7 +146,7 @@ type expr = spanned[expr_]; tag expr_ { expr_vec(vec[@expr], ann); expr_tup(vec[elt], ann); - expr_rec(vec[field], ann); + expr_rec(vec[field], option.t[@expr], ann); expr_call(@expr, vec[@expr], ann); expr_bind(@expr, vec[option.t[@expr]], ann); expr_binary(binop, @expr, @expr, ann); diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 87bbe57f5cb..2f037dfbcee 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -529,14 +529,37 @@ impure fn parse_bottom_expr(parser p) -> @ast.expr { case (token.REC) { p.bump(); - auto pf = parse_field; - auto fs = - parse_seq[ast.field](token.LPAREN, - token.RPAREN, - some(token.COMMA), - pf, p); - hi = fs.span; - ex = ast.expr_rec(fs.node, ast.ann_none); + expect(p, token.LPAREN); + auto fields = vec(parse_field(p)); + + auto more = true; + auto base = none[@ast.expr]; + while (more) { + alt (p.peek()) { + case (token.RPAREN) { + hi = p.get_span(); + p.bump(); + more = false; + } + case (token.WITH) { + p.bump(); + base = some[@ast.expr](parse_expr(p)); + hi = p.get_span(); + expect(p, token.RPAREN); + more = false; + } + case (token.COMMA) { + p.bump(); + fields += parse_field(p); + } + case (?t) { + unexpected(p, t); + } + } + + } + + ex = ast.expr_rec(fields, base, ast.ann_none); } case (token.BIND) { @@ -1370,7 +1393,7 @@ fn stmt_ends_with_semi(@ast.stmt stmt) -> bool { alt (e.node) { case (ast.expr_vec(_,_)) { ret true; } case (ast.expr_tup(_,_)) { ret true; } - case (ast.expr_rec(_,_)) { ret true; } + case (ast.expr_rec(_,_,_)) { ret true; } case (ast.expr_call(_,_,_)) { ret true; } case (ast.expr_binary(_,_,_,_)) { ret true; } case (ast.expr_unary(_,_,_)) { ret true; } diff --git a/src/comp/middle/fold.rs b/src/comp/middle/fold.rs index 5930ba75280..4ba65a7bb24 100644 --- a/src/comp/middle/fold.rs +++ b/src/comp/middle/fold.rs @@ -75,7 +75,8 @@ type ast_fold[ENV] = vec[ast.elt] es, ann a) -> @expr) fold_expr_tup, (fn(&ENV e, &span sp, - vec[ast.field] fields, ann a) -> @expr) fold_expr_rec, + vec[ast.field] fields, + option.t[@expr] base, ann a) -> @expr) fold_expr_rec, (fn(&ENV e, &span sp, @expr f, vec[@expr] args, @@ -479,12 +480,19 @@ fn fold_expr[ENV](&ENV env, ast_fold[ENV] fld, &@expr e) -> @expr { ret fld.fold_expr_tup(env_, e.span, elts, t); } - case (ast.expr_rec(?fs, ?t)) { + case (ast.expr_rec(?fs, ?base, ?t)) { let vec[ast.field] fields = vec(); + let option.t[@expr] b = none[@expr]; for (ast.field f in fs) { fields += fold_rec_field(env, fld, f); } - ret fld.fold_expr_rec(env_, e.span, fields, t); + alt (base) { + case (none[@ast.expr]) { } + case (some[@ast.expr](?eb)) { + b = some[@expr](fold_expr(env_, fld, eb)); + } + } + ret fld.fold_expr_rec(env_, e.span, fields, b, t); } case (ast.expr_call(?f, ?args, ?t)) { @@ -1011,8 +1019,9 @@ fn identity_fold_expr_tup[ENV](&ENV env, &span sp, } fn identity_fold_expr_rec[ENV](&ENV env, &span sp, - vec[ast.field] fields, ann a) -> @expr { - ret @respan(sp, ast.expr_rec(fields, a)); + vec[ast.field] fields, + option.t[@expr] base, ann a) -> @expr { + ret @respan(sp, ast.expr_rec(fields, base, a)); } fn identity_fold_expr_call[ENV](&ENV env, &span sp, @expr f, @@ -1358,7 +1367,7 @@ fn new_identity_fold[ENV]() -> ast_fold[ENV] { fold_expr_vec = bind identity_fold_expr_vec[ENV](_,_,_,_), fold_expr_tup = bind identity_fold_expr_tup[ENV](_,_,_,_), - fold_expr_rec = bind identity_fold_expr_rec[ENV](_,_,_,_), + fold_expr_rec = bind identity_fold_expr_rec[ENV](_,_,_,_,_), fold_expr_call = bind identity_fold_expr_call[ENV](_,_,_,_,_), fold_expr_bind = bind identity_fold_expr_bind[ENV](_,_,_,_,_), fold_expr_binary = bind identity_fold_expr_binary[ENV](_,_,_,_,_,_), diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index c1a4aa6f62a..972683e9ce4 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -2984,7 +2984,10 @@ fn trans_vec(@block_ctxt cx, vec[@ast.expr] args, } fn trans_rec(@block_ctxt cx, vec[ast.field] fields, - &ast.ann ann) -> result { + option.t[@ast.expr] base, &ast.ann ann) -> result { + + // FIXME: handle presence of a nonempty base. + check (base == none[@ast.expr]); auto bcx = cx; auto t = node_ann_type(bcx.fcx.ccx, ann); @@ -3099,8 +3102,8 @@ 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); + case (ast.expr_rec(?args, ?base, ?ann)) { + ret trans_rec(cx, args, base, ann); } // lval cases fall through to trans_lval and then diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index b9753474e3d..2083ef2b807 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -667,7 +667,7 @@ fn expr_ty(@ast.expr expr) -> @t { alt (expr.node) { case (ast.expr_vec(_, ?ann)) { ret ann_to_type(ann); } case (ast.expr_tup(_, ?ann)) { ret ann_to_type(ann); } - case (ast.expr_rec(_, ?ann)) { ret ann_to_type(ann); } + case (ast.expr_rec(_, _, ?ann)) { ret ann_to_type(ann); } case (ast.expr_bind(_, _, ?ann)) { ret ann_to_type(ann); } case (ast.expr_call(_, _, ?ann)) { ret ann_to_type(ann); } case (ast.expr_binary(_, _, _, ?ann)) { ret ann_to_type(ann); } diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 748dd879730..19e4a9b203b 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -910,7 +910,12 @@ fn demand_expr_full(&@fn_ctxt fcx, @ty.t expected, @ast.expr e, } e_1 = ast.expr_tup(elts_1, ast.ann_type(t)); } - case (ast.expr_rec(?fields_0, ?ann)) { + case (ast.expr_rec(?fields_0, ?base_0, ?ann)) { + + // FIXME: handle presence of a nonempty base. + check (base_0 == none[@ast.expr]); + auto base_1 = base_0; + auto t = demand(fcx, e.span, expected, ann_to_type(ann)); let vec[ast.field] fields_1 = vec(); alt (t.struct) { @@ -931,7 +936,7 @@ fn demand_expr_full(&@fn_ctxt fcx, @ty.t expected, @ast.expr e, fail; } } - e_1 = ast.expr_rec(fields_1, ast.ann_type(t)); + e_1 = ast.expr_rec(fields_1, base_1, ast.ann_type(t)); } case (ast.expr_bind(?sube, ?es, ?ann)) { auto t = demand(fcx, e.span, expected, ann_to_type(ann)); @@ -1610,7 +1615,12 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { ast.expr_tup(elts_1, ann)); } - case (ast.expr_rec(?fields, _)) { + case (ast.expr_rec(?fields, ?base, _)) { + + // FIXME: handle presence of a nonempty base. + check (base == none[@ast.expr]); + auto base_1 = base; + let vec[ast.field] fields_1 = vec(); let vec[field] fields_t = vec(); @@ -1626,7 +1636,7 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { auto ann = ast.ann_type(plain_ty(ty.ty_rec(fields_t))); ret @fold.respan[ast.expr_](expr.span, - ast.expr_rec(fields_1, ann)); + ast.expr_rec(fields_1, base_1, ann)); } case (ast.expr_field(?base, ?field, _)) {