Skip to content

Commit 33d0542

Browse files
committed
Bumped rustc version
* Support multiple patterns in 'if let' and 'while let' * Check path segment length in path resolution * Tweaked some comments
1 parent 8900fc1 commit 33d0542

File tree

15 files changed

+85
-63
lines changed

15 files changed

+85
-63
lines changed

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
# Cabal related files
2+
cabal.project.local
3+
dist/
4+
dist-newstyle/
5+
resources/
6+
17
# Stack related files
28
.stack-work/
39
stack.yaml

ChangeLog.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,6 @@
66
* Parser module (using Alex and Happy)
77
* Pretty-printing module (using Wadler's prettier)
88
* Resolving module for validating ASTs
9+
* Unit testsuite
10+
* Difference testsuite
11+
* Benchmarks

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@ A typical use looks like:
1515
>>> import Language.Rust.Parser
1616
>>> let inp = inputStreamFromString "fn main () { println!(\"Hello world!\"); }"
1717
inp :: InputStream
18-
>>> let Right sourceFile = parse @(SourceFile Span) inp
18+
>>> let sourceFile = parse' @(SourceFile Span) inp
1919
sourceFile :: SourceFile Span
2020

2121
>>> -- Sample use of the pretty-printer
2222
>>> import Language.Rust.Pretty
23-
>>> pretty sourceFile
23+
>>> pretty' sourceFile
2424
fn main() {
2525
println!("Hello world!");
2626
}

bench/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Benchmarks how much memory is allocated by the runtime when parsing the files in
1212
`sample-sources` directory at the project root. Resulting information is stored in a JSON file in
1313
the `allocations` folder (automatically created in this directory).
1414

15-
## `timimng-benchmarks`
15+
## `timing-benchmarks`
1616

1717
Benchmark how long it takes to parse the files inside the `sample-sources` directory. Resulting
1818
information is stored in a JSON file in the `timings` folder (automatically created in this

language-rust.cabal

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ library
8585
, array >=0.5 && <0.6
8686
, deepseq >=1.1
8787
if impl(ghc < 8)
88-
build-depends: semigroups >= 0.18
88+
build-depends: semigroups >=0.18
8989

9090
if flag(useByteStrings)
9191
cpp-options: -DUSE_BYTESTRING
@@ -141,8 +141,8 @@ test-suite rustc-tests
141141
, prettyprinter >=1.1
142142
, bytestring >=0.10
143143
, aeson >= 0.11.0.0
144-
, directory >= 1.2.5.0
145-
, filepath >= 1.4.0.0
144+
, directory >=1.2.5.0
145+
, filepath >=1.4.0.0
146146
, test-framework >=0.8.0
147147
, vector >=0.10.0
148148
, text >=1.2.0
@@ -184,8 +184,8 @@ benchmark allocation-benchmarks
184184
build-depends: base >=4.8 && <5.0
185185
, process >= 1.3
186186
, bytestring >=0.10
187-
, directory >= 1.2.5.0
188-
, filepath >= 1.4.0.0
187+
, directory >=1.2.5.0
188+
, filepath >=1.4.0.0
189189
, language-rust
190190
, weigh >=0.0.4
191191
, aeson >= 0.11.0.0

src/Language/Rust/Parser/Internal.y

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1132,8 +1132,8 @@ block_like_expr :: { Expr Span }
11321132
| label ':' for pat in nostruct_expr inner_attrs_block { let (as,b) = $> in ForLoop as $4 $6 b (Just $1) ($1 # b) }
11331133
| while nostruct_expr inner_attrs_block { let (as,b) = $> in While as $2 b Nothing ($1 # b) }
11341134
| label ':' while nostruct_expr inner_attrs_block { let (as,b) = $> in While as $4 b (Just $1) ($1 # b) }
1135-
| while let pat '=' nostruct_expr inner_attrs_block { let (as,b) = $> in WhileLet as $3 $5 b Nothing ($1 # b) }
1136-
| label ':' while let pat '=' nostruct_expr inner_attrs_block { let (as,b) = $> in WhileLet as $5 $7 b (Just $1) ($1 # b) }
1135+
| while let pats '=' nostruct_expr inner_attrs_block { let (as,b) = $> in WhileLet as $3 $5 b Nothing ($1 # b) }
1136+
| label ':' while let pats '=' nostruct_expr inner_attrs_block { let (as,b) = $> in WhileLet as $5 $7 b (Just $1) ($1 # b) }
11371137
| match nostruct_expr '{' '}' { Match [] $2 [] ($1 # $>) }
11381138
| match nostruct_expr '{' inner_attrs '}' { Match (toList $4) $2 [] ($1 # $>) }
11391139
| match nostruct_expr '{' arms '}' { Match [] $2 $4 ($1 # $>) }
@@ -1144,7 +1144,7 @@ block_like_expr :: { Expr Span }
11441144
-- 'if' expressions are a bit special since they can have an arbitrary number of 'else if' chains.
11451145
if_expr :: { Expr Span }
11461146
: if nostruct_expr block else_expr { If [] $2 $3 $4 ($1 # $3 # $>) }
1147-
| if let pat '=' nostruct_expr block else_expr { IfLet [] $3 $5 $6 $7 ($1 # $6 # $>) }
1147+
| if let pats '=' nostruct_expr block else_expr { IfLet [] $3 $5 $6 $7 ($1 # $6 # $>) }
11481148

11491149
else_expr :: { Maybe (Expr Span) }
11501150
: else block { Just (BlockExpr [] $2 (spanOf $2)) }
@@ -1156,10 +1156,11 @@ else_expr :: { Maybe (Expr Span) }
11561156
arms :: { [Arm Span] }
11571157
: ntArm { [$1] }
11581158
| ntArm arms { $1 : $2 }
1159-
| many(outer_attribute) sep_by1(pat,'|') arm_guard '=>' expr_arms
1160-
{ let (e,as) = $> in (Arm $1 (toNonEmpty $2) $3 e ($1 # $2 # e) : as) }
1161-
| many(outer_attribute) '|' sep_by1(pat,'|') arm_guard '=>' expr_arms
1162-
{ let (e,as) = $> in (Arm $1 (toNonEmpty $3) $4 e ($1 # $2 # e) : as) }
1159+
| many(outer_attribute) pats arm_guard '=>' expr_arms { let (e,as) = $> in (Arm $1 $2 $3 e ($1 # $2 # e) : as) }
1160+
1161+
pats :: { NonEmpty (Pat Span) }
1162+
: '|' sep_by1(pat,'|') { toNonEmpty $2 }
1163+
| sep_by1(pat,'|') { toNonEmpty $1 }
11631164

11641165
arm_guard :: { Maybe (Expr Span) }
11651166
: {- empty -} { Nothing }
@@ -1231,15 +1232,18 @@ vis_safety_block :: { Expr Span }
12311232
in noVis $1 e
12321233
}
12331234

1234-
-- an expression starting with 'union' (as an identifier) that won't cause conflicts with stmts
1235-
vis_union_nonblock_expr :: { Expr Span }
1236-
: union_expr { $1 }
1237-
| left_gen_expression(vis_union_nonblock_expr, expr, expr) { $1 }
1235+
-- an expression starting with 'union' or 'default' (as identifiers) that won't cause conflicts with stmts
1236+
vis_union_def_nonblock_expr :: { Expr Span }
1237+
: union_default_expr { $1 }
1238+
| left_gen_expression(vis_union_def_nonblock_expr, expr, expr) { $1 }
12381239
1239-
union_expr :: { Expr Span }
1240+
union_default_expr :: { Expr Span }
12401241
: pub_or_inherited union {%
12411242
noVis $1 (PathExpr [] Nothing (Path False [PathSegment "union" Nothing (spanOf $2)] (spanOf $1)) (spanOf $1))
12421243
}
1244+
| pub_or_inherited default {%
1245+
noVis $1 (PathExpr [] Nothing (Path False [PathSegment "default" Nothing (spanOf $2)] (spanOf $1)) (spanOf $1))
1246+
}
12431247
12441248
12451249
----------------
@@ -1253,7 +1257,7 @@ stmt :: { Stmt Span }
12531257
| many(outer_attribute) nonblock_expr ';' { toStmt ($1 `addAttrs` $2) True False ($1 # $2 # $3) }
12541258
| many(outer_attribute) block_like_expr ';' { toStmt ($1 `addAttrs` $2) True True ($1 # $2 # $3) }
12551259
| many(outer_attribute) blockpostfix_expr ';' { toStmt ($1 `addAttrs` $2) True True ($1 # $2 # $3) }
1256-
| many(outer_attribute) vis_union_nonblock_expr ';' { toStmt ($1 `addAttrs` $2) True False ($1 # $2 # $3) }
1260+
| many(outer_attribute) vis_union_def_nonblock_expr ';' { toStmt ($1 `addAttrs` $2) True False ($1 # $2 # $3) }
12571261
| many(outer_attribute) block_like_expr %prec NOSEMI { toStmt ($1 `addAttrs` $2) False True ($1 # $2) }
12581262
| many(outer_attribute) vis_safety_block ';' { toStmt ($1 `addAttrs` $2) True True ($1 # $2 # $>) }
12591263
| many(outer_attribute) vis_safety_block %prec NOSEMI { toStmt ($1 `addAttrs` $2) False True ($1 # $2) }

src/Language/Rust/Pretty/Internal.hs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ import Data.Text.Prettyprint.Doc hiding ( (<+>), hsep, indent, vsep )
107107
import Data.Maybe ( maybeToList, fromMaybe )
108108
import Data.Foldable ( toList )
109109
import Data.List ( unfoldr )
110+
import qualified Data.List.NonEmpty as N
110111

111112
-- | Print a source file
112113
printSourceFile :: SourceFile a -> Doc a
@@ -136,7 +137,8 @@ printType (TupTy [elt] x) = annotate x (block Paren True "" mempty [ prin
136137
printType (TupTy elts x) = annotate x (block Paren True "," mempty (printType `map` elts))
137138
printType (PathTy Nothing p x) = annotate x (printPath p False)
138139
printType (PathTy (Just q) p x) = annotate x (printQPath p q False)
139-
printType (TraitObject bs x) = annotate x (printBounds mempty (toList bs))
140+
printType (TraitObject bs x) = let prefix = if null (N.tail bs) then "dyn" else mempty
141+
in annotate x (printBounds prefix (toList bs))
140142
printType (ImplTrait bs x) = annotate x (printBounds "impl" (toList bs))
141143
printType (ParenTy ty x) = annotate x ("(" <> printType ty <> ")")
142144
printType (Typeof e x) = annotate x ("typeof" <> block Paren True mempty mempty [ printExpr e ])
@@ -373,9 +375,9 @@ printExprOuterAttrStyle expr isInline = glue (printEitherAttrs (expressionAttrs
373375
in annotate x (hsep [ f e, "as", printType ty ])
374376
TypeAscription _ e ty x -> annotate x (printExpr e <> ":" <+> printType ty)
375377
If _ test blk els x -> annotate x (hsep [ "if", printExpr test, printBlock blk, printElse els ])
376-
IfLet _ pat e blk els x -> annotate x (hsep [ "if let", printPat pat, "=", printExpr e, printBlock blk, printElse els ])
378+
IfLet _ pats e blk els x -> annotate x (hsep [ "if let", printPats pats, "=", printExpr e, printBlock blk, printElse els ])
377379
While as test blk lbl x -> annotate x (hsep [ printLbl lbl, "while", printExpr test, printBlockWithAttrs True blk as ])
378-
WhileLet as p e blk lbl x -> annotate x (hsep [ printLbl lbl, "while let", printPat p, "=", printExpr e, printBlockWithAttrs True blk as ])
380+
WhileLet as ps e blk lbl x -> annotate x (hsep [ printLbl lbl, "while let", printPats ps, "=", printExpr e, printBlockWithAttrs True blk as ])
379381
ForLoop as pat e blk lbl x -> annotate x (hsep [ printLbl lbl, "for", printPat pat, "in", printExpr e, printBlockWithAttrs True blk as ])
380382
Loop as blk lbl x -> annotate x (hsep [ printLbl lbl, "loop", printBlockWithAttrs True blk as ])
381383
Match as e arms x -> annotate x (hsep [ "match", printExpr e, block Brace False "," (printInnerAttrs as) (printArm `map` arms) ])
@@ -506,11 +508,14 @@ printFnBlockArgs (FnDecl args ret _ x) = annotate x ("|" <> args' <> "|" <+> ret
506508
-- | Print the arm of a match expression (@print_arm@)
507509
printArm :: Arm a -> Doc a
508510
printArm (Arm as pats guard body x) = annotate x $ printOuterAttrs as
509-
</> group (foldr1 (\a b -> a <+> "|" <#> b) (printPat `map` toList pats))
511+
</> printPats pats
510512
<+> perhaps (\e -> "if" <+> printExpr e) guard
511513
<+> "=>"
512514
<+> printExpr body
513515

516+
printPats :: Foldable f => f (Pat a) -> Doc a
517+
printPats pats = group (foldr1 (\a b -> a <+> "|" <#> b) (printPat `map` toList pats))
518+
514519
-- | Print a block
515520
printBlock :: Block a -> Doc a
516521
printBlock blk = printBlockWithAttrs True blk []
@@ -532,7 +537,7 @@ printBlockWithAttrs b (Block stmts rules x) as = annotate x (printUnsafety rules
532537
printElse :: Maybe (Expr a) -> Doc a
533538
printElse Nothing = mempty
534539
printElse (Just (If _ e t s x)) = annotate x (hsep [ "else if", printExpr e, printBlock t, printElse s ])
535-
printElse (Just (IfLet _ p e t s x)) = annotate x (hsep [ "else if let", printPat p, "=", printExpr e, printBlock t, printElse s ])
540+
printElse (Just (IfLet _ p e t s x)) = annotate x (hsep [ "else if let", printPats p, "=", printExpr e, printBlock t, printElse s ])
536541
printElse (Just (BlockExpr _ blk x)) = annotate x (hsep [ "else", printBlock blk ])
537542
printElse _ = error "printElse saw `if` with a weird alternative"
538543

src/Language/Rust/Pretty/Literals.hs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ Portability : portable
99
1010
Functions for pretty-printing literals.
1111
-}
12-
{-# OPTIONS_HADDOCK hide, not-home #-}
1312
{-# LANGUAGE OverloadedStrings #-}
1413

1514
module Language.Rust.Pretty.Literals (

src/Language/Rust/Pretty/Resolve.hs

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,8 @@ data ResolveFail = ResolveFail [Dynamic] String deriving (Typeable)
147147

148148
-- | Does not show context information
149149
instance Show ResolveFail where
150-
showsPrec p (ResolveFail _ msg) = showParen (p >= 11) (showString err)
151-
where err = unwords [ "invalid AST", "(" ++ msg ++ ")" ]
150+
showsPrec p (ResolveFail _ msg) = showParen (p >= 11) (showString expl)
151+
where expl = unwords [ "invalid AST", "(" ++ msg ++ ")" ]
152152

153153
instance Exception ResolveFail
154154

@@ -226,10 +226,10 @@ resolveIdent :: Ident -> ResolveM Ident
226226
resolveIdent i@(Ident s _) =
227227
scope i $ case toks of
228228
Right [Spanned (IdentTok i') _]
229-
| i /= i' -> err i "identifier does not lex properly"
230-
| i `elem` keywords -> err i "identifier is a keyword"
229+
| i /= i' -> err i ("identifier `" ++ s ++ "' does not lex properly")
230+
| i `elem` keywords -> err i ("identifier `" ++ s ++ "' is a keyword")
231231
| otherwise -> pure i
232-
_ -> err i "identifier does not lex properly"
232+
_ -> err i ("identifier `" ++ s ++ "' does not lex properly")
233233

234234
where
235235

@@ -321,12 +321,14 @@ instance Resolve (Lit a) where resolveM = resolveLit
321321
-- different underlying invariants.
322322
data PathType
323323
= ModPath
324+
| UsePath -- ^ similar to 'ModPath', but can have no segments
324325
| TypePath
325326
| ExprPath
326327
deriving (Eq)
327328

328329
instance Show PathType where
329330
show ModPath = "mod path"
331+
show UsePath = "use tree path"
330332
show TypePath = "type path"
331333
show ExprPath = "expression path"
332334

@@ -337,6 +339,7 @@ instance Show PathType where
337339
--
338340
-- TODO: guard against no path segments...
339341
resolvePath :: (Typeable a, Monoid a) => PathType -> Path a -> ResolveM (Path a)
342+
resolvePath t p@(Path _ [] _) | t /= UsePath = scope p $ err p "path must have at least one segment"
340343
resolvePath t p@(Path g segs x) = scope p $
341344
if null [ () | PathSegment _ (Just a) _ <- segs, not (isParamsForPath t a) ]
342345
then Path g <$> traverse resolveSeg segs <*> pure x
@@ -391,6 +394,7 @@ instance (Typeable a, Monoid a) => Resolve (QSelf a) where resolveM = resolveQSe
391394
resolveLifetime :: Typeable a => Lifetime a -> ResolveM (Lifetime a)
392395
resolveLifetime l@(Lifetime n _)
393396
| n == "static" = pure l
397+
| n == "_" = pure l
394398
| otherwise = scope l (resolveIdent (mkIdent n) *> pure l)
395399

396400
instance Typeable a => Resolve (Lifetime a) where resolveM = resolveLifetime
@@ -580,8 +584,8 @@ resolvePat p@(PathP q@(Just (QSelf _ i)) p'@(Path g s x) x')
580584
| i < 0 || i >= length s = scope p (err p "index given by QSelf is outside the possible range")
581585
| i == 0 = scope p (PathP <$> traverse resolveQSelf q <*> resolvePath ExprPath p' <*> pure x)
582586
| otherwise = scope p $ do
583-
tyP@(Path _ tyPSegs _) <- resolvePath TypePath $ Path g (take i s) mempty
584-
exprP@(Path _ exprPSegs _) <- resolvePath ExprPath $ Path False (drop i s) x
587+
Path _ tyPSegs _ <- resolvePath TypePath $ Path g (take i s) mempty
588+
Path _ exprPSegs _ <- resolvePath ExprPath $ Path False (drop i s) x
585589
q' <- traverse resolveQSelf q
586590
pure (PathP q' (Path g (tyPSegs <> exprPSegs) x) x')
587591
-- TupleP
@@ -922,8 +926,8 @@ resolveExprP _ _ p@(PathExpr as q@(Just (QSelf _ i)) p'@(Path g s x) x')
922926
pure (PathExpr as' q' p'' x)
923927
| otherwise = scope p $ do
924928
as' <- traverse (resolveAttr OuterAttr) as
925-
tyP@(Path _ tyPSegs _) <- resolvePath TypePath $ Path g (take i s) mempty
926-
exprP@(Path _ exprPSegs _) <- resolvePath ExprPath $ Path False (drop i s) x
929+
Path _ tyPSegs _ <- resolvePath TypePath $ Path g (take i s) mempty
930+
Path _ exprPSegs _ <- resolvePath ExprPath $ Path False (drop i s) x
927931
q' <- traverse resolveQSelf q
928932
pure (PathExpr as' q' (Path g (tyPSegs <> exprPSegs) x) x')
929933
resolveExprP _ _ i@(Lit as l x) = scope i $ do
@@ -978,7 +982,7 @@ resolveExprP p c i@(If as e b es x) = scope i $ do
978982
pure (If as' e' b' es' x)
979983
resolveExprP p c i@(IfLet as p' e b es x) = scope i $ do
980984
as' <- traverse (resolveAttr OuterAttr) as
981-
p'' <- resolvePat p'
985+
p'' <- traverse resolvePat p'
982986
e' <- resolveExprP 0 NoStructExpr e
983987
b' <- resolveBlock b
984988
es' <- case es of
@@ -996,7 +1000,7 @@ resolveExprP _ _ w@(While as e b l x) = scope w $ do
9961000
pure (While as' e' b' l' x)
9971001
resolveExprP _ _ w@(WhileLet as p' e b l x) = scope w $ do
9981002
as' <- traverse (resolveAttr EitherAttr) as
999-
p'' <- resolvePat p'
1003+
p'' <- traverse resolvePat p'
10001004
e' <- resolveExprP 0 NoStructExpr e
10011005
b' <- resolveBlock b
10021006
l' <- traverse resolveLbl l
@@ -1451,10 +1455,10 @@ resolveUseTree v@(UseTreeSimple p i x) = scope v $ do
14511455
i' <- traverse resolveIdent i
14521456
pure (UseTreeSimple p' i' x)
14531457
resolveUseTree v@(UseTreeGlob p x) = scope v $ do
1454-
p' <- resolvePath ModPath p
1458+
p' <- resolvePath UsePath p
14551459
pure (UseTreeGlob p' x)
14561460
resolveUseTree v@(UseTreeNested p ns x) = scope v $ do
1457-
p' <- resolvePath ModPath p
1461+
p' <- resolvePath UsePath p
14581462
ns' <- traverse resolveUseTree ns
14591463
pure (UseTreeNested p' ns' x)
14601464

src/Language/Rust/Pretty/Util.hs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@ same problem shows up for @hsep@, @<#>@, @vsep@, @</>@, etc.
1919
My solution has been to redefine my versions of these functions which _do_ treat 'mempty' as a
2020
neutral element for @<+>@, @hsep@, @<#>@, @vsep@, and @</>@.
2121
-}
22-
{-# OPTIONS_HADDOCK hide, not-home #-}
23-
{-# LANGUAGE OverloadedStrings #-}
22+
{-# LANGUAGE OverloadedStrings #-}
2423

2524
module Language.Rust.Pretty.Util where
2625

0 commit comments

Comments
 (0)