2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1995
4 \section[TcPat]{Typechecking patterns}
7 #include "HsVersions.h"
16 import TcMonad -- typechecking monad machinery
17 import TcMonadFns ( newOpenTyVarTy, newPolyTyVarTy,
18 newPolyTyVarTys, copyTyVars, newMethod,
21 import AbsSyn -- the stuff being typechecked
23 import AbsPrel ( charPrimTy, intPrimTy, floatPrimTy,
24 doublePrimTy, charTy, stringTy, mkListTy,
25 mkTupleTy, addrTy, addrPrimTy, --OLD: eqStringId
27 IF_ATTACK_PRAGMAS(COMMA tagOf_PrimOp)
28 IF_ATTACK_PRAGMAS(COMMA pprPrimOp)
30 ,mkProcessorTy, toDomainId
31 #endif {- Data Parallel Haskell -}
33 import AbsUniType ( instantiateTauTy, applyTyCon, InstTyEnv(..)
34 IF_ATTACK_PRAGMAS(COMMA instantiateTy)
36 import CmdLineOpts ( GlobalSwitch(..) )
37 import Id ( mkInstId, getIdUniType, getDataConSig,
38 getInstantiatedDataConSig, Id, DataCon(..)
41 import E ( lookupE_Binder, lookupE_Value,
42 lookupE_ClassOpByKey, E,
43 LVE(..), TCE(..), UniqFM, CE(..)
44 -- TCE and CE for pragmas only
46 import Errors ( dataConArityErr, Error(..), UnifyErrContext(..)
48 import LIE ( nullLIE, plusLIE, mkLIE, LIE )
50 import Unique -- some ClassKey stuff
55 #endif {- Data Parallel Haskell -}
58 The E passed in already contains bindings for all the variables in
59 the pattern, usually to fresh type variables (but maybe not, if there
60 were type signatures present).
63 tcPat :: E -> RenamedPat -> TcM (TypecheckedPat, LIE, UniType)
66 %************************************************************************
68 \subsection{Variables, wildcards, lazy pats, as-pats}
70 %************************************************************************
73 tcPat e (VarPatIn name)
75 id = lookupE_Binder e name
77 returnTc (VarPat id, nullLIE, getIdUniType id)
79 tcPat e (LazyPatIn pat)
80 = tcPat e pat `thenTc` \ (pat', lie, ty) ->
81 returnTc (LazyPat pat', lie, ty)
83 tcPat e pat_in@(AsPatIn name pat)
85 id = lookupE_Binder e name
87 tcPat e pat `thenTc` \ (pat', lie, ty) ->
88 unifyTauTy (getIdUniType id) ty (PatCtxt pat_in) `thenTc_`
89 returnTc (AsPat id pat', lie, ty)
92 = newOpenTyVarTy `thenNF_Tc` \ tyvar_ty ->
93 returnTc (WildPat tyvar_ty, nullLIE, tyvar_ty)
96 %************************************************************************
98 \subsection{Explicit lists and tuples}
100 %************************************************************************
103 tcPat e pat_in@(ListPatIn pats)
104 = tcPats e pats `thenTc` \ (pats', lie, tys) ->
105 newPolyTyVarTy `thenNF_Tc` \ tyvar_ty ->
107 unifyTauTyList (tyvar_ty:tys) (PatCtxt pat_in) `thenTc_`
109 returnTc (ListPat tyvar_ty pats', lie, mkListTy tyvar_ty)
111 tcPat e pat_in@(TuplePatIn pats)
115 tcPats e pats `thenTc` \ (pats', lie, tys) ->
117 -- We have to unify with fresh polymorphic type variables, to
118 -- make sure we record that the tuples can only contain boxed
120 newPolyTyVarTys arity `thenNF_Tc` \ tyvar_tys ->
122 unifyTauTyLists tyvar_tys tys (PatCtxt pat_in) `thenTc_`
124 -- possibly do the "make all tuple-pats irrefutable" test:
125 getSwitchCheckerTc `thenNF_Tc` \ sw_chkr ->
127 unmangled_result = TuplePat pats'
129 -- Under flag control turn a pattern (x,y,z) into ~(x,y,z)
130 -- so that we can experiment with lazy tuple-matching.
131 -- This is a pretty odd place to make the switch, but
132 -- it was easy to do.
133 possibly_mangled_result
134 = if sw_chkr IrrefutableTuples
135 then LazyPat unmangled_result
136 else unmangled_result
138 -- ToDo: IrrefutableEverything
140 returnTc (possibly_mangled_result, lie, mkTupleTy arity tys)
143 %************************************************************************
145 \subsection{Other constructors}
147 %************************************************************************
149 Constructor patterns are a little fun:
152 typecheck the arguments
154 look up the constructor
156 specialise its type (ignore the translation this produces)
158 check that the context produced by this specialisation is empty
160 get the arguments out of the function type produced from specialising
162 unify them with the types of the patterns
164 back substitute with the type of the result of the constructor
167 ToDo: exploit new representation of constructors to make this more
171 tcPat e pat_in@(ConPatIn name pats)
173 con_id = lookupE_Value e name
175 tcPats e pats `thenTc` \ (pats', lie, tys) ->
177 matchConArgTys con_id tys (\ ty -> PatCtxt pat_in) `thenTc` \ data_ty ->
179 returnTc (ConPat con_id data_ty pats', lie, data_ty)
181 tcPat e pat_in@(ConOpPatIn pat1 op pat2) -- & in binary-op form...
183 con_id = lookupE_Value e op
185 tcPats e [pat1, pat2] `thenTc` \ ([pat1',pat2'], lie, tys) ->
186 -- ToDo: there exists a less ugly way, no doubt...
188 matchConArgTys con_id tys (\ ty -> PatCtxt pat_in) `thenTc` \ data_ty ->
190 returnTc (ConOpPat pat1' con_id pat2' data_ty, lie, data_ty)
193 %************************************************************************
195 \subsection{Non-overloaded literals}
197 %************************************************************************
200 tcPat e (LitPatIn lit@(CharLit str))
201 = returnTc (LitPat lit charTy, nullLIE, charTy)
203 tcPat e (LitPatIn lit@(StringLit str))
204 = getSrcLocTc `thenNF_Tc` \ loc ->
206 origin = LiteralOrigin lit loc
207 eq_id = lookupE_ClassOpByKey e eqClassKey SLIT("==")
209 newMethod origin eq_id [stringTy] `thenNF_Tc` \ eq ->
211 comp_op = App (Var (mkInstId eq)) (Lit lit)
213 returnTc (NPat lit stringTy comp_op, mkLIE [eq], stringTy)
216 tcPat e (LitPatIn lit@(StringLit str))
217 = returnTc (NPat lit stringTy comp_op, nullLIE, stringTy)
219 comp_op = App (Var eqStringId) (Lit lit)
222 tcPat e (LitPatIn lit@(IntPrimLit _))
223 = returnTc (LitPat lit intPrimTy, nullLIE, intPrimTy)
224 tcPat e (LitPatIn lit@(CharPrimLit _))
225 = returnTc (LitPat lit charPrimTy, nullLIE, charPrimTy)
226 tcPat e (LitPatIn lit@(StringPrimLit _))
227 = returnTc (LitPat lit addrPrimTy, nullLIE, addrPrimTy)
228 tcPat e (LitPatIn lit@(FloatPrimLit _))
229 = returnTc (LitPat lit floatPrimTy, nullLIE, floatPrimTy)
230 tcPat e (LitPatIn lit@(DoublePrimLit _))
231 = returnTc (LitPat lit doublePrimTy, nullLIE, doublePrimTy)
234 %************************************************************************
236 \subsection{Overloaded patterns: int literals and \tr{n+k} patterns}
238 %************************************************************************
241 tcPat e (LitPatIn lit@(IntLit i))
242 = getSrcLocTc `thenNF_Tc` \ loc ->
244 origin = LiteralOrigin lit loc
246 newPolyTyVarTy `thenNF_Tc` \ tyvar_ty ->
248 from_int = lookupE_ClassOpByKey e numClassKey SLIT("fromInt")
249 from_integer = lookupE_ClassOpByKey e numClassKey SLIT("fromInteger")
250 eq_id = lookupE_ClassOpByKey e eqClassKey SLIT("==")
252 newOverloadedLit origin
253 (OverloadedIntegral i from_int from_integer)
254 tyvar_ty `thenNF_Tc` \ over_lit ->
256 newMethod origin eq_id [tyvar_ty] `thenNF_Tc` \ eq ->
258 returnTc (NPat lit tyvar_ty (App (Var (mkInstId eq))
259 (Var (mkInstId over_lit))),
260 mkLIE [over_lit, eq],
263 tcPat e (LitPatIn lit@(FracLit f))
264 = getSrcLocTc `thenNF_Tc` \ loc ->
266 origin = LiteralOrigin lit loc
268 newPolyTyVarTy `thenNF_Tc` \ tyvar_ty ->
270 eq_id = lookupE_ClassOpByKey e eqClassKey SLIT("==")
271 from_rational = lookupE_ClassOpByKey e fractionalClassKey SLIT("fromRational")
273 newOverloadedLit origin
274 (OverloadedFractional f from_rational)
275 tyvar_ty `thenNF_Tc` \ over_lit ->
277 newMethod origin eq_id [tyvar_ty] `thenNF_Tc` \ eq ->
279 returnTc (NPat lit tyvar_ty (App (Var (mkInstId eq))
280 (Var (mkInstId over_lit))),
281 mkLIE [over_lit, eq],
284 tcPat e (LitPatIn lit@(LitLitLitIn s))
285 = error "tcPat: can't handle ``literal-literal'' patterns"
287 = getSrcLocTc `thenNF_Tc` \ loc ->
289 origin = LiteralOrigin lit loc
291 newPolyTyVarTy `thenNF_Tc` \ tyvar_ty ->
293 eq_id = lookupE_ClassOpByKey e eqClassKey "=="
295 newOverloadedLit origin
297 tyvar_ty `thenNF_Tc` \ over_lit ->
299 newMethod origin eq_id [tyvar_ty] `thenNF_Tc` \ eq ->
301 returnTc (NPat lit tyvar_ty (App (Var (mkInstId eq))
302 (Var (mkInstId over_lit))),
303 mkLIE [over_lit, eq],
307 tcPat e (NPlusKPatIn name lit@(IntLit k))
308 = getSrcLocTc `thenNF_Tc` \ loc ->
310 origin = LiteralOrigin lit loc
312 local = lookupE_Binder e name
313 local_ty = getIdUniType local
315 ge_id = lookupE_ClassOpByKey e ordClassKey SLIT(">=")
316 minus_id = lookupE_ClassOpByKey e numClassKey SLIT("-")
317 from_int = lookupE_ClassOpByKey e numClassKey SLIT("fromInt")
318 from_integer = lookupE_ClassOpByKey e numClassKey SLIT("fromInteger")
320 newOverloadedLit origin
321 (OverloadedIntegral k from_int from_integer)
322 local_ty `thenNF_Tc` \ over_lit ->
324 newMethod origin ge_id [local_ty] `thenNF_Tc` \ ge ->
325 newMethod origin minus_id [local_ty] `thenNF_Tc` \ minus ->
327 returnTc (NPlusKPat local lit local_ty
328 (Var (mkInstId over_lit))
330 (Var (mkInstId minus)),
331 mkLIE [over_lit, ge, minus],
334 tcPat e (NPlusKPatIn pat other) = panic "TcPat:NPlusKPat: not an IntLit"
337 tcPat e (ProcessorPatIn pats pat)
338 = tcPidPats e pats `thenTc` \ (pats',convs, lie, tys)->
339 tcPat e pat `thenTc` \ (pat', ty, lie') ->
340 returnTc (ProcessorPat pats' convs pat',
342 mkProcessorTy tys ty)
343 #endif {- Data Parallel Haskell -}
346 %************************************************************************
348 \subsection{Lists of patterns}
350 %************************************************************************
353 tcPats :: E -> [RenamedPat] -> TcM ([TypecheckedPat], LIE, [UniType])
355 tcPats e [] = returnTc ([], nullLIE, [])
358 = tcPat e pat `thenTc` \ (pat', lie, ty) ->
359 tcPats e pats `thenTc` \ (pats', lie', tys) ->
361 returnTc (pat':pats', plusLIE lie lie', ty:tys)
364 @matchConArgTys@ grabs the signature of the data constructor, and
365 unifies the actual args against the expected ones.
368 matchConArgTys :: Id -> [UniType] -> (UniType -> UnifyErrContext) -> TcM UniType
370 matchConArgTys con_id arg_tys err_ctxt
372 no_of_args = length arg_tys
373 (sig_tyvars, sig_theta, sig_tys, _) = getDataConSig con_id
374 -- Ignore the sig_theta; overloaded constructors only
375 -- behave differently when called, not when used for
377 con_arity = length sig_tys
379 getSrcLocTc `thenNF_Tc` \ loc ->
380 checkTc (con_arity /= no_of_args)
381 (dataConArityErr con_id con_arity no_of_args loc) `thenTc_`
383 copyTyVars sig_tyvars `thenNF_Tc` \ (inst_env, _, new_tyvar_tys) ->
385 (_,inst_arg_tys,inst_result_ty) = getInstantiatedDataConSig con_id new_tyvar_tys
387 unifyTauTyLists arg_tys inst_arg_tys (err_ctxt inst_result_ty) `thenTc_`
388 returnTc inst_result_ty