aboutsummaryrefslogtreecommitdiff
path: root/src/comp
diff options
context:
space:
mode:
authorPatrick Walton <[email protected]>2010-11-29 17:11:03 -0800
committerPatrick Walton <[email protected]>2010-11-29 17:11:41 -0800
commit6c5a05b819c4dc7e3c47056a61a27fa4f11a364f (patch)
treef0f8e89877aceb4bb1c906925c270d38c01be372 /src/comp
parentTeach fold about ty_rec. (diff)
downloadrust-6c5a05b819c4dc7e3c47056a61a27fa4f11a364f.tar.xz
rust-6c5a05b819c4dc7e3c47056a61a27fa4f11a364f.zip
rustc: Implement the block syntax discussed on the mailing list
Diffstat (limited to 'src/comp')
-rw-r--r--src/comp/front/ast.rs1
-rw-r--r--src/comp/front/parser.rs117
-rw-r--r--src/comp/middle/fold.rs14
-rw-r--r--src/comp/middle/trans.rs13
-rw-r--r--src/comp/middle/typeck.rs43
5 files changed, 144 insertions, 44 deletions
diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs
index f90f8df6..a1670c70 100644
--- a/src/comp/front/ast.rs
+++ b/src/comp/front/ast.rs
@@ -39,6 +39,7 @@ type crate_ = rec(_mod module);
type block = spanned[block_];
type block_ = rec(vec[@stmt] stmts,
+ option.t[@expr] expr,
hashmap[ident,uint] index);
type pat = spanned[pat_];
diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs
index f0014f6b..b23fa0aa 100644
--- a/src/comp/front/parser.rs
+++ b/src/comp/front/parser.rs
@@ -761,7 +761,6 @@ impure fn parse_do_while_expr(parser p) -> @ast.expr {
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 @@ impure fn parse_let(parser p) -> @ast.decl {
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 @@ impure fn parse_auto(parser p) -> @ast.decl {
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 @@ impure fn parse_stmt(parser p) -> @ast.stmt {
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 @@ impure fn parse_stmt(parser p) -> @ast.stmt {
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 @@ impure fn parse_stmt(parser p) -> @ast.stmt {
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 @@ impure fn parse_stmt(parser p) -> @ast.stmt {
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 @@ impure fn parse_stmt(parser p) -> @ast.stmt {
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 @@ impure fn parse_block(parser p) -> ast.block {
}
}
}
- 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 {
diff --git a/src/comp/middle/fold.rs b/src/comp/middle/fold.rs
index ff8f5505..c97dceb4 100644
--- a/src/comp/middle/fold.rs
+++ b/src/comp/middle/fold.rs
@@ -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 {
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index 9aa367d5..8caaf5f7 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -1488,6 +1488,19 @@ impure fn trans_block(@block_ctxt cx, &ast.block b) -> result {
}
}
+ 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);
}
diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs
index 0aabcac3..58f723bd 100644
--- a/src/comp/middle/typeck.rs
+++ b/src/comp/middle/typeck.rs
@@ -398,19 +398,6 @@ fn collect_item_types(@ast.crate crate) -> tup(@ast.crate, @ty_table) {
// 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);