2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1996
4 \section[MatchCon]{Pattern-matching constructors}
7 #include "HsVersions.h"
9 module MatchCon ( matchConFamily ) where
12 #if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ <= 201
13 IMPORT_DELOOPER(DsLoop) ( match ) -- break match-ish loop
15 import {-# SOURCE #-} Match
18 import HsSyn ( OutPat(..), HsLit, HsExpr )
19 import DsHsSyn ( outPatType )
24 import Id ( GenId{-instances-}, SYN_IE(Id) )
25 import Util ( panic, assertPanic )
28 We are confronted with the first column of patterns in a set of
29 equations, all beginning with constructors from one ``family'' (e.g.,
30 @[]@ and @:@ make up the @List@ ``family''). We want to generate the
31 alternatives for a @Case@ expression. There are several choices:
34 Generate an alternative for every constructor in the family, whether
35 they are used in this set of equations or not; this is what the Wadler
39 (a)~Simple. (b)~It may also be that large sparsely-used constructor
40 families are mainly handled by the code for literals.
42 (a)~Not practical for large sparsely-used constructor families, e.g.,
43 the ASCII character set. (b)~Have to look up a list of what
44 constructors make up the whole family.
48 Generate an alternative for each constructor used, then add a default
49 alternative in case some constructors in the family weren't used.
52 (a)~Alternatives aren't generated for unused constructors. (b)~The
53 STG is quite happy with defaults. (c)~No lookup in an environment needed.
55 (a)~A spurious default alternative may be generated.
59 ``Do it right:'' generate an alternative for each constructor used,
60 and add a default alternative if all constructors in the family
64 (a)~You will get cases with only one alternative (and no default),
65 which should be amenable to optimisation. Tuples are a common example.
67 (b)~Have to look up constructor families in TDE (as above).
71 We are implementing the ``do-it-right'' option for now. The arguments
72 to @matchConFamily@ are the same as to @match@; the extra @Int@
73 returned is the number of constructors in the family.
75 The function @matchConFamily@ is concerned with this
76 have-we-used-all-the-constructors? question; the local function
77 @match_cons_used@ does all the real work.
79 matchConFamily :: [Id]
81 -> [EquationInfo] -- Shadows
84 matchConFamily (var:vars) eqns_info shadows
85 = match_cons_used vars eqns_info shadows `thenDs` \ alts ->
86 mkCoAlgCaseMatchResult var alts
89 And here is the local function that does all the work. It is
90 more-or-less the @matchCon@/@matchClause@ functions on page~94 in
91 Wadler's chapter in SLPJ.
93 match_cons_used _ [{- no more eqns -}] _ = returnDs []
95 match_cons_used vars eqns_info@(EqnInfo (ConPat data_con _ arg_pats : ps1) _ : eqns) shadows
97 (eqns_for_this_con, eqns_not_for_this_con) = splitByCon eqns_info
98 (shadows_for_this_con, shadows_not_for_this_con) = splitByCon shadows
100 -- Go ahead and do the recursive call to make the alts
101 -- for the other ConPats in this con family...
102 match_cons_used vars eqns_not_for_this_con shadows_not_for_this_con `thenDs` \ rest_of_alts ->
104 -- Make new vars for the con arguments; avoid new locals where possible
105 selectMatchVars arg_pats `thenDs` \ new_vars ->
107 -- Now do the business to make the alt for _this_ ConPat ...
108 match (new_vars++vars)
109 (map shift_con_pat eqns_for_this_con)
110 (map shift_con_pat shadows_for_this_con) `thenDs` \ match_result ->
113 (data_con, new_vars, match_result)
117 splitByCon :: [EquationInfo] -> ([EquationInfo], [EquationInfo])
118 splitByCon [] = ([],[])
119 splitByCon (info@(EqnInfo (pat : _) _) : rest)
121 ConPat n _ _ | n == data_con -> (info:rest_yes, rest_no)
122 WildPat _ -> (info:rest_yes, info:rest_no)
123 -- WildPats will be in the shadows only,
124 -- and they go into both groups
125 other_pat -> (rest_yes, info:rest_no)
127 (rest_yes, rest_no) = splitByCon rest
129 shift_con_pat :: EquationInfo -> EquationInfo
130 shift_con_pat (EqnInfo (ConPat _ _ pats': pats) match_result)
131 = EqnInfo (pats' ++ pats) match_result
132 shift_con_pat (EqnInfo (WildPat _: pats) match_result) -- Will only happen in shadow
133 = EqnInfo ([WildPat (outPatType arg_pat) | arg_pat <- arg_pats] ++ pats) match_result
134 shift_con_pat other = panic "matchConFamily:match_cons_used:shift_con_pat"
137 Note on @shift_con_pats@ just above: does what the list comprehension in
138 @matchClause@ (SLPJ, p.~94) does, except things are trickier in real
139 life. Works for @ConPats@, and we want it to fail catastrophically
140 for anything else (which a list comprehension wouldn't).
141 Cf.~@shift_lit_pats@ in @MatchLits@.