提交 6c5a05b8 编写于 作者: P Patrick Walton

rustc: Implement the block syntax discussed on the mailing list

上级 6c4e9750
......@@ -39,6 +39,7 @@
type block = spanned[block_];
type block_ = rec(vec[@stmt] stmts,
option.t[@expr] expr,
hashmap[ident,uint] index);
type pat = spanned[pat_];
......
......@@ -761,7 +761,6 @@ fn spanned[T](&span lo, &span hi, &T node) -> ast.spanned[T] {
expect (p, token.LPAREN);
auto cond = parse_expr(p);
expect(p, token.RPAREN);
expect(p, token.SEMI);
hi = cond.span;
ret @spanned(lo, hi, ast.expr_do_while(body, cond, ast.ann_none));
}
......@@ -891,7 +890,6 @@ fn spanned[T](&span lo, &span hi, &T node) -> ast.spanned[T] {
auto init = parse_initializer(p);
auto hi = p.get_span();
expect(p, token.SEMI);
let ast.local local = rec(ty = some(ty),
infer = false,
......@@ -911,7 +909,6 @@ fn spanned[T](&span lo, &span hi, &T node) -> ast.spanned[T] {
auto init = parse_initializer(p);
auto hi = p.get_span();
expect(p, token.SEMI);
let ast.local local = rec(ty = none[@ast.ty],
infer = true,
......@@ -931,7 +928,6 @@ fn spanned[T](&span lo, &span hi, &T node) -> ast.spanned[T] {
p.bump();
auto e = parse_expr(p);
auto hi = p.get_span();
expect(p, token.SEMI);
ret @spanned(lo, hi, ast.stmt_log(e));
}
......@@ -941,7 +937,6 @@ fn spanned[T](&span lo, &span hi, &T node) -> ast.spanned[T] {
case (token.LPAREN) {
auto e = parse_expr(p);
auto hi = p.get_span();
expect(p, token.SEMI);
ret @spanned(lo, hi, ast.stmt_check_expr(e));
}
case (_) {
......@@ -954,13 +949,11 @@ fn spanned[T](&span lo, &span hi, &T node) -> ast.spanned[T] {
p.bump();
alt (p.peek()) {
case (token.SEMI) {
p.bump();
ret @spanned(lo, p.get_span(),
ast.stmt_ret(none[@ast.expr]));
}
case (_) {
auto e = parse_expr(p);
expect(p, token.SEMI);
ret @spanned(lo, e.span,
ast.stmt_ret(some[@ast.expr](e)));
}
......@@ -1012,7 +1005,6 @@ fn spanned[T](&span lo, &span hi, &T node) -> ast.spanned[T] {
case (_) {
auto e = parse_expr(p);
auto hi = p.get_span();
expect(p, token.SEMI);
ret @spanned(lo, hi, ast.stmt_expr(e));
}
}
......@@ -1020,16 +1012,10 @@ fn spanned[T](&span lo, &span hi, &T node) -> ast.spanned[T] {
fail;
}
impure fn parse_block(parser p) -> ast.block {
auto f = parse_stmt;
// FIXME: passing parse_stmt as an lval doesn't work at the moment.
auto stmts = parse_seq[@ast.stmt](token.LBRACE,
token.RBRACE,
none[token.token],
f, p);
fn index_block(vec[@ast.stmt] stmts, option.t[@ast.expr] expr) -> ast.block_ {
auto index = new_str_hash[uint]();
auto u = 0u;
for (@ast.stmt s in stmts.node) {
for (@ast.stmt s in stmts) {
// FIXME: typestate bug requires we do this up top, not
// down below loop. Sigh.
u += 1u;
......@@ -1056,8 +1042,103 @@ fn spanned[T](&span lo, &span hi, &T node) -> ast.spanned[T] {
}
}
}
let ast.block_ b = rec(stmts=stmts.node, index=index);
ret spanned(stmts.span, stmts.span, b);
ret rec(stmts=stmts, expr=expr, index=index);
}
fn stmt_to_expr(@ast.stmt stmt) -> option.t[@ast.expr] {
alt (stmt.node) {
case (ast.stmt_expr(?e)) { ret some[@ast.expr](e); }
case (_) { /* fall through */ }
}
ret none[@ast.expr];
}
fn stmt_ends_with_semi(@ast.stmt stmt) -> bool {
alt (stmt.node) {
case (ast.stmt_decl(_)) { ret true; } // FIXME
case (ast.stmt_ret(_)) { ret true; }
case (ast.stmt_log(_)) { ret true; }
case (ast.stmt_check_expr(_)) { ret true; }
case (ast.stmt_expr(?e)) {
alt (e.node) {
case (ast.expr_vec(_,_)) { ret true; }
case (ast.expr_tup(_,_)) { 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; }
case (ast.expr_lit(_,_)) { ret true; }
case (ast.expr_cast(_,_,_)) { ret true; }
case (ast.expr_if(_,_,_,_)) { ret false; }
case (ast.expr_while(_,_,_)) { ret false; }
case (ast.expr_do_while(_,_,_)) { ret false; }
case (ast.expr_alt(_,_,_)) { ret false; }
case (ast.expr_block(_,_)) { ret false; }
case (ast.expr_assign(_,_,_)) { ret true; }
case (ast.expr_field(_,_,_)) { ret true; }
case (ast.expr_index(_,_,_)) { ret true; }
case (ast.expr_name(_,_,_)) { ret true; }
case (_) { fail; }
}
}
case (_) { fail; }
}
}
impure fn parse_block(parser p) -> ast.block {
auto lo = p.get_span();
let vec[@ast.stmt] stmts = vec();
let option.t[@ast.expr] expr = none[@ast.expr];
expect(p, token.LBRACE);
while (p.peek() != token.RBRACE) {
alt (p.peek()) {
case (token.RBRACE) {
// empty; fall through to next iteration
}
case (token.SEMI) {
p.bump();
// empty
}
case (_) {
auto stmt = parse_stmt(p);
alt (stmt_to_expr(stmt)) {
case (some[@ast.expr](?e)) {
alt (p.peek()) {
case (token.SEMI) {
p.bump();
stmts += vec(stmt);
}
case (token.RBRACE) { expr = some(e); }
case (?t) {
if (stmt_ends_with_semi(stmt)) {
p.err("expected ';' or '}' after " +
"expression but found " +
token.to_str(t));
fail;
}
stmts += vec(stmt);
}
}
}
case (none[@ast.expr]) {
// Not an expression statement.
stmts += vec(stmt);
if (stmt_ends_with_semi(stmt)) {
expect(p, token.SEMI);
}
}
}
}
}
}
p.bump();
auto hi = p.get_span();
auto bloc = index_block(stmts, expr);
ret spanned[ast.block_](lo, hi, bloc);
}
impure fn parse_ty_param(parser p) -> ast.ty_param {
......
......@@ -529,7 +529,19 @@ fn fold_block[ENV](&ENV env, ast_fold[ENV] fld, &block blk) -> block {
for (@ast.stmt s in blk.node.stmts) {
append[@ast.stmt](stmts, fold_stmt[ENV](env_, fld, s));
}
ret respan(blk.span, rec(stmts=stmts with blk.node));
auto expr = none[@ast.expr];
alt (blk.node.expr) {
case (some[@ast.expr](?e)) {
expr = some[@ast.expr](fold_expr[ENV](env_, fld, e));
}
case (none[@ast.expr]) {
// empty
}
}
// FIXME: should we reindex?
ret respan(blk.span, rec(stmts=stmts, expr=expr, index=blk.node.index));
}
fn fold_arg[ENV](&ENV env, ast_fold[ENV] fld, &arg a) -> arg {
......
......@@ -1488,6 +1488,19 @@ fn trans_block_cleanups(@block_ctxt cx,
}
}
alt (b.node.expr) {
case (some[@ast.expr](?e)) {
r = trans_expr(bcx, e);
bcx = r.bcx;
if (is_terminated(bcx)) {
ret r;
}
}
case (none[@ast.expr]) {
r = res(bcx, C_nil());
}
}
bcx = trans_block_cleanups(bcx, bcx);
ret res(bcx, r.val);
}
......
......@@ -398,19 +398,6 @@ fn trans_ty_item_to_ty(@hashmap[ast.def_id,@ast.item] id_to_ty_item,
// Expression utilities
fn last_expr_of_block(&ast.block bloc) -> option.t[@ast.expr] {
auto len = _vec.len[@ast.stmt](bloc.node.stmts);
if (len == 0u) {
ret none[@ast.expr];
}
auto last_stmt = bloc.node.stmts.(len - 1u);
alt (last_stmt.node) {
case (ast.stmt_expr(?e)) { ret some[@ast.expr](e); }
case (_) { ret none[@ast.expr]; }
}
}
fn field_num(session.session sess, &span sp, &ast.ident id) -> uint {
let uint accum = 0u;
let uint i = 0u;
......@@ -546,7 +533,7 @@ fn stmt_ty(@ast.stmt s) -> @ty {
}
fn block_ty(&ast.block b) -> @ty {
alt (last_expr_of_block(b)) {
alt (b.node.expr) {
case (some[@ast.expr](?e)) { ret expr_ty(e); }
case (none[@ast.expr]) { ret plain_ty(ty_nil); }
}
......@@ -965,18 +952,12 @@ fn demand_expr(&fn_ctxt fcx, @ty expected, @ast.expr e) -> @ast.expr {
// Type unification over typed blocks.
fn demand_block(&fn_ctxt fcx, @ty expected, &ast.block bloc) -> ast.block {
alt (last_expr_of_block(bloc)) {
alt (bloc.node.expr) {
case (some[@ast.expr](?e_0)) {
auto e_1 = demand_expr(fcx, expected, e_0);
auto len = _vec.len[@ast.stmt](bloc.node.stmts);
auto last_stmt_0 = bloc.node.stmts.(len - 1u);
auto prev_stmts = _vec.pop[@ast.stmt](bloc.node.stmts);
auto last_stmt_1 = @fold.respan[ast.stmt_](last_stmt_0.span,
ast.stmt_expr(e_1));
auto stmts_1 = prev_stmts + vec(last_stmt_1);
auto block_ = rec(stmts=stmts_1, index=bloc.node.index);
auto block_ = rec(stmts=bloc.node.stmts,
expr=some[@ast.expr](e_1),
index=bloc.node.index);
ret fold.respan[ast.block_](bloc.span, block_);
}
case (none[@ast.expr]) {
......@@ -1386,8 +1367,18 @@ fn check_block(&fn_ctxt fcx, &ast.block block) -> ast.block {
for (@ast.stmt s in block.node.stmts) {
append[@ast.stmt](stmts, check_stmt(fcx, s));
}
auto expr = none[@ast.expr];
alt (block.node.expr) {
case (none[@ast.expr]) { /* empty */ }
case (some[@ast.expr](?e)) {
expr = some[@ast.expr](check_expr(fcx, e));
}
}
ret fold.respan[ast.block_](block.span,
rec(stmts=stmts, index=block.node.index));
rec(stmts=stmts, expr=expr,
index=block.node.index));
}
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,
locals = local_ty_table,
ccx = ccx);
// TODO: Make sure the type of the block agrees with the function type.
auto block_t = check_block(fcx, f.body);
auto block_wb = writeback(fcx, block_t);
auto fn_t = rec(inputs=f.inputs, output=f.output, body=block_wb);
auto item = ast.item_fn(ident, fn_t, ty_params, id, fn_ann);
ret @fold.respan[ast.item_](sp, item);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册