[project @ 1996-04-20 10:37:06 by partain]
[ghc-hetmet.git] / ghc / compiler / hsSyn / HsPat.lhs
1 %
2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1996
3 %
4 \section[PatSyntax]{Abstract Haskell syntax---patterns}
5
6 \begin{code}
7 #include "HsVersions.h"
8
9 module HsPat (
10         InPat(..),
11         OutPat(..),
12
13         unfailablePats, unfailablePat,
14         patsAreAllCons, isConPat,
15         patsAreAllLits, isLitPat,
16         irrefutablePat,
17         collectPatBinders
18     ) where
19
20 import Ubiq
21
22 -- friends:
23 import HsLit            ( HsLit )
24 import HsLoop           ( HsExpr )
25
26 -- others:
27 import Id               ( GenId, dataConSig )
28 import Maybes           ( maybeToBool )
29 import Name             ( pprSym, pprNonSym )
30 import Outputable       ( interppSP, interpp'SP, ifPprShowAll )
31 import PprStyle         ( PprStyle(..) )
32 import Pretty
33 import TyCon            ( maybeTyConSingleCon )
34 import PprType          ( GenType )
35 \end{code}
36
37 Patterns come in distinct before- and after-typechecking flavo(u)rs.
38 \begin{code}
39 data InPat name
40   = WildPatIn                           -- wild card
41   | VarPatIn        name                -- variable
42   | LitPatIn        HsLit               -- literal
43   | LazyPatIn       (InPat name)        -- lazy pattern
44   | AsPatIn         name                -- as pattern
45                     (InPat name)
46   | ConPatIn        name                -- constructed type
47                     [InPat name]
48   | ConOpPatIn      (InPat name)
49                     name
50                     (InPat name)
51
52   -- We preserve prefix negation and parenthesis for the precedence parser.
53
54   | NegPatIn        (InPat name)        -- negated pattern
55   | ParPatIn        (InPat name)        -- parenthesised pattern
56
57   | ListPatIn       [InPat name]        -- syntactic list
58                                         -- must have >= 1 elements
59   | TuplePatIn      [InPat name]        -- tuple
60
61   | RecPatIn        name                -- record
62                     [(name, InPat name, Bool)]  -- True <=> source used punning
63
64 data OutPat tyvar uvar id
65   = WildPat         (GenType tyvar uvar)                        -- wild card
66
67   | VarPat          id                          -- variable (type is in the Id)
68
69   | LazyPat         (OutPat tyvar uvar id)      -- lazy pattern
70
71   | AsPat           id                          -- as pattern
72                     (OutPat tyvar uvar id)
73
74   | ConPat          Id                          -- Constructor is always an Id
75                     (GenType tyvar uvar)        -- the type of the pattern
76                     [(OutPat tyvar uvar id)]
77
78   | ConOpPat        (OutPat tyvar uvar id)      -- just a special case...
79                     Id
80                     (OutPat tyvar uvar id)
81                     (GenType tyvar uvar)
82   | ListPat                                     -- syntactic list
83                     (GenType tyvar uvar)        -- the type of the elements
84                     [(OutPat tyvar uvar id)]
85
86   | TuplePat        [(OutPat tyvar uvar id)]    -- tuple
87                                                 -- UnitPat is TuplePat []
88
89   | RecPat          Id                          -- record constructor
90                     (GenType tyvar uvar)        -- the type of the pattern
91                     [(id, OutPat tyvar uvar id, Bool)]  -- True <=> source used punning
92
93   | LitPat          -- Used for *non-overloaded* literal patterns:
94                     -- Int#, Char#, Int, Char, String, etc.
95                     HsLit
96                     (GenType tyvar uvar)        -- type of pattern
97
98   | NPat            -- Used for *overloaded* literal patterns
99                     HsLit                       -- the literal is retained so that
100                                                 -- the desugarer can readily identify
101                                                 -- equations with identical literal-patterns
102                     (GenType tyvar uvar)        -- type of pattern, t
103                     (HsExpr tyvar uvar id (OutPat tyvar uvar id))
104                                                 -- of type t -> Bool; detects match
105
106   |  DictPat        -- Used when destructing Dictionaries with an explicit case
107                     [id]                        -- superclass dicts
108                     [id]                        -- methods
109 \end{code}
110
111 \begin{code}
112 instance (Outputable name, NamedThing name) => Outputable (InPat name) where
113     ppr = pprInPat
114
115 pprInPat :: (Outputable name, NamedThing name) => PprStyle -> InPat name -> Pretty
116
117 pprInPat sty (WildPatIn)        = ppStr "_"
118 pprInPat sty (VarPatIn var)     = pprNonSym sty var
119 pprInPat sty (LitPatIn s)       = ppr sty s
120 pprInPat sty (LazyPatIn pat)    = ppBeside (ppChar '~') (ppr sty pat)
121 pprInPat sty (AsPatIn name pat)
122     = ppBesides [ppLparen, ppr sty name, ppChar '@', ppr sty pat, ppRparen]
123
124 pprInPat sty (ConPatIn c pats)
125  = if null pats then
126       ppr sty c
127    else
128       ppBesides [ppLparen, ppr sty c, ppSP, interppSP sty pats, ppRparen]
129
130
131 pprInPat sty (ConOpPatIn pat1 op pat2)
132  = ppBesides [ppLparen, ppr sty pat1, ppSP, ppr sty op, ppSP, ppr sty pat2, ppRparen]
133
134         -- ToDo: use pprSym to print op (but this involves fiddling various
135         -- contexts & I'm lazy...); *PatIns are *rarely* printed anyway... (WDP)
136
137 pprInPat sty (NegPatIn pat)
138   = let
139         pp_pat = pprInPat sty pat
140     in
141     ppBeside (ppChar '-') (
142     case pat of
143       LitPatIn _ -> pp_pat
144       _          -> ppParens pp_pat
145     )
146
147 pprInPat sty (ParPatIn pat)
148   = ppParens (pprInPat sty pat)
149
150 pprInPat sty (ListPatIn pats)
151   = ppBesides [ppLbrack, interpp'SP sty pats, ppRbrack]
152 pprInPat sty (TuplePatIn pats)
153   = ppBesides [ppLparen, interpp'SP sty pats, ppRparen]
154
155 pprInPat sty (RecPatIn con rpats)
156   = ppBesides [ppr sty con, ppSP, ppChar '{', ppInterleave ppComma (map pp_rpat rpats), ppChar '}']
157   where
158     pp_rpat (v, _, True{-pun-}) = ppr sty v
159     pp_rpat (v, p, _) = ppCat [ppr sty v, ppStr "<-", ppr sty p]
160 \end{code}
161
162 \begin{code}
163 instance (Eq tyvar, Outputable tyvar, Eq uvar, Outputable uvar,
164           NamedThing id, Outputable id)
165        => Outputable (OutPat tyvar uvar id) where
166     ppr = pprOutPat
167 \end{code}
168
169 \begin{code}
170 pprOutPat sty (WildPat ty)      = ppChar '_'
171 pprOutPat sty (VarPat var)      = pprNonSym sty var
172 pprOutPat sty (LazyPat pat)     = ppBesides [ppChar '~', ppr sty pat]
173 pprOutPat sty (AsPat name pat)
174   = ppBesides [ppLparen, ppr sty name, ppChar '@', ppr sty pat, ppRparen]
175
176 pprOutPat sty (ConPat name ty [])
177   = ppBeside (ppr sty name)
178         (ifPprShowAll sty (pprConPatTy sty ty))
179
180 pprOutPat sty (ConPat name ty pats)
181   = ppBesides [ppLparen, ppr sty name, ppSP,
182          interppSP sty pats, ppRparen,
183          ifPprShowAll sty (pprConPatTy sty ty) ]
184
185 pprOutPat sty (ConOpPat pat1 op pat2 ty)
186   = ppBesides [ppLparen, ppr sty pat1, ppSP, pprSym sty op, ppSP, ppr sty pat2, ppRparen]
187
188 pprOutPat sty (ListPat ty pats)
189   = ppBesides [ppLbrack, interpp'SP sty pats, ppRbrack]
190 pprOutPat sty (TuplePat pats)
191   = ppBesides [ppLparen, interpp'SP sty pats, ppRparen]
192
193 pprOutPat sty (RecPat con ty rpats)
194   = ppBesides [ppr sty con, ppChar '{', ppInterleave ppComma (map pp_rpat rpats), ppChar '}']
195   where
196 --  pp_rpat (v, _, True{-pun-}) = ppr sty v
197     pp_rpat (v, p, _) = ppBesides [ppr sty v, ppStr "<-", ppr sty p]
198
199 pprOutPat sty (LitPat l ty)     = ppr sty l     -- ToDo: print more
200 pprOutPat sty (NPat   l ty e)   = ppr sty l     -- ToDo: print more
201
202 pprOutPat sty (DictPat dicts methods)
203  = ppSep [ppBesides [ppLparen, ppPStr SLIT("{-dict-}")],
204           ppBracket (interpp'SP sty dicts),
205           ppBesides [ppBracket (interpp'SP sty methods), ppRparen]]
206
207 pprConPatTy sty ty
208  = ppParens (ppr sty ty)
209 \end{code}
210
211 %************************************************************************
212 %*                                                                      *
213 %* predicates for checking things about pattern-lists in EquationInfo   *
214 %*                                                                      *
215 %************************************************************************
216 \subsection[Pat-list-predicates]{Look for interesting things in patterns}
217
218 Unlike in the Wadler chapter, where patterns are either ``variables''
219 or ``constructors,'' here we distinguish between:
220 \begin{description}
221 \item[unfailable:]
222 Patterns that cannot fail to match: variables, wildcards, and lazy
223 patterns.
224
225 These are the irrefutable patterns; the two other categories
226 are refutable patterns.
227
228 \item[constructor:]
229 A non-literal constructor pattern (see next category).
230
231 \item[literal patterns:]
232 At least the numeric ones may be overloaded.
233 \end{description}
234
235 A pattern is in {\em exactly one} of the above three categories; `as'
236 patterns are treated specially, of course.
237
238 \begin{code}
239 unfailablePats :: [OutPat a b c] -> Bool
240 unfailablePats pat_list = all unfailablePat pat_list
241
242 unfailablePat (AsPat    _ pat)  = unfailablePat pat
243 unfailablePat (WildPat  _)      = True
244 unfailablePat (VarPat   _)      = True
245 unfailablePat (LazyPat  _)      = True
246 unfailablePat (DictPat ds ms)   = (length ds + length ms) <= 1
247 unfailablePat other             = False
248
249 patsAreAllCons :: [OutPat a b c] -> Bool
250 patsAreAllCons pat_list = all isConPat pat_list
251
252 isConPat (AsPat _ pat)          = isConPat pat
253 isConPat (ConPat _ _ _)         = True
254 isConPat (ConOpPat _ _ _ _)     = True
255 isConPat (ListPat _ _)          = True
256 isConPat (TuplePat _)           = True
257 isConPat (DictPat ds ms)        = (length ds + length ms) > 1
258 isConPat other                  = False
259
260 patsAreAllLits :: [OutPat a b c] -> Bool
261 patsAreAllLits pat_list = all isLitPat pat_list
262
263 isLitPat (AsPat _ pat)  = isLitPat pat
264 isLitPat (LitPat _ _)   = True
265 isLitPat (NPat   _ _ _) = True
266 isLitPat other          = False
267 \end{code}
268
269 A pattern is irrefutable if a match on it cannot fail
270 (at any depth).
271 \begin{code}
272 irrefutablePat :: OutPat a b c -> Bool
273
274 irrefutablePat (WildPat _)                = True
275 irrefutablePat (VarPat _)                 = True
276 irrefutablePat (LazyPat _)                = True
277 irrefutablePat (AsPat _ pat)              = irrefutablePat pat
278 irrefutablePat (ConPat con tys pats)      = all irrefutablePat pats && only_con con
279 irrefutablePat (ConOpPat pat1 con pat2 _) = irrefutablePat pat1 && irrefutablePat pat1 && only_con con
280 irrefutablePat (ListPat _ _)              = False
281 irrefutablePat (TuplePat pats)            = all irrefutablePat pats
282 irrefutablePat (DictPat _ _)              = True
283 irrefutablePat other_pat                  = False   -- Literals, NPat
284
285 only_con con = maybeToBool (maybeTyConSingleCon tycon)
286                where
287                  (_,_,_,tycon) = dataConSig con
288 \end{code}
289
290 This function @collectPatBinders@ works with the ``collectBinders''
291 functions for @HsBinds@, etc.  The order in which the binders are
292 collected is important; see @HsBinds.lhs@.
293 \begin{code}
294 collectPatBinders :: InPat a -> [a]
295
296 collectPatBinders (VarPatIn var)     = [var]
297 collectPatBinders (LazyPatIn pat)    = collectPatBinders pat
298 collectPatBinders (AsPatIn a pat)    = a : collectPatBinders pat
299 collectPatBinders (ConPatIn c pats)  = concat (map collectPatBinders pats)
300 collectPatBinders (ConOpPatIn p1 c p2)= collectPatBinders p1 ++ collectPatBinders p2
301 collectPatBinders (NegPatIn  pat)    = collectPatBinders pat
302 collectPatBinders (ParPatIn  pat)    = collectPatBinders pat
303 collectPatBinders (ListPatIn pats)   = concat (map collectPatBinders pats)
304 collectPatBinders (TuplePatIn pats)  = concat (map collectPatBinders pats)
305 collectPatBinders any_other_pat      = [ {-no binders-} ]
306 \end{code}