Skip to content

Commit 6c5a05b

Browse files
committed
rustc: Implement the block syntax discussed on the mailing list
1 parent 6c4e975 commit 6c5a05b

File tree

5 files changed

+144
-44
lines changed

5 files changed

+144
-44
lines changed

src/comp/front/ast.rs

+1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ type crate_ = rec(_mod module);
3939

4040
type block = spanned[block_];
4141
type block_ = rec(vec[@stmt] stmts,
42+
option.t[@expr] expr,
4243
hashmap[ident,uint] index);
4344

4445
type pat = spanned[pat_];

src/comp/front/parser.rs

+99-18
Original file line numberDiff line numberDiff line change
@@ -761,7 +761,6 @@ impure fn parse_do_while_expr(parser p) -> @ast.expr {
761761
expect (p, token.LPAREN);
762762
auto cond = parse_expr(p);
763763
expect(p, token.RPAREN);
764-
expect(p, token.SEMI);
765764
hi = cond.span;
766765
ret @spanned(lo, hi, ast.expr_do_while(body, cond, ast.ann_none));
767766
}
@@ -891,7 +890,6 @@ impure fn parse_let(parser p) -> @ast.decl {
891890
auto init = parse_initializer(p);
892891

893892
auto hi = p.get_span();
894-
expect(p, token.SEMI);
895893

896894
let ast.local local = rec(ty = some(ty),
897895
infer = false,
@@ -911,7 +909,6 @@ impure fn parse_auto(parser p) -> @ast.decl {
911909
auto init = parse_initializer(p);
912910

913911
auto hi = p.get_span();
914-
expect(p, token.SEMI);
915912

916913
let ast.local local = rec(ty = none[@ast.ty],
917914
infer = true,
@@ -931,7 +928,6 @@ impure fn parse_stmt(parser p) -> @ast.stmt {
931928
p.bump();
932929
auto e = parse_expr(p);
933930
auto hi = p.get_span();
934-
expect(p, token.SEMI);
935931
ret @spanned(lo, hi, ast.stmt_log(e));
936932
}
937933

@@ -941,7 +937,6 @@ impure fn parse_stmt(parser p) -> @ast.stmt {
941937
case (token.LPAREN) {
942938
auto e = parse_expr(p);
943939
auto hi = p.get_span();
944-
expect(p, token.SEMI);
945940
ret @spanned(lo, hi, ast.stmt_check_expr(e));
946941
}
947942
case (_) {
@@ -954,13 +949,11 @@ impure fn parse_stmt(parser p) -> @ast.stmt {
954949
p.bump();
955950
alt (p.peek()) {
956951
case (token.SEMI) {
957-
p.bump();
958952
ret @spanned(lo, p.get_span(),
959953
ast.stmt_ret(none[@ast.expr]));
960954
}
961955
case (_) {
962956
auto e = parse_expr(p);
963-
expect(p, token.SEMI);
964957
ret @spanned(lo, e.span,
965958
ast.stmt_ret(some[@ast.expr](e)));
966959
}
@@ -1012,24 +1005,17 @@ impure fn parse_stmt(parser p) -> @ast.stmt {
10121005
case (_) {
10131006
auto e = parse_expr(p);
10141007
auto hi = p.get_span();
1015-
expect(p, token.SEMI);
10161008
ret @spanned(lo, hi, ast.stmt_expr(e));
10171009
}
10181010
}
10191011
p.err("expected statement");
10201012
fail;
10211013
}
10221014

1023-
impure fn parse_block(parser p) -> ast.block {
1024-
auto f = parse_stmt;
1025-
// FIXME: passing parse_stmt as an lval doesn't work at the moment.
1026-
auto stmts = parse_seq[@ast.stmt](token.LBRACE,
1027-
token.RBRACE,
1028-
none[token.token],
1029-
f, p);
1015+
fn index_block(vec[@ast.stmt] stmts, option.t[@ast.expr] expr) -> ast.block_ {
10301016
auto index = new_str_hash[uint]();
10311017
auto u = 0u;
1032-
for (@ast.stmt s in stmts.node) {
1018+
for (@ast.stmt s in stmts) {
10331019
// FIXME: typestate bug requires we do this up top, not
10341020
// down below loop. Sigh.
10351021
u += 1u;
@@ -1056,8 +1042,103 @@ impure fn parse_block(parser p) -> ast.block {
10561042
}
10571043
}
10581044
}
1059-
let ast.block_ b = rec(stmts=stmts.node, index=index);
1060-
ret spanned(stmts.span, stmts.span, b);
1045+
ret rec(stmts=stmts, expr=expr, index=index);
1046+
}
1047+
1048+
fn stmt_to_expr(@ast.stmt stmt) -> option.t[@ast.expr] {
1049+
alt (stmt.node) {
1050+
case (ast.stmt_expr(?e)) { ret some[@ast.expr](e); }
1051+
case (_) { /* fall through */ }
1052+
}
1053+
ret none[@ast.expr];
1054+
}
1055+
1056+
fn stmt_ends_with_semi(@ast.stmt stmt) -> bool {
1057+
alt (stmt.node) {
1058+
case (ast.stmt_decl(_)) { ret true; } // FIXME
1059+
case (ast.stmt_ret(_)) { ret true; }
1060+
case (ast.stmt_log(_)) { ret true; }
1061+
case (ast.stmt_check_expr(_)) { ret true; }
1062+
case (ast.stmt_expr(?e)) {
1063+
alt (e.node) {
1064+
case (ast.expr_vec(_,_)) { ret true; }
1065+
case (ast.expr_tup(_,_)) { ret true; }
1066+
case (ast.expr_rec(_,_)) { ret true; }
1067+
case (ast.expr_call(_,_,_)) { ret true; }
1068+
case (ast.expr_binary(_,_,_,_)) { ret true; }
1069+
case (ast.expr_unary(_,_,_)) { ret true; }
1070+
case (ast.expr_lit(_,_)) { ret true; }
1071+
case (ast.expr_cast(_,_,_)) { ret true; }
1072+
case (ast.expr_if(_,_,_,_)) { ret false; }
1073+
case (ast.expr_while(_,_,_)) { ret false; }
1074+
case (ast.expr_do_while(_,_,_)) { ret false; }
1075+
case (ast.expr_alt(_,_,_)) { ret false; }
1076+
case (ast.expr_block(_,_)) { ret false; }
1077+
case (ast.expr_assign(_,_,_)) { ret true; }
1078+
case (ast.expr_field(_,_,_)) { ret true; }
1079+
case (ast.expr_index(_,_,_)) { ret true; }
1080+
case (ast.expr_name(_,_,_)) { ret true; }
1081+
case (_) { fail; }
1082+
}
1083+
}
1084+
case (_) { fail; }
1085+
}
1086+
}
1087+
1088+
impure fn parse_block(parser p) -> ast.block {
1089+
auto lo = p.get_span();
1090+
1091+
let vec[@ast.stmt] stmts = vec();
1092+
let option.t[@ast.expr] expr = none[@ast.expr];
1093+
1094+
expect(p, token.LBRACE);
1095+
while (p.peek() != token.RBRACE) {
1096+
alt (p.peek()) {
1097+
case (token.RBRACE) {
1098+
// empty; fall through to next iteration
1099+
}
1100+
case (token.SEMI) {
1101+
p.bump();
1102+
// empty
1103+
}
1104+
case (_) {
1105+
auto stmt = parse_stmt(p);
1106+
alt (stmt_to_expr(stmt)) {
1107+
case (some[@ast.expr](?e)) {
1108+
alt (p.peek()) {
1109+
case (token.SEMI) {
1110+
p.bump();
1111+
stmts += vec(stmt);
1112+
}
1113+
case (token.RBRACE) { expr = some(e); }
1114+
case (?t) {
1115+
if (stmt_ends_with_semi(stmt)) {
1116+
p.err("expected ';' or '}' after " +
1117+
"expression but found " +
1118+
token.to_str(t));
1119+
fail;
1120+
}
1121+
stmts += vec(stmt);
1122+
}
1123+
}
1124+
}
1125+
case (none[@ast.expr]) {
1126+
// Not an expression statement.
1127+
stmts += vec(stmt);
1128+
if (stmt_ends_with_semi(stmt)) {
1129+
expect(p, token.SEMI);
1130+
}
1131+
}
1132+
}
1133+
}
1134+
}
1135+
}
1136+
1137+
p.bump();
1138+
auto hi = p.get_span();
1139+
1140+
auto bloc = index_block(stmts, expr);
1141+
ret spanned[ast.block_](lo, hi, bloc);
10611142
}
10621143

10631144
impure fn parse_ty_param(parser p) -> ast.ty_param {

src/comp/middle/fold.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -529,7 +529,19 @@ fn fold_block[ENV](&ENV env, ast_fold[ENV] fld, &block blk) -> block {
529529
for (@ast.stmt s in blk.node.stmts) {
530530
append[@ast.stmt](stmts, fold_stmt[ENV](env_, fld, s));
531531
}
532-
ret respan(blk.span, rec(stmts=stmts with blk.node));
532+
533+
auto expr = none[@ast.expr];
534+
alt (blk.node.expr) {
535+
case (some[@ast.expr](?e)) {
536+
expr = some[@ast.expr](fold_expr[ENV](env_, fld, e));
537+
}
538+
case (none[@ast.expr]) {
539+
// empty
540+
}
541+
}
542+
543+
// FIXME: should we reindex?
544+
ret respan(blk.span, rec(stmts=stmts, expr=expr, index=blk.node.index));
533545
}
534546

535547
fn fold_arg[ENV](&ENV env, ast_fold[ENV] fld, &arg a) -> arg {

src/comp/middle/trans.rs

+13
Original file line numberDiff line numberDiff line change
@@ -1488,6 +1488,19 @@ impure fn trans_block(@block_ctxt cx, &ast.block b) -> result {
14881488
}
14891489
}
14901490

1491+
alt (b.node.expr) {
1492+
case (some[@ast.expr](?e)) {
1493+
r = trans_expr(bcx, e);
1494+
bcx = r.bcx;
1495+
if (is_terminated(bcx)) {
1496+
ret r;
1497+
}
1498+
}
1499+
case (none[@ast.expr]) {
1500+
r = res(bcx, C_nil());
1501+
}
1502+
}
1503+
14911504
bcx = trans_block_cleanups(bcx, bcx);
14921505
ret res(bcx, r.val);
14931506
}

src/comp/middle/typeck.rs

+18-25
Original file line numberDiff line numberDiff line change
@@ -398,19 +398,6 @@ fn collect_item_types(@ast.crate crate) -> tup(@ast.crate, @ty_table) {
398398

399399
// Expression utilities
400400

401-
fn last_expr_of_block(&ast.block bloc) -> option.t[@ast.expr] {
402-
auto len = _vec.len[@ast.stmt](bloc.node.stmts);
403-
if (len == 0u) {
404-
ret none[@ast.expr];
405-
}
406-
auto last_stmt = bloc.node.stmts.(len - 1u);
407-
alt (last_stmt.node) {
408-
case (ast.stmt_expr(?e)) { ret some[@ast.expr](e); }
409-
case (_) { ret none[@ast.expr]; }
410-
}
411-
}
412-
413-
414401
fn field_num(session.session sess, &span sp, &ast.ident id) -> uint {
415402
let uint accum = 0u;
416403
let uint i = 0u;
@@ -546,7 +533,7 @@ fn stmt_ty(@ast.stmt s) -> @ty {
546533
}
547534

548535
fn block_ty(&ast.block b) -> @ty {
549-
alt (last_expr_of_block(b)) {
536+
alt (b.node.expr) {
550537
case (some[@ast.expr](?e)) { ret expr_ty(e); }
551538
case (none[@ast.expr]) { ret plain_ty(ty_nil); }
552539
}
@@ -965,18 +952,12 @@ fn demand_expr(&fn_ctxt fcx, @ty expected, @ast.expr e) -> @ast.expr {
965952

966953
// Type unification over typed blocks.
967954
fn demand_block(&fn_ctxt fcx, @ty expected, &ast.block bloc) -> ast.block {
968-
alt (last_expr_of_block(bloc)) {
955+
alt (bloc.node.expr) {
969956
case (some[@ast.expr](?e_0)) {
970957
auto e_1 = demand_expr(fcx, expected, e_0);
971-
972-
auto len = _vec.len[@ast.stmt](bloc.node.stmts);
973-
auto last_stmt_0 = bloc.node.stmts.(len - 1u);
974-
auto prev_stmts = _vec.pop[@ast.stmt](bloc.node.stmts);
975-
auto last_stmt_1 = @fold.respan[ast.stmt_](last_stmt_0.span,
976-
ast.stmt_expr(e_1));
977-
auto stmts_1 = prev_stmts + vec(last_stmt_1);
978-
979-
auto block_ = rec(stmts=stmts_1, index=bloc.node.index);
958+
auto block_ = rec(stmts=bloc.node.stmts,
959+
expr=some[@ast.expr](e_1),
960+
index=bloc.node.index);
980961
ret fold.respan[ast.block_](bloc.span, block_);
981962
}
982963
case (none[@ast.expr]) {
@@ -1386,8 +1367,18 @@ fn check_block(&fn_ctxt fcx, &ast.block block) -> ast.block {
13861367
for (@ast.stmt s in block.node.stmts) {
13871368
append[@ast.stmt](stmts, check_stmt(fcx, s));
13881369
}
1370+
1371+
auto expr = none[@ast.expr];
1372+
alt (block.node.expr) {
1373+
case (none[@ast.expr]) { /* empty */ }
1374+
case (some[@ast.expr](?e)) {
1375+
expr = some[@ast.expr](check_expr(fcx, e));
1376+
}
1377+
}
1378+
13891379
ret fold.respan[ast.block_](block.span,
1390-
rec(stmts=stmts, index=block.node.index));
1380+
rec(stmts=stmts, expr=expr,
1381+
index=block.node.index));
13911382
}
13921383

13931384
fn check_fn(&@crate_ctxt ccx, &span sp, ast.ident ident, &ast._fn f,
@@ -1411,8 +1402,10 @@ fn check_fn(&@crate_ctxt ccx, &span sp, ast.ident ident, &ast._fn f,
14111402
locals = local_ty_table,
14121403
ccx = ccx);
14131404

1405+
// TODO: Make sure the type of the block agrees with the function type.
14141406
auto block_t = check_block(fcx, f.body);
14151407
auto block_wb = writeback(fcx, block_t);
1408+
14161409
auto fn_t = rec(inputs=f.inputs, output=f.output, body=block_wb);
14171410
auto item = ast.item_fn(ident, fn_t, ty_params, id, fn_ann);
14181411
ret @fold.respan[ast.item_](sp, item);

0 commit comments

Comments
 (0)