@@ -398,25 +398,51 @@ fn parse_arg_mode(p: parser) -> ast::mode {
398
398
} else { ast:: infer ( p. get_id ( ) ) }
399
399
}
400
400
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 {
402
422
let m = parse_arg_mode ( p) ;
403
423
let i = parse_value_ident ( p) ;
404
424
expect ( p, token:: COLON ) ;
405
425
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 ( ) } )
407
427
}
408
428
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
+ }
420
446
}
421
447
422
448
fn maybe_parse_dollar_mac ( p : parser ) -> option < ast:: mac_ > {
@@ -1149,74 +1175,27 @@ fn parse_if_expr(p: parser) -> @ast::expr {
1149
1175
}
1150
1176
}
1151
1177
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 ;
1187
1180
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) ;
1202
1182
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) ;
1205
1187
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) ;
1210
1188
let body = parse_block ( p) ;
1211
1189
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 ) ) ;
1213
1191
}
1214
1192
1215
1193
fn parse_fn_block_expr ( p : parser ) -> @ast:: expr {
1216
1194
let lo = p. last_span . lo ;
1217
- let decl = parse_fn_block_decl ( p) ;
1195
+ let ( decl, captures ) = parse_fn_block_decl ( p) ;
1218
1196
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) ) ;
1220
1199
}
1221
1200
1222
1201
fn parse_else_expr ( p : parser ) -> @ast:: expr {
@@ -1699,46 +1678,107 @@ fn parse_ty_params(p: parser) -> [ast::ty_param] {
1699
1678
} else { [ ] }
1700
1679
}
1701
1680
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 ] =
1705
1738
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
+
1707
1744
// Use the args list to translate each bound variable
1708
1745
// mentioned in a constraint to an arg index.
1709
1746
// Seems weird to do this in the parser, but I'm not sure how else to.
1710
1747
let mut constrs = [ ] ;
1711
1748
if p. token == token:: COLON {
1712
1749
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) ;
1714
1751
}
1715
1752
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 ) ;
1721
1758
}
1722
1759
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
+ } ;
1732
1771
let output = if eat ( p, token:: RARROW ) {
1733
1772
parse_ty ( p, false )
1734
1773
} else {
1735
1774
@{ id: p. get_id ( ) , node: ast:: ty_infer, span: p. span }
1736
1775
} ;
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) ) ;
1742
1782
}
1743
1783
1744
1784
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,
1760
1800
attrs : [ ast:: attribute ] ) -> @ast:: item {
1761
1801
let lo = p. last_span . lo ;
1762
1802
let t = parse_fn_header ( p) ;
1763
- let decl = parse_fn_decl ( p, purity) ;
1803
+ let ( decl, _ ) = parse_fn_decl ( p, purity, parse_arg ) ;
1764
1804
let ( inner_attrs, body) = parse_inner_attrs_and_block ( p, true ) ;
1765
1805
let attrs = attrs + inner_attrs;
1766
1806
ret mk_item( p, lo, body. span . hi , t. ident ,
@@ -1785,7 +1825,7 @@ fn parse_method(p: parser, pr: ast::privacy) -> @ast::method {
1785
1825
let lo = p. span . lo , pur = parse_fn_purity ( p) ;
1786
1826
let ident = parse_method_name ( p) ;
1787
1827
let tps = parse_ty_params ( p) ;
1788
- let decl = parse_fn_decl ( p, pur) ;
1828
+ let ( decl, _ ) = parse_fn_decl ( p, pur, parse_arg ) ;
1789
1829
let ( inner_attrs, body) = parse_inner_attrs_and_block ( p, true ) ;
1790
1830
let attrs = attrs + inner_attrs;
1791
1831
@{ 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)
1969
2009
let lo = p. last_span . lo ;
1970
2010
// Can ctors have attrs?
1971
2011
// 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 ) ;
1973
2013
let decl = { output : @{ id : p. get_id ( ) ,
1974
2014
node : ast:: ty_path ( class_name_with_tps, p. get_id ( ) ) ,
1975
2015
span : decl_. output . span }
@@ -2048,7 +2088,7 @@ fn parse_item_native_fn(p: parser, attrs: [ast::attribute],
2048
2088
purity : ast:: purity ) -> @ast:: native_item {
2049
2089
let lo = p. last_span . lo ;
2050
2090
let t = parse_fn_header ( p) ;
2051
- let decl = parse_fn_decl ( p, purity) ;
2091
+ let ( decl, _ ) = parse_fn_decl ( p, purity, parse_arg ) ;
2052
2092
let mut hi = p. span . hi ;
2053
2093
expect ( p, token:: SEMI ) ;
2054
2094
ret @{ ident : t. ident ,
0 commit comments