Skip to content

Commit 941101a

Browse files
committed
define ty and update parser for sendable lambdas
1 parent 327ec89 commit 941101a

File tree

3 files changed

+97
-7
lines changed

3 files changed

+97
-7
lines changed

src/comp/middle/ty.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -980,6 +980,7 @@ fn type_kind(cx: ctxt, ty: t) -> ast::kind {
980980
alt proto {
981981
ast::proto_block. { ast::kind_noncopyable }
982982
ast::proto_shared(_) { ast::kind_copyable }
983+
ast::proto_send. { ast::kind_sendable }
983984
ast::proto_bare. { ast::kind_sendable }
984985
}
985986
}

src/comp/syntax/ast.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ tag proto_sugar {
113113

114114
tag proto {
115115
proto_bare;
116+
proto_send;
116117
proto_shared(proto_sugar);
117118
proto_block;
118119
}
@@ -198,7 +199,7 @@ tag expr_ {
198199
expr_for(@local, @expr, blk);
199200
expr_do_while(blk, @expr);
200201
expr_alt(@expr, [arm]);
201-
expr_fn(_fn);
202+
expr_fn(_fn, @capture);
202203
expr_block(blk);
203204

204205
/*
@@ -233,6 +234,15 @@ tag expr_ {
233234
expr_mac(mac);
234235
}
235236

237+
// At the moment, one can only capture local variables.
238+
type capture_ = {
239+
is_send: bool,
240+
copies: [ident],
241+
moves: [ident]
242+
};
243+
244+
type capture = spanned<capture_>;
245+
236246
/*
237247
// Says whether this is a block the user marked as
238248
// "unchecked"

src/comp/syntax/parse/parser.rs

Lines changed: 85 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@ tag restriction { UNRESTRICTED; RESTRICT_NO_CALL_EXPRS; RESTRICT_NO_BAR_OP; }
1414

1515
tag file_type { CRATE_FILE; SOURCE_FILE; }
1616

17+
tag fn_kw {
18+
fn_kw_fn;
19+
fn_kw_lambda;
20+
fn_kw_block;
21+
};
22+
1723
type parse_sess = @{cm: codemap::codemap, mutable next_id: node_id};
1824

1925
fn next_node_id(sess: parse_sess) -> node_id {
@@ -536,7 +542,14 @@ fn parse_ty(p: parser, colons_before_params: bool) -> @ast::ty {
536542
} else if eat_word(p, "block") {
537543
t = parse_ty_fn(ast::proto_block, p);
538544
} 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+
}
540553
} else if eat_word(p, "obj") {
541554
t = parse_ty_obj(p);
542555
} else if p.peek() == token::MOD_SEP || is_ident(p.peek()) {
@@ -831,11 +844,11 @@ fn parse_bottom_expr(p: parser) -> @ast::expr {
831844
*/
832845
} else if eat_word(p, "fn") {
833846
let proto = parse_fn_anon_proto(p);
834-
ret parse_fn_expr(p, proto);
847+
ret parse_fn_expr(p, fn_kw_fn);
835848
} else if eat_word(p, "block") {
836-
ret parse_fn_expr(p, ast::proto_block);
849+
ret parse_fn_expr(p, fn_kw_block);
837850
} 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);
839852
} else if eat_word(p, "unchecked") {
840853
ret parse_block_expr(p, lo, ast::unchecked_blk);
841854
} else if eat_word(p, "unsafe") {
@@ -1274,12 +1287,78 @@ fn parse_if_expr(p: parser) -> @ast::expr {
12741287
}
12751288
}
12761289

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 {
12781349
let lo = p.get_last_lo_pos();
1350+
let cap = parse_capture_clause(p);
12791351
let decl = parse_fn_decl(p, ast::impure_fn, ast::il_normal);
12801352
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+
}
12811360
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));
12831362
}
12841363

12851364
fn parse_fn_block_expr(p: parser) -> @ast::expr {

0 commit comments

Comments
 (0)