Skip to content

Commit a178a62

Browse files
committed
Add async blocks & try blocks
In Rust 1.37, `catch`, `yield`, and `dyn` ceased to be "weak" keywords. This simplifies the grammar a bit \o/. `do catch { ... }` has turned into `try { ... }` and `async`-prefixed blocks are now a thing.
1 parent 9d509c4 commit a178a62

File tree

7 files changed

+73
-74
lines changed

7 files changed

+73
-74
lines changed

src/Language/Rust/Parser/Internal.y

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -171,11 +171,15 @@ import qualified Data.List.NonEmpty as N
171171

172172
-- Strict keywords used in the language
173173
as { Spanned (IdentTok "as") _ }
174+
async { Spanned (IdentTok "async") _ }
175+
await { Spanned (IdentTok "await") _ }
174176
box { Spanned (IdentTok "box") _ }
175177
break { Spanned (IdentTok "break") _ }
176178
const { Spanned (IdentTok "const") _ }
177179
continue { Spanned (IdentTok "continue") _ }
178180
crate { Spanned (IdentTok "crate") _ }
181+
do { Spanned (IdentTok "do") _ }
182+
dyn { Spanned (IdentTok "dyn") _ }
179183
else { Spanned (IdentTok "else") _ }
180184
enum { Spanned (IdentTok "enum") _ }
181185
extern { Spanned (IdentTok "extern") _ }
@@ -201,12 +205,13 @@ import qualified Data.List.NonEmpty as N
201205
super { Spanned (IdentTok "super") _ }
202206
trait { Spanned (IdentTok "trait") _ }
203207
true { Spanned (IdentTok "true") _ }
208+
try { Spanned (IdentTok "try") _ }
204209
type { Spanned (IdentTok "type") _ }
205210
unsafe { Spanned (IdentTok "unsafe") _ }
206211
use { Spanned (IdentTok "use") _ }
207212
where { Spanned (IdentTok "where") _ }
208213
while { Spanned (IdentTok "while") _ }
209-
do { Spanned (IdentTok "do") _ }
214+
yield { Spanned (IdentTok "yield") _ }
210215

211216
-- Keywords reserved for future use
212217
abstract { Spanned (IdentTok "abstract") _ }
@@ -227,10 +232,7 @@ import qualified Data.List.NonEmpty as N
227232
-- Weak keywords, have special meaning only in specific contexts.
228233
default { Spanned (IdentTok "default") _ }
229234
union { Spanned (IdentTok "union") _ }
230-
catch { Spanned (IdentTok "catch") _ }
231235
auto { Spanned (IdentTok "auto") _ }
232-
yield { Spanned (IdentTok "yield") _ }
233-
dyn { Spanned (IdentTok "dyn") _ }
234236

235237
-- Comments
236238
outerDoc { Spanned (Doc _ Outer _) _ }
@@ -277,7 +279,7 @@ import qualified Data.List.NonEmpty as N
277279
%nonassoc mut DEF EQ '::'
278280

279281
-- These are all identifiers of sorts ('union' and 'default' are "weak" keywords)
280-
%nonassoc IDENT ntIdent default union catch self Self super auto dyn crate
282+
%nonassoc IDENT ntIdent default union self Self super auto crate
281283

282284
-- These are all very low precedence unary operators
283285
%nonassoc box return yield break continue for IMPLTRAIT LAMBDA
@@ -325,17 +327,15 @@ import qualified Data.List.NonEmpty as N
325327
%%
326328
327329
-- Unwraps the IdentTok into just an Ident
328-
-- For questionable reasons of backwards compatibility, 'union', 'default', and 'catch' can be used
330+
-- For questionable reasons of backwards compatibility, 'union', and 'default' can be used
329331
-- as identifiers, even if they are also keywords. They are "contextual" keywords.
330332
--
331333
-- Union's RFC: https://github.com/rust-lang/rfcs/blob/master/text/1444-union.md
332334
ident :: { Spanned Ident }
333335
: ntIdent { fmap (\(Interpolated (NtIdent i)) -> i) $1 }
334336
| union { toIdent $1 }
335337
| default { toIdent $1 }
336-
| catch { toIdent $1 }
337338
| auto { toIdent $1 }
338-
| dyn { toIdent $1 }
339339
| IDENT { toIdent $1 }
340340

341341
-- This should precede any '>' token which could be absorbed in a '>>', '>=', or '>>=' token. Its
@@ -554,7 +554,7 @@ path_segments_with_colons :: { Reversed NonEmpty (PathSegment Span) }
554554
case (unsnoc $1, unspan $3) of
555555
((rst, PathSegment i Nothing x), (lts, tys, bds)) ->
556556
let seg = PathSegment i (Just (AngleBracketed lts tys bds (spanOf $3))) (x # $3)
557-
in pure $ snoc rst seg
557+
in pure $ snoc rst seg
558558
_ -> fail "invalid path segment in expression path"
559559
}
560560

@@ -1002,7 +1002,6 @@ left_gen_expression(lhs,rhs,rhs2) :: { Expr Span }
10021002
| lhs '...' rhs2 %prec INFIXRNG { Range [] (Just $1) (Just $3) Closed ($1 # $>) }
10031003
| lhs '..=' rhs2 %prec INFIXRNG { Range [] (Just $1) (Just $3) Closed ($1 # $>) }
10041004
-- assignment expressions
1005-
| lhs '<-' rhs { InPlace [] $1 $3 ($1 # $>) }
10061005
| lhs '=' rhs { Assign [] $1 $3 ($1 # $>) }
10071006
| lhs '>>=' rhs { AssignOp [] ShrOp $1 $3 ($1 # $>) }
10081007
| lhs '<<=' rhs { AssignOp [] ShlOp $1 $3 ($1 # $>) }
@@ -1155,11 +1154,13 @@ block_like_expr :: { Expr Span }
11551154
| match nostruct_expr '{' arms '}' { Match [] $2 $4 ($1 # $>) }
11561155
| match nostruct_expr '{' inner_attrs arms '}' { Match (toList $4) $2 $5 ($1 # $>) }
11571156
| expr_path '!' '{' token_stream '}' { MacExpr [] (Mac $1 $4 ($1 # $>)) ($1 # $>) }
1158-
| do catch inner_attrs_block { let (as,b) = $> in Catch as b ($1 # b) }
1157+
| try inner_attrs_block { let (as,b) = $> in TryBlock as b ($1 # b) }
1158+
| async inner_attrs_block { let (as,b) = $> in Async as Ref b ($1 # b) }
1159+
| async move inner_attrs_block { let (as,b) = $> in Async as Value b ($1 # b) }
11591160

11601161
-- 'if' expressions are a bit special since they can have an arbitrary number of 'else if' chains.
11611162
if_expr :: { Expr Span }
1162-
: if nostruct_expr block else_expr { If [] $2 $3 $4 ($1 # $3 # $>) }
1163+
: if nostruct_expr block else_expr { If [] $2 $3 $4 ($1 # $3 # $>) }
11631164
| if let pats '=' nostruct_expr block else_expr { IfLet [] $3 $5 $6 $7 ($1 # $6 # $>) }
11641165

11651166
else_expr :: { Maybe (Expr Span) }
@@ -1631,6 +1632,7 @@ token :: { Spanned Token }
16311632
| const { $1 }
16321633
| continue { $1 }
16331634
| crate { $1 }
1635+
| dyn { $1 }
16341636
| else { $1 }
16351637
| enum { $1 }
16361638
| extern { $1 }
@@ -1656,11 +1658,13 @@ token :: { Spanned Token }
16561658
| super { $1 }
16571659
| trait { $1 }
16581660
| true { $1 }
1661+
| try { $1 }
16591662
| type { $1 }
16601663
| unsafe { $1 }
16611664
| use { $1 }
16621665
| where { $1 }
16631666
| while { $1 }
1667+
| yield { $1 }
16641668
-- Keywords reserved for future use
16651669
| abstract { $1 }
16661670
| alignof { $1 }
@@ -1680,10 +1684,7 @@ token :: { Spanned Token }
16801684
-- Weak keywords, have special meaning only in specific contexts.
16811685
| default { $1 }
16821686
| union { $1 }
1683-
| catch { $1 }
16841687
| auto { $1 }
1685-
| yield { $1 }
1686-
| dyn { $1 }
16871688
-- Comments
16881689
| outerDoc { $1 }
16891690
| innerDoc { $1 }
@@ -1808,7 +1809,7 @@ expParseError (Spanned t _, exps) = fail $ "Syntax error: unexpected `" ++ show
18081809
words "'||' '&&' '<<' '(' '[' '{' box break continue" ++
18091810
words "for if loop match move return Self self " ++
18101811
words "static super unsafe while do default union " ++
1811-
words "catch auto yield dyn"
1812+
words "auto yield try async"
18121813

18131814
lit = boolLit ++ byteLit ++ charLit ++ intLit ++ floatLit ++ strLit ++
18141815
byteStrLit ++ rawStrLit ++ rawByteStrLit
@@ -1862,7 +1863,6 @@ macroItem as i mac x = MacItem as i mac x
18621863
-- | Add attributes to an expression
18631864
addAttrs :: [Attribute Span] -> Expr Span -> Expr Span
18641865
addAttrs as (Box as' e s) = Box (as ++ as') e s
1865-
addAttrs as (InPlace as' e1 e2 s) = InPlace (as ++ as') e1 e2 s
18661866
addAttrs as (Vec as' e s) = Vec (as ++ as') e s
18671867
addAttrs as (Call as' f es s) = Call (as ++ as') f es s
18681868
addAttrs as (MethodCall as' i s tys es s') = MethodCall (as ++ as') i s tys es s'
@@ -1881,7 +1881,8 @@ addAttrs as (Loop as' b l s) = Loop (as ++ as') b l s
18811881
addAttrs as (Match as' e a s) = Match (as ++ as') e a s
18821882
addAttrs as (Closure as' m c f e s) = Closure (as ++ as') m c f e s
18831883
addAttrs as (BlockExpr as' b s) = BlockExpr (as ++ as') b s
1884-
addAttrs as (Catch as' b s) = Catch (as ++ as') b s
1884+
addAttrs as (TryBlock as' b s) = TryBlock (as ++ as') b s
1885+
addAttrs as (Async as' c b s) = Async (as ++ as') c b s
18851886
addAttrs as (Assign as' e1 e2 s) = Assign (as ++ as') e1 e2 s
18861887
addAttrs as (AssignOp as' b e1 e2 s) = AssignOp (as ++ as') b e1 e2 s
18871888
addAttrs as (FieldAccess as' e i s) = FieldAccess (as ++ as') e i s

src/Language/Rust/Pretty/Internal.hs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,6 @@ printExprOuterAttrStyle :: Expr a -> Bool -> Doc a
362362
printExprOuterAttrStyle expr isInline = glue (printEitherAttrs (expressionAttrs expr) Outer isInline) $
363363
case expr of
364364
Box _ e x -> annotate x ("box" <+> printExpr e)
365-
InPlace _ place e x -> annotate x (hsep [ printExpr place, "<-", printExpr e ])
366365
Vec as exprs x -> annotate x (block Bracket True "," (printInnerAttrs as) (printExpr <$> exprs))
367366
Call _ func [arg] x -> annotate x (printExpr func <> parens (printExpr arg))
368367
Call _ func args x -> annotate x (printExpr func <> block Paren True "," mempty (printExpr <$> args))
@@ -386,7 +385,10 @@ printExprOuterAttrStyle expr isInline = glue (printEitherAttrs (expressionAttrs
386385
, when (cap == Value) "move"
387386
, printFnBlockArgs decl <+> printExpr body])
388387
BlockExpr attrs blk x -> annotate x (printBlockWithAttrs True blk attrs)
389-
Catch attrs blk x -> annotate x ("do catch" <+> printBlockWithAttrs True blk attrs)
388+
TryBlock attrs blk x -> annotate x ("try" <+> printBlockWithAttrs True blk attrs)
389+
Async attrs cap blk x -> annotate x (hsep [ "async"
390+
, when (cap == Value) "move"
391+
, printBlockWithAttrs True blk attrs])
390392
Assign _ lhs rhs x -> annotate x (hsep [ printExpr lhs, "=", printExpr rhs ])
391393
AssignOp _ op lhs rhs x -> annotate x (hsep [ printExpr lhs, printBinOp op <> "=", printExpr rhs ])
392394
FieldAccess{} -> chainedMethodCalls expr False id
@@ -452,7 +454,6 @@ printStr sty str = unAnnotate (printLit (Str str sty Unsuffixed ()))
452454
-- | Extract from an expression its attributes
453455
expressionAttrs :: Expr a -> [Attribute a]
454456
expressionAttrs (Box as _ _) = as
455-
expressionAttrs (InPlace as _ _ _) = as
456457
expressionAttrs (Vec as _ _) = as
457458
expressionAttrs (Call as _ _ _) = as
458459
expressionAttrs (MethodCall as _ _ _ _ _) = as
@@ -471,7 +472,8 @@ expressionAttrs (Loop as _ _ _) = as
471472
expressionAttrs (Match as _ _ _) = as
472473
expressionAttrs (Closure as _ _ _ _ _) = as
473474
expressionAttrs (BlockExpr as _ _) = as
474-
expressionAttrs (Catch as _ _) = as
475+
expressionAttrs (TryBlock as _ _) = as
476+
expressionAttrs (Async as _ _ _) = as
475477
expressionAttrs (Assign as _ _ _) = as
476478
expressionAttrs (AssignOp as _ _ _ _) = as
477479
expressionAttrs (FieldAccess as _ _ _) = as

src/Language/Rust/Pretty/Resolve.hs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -800,12 +800,6 @@ resolveExprP p c a@(AssignOp as o l r x) = scope a $ parenE (p > 1) $ do
800800
l' <- resolveLhsExprP 2 c l
801801
r' <- resolveExprP 1 (rhs c) r
802802
pure (AssignOp as' o l' r' x)
803-
resolveExprP p c i@(InPlace as l r x) = scope i $ parenE (p > 2) $ do
804-
as' <- traverse (resolveAttr OuterAttr) as
805-
--l' <- resolveExprP 3 (lhs c) l
806-
l' <- resolveLhsExprP 3 c l
807-
r' <- resolveExprP 2 (rhs c) r
808-
pure (InPlace as' l' r' x)
809803
-- Range expressions
810804
resolveExprP _ _ r@(Range _ _ Nothing Closed _) = scope r (err r "inclusive ranges must be bounded at the end")
811805
resolveExprP _ _ r@(Range as Nothing Nothing rl x) = scope r $ do
@@ -1034,10 +1028,14 @@ resolveExprP _ _ m@(Match as e ar x) = scope m $ do
10341028
e' <- resolveExprP 0 AnyExpr e
10351029
ar' <- traverse resolveArm ar
10361030
pure (Match as' e' ar' x)
1037-
resolveExprP _ _ c@(Catch as b x) = scope c $ do
1031+
resolveExprP _ _ c@(TryBlock as b x) = scope c $ do
1032+
as' <- traverse (resolveAttr EitherAttr) as
1033+
b' <- resolveBlock b
1034+
pure (TryBlock as' b' x)
1035+
resolveExprP _ _ c@(Async as c' b x) = scope c $ do
10381036
as' <- traverse (resolveAttr EitherAttr) as
10391037
b' <- resolveBlock b
1040-
pure (Catch as' b' x)
1038+
pure (Async as' c' b' x)
10411039

10421040
isBlockLike :: Expr a -> Bool
10431041
isBlockLike If{} = True

src/Language/Rust/Syntax/AST.hs

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ data Abi
154154
-- trait Foo {
155155
-- // Regular argument
156156
-- fn new(x: usize) -> Foo;
157-
--
157+
--
158158
-- // Self argument, by value
159159
-- fn foo(self) -> i32;
160160
-- fn bar(mut self);
@@ -252,7 +252,7 @@ data BinOp
252252
deriving (Eq, Ord, Enum, Bounded, Show, Typeable, Data, Generic, NFData)
253253

254254
-- | Describes how a value bound to an identifier in a pattern is going to be borrowed
255-
-- (@syntax::ast::BindingMode@).
255+
-- (@syntax::ast::BindingMode@).
256256
--
257257
-- Example: @&mut@ in @|&mut x: i32| -> { x += 1 }@
258258
data BindingMode
@@ -268,7 +268,7 @@ data Block a = Block [Stmt a] Unsafety a
268268
deriving (Eq, Ord, Show, Functor, Typeable, Data, Generic, Generic1, NFData)
269269

270270
instance Located a => Located (Block a) where spanOf (Block _ _ s) = spanOf s
271-
271+
272272
-- | Describes how a 'Closure' should close over its free variables (@syntax::ast::CaptureBy@).
273273
data CaptureBy
274274
= Value -- ^ make copies of free variables closed over (@move@ closures)
@@ -277,21 +277,19 @@ data CaptureBy
277277

278278
-- | Const annotation to specify if a function or method is allowed to be called in constants
279279
-- context with constant arguments (@syntax::ast::Constness@). [Relevant
280-
-- RFC](https://github.com/rust-lang/rfcs/blob/master/text/0911-const-fn.md)
280+
-- RFC](https://github.com/rust-lang/rfcs/blob/master/text/0911-const-fn.md)
281281
--
282282
-- Example: @const@ in @const fn inc(x: i32) -> i32 { x + 1 }@
283283
data Constness = Const | NotConst deriving (Eq, Ord, Enum, Bounded, Show, Typeable, Data, Generic, NFData)
284284

285-
-- | An 'ImplItem' can be marked @default@ (@syntax::ast::Defaultness@).
285+
-- | An 'ImplItem' can be marked @default@ (@syntax::ast::Defaultness@).
286286
data Defaultness = Default | Final deriving (Eq, Ord, Enum, Bounded, Show, Typeable, Data, Generic, NFData)
287287

288288
-- | Expression (@syntax::ast::Expr@). Note that Rust pushes into expressions an unusual number
289289
-- of constructs including @if@, @while@, @match@, etc.
290290
data Expr a
291291
-- | box expression (example: @box x@)
292292
= Box [Attribute a] (Expr a) a
293-
-- | in-place expression - first 'Expr' is the place, second one is the value (example: @x <- y@)
294-
| InPlace [Attribute a] (Expr a) (Expr a) a
295293
-- | array literal (example: @[a, b, c, d]@)
296294
| Vec [Attribute a] [Expr a] a
297295
-- | function call where the first 'Expr' is the function itself, and the @['Expr']@ is the list of
@@ -311,7 +309,7 @@ data Expr a
311309
| Lit [Attribute a] (Lit a) a
312310
-- | cast (example: @foo as f64@)
313311
| Cast [Attribute a] (Expr a) (Ty a) a
314-
-- | type annotation (example: @x: i32@)
312+
-- | type annotation (example: @x: i32@)
315313
| TypeAscription [Attribute a] (Expr a) (Ty a) a
316314
-- | if expression, with an optional @else@ block. In the case the @else@ block is missing, the
317315
-- type of the @if@ is inferred to be @()@. (example: @if 1 == 2 { (1,1) } else { (2,2) }@
@@ -332,8 +330,10 @@ data Expr a
332330
| Closure [Attribute a] Movability CaptureBy (FnDecl a) (Expr a) a
333331
-- | (possibly unsafe) block (example: @unsafe { 1 }@)
334332
| BlockExpr [Attribute a] (Block a) a
335-
-- | a catch block (example: @do catch { 1 }@)
336-
| Catch [Attribute a] (Block a) a
333+
-- | a try block (example: @try { 1 }@)
334+
| TryBlock [Attribute a] (Block a) a
335+
-- | an async block (example: @async move { 1 }@)
336+
| Async [Attribute a] CaptureBy (Block a) a
337337
-- | assignment (example: @a = foo()@)
338338
| Assign [Attribute a] (Expr a) (Expr a) a
339339
-- | assignment with an operator (example: @a += 1@)
@@ -346,12 +346,12 @@ data Expr a
346346
| Index [Attribute a] (Expr a) (Expr a) a
347347
-- | range (examples: @1..2@, @1..@, @..2@, @1...2@, @1...@, @...2@)
348348
| Range [Attribute a] (Maybe (Expr a)) (Maybe (Expr a)) RangeLimits a
349-
-- | variable reference
349+
-- | variable reference
350350
| PathExpr [Attribute a] (Maybe (QSelf a)) (Path a) a
351351
-- | referencing operation (example: @&a or &mut a@)
352352
| AddrOf [Attribute a] Mutability (Expr a) a
353353
-- | @break@ with an optional label and expression denoting what to break out of and what to
354-
-- return (example: @break 'lbl 1@)
354+
-- return (example: @break 'lbl 1@)
355355
| Break [Attribute a] (Maybe (Label a)) (Maybe (Expr a)) a
356356
-- | @continue@ with an optional label (example: @continue@)
357357
| Continue [Attribute a] (Maybe (Label a)) a
@@ -373,7 +373,6 @@ data Expr a
373373

374374
instance Located a => Located (Expr a) where
375375
spanOf (Box _ _ s) = spanOf s
376-
spanOf (InPlace _ _ _ s) = spanOf s
377376
spanOf (Vec _ _ s) = spanOf s
378377
spanOf (Call _ _ _ s) = spanOf s
379378
spanOf (MethodCall _ _ _ _ _ s) = spanOf s
@@ -392,7 +391,8 @@ instance Located a => Located (Expr a) where
392391
spanOf (Match _ _ _ s) = spanOf s
393392
spanOf (Closure _ _ _ _ _ s) = spanOf s
394393
spanOf (BlockExpr _ _ s) = spanOf s
395-
spanOf (Catch _ _ s) = spanOf s
394+
spanOf (TryBlock _ _ s) = spanOf s
395+
spanOf (Async _ _ _ s) = spanOf s
396396
spanOf (Assign _ _ _ s) = spanOf s
397397
spanOf (AssignOp _ _ _ _ s) = spanOf s
398398
spanOf (FieldAccess _ _ _ s) = spanOf s
@@ -705,11 +705,11 @@ byteStr s = ByteStr (map (fromIntegral . ord) s)
705705
suffix :: Lit a -> Suffix
706706
suffix (Str _ _ s _) = s
707707
suffix (ByteStr _ _ s _) = s
708-
suffix (Char _ s _) = s
709-
suffix (Byte _ s _) = s
710-
suffix (Int _ _ s _) = s
708+
suffix (Char _ s _) = s
709+
suffix (Byte _ s _) = s
710+
suffix (Int _ _ s _) = s
711711
suffix (Float _ s _) = s
712-
suffix (Bool _ s _) = s
712+
suffix (Bool _ s _) = s
713713

714714
-- | The base of the number in an @Int@ literal can be binary (e.g. @0b1100@), octal (e.g. @0o14@),
715715
-- decimal (e.g. @12@), or hexadecimal (e.g. @0xc@).

0 commit comments

Comments
 (0)