@@ -14,6 +14,12 @@ tag restriction { UNRESTRICTED; RESTRICT_NO_CALL_EXPRS; RESTRICT_NO_BAR_OP; }
14
14
15
15
tag file_type { CRATE_FILE ; SOURCE_FILE ; }
16
16
17
+ tag fn_kw {
18
+ fn_kw_fn;
19
+ fn_kw_lambda;
20
+ fn_kw_block;
21
+ } ;
22
+
17
23
type parse_sess = @{ cm : codemap:: codemap , mutable next_id: node_id } ;
18
24
19
25
fn next_node_id ( sess : parse_sess ) -> node_id {
@@ -536,7 +542,14 @@ fn parse_ty(p: parser, colons_before_params: bool) -> @ast::ty {
536
542
} else if eat_word ( p, "block" ) {
537
543
t = parse_ty_fn ( ast:: proto_block, p) ;
538
544
} else if eat_word ( p, "lambda" ) {
539
- t = parse_ty_fn ( ast:: proto_shared ( ast:: sugar_sexy) , p) ;
545
+ if p. peek ( ) == token:: LBRACE { // lambda[send](...)
546
+ expect ( p, token:: LBRACE ) ;
547
+ expect_word ( p, "send" ) ;
548
+ expect ( p, token:: RBRACE ) ;
549
+ t = parse_ty_fn ( ast:: proto_send, p) ;
550
+ } else { // lambda(...)
551
+ t = parse_ty_fn ( ast:: proto_shared ( ast:: sugar_sexy) , p) ;
552
+ }
540
553
} else if eat_word ( p, "obj" ) {
541
554
t = parse_ty_obj ( p) ;
542
555
} else if p. peek ( ) == token:: MOD_SEP || is_ident ( p. peek ( ) ) {
@@ -831,11 +844,11 @@ fn parse_bottom_expr(p: parser) -> @ast::expr {
831
844
*/
832
845
} else if eat_word ( p, "fn" ) {
833
846
let proto = parse_fn_anon_proto ( p) ;
834
- ret parse_fn_expr ( p, proto ) ;
847
+ ret parse_fn_expr ( p, fn_kw_fn ) ;
835
848
} else if eat_word ( p, "block" ) {
836
- ret parse_fn_expr ( p, ast :: proto_block ) ;
849
+ ret parse_fn_expr ( p, fn_kw_block ) ;
837
850
} else if eat_word ( p, "lambda" ) {
838
- ret parse_fn_expr ( p, ast :: proto_shared ( ast :: sugar_sexy ) ) ;
851
+ ret parse_fn_expr ( p, fn_kw_lambda ) ;
839
852
} else if eat_word ( p, "unchecked" ) {
840
853
ret parse_block_expr ( p, lo, ast:: unchecked_blk) ;
841
854
} else if eat_word ( p, "unsafe" ) {
@@ -1274,12 +1287,78 @@ fn parse_if_expr(p: parser) -> @ast::expr {
1274
1287
}
1275
1288
}
1276
1289
1277
- fn parse_fn_expr ( p : parser , proto : ast:: proto ) -> @ast:: expr {
1290
+ // Parses:
1291
+ //
1292
+ // CC := [send; copy ID*; move ID*]
1293
+ //
1294
+ // where any part is optional and trailing ; is permitted.
1295
+ fn parse_capture_clause ( p : parser ) -> ( bool , @ast:: capture ) {
1296
+ fn expect_opt_trailing_semi ( p : parser ) {
1297
+ if !eat ( p, token:: SEMI ) {
1298
+ if p. peek ( ) != token:: RBRACE {
1299
+ p. fatal ( "expecting ; or ]" ) ;
1300
+ }
1301
+ }
1302
+ }
1303
+
1304
+ fn eat_ident_list ( p : parser ) -> [ ast:: ident ] {
1305
+ let res = [ ] ;
1306
+ while true {
1307
+ alt p. peek ( ) {
1308
+ token:: IDENT ( _, _) {
1309
+ res += parse_ident ( p) ;
1310
+ if !eat ( p, token:: COMMA ) {
1311
+ ret res;
1312
+ }
1313
+ }
1314
+
1315
+ _ { ret res; }
1316
+ }
1317
+ }
1318
+ }
1319
+
1320
+ let is_send = false ;
1321
+ let copies = [ ] ;
1322
+ let moves = [ ] ;
1323
+
1324
+ if p. peek ( ) != token:: LBRACE {
1325
+ ret ( is_send, captures) ;
1326
+ }
1327
+
1328
+ expect ( p, token:: LBRACE ) ;
1329
+ while p. peek ( ) != token:: RBRACE {
1330
+ if eat_word ( p, "send" ) {
1331
+ is_send = true ;
1332
+ expect_opt_trailing_semi ( p) ;
1333
+ } else if eat_word ( p, "copy" ) {
1334
+ copies += eat_ident_list ( ) ;
1335
+ expect_opt_trailing_semi ( p) ;
1336
+ } else if eat_word ( p, "move" ) {
1337
+ moves += eat_ident_list ( ) ;
1338
+ expect_opt_trailing_semi ( p) ;
1339
+ } else {
1340
+ let s: str = "expecting send, copy, or move clause" ;
1341
+ p. fatal ( s) ;
1342
+ }
1343
+ }
1344
+
1345
+ ret @{ is_send : is_send, copies : copies, moves : moves} ;
1346
+ }
1347
+
1348
+ fn parse_fn_expr ( p : parser , kw : fn_kw ) -> @ast:: expr {
1278
1349
let lo = p. get_last_lo_pos ( ) ;
1350
+ let cap = parse_capture_clause ( p) ;
1279
1351
let decl = parse_fn_decl ( p, ast:: impure_fn, ast:: il_normal) ;
1280
1352
let body = parse_block ( p) ;
1353
+ let proto = alt ( kw, cap. is_send ) {
1354
+ ( fn_kw_fn. , true ) { ast:: proto_bare }
1355
+ ( fn_kw_lambda. , true ) { ast:: proto_send }
1356
+ ( fn_kw_lambda. , false ) { ast:: proto_shared ( ast:: sugar_sexy) }
1357
+ ( fn_kw_block. , false ) { ast:: proto_block }
1358
+ ( _, true ) { p. fatal ( "only lambda can be declared sendable" ) ; }
1359
+ }
1281
1360
let _fn = { decl: decl, proto: proto, body: body} ;
1282
- ret mk_expr( p, lo, body. span . hi , ast:: expr_fn ( _fn) ) ;
1361
+ ret mk_expr( p, lo, body. span . hi , ast:: expr_fn ( _fn, cap ) ) ;
1283
1362
}
1284
1363
1285
1364
fn parse_fn_block_expr ( p : parser ) -> @ast:: expr {
0 commit comments