Skip to content

Commit 50ec6bd

Browse files
committed
new cap clause syntax
1 parent 8affc78 commit 50ec6bd

31 files changed

+444
-357
lines changed

src/fuzzer/fuzzer.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,11 +154,11 @@ fn steal(crate: ast::crate, tm: test_mode) -> stolen_stuff {
154154
fn safe_to_replace_expr(e: ast::expr_, _tm: test_mode) -> bool {
155155
alt e {
156156
// https://github.com/mozilla/rust/issues/652
157-
ast::expr_if(_, _, _) { false }
157+
ast::expr_if(*) { false }
158158
ast::expr_block(_) { false }
159159

160160
// expr_call is also missing a constraint
161-
ast::expr_fn_block(_, _) { false }
161+
ast::expr_fn_block(*) { false }
162162

163163
_ { true }
164164
}

src/libcore/vec.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1096,6 +1096,14 @@ impl extensions<T> for [T] {
10961096
#[inline]
10971097
fn map<U>(f: fn(T) -> U) -> [U] { map(self, f) }
10981098
#[doc = "
1099+
Apply a function to the index and value of each element in the vector
1100+
and return the results
1101+
"]
1102+
fn mapi<U>(f: fn(uint, T) -> U) -> [U] {
1103+
let mut i = 0u;
1104+
self.map { |e| i += 1u; f(i - 1u, e) }
1105+
}
1106+
#[doc = "
10991107
Apply a function to each element of a vector and return a concatenation
11001108
of each result vector
11011109
"]

src/librustsyntax/ast.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -311,8 +311,8 @@ enum expr_ {
311311
(implicit) condition is always true. */
312312
expr_loop(blk),
313313
expr_alt(@expr, [arm], alt_mode),
314-
expr_fn(proto, fn_decl, blk, @capture_clause),
315-
expr_fn_block(fn_decl, blk),
314+
expr_fn(proto, fn_decl, blk, capture_clause),
315+
expr_fn_block(fn_decl, blk, capture_clause),
316316
// Inner expr is always an expr_fn_block. We need the wrapping node to
317317
// sanely type this (a function returning nil on the inside but bool on
318318
// the outside).
@@ -356,15 +356,13 @@ enum expr_ {
356356
#[auto_serialize]
357357
type capture_item = {
358358
id: int,
359+
is_move: bool,
359360
name: ident, // Currently, can only capture a local var.
360361
span: span
361362
};
362363

363364
#[auto_serialize]
364-
type capture_clause = {
365-
copies: [@capture_item],
366-
moves: [@capture_item]
367-
};
365+
type capture_clause = [capture_item];
368366

369367
/*
370368
// Says whether this is a block the user marked as

src/librustsyntax/fold.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -456,8 +456,9 @@ fn noop_fold_expr(e: expr_, fld: ast_fold) -> expr_ {
456456
expr_fn(proto, fold_fn_decl(decl, fld),
457457
fld.fold_block(body), captures)
458458
}
459-
expr_fn_block(decl, body) {
460-
expr_fn_block(fold_fn_decl(decl, fld), fld.fold_block(body))
459+
expr_fn_block(decl, body, captures) {
460+
expr_fn_block(fold_fn_decl(decl, fld), fld.fold_block(body),
461+
captures)
461462
}
462463
expr_block(blk) { expr_block(fld.fold_block(blk)) }
463464
expr_move(el, er) {

src/librustsyntax/parse/parser.rs

Lines changed: 139 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -398,25 +398,51 @@ fn parse_arg_mode(p: parser) -> ast::mode {
398398
} else { ast::infer(p.get_id()) }
399399
}
400400

401-
fn parse_arg(p: parser) -> ast::arg {
401+
fn parse_capture_item_or(
402+
p: parser,
403+
parse_arg_fn: fn() -> arg_or_capture_item) -> arg_or_capture_item {
404+
405+
fn parse_capture_item(p: parser, is_move: bool) -> ast::capture_item {
406+
let id = p.get_id();
407+
let sp = mk_sp(p.span.lo, p.span.hi);
408+
let ident = parse_ident(p);
409+
{id: id, is_move: is_move, name: ident, span: sp}
410+
}
411+
412+
if eat_keyword(p, "move") {
413+
either::right(parse_capture_item(p, true))
414+
} else if eat_keyword(p, "copy") {
415+
either::right(parse_capture_item(p, false))
416+
} else {
417+
parse_arg_fn()
418+
}
419+
}
420+
421+
fn parse_arg(p: parser) -> arg_or_capture_item {
402422
let m = parse_arg_mode(p);
403423
let i = parse_value_ident(p);
404424
expect(p, token::COLON);
405425
let t = parse_ty(p, false);
406-
ret {mode: m, ty: t, ident: i, id: p.get_id()};
426+
either::left({mode: m, ty: t, ident: i, id: p.get_id()})
407427
}
408428

409-
fn parse_fn_block_arg(p: parser) -> ast::arg {
410-
let m = parse_arg_mode(p);
411-
let i = parse_value_ident(p);
412-
let t = if eat(p, token::COLON) {
413-
parse_ty(p, false)
414-
} else {
415-
@{id: p.get_id(),
416-
node: ast::ty_infer,
417-
span: mk_sp(p.span.lo, p.span.hi)}
418-
};
419-
ret {mode: m, ty: t, ident: i, id: p.get_id()};
429+
fn parse_arg_or_capture_item(p: parser) -> arg_or_capture_item {
430+
parse_capture_item_or(p) {|| parse_arg(p) }
431+
}
432+
433+
fn parse_fn_block_arg(p: parser) -> arg_or_capture_item {
434+
parse_capture_item_or(p) {||
435+
let m = parse_arg_mode(p);
436+
let i = parse_value_ident(p);
437+
let t = if eat(p, token::COLON) {
438+
parse_ty(p, false)
439+
} else {
440+
@{id: p.get_id(),
441+
node: ast::ty_infer,
442+
span: mk_sp(p.span.lo, p.span.hi)}
443+
};
444+
either::left({mode: m, ty: t, ident: i, id: p.get_id()})
445+
}
420446
}
421447

422448
fn maybe_parse_dollar_mac(p: parser) -> option<ast::mac_> {
@@ -1149,74 +1175,27 @@ fn parse_if_expr(p: parser) -> @ast::expr {
11491175
}
11501176
}
11511177

1152-
// Parses:
1153-
//
1154-
// CC := [copy ID*; move ID*]
1155-
//
1156-
// where any part is optional and trailing ; is permitted.
1157-
fn parse_capture_clause(p: parser) -> @ast::capture_clause {
1158-
fn expect_opt_trailing_semi(p: parser) {
1159-
if !eat(p, token::SEMI) {
1160-
if p.token != token::RBRACKET {
1161-
p.fatal("expecting ; or ]");
1162-
}
1163-
}
1164-
}
1165-
1166-
fn eat_ident_list(p: parser) -> [@ast::capture_item] {
1167-
let mut res = [];
1168-
loop {
1169-
alt p.token {
1170-
token::IDENT(_, _) {
1171-
let id = p.get_id();
1172-
let sp = mk_sp(p.span.lo, p.span.hi);
1173-
let ident = parse_ident(p);
1174-
res += [@{id:id, name:ident, span:sp}];
1175-
if !eat(p, token::COMMA) {
1176-
ret res;
1177-
}
1178-
}
1179-
1180-
_ { ret res; }
1181-
}
1182-
};
1183-
}
1184-
1185-
let mut copies = [];
1186-
let mut moves = [];
1178+
fn parse_fn_expr(p: parser, proto: ast::proto) -> @ast::expr {
1179+
let lo = p.last_span.lo;
11871180

1188-
if eat(p, token::LBRACKET) {
1189-
while !eat(p, token::RBRACKET) {
1190-
if eat_keyword(p, "copy") {
1191-
copies += eat_ident_list(p);
1192-
expect_opt_trailing_semi(p);
1193-
} else if eat_keyword(p, "move") {
1194-
moves += eat_ident_list(p);
1195-
expect_opt_trailing_semi(p);
1196-
} else {
1197-
let s: str = "expecting send, copy, or move clause";
1198-
p.fatal(s);
1199-
}
1200-
}
1201-
}
1181+
let cc_old = parse_old_skool_capture_clause(p);
12021182

1203-
ret @{copies: copies, moves: moves};
1204-
}
1183+
// if we want to allow fn expression argument types to be inferred in the
1184+
// future, just have to change parse_arg to parse_fn_block_arg.
1185+
let (decl, capture_clause) =
1186+
parse_fn_decl(p, ast::impure_fn, parse_arg_or_capture_item);
12051187

1206-
fn parse_fn_expr(p: parser, proto: ast::proto) -> @ast::expr {
1207-
let lo = p.last_span.lo;
1208-
let capture_clause = parse_capture_clause(p);
1209-
let decl = parse_fn_decl(p, ast::impure_fn);
12101188
let body = parse_block(p);
12111189
ret mk_expr(p, lo, body.span.hi,
1212-
ast::expr_fn(proto, decl, body, capture_clause));
1190+
ast::expr_fn(proto, decl, body, capture_clause + cc_old));
12131191
}
12141192

12151193
fn parse_fn_block_expr(p: parser) -> @ast::expr {
12161194
let lo = p.last_span.lo;
1217-
let decl = parse_fn_block_decl(p);
1195+
let (decl, captures) = parse_fn_block_decl(p);
12181196
let body = parse_block_tail(p, lo, ast::default_blk);
1219-
ret mk_expr(p, lo, body.span.hi, ast::expr_fn_block(decl, body));
1197+
ret mk_expr(p, lo, body.span.hi,
1198+
ast::expr_fn_block(decl, body, captures));
12201199
}
12211200

12221201
fn parse_else_expr(p: parser) -> @ast::expr {
@@ -1699,46 +1678,107 @@ fn parse_ty_params(p: parser) -> [ast::ty_param] {
16991678
} else { [] }
17001679
}
17011680

1702-
fn parse_fn_decl(p: parser, purity: ast::purity)
1703-
-> ast::fn_decl {
1704-
let inputs: ast::spanned<[ast::arg]> =
1681+
// FIXME Remove after snapshot
1682+
fn parse_old_skool_capture_clause(p: parser) -> ast::capture_clause {
1683+
fn expect_opt_trailing_semi(p: parser) {
1684+
if !eat(p, token::SEMI) {
1685+
if p.token != token::RBRACKET {
1686+
p.fatal("expecting ; or ]");
1687+
}
1688+
}
1689+
}
1690+
1691+
fn eat_ident_list(p: parser, is_move: bool) -> [ast::capture_item] {
1692+
let mut res = [];
1693+
loop {
1694+
alt p.token {
1695+
token::IDENT(_, _) {
1696+
let id = p.get_id();
1697+
let sp = mk_sp(p.span.lo, p.span.hi);
1698+
let ident = parse_ident(p);
1699+
res += [{id:id, is_move: is_move, name:ident, span:sp}];
1700+
if !eat(p, token::COMMA) {
1701+
ret res;
1702+
}
1703+
}
1704+
1705+
_ { ret res; }
1706+
}
1707+
};
1708+
}
1709+
1710+
let mut cap_items = [];
1711+
1712+
if eat(p, token::LBRACKET) {
1713+
while !eat(p, token::RBRACKET) {
1714+
if eat_keyword(p, "copy") {
1715+
cap_items += eat_ident_list(p, false);
1716+
expect_opt_trailing_semi(p);
1717+
} else if eat_keyword(p, "move") {
1718+
cap_items += eat_ident_list(p, true);
1719+
expect_opt_trailing_semi(p);
1720+
} else {
1721+
let s: str = "expecting send, copy, or move clause";
1722+
p.fatal(s);
1723+
}
1724+
}
1725+
}
1726+
1727+
ret cap_items;
1728+
}
1729+
1730+
type arg_or_capture_item = either<ast::arg, ast::capture_item>;
1731+
1732+
1733+
fn parse_fn_decl(p: parser, purity: ast::purity,
1734+
parse_arg_fn: fn(parser) -> arg_or_capture_item)
1735+
-> (ast::fn_decl, ast::capture_clause) {
1736+
1737+
let args_or_capture_items: [arg_or_capture_item] =
17051738
parse_seq(token::LPAREN, token::RPAREN, seq_sep(token::COMMA),
1706-
parse_arg, p);
1739+
parse_arg_fn, p).node;
1740+
1741+
let inputs = either::lefts(args_or_capture_items);
1742+
let capture_clause = either::rights(args_or_capture_items);
1743+
17071744
// Use the args list to translate each bound variable
17081745
// mentioned in a constraint to an arg index.
17091746
// Seems weird to do this in the parser, but I'm not sure how else to.
17101747
let mut constrs = [];
17111748
if p.token == token::COLON {
17121749
p.bump();
1713-
constrs = parse_constrs({|x| parse_ty_constr(inputs.node, x) }, p);
1750+
constrs = parse_constrs({|x| parse_ty_constr(inputs, x) }, p);
17141751
}
17151752
let (ret_style, ret_ty) = parse_ret_ty(p);
1716-
ret {inputs: inputs.node,
1717-
output: ret_ty,
1718-
purity: purity,
1719-
cf: ret_style,
1720-
constraints: constrs};
1753+
ret ({inputs: inputs,
1754+
output: ret_ty,
1755+
purity: purity,
1756+
cf: ret_style,
1757+
constraints: constrs}, capture_clause);
17211758
}
17221759

1723-
fn parse_fn_block_decl(p: parser) -> ast::fn_decl {
1724-
let inputs = if eat(p, token::OROR) {
1725-
[]
1726-
} else {
1727-
parse_seq(token::BINOP(token::OR),
1728-
token::BINOP(token::OR),
1729-
seq_sep(token::COMMA),
1730-
parse_fn_block_arg, p).node
1731-
};
1760+
fn parse_fn_block_decl(p: parser) -> (ast::fn_decl, ast::capture_clause) {
1761+
let inputs_captures = {
1762+
if eat(p, token::OROR) {
1763+
[]
1764+
} else {
1765+
parse_seq(token::BINOP(token::OR),
1766+
token::BINOP(token::OR),
1767+
seq_sep(token::COMMA),
1768+
parse_fn_block_arg, p).node
1769+
}
1770+
};
17321771
let output = if eat(p, token::RARROW) {
17331772
parse_ty(p, false)
17341773
} else {
17351774
@{id: p.get_id(), node: ast::ty_infer, span: p.span}
17361775
};
1737-
ret {inputs: inputs,
1738-
output: output,
1739-
purity: ast::impure_fn,
1740-
cf: ast::return_val,
1741-
constraints: []};
1776+
ret ({inputs: either::lefts(inputs_captures),
1777+
output: output,
1778+
purity: ast::impure_fn,
1779+
cf: ast::return_val,
1780+
constraints: []},
1781+
either::rights(inputs_captures));
17421782
}
17431783

17441784
fn parse_fn_header(p: parser) -> {ident: ast::ident, tps: [ast::ty_param]} {
@@ -1760,7 +1800,7 @@ fn parse_item_fn(p: parser, purity: ast::purity,
17601800
attrs: [ast::attribute]) -> @ast::item {
17611801
let lo = p.last_span.lo;
17621802
let t = parse_fn_header(p);
1763-
let decl = parse_fn_decl(p, purity);
1803+
let (decl, _) = parse_fn_decl(p, purity, parse_arg);
17641804
let (inner_attrs, body) = parse_inner_attrs_and_block(p, true);
17651805
let attrs = attrs + inner_attrs;
17661806
ret mk_item(p, lo, body.span.hi, t.ident,
@@ -1785,7 +1825,7 @@ fn parse_method(p: parser, pr: ast::privacy) -> @ast::method {
17851825
let lo = p.span.lo, pur = parse_fn_purity(p);
17861826
let ident = parse_method_name(p);
17871827
let tps = parse_ty_params(p);
1788-
let decl = parse_fn_decl(p, pur);
1828+
let (decl, _) = parse_fn_decl(p, pur, parse_arg);
17891829
let (inner_attrs, body) = parse_inner_attrs_and_block(p, true);
17901830
let attrs = attrs + inner_attrs;
17911831
@{ident: ident, attrs: attrs, tps: tps, decl: decl, body: body,
@@ -1969,7 +2009,7 @@ fn parse_class_item(p:parser, class_name_with_tps: @ast::path)
19692009
let lo = p.last_span.lo;
19702010
// Can ctors have attrs?
19712011
// result type is always the type of the class
1972-
let decl_ = parse_fn_decl(p, ast::impure_fn);
2012+
let (decl_, _) = parse_fn_decl(p, ast::impure_fn, parse_arg);
19732013
let decl = {output: @{id: p.get_id(),
19742014
node: ast::ty_path(class_name_with_tps, p.get_id()),
19752015
span: decl_.output.span}
@@ -2048,7 +2088,7 @@ fn parse_item_native_fn(p: parser, attrs: [ast::attribute],
20482088
purity: ast::purity) -> @ast::native_item {
20492089
let lo = p.last_span.lo;
20502090
let t = parse_fn_header(p);
2051-
let decl = parse_fn_decl(p, purity);
2091+
let (decl, _) = parse_fn_decl(p, purity, parse_arg);
20522092
let mut hi = p.span.hi;
20532093
expect(p, token::SEMI);
20542094
ret @{ident: t.ident,

0 commit comments

Comments
 (0)