2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1996
4 \section[TcPat]{Typechecking patterns}
7 #include "HsVersions.h"
9 module TcPat ( tcPat ) where
13 import HsSyn ( InPat(..), OutPat(..), HsExpr(..), HsLit(..),
14 Match, HsBinds, Qual, PolyType,
15 ArithSeqInfo, Stmt, Fake )
16 import RnHsSyn ( RenamedPat(..) )
17 import TcHsSyn ( TcPat(..), TcIdOcc(..) )
20 import Inst ( Inst, OverloadedLit(..), InstOrigin(..), LIE(..),
21 emptyLIE, plusLIE, newMethod, newOverloadedLit )
22 import TcEnv ( tcLookupGlobalValue, tcLookupGlobalValueByKey,
23 tcLookupLocalValueOK )
24 import TcType ( TcType(..), TcMaybe, tcInstType, newTyVarTy, newTyVarTys )
25 import Unify ( unifyTauTy, unifyTauTyList, unifyTauTyLists )
28 import CmdLineOpts ( opt_IrrefutableTuples )
29 import ErrUtils ( arityErr )
30 import Id ( GenId, idType )
31 import Kind ( Kind, mkBoxedTypeKind, mkTypeKind )
33 import PprType ( GenType, GenTyVar )
34 import PrelInfo ( charPrimTy, intPrimTy, floatPrimTy,
35 doublePrimTy, charTy, stringTy, mkListTy,
36 mkTupleTy, addrTy, addrPrimTy )
38 import Type ( Type(..), GenType, splitFunTy, splitSigmaTy )
39 import TyVar ( GenTyVar )
40 import Unique ( Unique, eqClassOpKey )
45 tcPat :: RenamedPat -> TcM s (TcPat s, LIE s, TcType s)
48 %************************************************************************
50 \subsection{Variables, wildcards, lazy pats, as-pats}
52 %************************************************************************
56 = tcLookupLocalValueOK "tcPat1" name `thenNF_Tc` \ id ->
57 returnTc (VarPat (TcId id), emptyLIE, idType id)
60 = tcPat pat `thenTc` \ (pat', lie, ty) ->
61 returnTc (LazyPat pat', lie, ty)
63 tcPat pat_in@(AsPatIn name pat)
64 = tcLookupLocalValueOK "tcPat2" name `thenNF_Tc` \ id ->
65 tcPat pat `thenTc` \ (pat', lie, ty) ->
66 tcAddErrCtxt (patCtxt pat_in) $
67 unifyTauTy (idType id) ty `thenTc_`
68 returnTc (AsPat (TcId id) pat', lie, ty)
71 = newTyVarTy mkTypeKind `thenNF_Tc` \ tyvar_ty ->
72 returnTc (WildPat tyvar_ty, emptyLIE, tyvar_ty)
75 %************************************************************************
77 \subsection{Explicit lists and tuples}
79 %************************************************************************
82 tcPat pat_in@(ListPatIn pats)
83 = tcPats pats `thenTc` \ (pats', lie, tys) ->
84 newTyVarTy mkBoxedTypeKind `thenNF_Tc` \ tyvar_ty ->
85 tcAddErrCtxt (patCtxt pat_in) $
86 unifyTauTyList (tyvar_ty:tys) `thenTc_`
88 returnTc (ListPat tyvar_ty pats', lie, mkListTy tyvar_ty)
90 tcPat pat_in@(TuplePatIn pats)
94 tcPats pats `thenTc` \ (pats', lie, tys) ->
96 -- Make sure we record that the tuples can only contain boxed types
97 newTyVarTys arity mkBoxedTypeKind `thenNF_Tc` \ tyvar_tys ->
99 tcAddErrCtxt (patCtxt pat_in) $
100 unifyTauTyLists tyvar_tys tys `thenTc_`
102 -- possibly do the "make all tuple-pats irrefutable" test:
104 unmangled_result = TuplePat pats'
106 -- Under flag control turn a pattern (x,y,z) into ~(x,y,z)
107 -- so that we can experiment with lazy tuple-matching.
108 -- This is a pretty odd place to make the switch, but
109 -- it was easy to do.
111 possibly_mangled_result
112 = if opt_IrrefutableTuples
113 then LazyPat unmangled_result
114 else unmangled_result
116 -- ToDo: IrrefutableEverything
118 returnTc (possibly_mangled_result, lie, mkTupleTy arity tys)
121 %************************************************************************
123 \subsection{Other constructors}
125 %************************************************************************
127 Constructor patterns are a little fun:
130 typecheck the arguments
132 look up the constructor
134 specialise its type (ignore the translation this produces)
136 check that the context produced by this specialisation is empty
138 get the arguments out of the function type produced from specialising
140 unify them with the types of the patterns
142 back substitute with the type of the result of the constructor
145 ToDo: exploit new representation of constructors to make this more
149 tcPat pat_in@(ConPatIn name pats)
150 = tcLookupGlobalValue name `thenNF_Tc` \ con_id ->
152 tcPats pats `thenTc` \ (pats', lie, tys) ->
154 tcAddErrCtxt (patCtxt pat_in) $
155 matchConArgTys con_id tys `thenTc` \ data_ty ->
157 returnTc (ConPat con_id data_ty pats',
161 tcPat pat_in@(ConOpPatIn pat1 op pat2) -- & in binary-op form...
162 = tcLookupGlobalValue op `thenNF_Tc` \ con_id ->
164 tcPat pat1 `thenTc` \ (pat1', lie1, ty1) ->
165 tcPat pat2 `thenTc` \ (pat2', lie2, ty2) ->
167 tcAddErrCtxt (patCtxt pat_in) $
168 matchConArgTys con_id [ty1,ty2] `thenTc` \ data_ty ->
170 returnTc (ConOpPat pat1' con_id pat2' data_ty,
175 %************************************************************************
177 \subsection{Non-overloaded literals}
179 %************************************************************************
182 tcPat (LitPatIn lit@(HsChar str))
183 = returnTc (LitPat lit charTy, emptyLIE, charTy)
185 tcPat (LitPatIn lit@(HsString str))
186 = tcLookupGlobalValueByKey eqClassOpKey `thenNF_Tc` \ sel_id ->
187 newMethod (LiteralOrigin lit)
188 (RealId sel_id) [stringTy] `thenNF_Tc` \ (lie, eq_id) ->
190 comp_op = HsApp (HsVar eq_id) (HsLitOut lit stringTy)
192 returnTc (NPat lit stringTy comp_op, lie, stringTy)
194 tcPat (LitPatIn lit@(HsIntPrim _))
195 = returnTc (LitPat lit intPrimTy, emptyLIE, intPrimTy)
196 tcPat (LitPatIn lit@(HsCharPrim _))
197 = returnTc (LitPat lit charPrimTy, emptyLIE, charPrimTy)
198 tcPat (LitPatIn lit@(HsStringPrim _))
199 = returnTc (LitPat lit addrPrimTy, emptyLIE, addrPrimTy)
200 tcPat (LitPatIn lit@(HsFloatPrim _))
201 = returnTc (LitPat lit floatPrimTy, emptyLIE, floatPrimTy)
202 tcPat (LitPatIn lit@(HsDoublePrim _))
203 = returnTc (LitPat lit doublePrimTy, emptyLIE, doublePrimTy)
206 %************************************************************************
208 \subsection{Overloaded patterns: int literals and \tr{n+k} patterns}
210 %************************************************************************
213 tcPat (LitPatIn lit@(HsInt i))
214 = newTyVarTy mkBoxedTypeKind `thenNF_Tc` \ tyvar_ty ->
215 newOverloadedLit origin
216 (OverloadedIntegral i) tyvar_ty `thenNF_Tc` \ (lie1, over_lit_id) ->
218 tcLookupGlobalValueByKey eqClassOpKey `thenNF_Tc` \ eq_sel_id ->
219 newMethod origin (RealId eq_sel_id) [tyvar_ty] `thenNF_Tc` \ (lie2, eq_id) ->
221 returnTc (NPat lit tyvar_ty (HsApp (HsVar eq_id)
222 (HsVar over_lit_id)),
226 origin = LiteralOrigin lit
228 tcPat (LitPatIn lit@(HsFrac f))
229 = newTyVarTy mkBoxedTypeKind `thenNF_Tc` \ tyvar_ty ->
230 newOverloadedLit origin
231 (OverloadedFractional f) tyvar_ty `thenNF_Tc` \ (lie1, over_lit_id) ->
233 tcLookupGlobalValueByKey eqClassOpKey `thenNF_Tc` \ eq_sel_id ->
234 newMethod origin (RealId eq_sel_id) [tyvar_ty] `thenNF_Tc` \ (lie2, eq_id) ->
236 returnTc (NPat lit tyvar_ty (HsApp (HsVar eq_id)
237 (HsVar over_lit_id)),
241 origin = LiteralOrigin lit
243 tcPat (LitPatIn lit@(HsLitLit s))
244 = error "tcPat: can't handle ``literal-literal'' patterns"
247 %************************************************************************
249 \subsection{Lists of patterns}
251 %************************************************************************
254 tcPats :: [RenamedPat] -> TcM s ([TcPat s], LIE s, [TcType s])
256 tcPats [] = returnTc ([], emptyLIE, [])
259 = tcPat pat `thenTc` \ (pat', lie, ty) ->
260 tcPats pats `thenTc` \ (pats', lie', tys) ->
262 returnTc (pat':pats', plusLIE lie lie', ty:tys)
265 @matchConArgTys@ grabs the signature of the data constructor, and
266 unifies the actual args against the expected ones.
269 matchConArgTys :: Id -> [TcType s] -> TcM s (TcType s)
271 matchConArgTys con_id arg_tys
272 = tcInstType [] (idType con_id) `thenNF_Tc` \ con_ty ->
274 no_of_args = length arg_tys
275 (con_tyvars, con_theta, con_tau) = splitSigmaTy con_ty
276 -- Ignore the sig_theta; overloaded constructors only
277 -- behave differently when called, not when used for
279 (con_args, con_result) = splitFunTy con_tau
280 con_arity = length con_args
282 checkTc (con_arity == no_of_args)
283 (arityErr "Constructor" con_id con_arity no_of_args) `thenTc_`
285 unifyTauTyLists arg_tys con_args `thenTc_`
290 % =================================================
295 patCtxt pat sty = ppHang (ppStr "In the pattern:") 4 (ppr sty pat)