diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2011-12-08 11:47:01 -0800 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2011-12-14 14:32:17 -0800 |
| commit | 941101a9cdcd45e674e8ef57201a99a9d454e89f (patch) | |
| tree | f02c79b4ec97cfe503b95cad9c29b9328a2a6b74 /src/comp/syntax/parse | |
| parent | 327ec89f693afcc901bbe3a82b0bb5b5eb1dc44d (diff) | |
| download | rust-941101a9cdcd45e674e8ef57201a99a9d454e89f.tar.gz rust-941101a9cdcd45e674e8ef57201a99a9d454e89f.zip | |
define ty and update parser for sendable lambdas
Diffstat (limited to 'src/comp/syntax/parse')
| -rw-r--r-- | src/comp/syntax/parse/parser.rs | 91 |
1 files changed, 85 insertions, 6 deletions
diff --git a/src/comp/syntax/parse/parser.rs b/src/comp/syntax/parse/parser.rs index 7ff08181e1a..e927ffbbeff 100644 --- a/src/comp/syntax/parse/parser.rs +++ b/src/comp/syntax/parse/parser.rs @@ -14,6 +14,12 @@ tag restriction { UNRESTRICTED; RESTRICT_NO_CALL_EXPRS; RESTRICT_NO_BAR_OP; } tag file_type { CRATE_FILE; SOURCE_FILE; } +tag fn_kw { + fn_kw_fn; + fn_kw_lambda; + fn_kw_block; +}; + type parse_sess = @{cm: codemap::codemap, mutable next_id: node_id}; fn next_node_id(sess: parse_sess) -> node_id { @@ -536,7 +542,14 @@ fn parse_ty(p: parser, colons_before_params: bool) -> @ast::ty { } else if eat_word(p, "block") { t = parse_ty_fn(ast::proto_block, p); } else if eat_word(p, "lambda") { - t = parse_ty_fn(ast::proto_shared(ast::sugar_sexy), p); + if p.peek() == token::LBRACE { // lambda[send](...) + expect(p, token::LBRACE); + expect_word(p, "send"); + expect(p, token::RBRACE); + t = parse_ty_fn(ast::proto_send, p); + } else { // lambda(...) + t = parse_ty_fn(ast::proto_shared(ast::sugar_sexy), p); + } } else if eat_word(p, "obj") { t = parse_ty_obj(p); } else if p.peek() == token::MOD_SEP || is_ident(p.peek()) { @@ -831,11 +844,11 @@ fn parse_bottom_expr(p: parser) -> @ast::expr { */ } else if eat_word(p, "fn") { let proto = parse_fn_anon_proto(p); - ret parse_fn_expr(p, proto); + ret parse_fn_expr(p, fn_kw_fn); } else if eat_word(p, "block") { - ret parse_fn_expr(p, ast::proto_block); + ret parse_fn_expr(p, fn_kw_block); } else if eat_word(p, "lambda") { - ret parse_fn_expr(p, ast::proto_shared(ast::sugar_sexy)); + ret parse_fn_expr(p, fn_kw_lambda); } else if eat_word(p, "unchecked") { ret parse_block_expr(p, lo, ast::unchecked_blk); } else if eat_word(p, "unsafe") { @@ -1274,12 +1287,78 @@ fn parse_if_expr(p: parser) -> @ast::expr { } } -fn parse_fn_expr(p: parser, proto: ast::proto) -> @ast::expr { +// Parses: +// +// CC := [send; copy ID*; move ID*] +// +// where any part is optional and trailing ; is permitted. +fn parse_capture_clause(p: parser) -> (bool, @ast::capture) { + fn expect_opt_trailing_semi(p: parser) { + if !eat(p, token::SEMI) { + if p.peek() != token::RBRACE { + p.fatal("expecting ; or ]"); + } + } + } + + fn eat_ident_list(p: parser) -> [ast::ident] { + let res = []; + while true { + alt p.peek() { + token::IDENT(_, _) { + res += parse_ident(p); + if !eat(p, token::COMMA) { + ret res; + } + } + + _ { ret res; } + } + } + } + + let is_send = false; + let copies = []; + let moves = []; + + if p.peek() != token::LBRACE { + ret (is_send, captures); + } + + expect(p, token::LBRACE); + while p.peek() != token::RBRACE { + if eat_word(p, "send") { + is_send = true; + expect_opt_trailing_semi(p); + } else if eat_word(p, "copy") { + copies += eat_ident_list(); + expect_opt_trailing_semi(p); + } else if eat_word(p, "move") { + moves += eat_ident_list(); + expect_opt_trailing_semi(p); + } else { + let s: str = "expecting send, copy, or move clause"; + p.fatal(s); + } + } + + ret @{is_send: is_send, copies: copies, moves: moves}; +} + +fn parse_fn_expr(p: parser, kw: fn_kw) -> @ast::expr { let lo = p.get_last_lo_pos(); + let cap = parse_capture_clause(p); let decl = parse_fn_decl(p, ast::impure_fn, ast::il_normal); let body = parse_block(p); + let proto = alt (kw, cap.is_send) { + (fn_kw_fn., true) { ast::proto_bare } + (fn_kw_lambda., true) { ast::proto_send } + (fn_kw_lambda., false) { ast::proto_shared(ast::sugar_sexy) } + (fn_kw_block., false) { ast::proto_block } + (_, true) { p.fatal("only lambda can be declared sendable"); } + } let _fn = {decl: decl, proto: proto, body: body}; - ret mk_expr(p, lo, body.span.hi, ast::expr_fn(_fn)); + ret mk_expr(p, lo, body.span.hi, ast::expr_fn(_fn, cap)); } fn parse_fn_block_expr(p: parser) -> @ast::expr { |
