Skip to content

Commit a531935

Browse files
knothedMarge Bot
authored andcommitted
Update Match Datatype
EquationInfo currently contains a list of the equation's patterns together with a CoreExpr that is to be evaluated after a successful match on this equation. All the match-functions only operate on the first pattern of an equation - after successfully matching it, match is called recursively on the tail of the pattern list. We can express this more clearly and make the code a little more elegant by updating the datatype of EquationInfo as follows: data EquationInfo = EqnMatch { eqn_pat = Pat GhcTc, eqn_rest = EquationInfo } | EqnDone { eqn_rhs = MatchResult CoreExpr } An EquationInfo now explicitly exposes its first pattern which most functions operate on, and exposes the equation that remains after processing the first pattern. An EqnDone signifies an empty equation where the CoreExpr can now be evaluated.
1 parent a80ca08 commit a531935

File tree

6 files changed

+138
-125
lines changed

6 files changed

+138
-125
lines changed

compiler/GHC/HsToCore/Expr.hs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -206,11 +206,8 @@ dsUnliftedBind (PatBind { pat_lhs = pat, pat_rhs = grhss
206206
-- ==> case rhs of C x# y# -> body
207207
do { match_nablas <- pmcGRHSs PatBindGuards grhss
208208
; rhs <- dsGuarded grhss ty match_nablas
209-
; let upat = unLoc pat
210-
eqn = EqnInfo { eqn_pats = [upat],
211-
eqn_orig = FromSource,
212-
eqn_rhs = cantFailMatchResult body }
213-
; var <- selectMatchVar ManyTy upat
209+
; let eqn = EqnMatch { eqn_pat = pat, eqn_rest = EqnDone (cantFailMatchResult body) }
210+
; var <- selectMatchVar ManyTy (unLoc pat)
214211
-- `var` will end up in a let binder, so the multiplicity
215212
-- doesn't matter.
216213
; result <- matchEquations PatBindRhs [var] [eqn] (exprType body)

compiler/GHC/HsToCore/Match.hs

Lines changed: 63 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,12 @@ import Language.Haskell.Syntax.Basic (Boxity(..))
2929

3030
import {-#SOURCE#-} GHC.HsToCore.Expr (dsExpr)
3131

32-
import GHC.Types.Basic ( Origin(..), isGenerated, requiresPMC )
32+
import GHC.Types.Basic ( Origin(..), requiresPMC )
3333
import GHC.Types.SourceText
34+
( FractionalLit,
35+
IntegralLit(il_value),
36+
negateFractionalLit,
37+
integralFractionalLit )
3438
import GHC.Driver.DynFlags
3539
import GHC.Hs
3640
import GHC.Hs.Syn.Type
@@ -193,13 +197,9 @@ match :: [MatchId] -- ^ Variables rep\'ing the exprs we\'re matching with
193197

194198
match [] ty eqns
195199
= assertPpr (not (null eqns)) (ppr ty) $
196-
return (foldr1 combineMatchResults match_results)
197-
where
198-
match_results = [ assert (null (eqn_pats eqn)) $
199-
eqn_rhs eqn
200-
| eqn <- eqns ]
200+
combineEqnRhss (NEL.fromList eqns)
201201

202-
match (v:vs) ty eqns -- Eqns *can* be empty
202+
match (v:vs) ty eqns -- Eqns can be empty, but each equation is nonempty
203203
= assertPpr (all (isInternalName . idName) vars) (ppr vars) $
204204
do { dflags <- getDynFlags
205205
; let platform = targetPlatform dflags
@@ -222,12 +222,11 @@ match (v:vs) ty eqns -- Eqns *can* be empty
222222
dropGroup :: Functor f => f (PatGroup,EquationInfo) -> f EquationInfo
223223
dropGroup = fmap snd
224224

225-
match_groups :: [NonEmpty (PatGroup,EquationInfo)] -> DsM (NonEmpty (MatchResult CoreExpr))
226-
-- Result list of [MatchResult CoreExpr] is always non-empty
225+
match_groups :: [NonEmpty (PatGroup,EquationInfoNE)] -> DsM (NonEmpty (MatchResult CoreExpr))
227226
match_groups [] = matchEmpty v ty
228227
match_groups (g:gs) = mapM match_group $ g :| gs
229228

230-
match_group :: NonEmpty (PatGroup,EquationInfo) -> DsM (MatchResult CoreExpr)
229+
match_group :: NonEmpty (PatGroup,EquationInfoNE) -> DsM (MatchResult CoreExpr)
231230
match_group eqns@((group,_) :| _)
232231
= case group of
233232
PgCon {} -> matchConFamily vars ty (ne $ subGroupUniq [(c,e) | (PgCon c, e) <- eqns'])
@@ -267,20 +266,20 @@ matchEmpty var res_ty
267266
mk_seq fail = return $ mkWildCase (Var var) (idScaledType var) res_ty
268267
[Alt DEFAULT [] fail]
269268

270-
matchVariables :: NonEmpty MatchId -> Type -> NonEmpty EquationInfo -> DsM (MatchResult CoreExpr)
269+
matchVariables :: NonEmpty MatchId -> Type -> NonEmpty EquationInfoNE -> DsM (MatchResult CoreExpr)
271270
-- Real true variables, just like in matchVar, SLPJ p 94
272271
-- No binding to do: they'll all be wildcards by now (done in tidy)
273272
matchVariables (_ :| vars) ty eqns = match vars ty $ NEL.toList $ shiftEqns eqns
274273

275-
matchBangs :: NonEmpty MatchId -> Type -> NonEmpty EquationInfo -> DsM (MatchResult CoreExpr)
274+
matchBangs :: NonEmpty MatchId -> Type -> NonEmpty EquationInfoNE -> DsM (MatchResult CoreExpr)
276275
matchBangs (var :| vars) ty eqns
277276
= do { match_result <- match (var:vars) ty $ NEL.toList $
278277
decomposeFirstPat getBangPat <$> eqns
279278
; return (mkEvalMatchResult var ty match_result) }
280279

281-
matchCoercion :: NonEmpty MatchId -> Type -> NonEmpty EquationInfo -> DsM (MatchResult CoreExpr)
280+
matchCoercion :: NonEmpty MatchId -> Type -> NonEmpty EquationInfoNE -> DsM (MatchResult CoreExpr)
282281
-- Apply the coercion to the match variable and then match that
283-
matchCoercion (var :| vars) ty (eqns@(eqn1 :| _))
282+
matchCoercion (var :| vars) ty eqns@(eqn1 :| _)
284283
= do { let XPat (CoPat co pat _) = firstPat eqn1
285284
; let pat_ty' = hsPatType pat
286285
; var' <- newUniqueId var (idMult var) pat_ty'
@@ -290,9 +289,9 @@ matchCoercion (var :| vars) ty (eqns@(eqn1 :| _))
290289
{ let bind = NonRec var' (core_wrap (Var var))
291290
; return (mkCoLetMatchResult bind match_result) } }
292291

293-
matchView :: NonEmpty MatchId -> Type -> NonEmpty EquationInfo -> DsM (MatchResult CoreExpr)
292+
matchView :: NonEmpty MatchId -> Type -> NonEmpty EquationInfoNE -> DsM (MatchResult CoreExpr)
294293
-- Apply the view function to the match variable and then match that
295-
matchView (var :| vars) ty (eqns@(eqn1 :| _))
294+
matchView (var :| vars) ty eqns@(eqn1 :| _)
296295
= do { -- we could pass in the expr from the PgView,
297296
-- but this needs to extract the pat anyway
298297
-- to figure out the type of the fresh variable
@@ -309,10 +308,9 @@ matchView (var :| vars) ty (eqns@(eqn1 :| _))
309308
match_result) }
310309

311310
-- decompose the first pattern and leave the rest alone
312-
decomposeFirstPat :: (Pat GhcTc -> Pat GhcTc) -> EquationInfo -> EquationInfo
313-
decomposeFirstPat extractpat (eqn@(EqnInfo { eqn_pats = pat : pats }))
314-
= eqn { eqn_pats = extractpat pat : pats}
315-
decomposeFirstPat _ _ = panic "decomposeFirstPat"
311+
decomposeFirstPat :: (Pat GhcTc -> Pat GhcTc) -> EquationInfoNE -> EquationInfoNE
312+
decomposeFirstPat extract eqn@(EqnMatch { eqn_pat = pat }) = eqn{eqn_pat = fmap extract pat}
313+
decomposeFirstPat _ (EqnDone {}) = panic "decomposeFirstPat"
316314

317315
getCoPat, getBangPat, getViewPat :: Pat GhcTc -> Pat GhcTc
318316
getCoPat (XPat (CoPat _ pat _)) = pat
@@ -405,15 +403,14 @@ tidyEqnInfo :: Id -> EquationInfo
405403
-- POST CONDITION: head pattern in the EqnInfo is
406404
-- one of these for which patGroup is defined.
407405

408-
tidyEqnInfo _ (EqnInfo { eqn_pats = [] })
409-
= panic "tidyEqnInfo"
406+
tidyEqnInfo _ eqn@(EqnDone {}) = return (idDsWrapper, eqn)
410407

411-
tidyEqnInfo v eqn@(EqnInfo { eqn_pats = pat : pats, eqn_orig = orig })
412-
= do { (wrap, pat') <- tidy1 v orig pat
413-
; return (wrap, eqn { eqn_pats = pat' : pats }) }
408+
tidyEqnInfo v eqn@(EqnMatch { eqn_pat = (L loc pat) }) = do
409+
(wrap, pat') <- tidy1 v (not . isGoodSrcSpan . locA $ loc) pat
410+
return (wrap, eqn{eqn_pat = L loc pat' })
414411

415412
tidy1 :: Id -- The Id being scrutinised
416-
-> Origin -- Was this a pattern the user wrote?
413+
-> Bool -- `True` if the pattern was generated, `False` if it was user-written
417414
-> Pat GhcTc -- The pattern against which it is to be matched
418415
-> DsM (DsWrapper, -- Extra bindings to do before the match
419416
Pat GhcTc) -- Equivalent pattern
@@ -424,10 +421,10 @@ tidy1 :: Id -- The Id being scrutinised
424421
-- It eliminates many pattern forms (as-patterns, variable patterns,
425422
-- list patterns, etc) and returns any created bindings in the wrapper.
426423

427-
tidy1 v o (ParPat _ _ pat _) = tidy1 v o (unLoc pat)
428-
tidy1 v o (SigPat _ pat _) = tidy1 v o (unLoc pat)
424+
tidy1 v g (ParPat _ _ pat _) = tidy1 v g (unLoc pat)
425+
tidy1 v g (SigPat _ pat _) = tidy1 v g (unLoc pat)
429426
tidy1 _ _ (WildPat ty) = return (idDsWrapper, WildPat ty)
430-
tidy1 v o (BangPat _ (L l p)) = tidy_bang_pat v o l p
427+
tidy1 v g (BangPat _ (L l p)) = tidy_bang_pat v g l p
431428

432429
-- case v of { x -> mr[] }
433430
-- = case v of { _ -> let x=v in mr[] }
@@ -436,8 +433,8 @@ tidy1 v _ (VarPat _ (L _ var))
436433

437434
-- case v of { x@p -> mr[] }
438435
-- = case v of { p -> let x=v in mr[] }
439-
tidy1 v o (AsPat _ (L _ var) _ pat)
440-
= do { (wrap, pat') <- tidy1 v o (unLoc pat)
436+
tidy1 v g (AsPat _ (L _ var) _ pat)
437+
= do { (wrap, pat') <- tidy1 v g (unLoc pat)
441438
; return (wrapBind var v . wrap, pat') }
442439

443440
{- now, here we handle lazy patterns:
@@ -489,22 +486,22 @@ tidy1 _ _ (SumPat tys pat alt arity)
489486
-- See Note [Unboxed tuple RuntimeRep vars] in TyCon
490487

491488
-- LitPats: we *might* be able to replace these w/ a simpler form
492-
tidy1 _ o (LitPat _ lit)
493-
= do { unless (isGenerated o) $
489+
tidy1 _ g (LitPat _ lit)
490+
= do { unless g $
494491
warnAboutOverflowedLit lit
495492
; return (idDsWrapper, tidyLitPat lit) }
496493

497494
-- NPats: we *might* be able to replace these w/ a simpler form
498-
tidy1 _ o (NPat ty (L _ lit@OverLit { ol_val = v }) mb_neg eq)
499-
= do { unless (isGenerated o) $
495+
tidy1 _ g (NPat ty (L _ lit@OverLit { ol_val = v }) mb_neg eq)
496+
= do { unless g $
500497
let lit' | Just _ <- mb_neg = lit{ ol_val = negateOverLitVal v }
501498
| otherwise = lit
502499
in warnAboutOverflowedOverLit lit'
503500
; return (idDsWrapper, tidyNPat lit mb_neg eq ty) }
504501

505502
-- NPlusKPat: we may want to warn about the literals
506-
tidy1 _ o n@(NPlusKPat _ _ (L _ lit1) lit2 _ _)
507-
= do { unless (isGenerated o) $ do
503+
tidy1 _ g n@(NPlusKPat _ _ (L _ lit1) lit2 _ _)
504+
= do { unless g $ do
508505
warnAboutOverflowedOverLit lit1
509506
warnAboutOverflowedOverLit lit2
510507
; return (idDsWrapper, n) }
@@ -514,28 +511,28 @@ tidy1 _ _ non_interesting_pat
514511
= return (idDsWrapper, non_interesting_pat)
515512

516513
--------------------
517-
tidy_bang_pat :: Id -> Origin -> SrcSpanAnnA -> Pat GhcTc
514+
tidy_bang_pat :: Id -> Bool -> SrcSpanAnnA -> Pat GhcTc
518515
-> DsM (DsWrapper, Pat GhcTc)
519516

520517
-- Discard par/sig under a bang
521-
tidy_bang_pat v o _ (ParPat _ _ (L l p) _) = tidy_bang_pat v o l p
522-
tidy_bang_pat v o _ (SigPat _ (L l p) _) = tidy_bang_pat v o l p
518+
tidy_bang_pat v g _ (ParPat _ _ (L l p) _) = tidy_bang_pat v g l p
519+
tidy_bang_pat v g _ (SigPat _ (L l p) _) = tidy_bang_pat v g l p
523520

524521
-- Push the bang-pattern inwards, in the hope that
525522
-- it may disappear next time
526-
tidy_bang_pat v o l (AsPat x v' at p)
527-
= tidy1 v o (AsPat x v' at (L l (BangPat noExtField p)))
528-
tidy_bang_pat v o l (XPat (CoPat w p t))
529-
= tidy1 v o (XPat $ CoPat w (BangPat noExtField (L l p)) t)
523+
tidy_bang_pat v g l (AsPat x v' at p)
524+
= tidy1 v g (AsPat x v' at (L l (BangPat noExtField p)))
525+
tidy_bang_pat v g l (XPat (CoPat w p t))
526+
= tidy1 v g (XPat $ CoPat w (BangPat noExtField (L l p)) t)
530527

531528
-- Discard bang around strict pattern
532-
tidy_bang_pat v o _ p@(LitPat {}) = tidy1 v o p
533-
tidy_bang_pat v o _ p@(ListPat {}) = tidy1 v o p
534-
tidy_bang_pat v o _ p@(TuplePat {}) = tidy1 v o p
535-
tidy_bang_pat v o _ p@(SumPat {}) = tidy1 v o p
529+
tidy_bang_pat v g _ p@(LitPat {}) = tidy1 v g p
530+
tidy_bang_pat v g _ p@(ListPat {}) = tidy1 v g p
531+
tidy_bang_pat v g _ p@(TuplePat {}) = tidy1 v g p
532+
tidy_bang_pat v g _ p@(SumPat {}) = tidy1 v g p
536533

537534
-- Data/newtype constructors
538-
tidy_bang_pat v o l p@(ConPat { pat_con = L _ (RealDataCon dc)
535+
tidy_bang_pat v g l p@(ConPat { pat_con = L _ (RealDataCon dc)
539536
, pat_args = args
540537
, pat_con_ext = ConPatTc
541538
{ cpt_arg_tys = arg_tys
@@ -544,8 +541,8 @@ tidy_bang_pat v o l p@(ConPat { pat_con = L _ (RealDataCon dc)
544541
-- Newtypes: push bang inwards (#9844)
545542
=
546543
if isNewTyCon (dataConTyCon dc)
547-
then tidy1 v o (p { pat_args = push_bang_into_newtype_arg l (scaledThing ty) args })
548-
else tidy1 v o p -- Data types: discard the bang
544+
then tidy1 v g (p { pat_args = push_bang_into_newtype_arg l (scaledThing ty) args })
545+
else tidy1 v g p -- Data types: discard the bang
549546
where
550547
(ty:_) = dataConInstArgTys dc arg_tys
551548

@@ -808,16 +805,14 @@ matchWrapper ctxt scrs (MG { mg_alts = L _ matches
808805
mk_eqn_info :: LMatch GhcTc (LHsExpr GhcTc) -> (Nablas, NonEmpty Nablas) -> DsM EquationInfo
809806
mk_eqn_info (L _ (Match { m_pats = pats, m_grhss = grhss })) (pat_nablas, rhss_nablas)
810807
= do { dflags <- getDynFlags
811-
; let upats = map (unLoc . decideBangHood dflags) pats
808+
; let upats = map (decideBangHood dflags) pats
812809
-- pat_nablas is the covered set *after* matching the pattern, but
813810
-- before any of the GRHSs. We extend the environment with pat_nablas
814811
-- (via updPmNablas) so that the where-clause of 'grhss' can profit
815812
-- from that knowledge (#18533)
816813
; match_result <- updPmNablas pat_nablas $
817814
dsGRHSs ctxt grhss rhs_ty rhss_nablas
818-
; return EqnInfo { eqn_pats = upats
819-
, eqn_orig = FromSource
820-
, eqn_rhs = match_result } }
815+
; return $ mkEqnInfo upats match_result }
821816

822817
discard_warnings_if_skip_pmc orig =
823818
if requiresPMC orig
@@ -958,10 +953,9 @@ matchSinglePatVar var mb_scrut ctx pat ty match_result
958953
pmcPatBind (DsMatchContext ctx locn) var (unLoc pat)
959954
else getLdiNablas
960955

961-
; let eqn_info = EqnInfo { eqn_pats = [unLoc (decideBangHood dflags pat)]
962-
, eqn_orig = FromSource
963-
, eqn_rhs =
964-
updPmNablasMatchResult ldi_nablas match_result }
956+
; let eqn_info = EqnMatch { eqn_pat = decideBangHood dflags pat
957+
, eqn_rest =
958+
EqnDone $ updPmNablasMatchResult ldi_nablas match_result }
965959
-- See Note [Long-distance information in do notation]
966960
-- in GHC.HsToCore.Expr.
967961

@@ -999,6 +993,13 @@ data PatGroup
999993
-- the LHsExpr is the expression e
1000994
Type -- the Type is the type of p (equivalently, the result type of e)
1001995

996+
instance Show PatGroup where
997+
show PgAny = "PgAny"
998+
show (PgCon _) = "PgCon"
999+
show (PgLit _) = "PgLit"
1000+
show (PgView _ _) = "PgView"
1001+
show _ = "PgOther"
1002+
10021003
{- Note [Don't use Literal for PgN]
10031004
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10041005
Previously we had, as PatGroup constructors
@@ -1019,7 +1020,7 @@ the PgN constructor as a FractionalLit if numeric, and add a PgOverStr construct
10191020
for overloaded strings.
10201021
-}
10211022

1022-
groupEquations :: Platform -> [EquationInfo] -> [NonEmpty (PatGroup, EquationInfo)]
1023+
groupEquations :: Platform -> [EquationInfoNE] -> [NonEmpty (PatGroup, EquationInfoNE)]
10231024
-- If the result is of form [g1, g2, g3],
10241025
-- (a) all the (pg,eq) pairs in g1 have the same pg
10251026
-- (b) none of the gi are empty
@@ -1163,8 +1164,8 @@ viewLExprEq (e1,_) (e2,_) = lexp e1 e2
11631164
exp (HsApp _ e1 e2) (HsApp _ e1' e2') = lexp e1 e1' && lexp e2 e2'
11641165
-- the fixities have been straightened out by now, so it's safe
11651166
-- to ignore them?
1166-
exp (OpApp _ l o ri) (OpApp _ l' o' ri') =
1167-
lexp l l' && lexp o o' && lexp ri ri'
1167+
exp (OpApp _ l g ri) (OpApp _ l' o' ri') =
1168+
lexp l l' && lexp g o' && lexp ri ri'
11681169
exp (NegApp _ e n) (NegApp _ e' n') = lexp e e' && syn_exp n n'
11691170
exp (SectionL _ e1 e2) (SectionL _ e1' e2') =
11701171
lexp e1 e1' && lexp e2 e2'

0 commit comments

Comments
 (0)