Skip to content

Commit 9e42339

Browse files
authored
Make Let-Pattern desugaring less brittle (purescript#3268)
The old code relies on the Parser inserting PositionedValue wrappers in certain places, so that some patterns miss. I wrote this code a while back with @paf31, when we were trying to add SourceSpans to Binders and Exprs.
1 parent d73957d commit 9e42339

1 file changed

Lines changed: 23 additions & 13 deletions

File tree

src/Language/PureScript/Sugar/LetPattern.hs

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,37 +6,47 @@ module Language.PureScript.Sugar.LetPattern (desugarLetPatternModule) where
66

77
import Prelude.Compat
88

9+
import Data.List (groupBy, concatMap)
10+
import Data.Function (on)
11+
912
import Language.PureScript.AST
13+
import Language.PureScript.Crash
1014

11-
-- |
12-
-- Replace every @BoundValueDeclaration@ in @Let@ expressions with @Case@
15+
-- | Replace every @BoundValueDeclaration@ in @Let@ expressions with @Case@
1316
-- expressions.
14-
--
1517
desugarLetPatternModule :: Module -> Module
1618
desugarLetPatternModule (Module ss coms mn ds exts) = Module ss coms mn (map desugarLetPattern ds) exts
1719

18-
-- |
19-
-- Desugar a single let expression
20-
--
20+
-- | Desugar a single let expression
2121
desugarLetPattern :: Declaration -> Declaration
2222
desugarLetPattern decl =
2323
let (f, _, _) = everywhereOnValues id replace id
2424
in f decl
2525
where
2626
replace :: Expr -> Expr
27-
replace (Let ds e) = go ds e
27+
replace (Let ds e) = go (partitionDecls ds) e
2828
replace other = other
2929

30-
go :: [Declaration]
30+
go :: [Either [Declaration] (SourceAnn, Binder, Expr)]
3131
-- ^ Declarations to desugar
3232
-> Expr
3333
-- ^ The original let-in result expression
3434
-> Expr
3535
go [] e = e
36-
go (BoundValueDeclaration (pos, com) binder boundE : ds) e =
36+
go (Right ((pos, com), binder, boundE) : ds) e =
3737
PositionedValue pos com $ Case [boundE] [CaseAlternative [binder] [MkUnguarded $ go ds e]]
38-
go (d:ds) e = append d $ go ds e
38+
go (Left ds:dss) e = Let ds (go dss e)
39+
40+
partitionDecls :: [Declaration] -> [Either [Declaration] (SourceAnn, Binder, Expr)]
41+
partitionDecls = concatMap f . groupBy ((==) `on` isBoundValueDeclaration)
42+
where
43+
f ds@(d:_)
44+
| isBoundValueDeclaration d = map (Right . g) ds
45+
f ds = [Left ds]
46+
47+
g (BoundValueDeclaration sa binder expr) = (sa, binder, expr)
48+
g _ = internalError "partitionDecls: the impossible happened."
3949

40-
append :: Declaration -> Expr -> Expr
41-
append d (Let ds e) = Let (d:ds) e
42-
append d e = Let [d] e
50+
isBoundValueDeclaration :: Declaration -> Bool
51+
isBoundValueDeclaration BoundValueDeclaration{} = True
52+
isBoundValueDeclaration _ = False

0 commit comments

Comments
 (0)