\begin{code}
-module Check ( check , ExhaustivePat, WarningPat, BoxedString(..) ) where
+module Check ( check , ExhaustivePat ) where
import HsSyn
import DsUtils ( EquationInfo(..),
MatchResult(..),
- EqnNo,
EqnSet,
CanItFail(..)
)
-import Id ( idType,
- Id,
- isTupleCon,
- getIdArity
- )
-import IdInfo ( ArityInfo(..) )
-import Lex ( isLexConSym )
-import Name ( occNameString,
- Name,
- getName,
- nameUnique,
- getOccName,
- getOccString
- )
+import Id ( idType )
+import DataCon ( DataCon, isTupleCon, isUnboxedTupleCon,
+ dataConSourceArity )
+import Name ( Name, mkLocalName, getOccName, isConSymOcc, getName, varOcc )
import Type ( Type,
isUnboxedType,
splitTyConApp_maybe
)
-import TyVar ( TyVar )
import TysPrim ( intPrimTy,
charPrimTy,
floatPrimTy,
)
import TysWiredIn ( nilDataCon, consDataCon,
mkTupleTy, tupleCon,
+ mkUnboxedTupleTy, unboxedTupleCon,
mkListTy,
charTy, charDataCon,
intTy, intDataCon,
wordTy, wordDataCon,
stringTy
)
+import Unique ( unboundKey )
import TyCon ( tyConDataCons )
import UniqSet
-import Unique ( Unique )
import Outputable
#include "HsVersions.h"
\begin{code}
-newtype BoxedString = BS String
-
-type WarningPat = InPat BoxedString
-type ExhaustivePat = ([WarningPat], [(BoxedString, [HsLit])])
-
-
-instance Outputable BoxedString where
- ppr (BS s) = text s
+type WarningPat = InPat Name
+type ExhaustivePat = ([WarningPat], [(Name, [HsLit])])
check :: [EquationInfo] -> ([ExhaustivePat],EqnSet)
untidy_exhaustive (pats, messages) =
(map untidy_pars pats, map untidy_message messages)
-untidy_message :: (BoxedString, [HsLit]) -> (BoxedString, [HsLit])
+untidy_message :: (Name, [HsLit]) -> (Name, [HsLit])
untidy_message (string, lits) = (string, map untidy_lit lits)
\end{code}
untidy b (ConOpPatIn pat1 name fixity pat2) =
pars b (ConOpPatIn (untidy_pars pat1) name fixity (untidy_pars pat2))
untidy _ (ListPatIn pats) = ListPatIn (map untidy_no_pars pats)
-untidy _ (TuplePatIn pats) = TuplePatIn (map untidy_no_pars pats)
+untidy _ (TuplePatIn pats boxed) = TuplePatIn (map untidy_no_pars pats) boxed
+untidy _ (SigPatIn pat ty) = panic "Check.untidy: SigPatIn"
untidy _ (LazyPatIn pat) = panic "Check.untidy: LazyPatIn"
untidy _ (AsPatIn name pat) = panic "Check.untidy: AsPatIn"
untidy _ (NPlusKPatIn name lit) = panic "Check.untidy: NPlusKPatIn"
check' :: [EquationInfo] -> ([ExhaustivePat],EqnSet)
check' [] = ([([],[])],emptyUniqSet)
-check' [EqnInfo n ctx ps (MatchResult CanFail _ _)]
+check' [EqnInfo n ctx ps (MatchResult CanFail _)]
| all_vars ps = ([(take (length ps) (repeat new_wild_pat),[])], unitUniqSet n)
-check' qs@((EqnInfo n ctx ps (MatchResult CanFail _ _)):_)
+check' qs@((EqnInfo n ctx ps (MatchResult CanFail _)):_)
| all_vars ps = (pats, addOneToUniqSet indexs n)
where
(pats,indexs) = check' (tail qs)
pats_indexs = map (\x -> construct_matrix x qs) cons
(pats,indexs) = unzip pats_indexs
-need_default_case :: [TypecheckedPat] -> [Id] -> [EquationInfo] -> ([ExhaustivePat],EqnSet)
+need_default_case :: [TypecheckedPat] -> [DataCon] -> [EquationInfo] -> ([ExhaustivePat],EqnSet)
need_default_case used_cons unused_cons qs
| length default_eqns == 0 = (pats_default_no_eqns,indexs)
| otherwise = (pats_default,indexs_default)
construct_matrix :: TypecheckedPat -> [EquationInfo] -> ([ExhaustivePat],EqnSet)
construct_matrix con qs =
-
(map (make_con con) pats,indexs)
where
(pats,indexs) = (check' (remove_first_column con qs))
remove_first_column :: TypecheckedPat -- Constructor
-> [EquationInfo]
-> [EquationInfo]
-remove_first_column (ConPat con _ con_pats) qs =
+remove_first_column (ConPat con _ _ _ con_pats) qs =
map shift_var (filter (is_var_con con) qs)
where
new_wilds = [WildPat (outPatType arg_pat) | arg_pat <- con_pats]
- shift_var (EqnInfo n ctx (ConPat _ _ ps':ps) result) =
- EqnInfo n ctx (ps'++ps) result
- shift_var (EqnInfo n ctx (WildPat _ :ps) result) =
- EqnInfo n ctx (new_wilds ++ ps) result
- shift_var _ = panic "Check.shift_var: Not implemented"
+ shift_var (EqnInfo n ctx (ConPat _ _ _ _ ps':ps) result) =
+ EqnInfo n ctx (ps'++ps) result
+ shift_var (EqnInfo n ctx (WildPat _ :ps) result) =
+ EqnInfo n ctx (new_wilds ++ ps) result
+ shift_var _ = panic "Check.Shift_var:No done"
make_row_vars :: [HsLit] -> EquationInfo -> ExhaustivePat
make_row_vars used_lits (EqnInfo _ _ pats _ ) =
(VarPatIn new_var:take (length (tail pats)) (repeat new_wild_pat),[(new_var,used_lits)])
- where new_var = BS "#x"
+ where new_var = hash_x
+
+hash_x = mkLocalName unboundKey {- doesn't matter much -}
+ (varOcc SLIT("#x"))
make_row_vars_for_constructor :: EquationInfo -> [WarningPat]
make_row_vars_for_constructor (EqnInfo _ _ pats _ ) = take (length (tail pats)) (repeat new_wild_pat)
compare_cons :: TypecheckedPat -> TypecheckedPat -> Bool
-compare_cons (ConPat id1 _ _) (ConPat id2 _ _) = id1 == id2
+compare_cons (ConPat id1 _ _ _ _) (ConPat id2 _ _ _ _) = id1 == id2
remove_dups :: [TypecheckedPat] -> [TypecheckedPat]
remove_dups [] = []
| otherwise = x : remove_dups xs
get_used_cons :: [EquationInfo] -> [TypecheckedPat]
-get_used_cons qs = remove_dups [con | (EqnInfo _ _ (con@(ConPat _ _ _):_) _) <- qs]
+get_used_cons qs = remove_dups [con | (EqnInfo _ _ (con@(ConPat _ _ _ _ _):_) _) <- qs]
remove_dups' :: [HsLit] -> [HsLit]
remove_dups' [] = []
get_used_lits' (q:qs) =
get_used_lits qs
-get_unused_cons :: [TypecheckedPat] -> [Id]
+get_unused_cons :: [TypecheckedPat] -> [DataCon]
get_unused_cons used_cons = unused_cons
where
- (ConPat _ ty _) = head used_cons
- Just (ty_con,_) = splitTyConApp_maybe ty
- all_cons = tyConDataCons ty_con
- used_cons_as_id = map (\ (ConPat id _ _) -> id) used_cons
- unused_cons = uniqSetToList (mkUniqSet all_cons `minusUniqSet` mkUniqSet used_cons_as_id)
+ (ConPat _ ty _ _ _) = head used_cons
+ Just (ty_con,_) = splitTyConApp_maybe ty
+ all_cons = tyConDataCons ty_con
+ used_cons_as_id = map (\ (ConPat id _ _ _ _) -> id) used_cons
+ unused_cons = uniqSetToList (mkUniqSet all_cons `minusUniqSet` mkUniqSet used_cons_as_id)
all_vars :: [TypecheckedPat] -> Bool
all_vars [] = True
remove_var _ = panic "Check:remove_var: equation not begin with a variable"
is_con :: EquationInfo -> Bool
-is_con (EqnInfo _ _ ((ConPat _ _ _):_) _) = True
+is_con (EqnInfo _ _ ((ConPat _ _ _ _ _):_) _) = True
is_con _ = False
is_lit :: EquationInfo -> Bool
is_var (EqnInfo _ _ ((WildPat _):_) _) = True
is_var _ = False
-is_var_con :: Id -> EquationInfo -> Bool
-is_var_con con (EqnInfo _ _ ((WildPat _):_) _) = True
-is_var_con con (EqnInfo _ _ ((ConPat id _ _):_) _) | id == con = True
-is_var_con con _ = False
+is_var_con :: DataCon -> EquationInfo -> Bool
+is_var_con con (EqnInfo _ _ ((WildPat _):_) _) = True
+is_var_con con (EqnInfo _ _ ((ConPat id _ _ _ _):_) _) | id == con = True
+is_var_con con _ = False
is_var_lit :: HsLit -> EquationInfo -> Bool
is_var_lit lit (EqnInfo _ _ ((WildPat _):_) _) = True
is_var_lit lit _ = False
\end{code}
-The difference between make_con and make_whole_con is that make_whole_con
-creates a new constructor with all their arguments, and make_con takes a
-list of arguments, creates the constructor getting their arguments from the
-list. See where are used for details.
+The difference beteewn make_con and make_whole_con is that
+make_wole_con creates a new constructor with all their arguments, and
+make_Con takes a list of argumntes, creates the contructor geting thir
+argumnts from the list. See where are used for details.
-We need to reconstruct the patterns (make the constructors infix and
+We need to reconstruct the patterns (make the constructors infix and
similar) at the same time that we create the constructors.
You can tell tuple constructors using
Rather clumsy but it works. (Simon Peyton Jones)
-We don't mind the nilDataCon because it doesn't change the way to print the
-message, we are searching only for things like: [1,2,3], not x:xs ....
-
+We con't mind the nilDataCon because it doesn't change the way to
+print the messsage, we are searching only for things like: [1,2,3],
+not x:xs ....
In reconstruct_pat we want to "undo" the work that we have done in simplify_pat
In particular:
((:) x xs) returns to be (x:xs)
(x:(...:[]) returns to be [x,...]
-The difficult case is the third one because we need to follow all the
-constructors until the [] to know that we need to use the second case,
+The difficult case is the third one becouse we need to follow all the
+contructors until the [] to know taht we need to use the second case,
not the second.
\begin{code}
-isInfixCon con = isLexConSym (occNameString (getOccName con))
+isInfixCon con = isConSymOcc (getOccName con)
-is_nil (ConPatIn (BS con) []) = con == getOccString nilDataCon
-is_nil _ = False
+is_nil (ConPatIn con []) = con == getName nilDataCon
+is_nil _ = False
is_list (ListPatIn _) = True
is_list _ = False
make_list _ _ = panic "Check.make_list: Invalid argument"
make_con :: TypecheckedPat -> ExhaustivePat -> ExhaustivePat
-make_con (ConPat id ty pats) (p:q:ps, constraints)
+make_con (ConPat id _ _ _ _) (p:q:ps, constraints)
| return_list id q = (make_list p q : ps, constraints)
| isInfixCon id = ((ConOpPatIn p name fixity q) : ps, constraints)
- where name = BS (getOccString id)
+ where name = getName id
fixity = panic "Check.make_con: Guessing fixity"
-make_con (ConPat id ty pats) (ps,constraints)
- | isTupleCon id = (TuplePatIn pats_con : rest_pats, constraints)
+
+make_con (ConPat id _ _ _ pats) (ps,constraints)
+ | isTupleCon id = (TuplePatIn pats_con True : rest_pats, constraints)
+ | isUnboxedTupleCon id = (TuplePatIn pats_con False : rest_pats, constraints)
| otherwise = (ConPatIn name pats_con : rest_pats, constraints)
where num_args = length pats
- name = BS (getOccString id)
+ name = getName id
pats_con = take num_args ps
rest_pats = drop num_args ps
-make_whole_con :: Id -> WarningPat
+make_whole_con :: DataCon -> WarningPat
make_whole_con con | isInfixCon con = ConOpPatIn new_wild_pat name fixity new_wild_pat
| otherwise = ConPatIn name pats
where
fixity = panic "Check.make_whole_con: Guessing fixity"
- name = BS (getOccString con)
- arity = get_int_arity con
+ name = getName con
+ arity = dataConSourceArity con
pats = take arity (repeat new_wild_pat)
new_wild_pat :: WarningPat
new_wild_pat = WildPatIn
-
-get_int_arity :: Id -> Int
-get_int_arity id = arity_to_int (getIdArity id)
- where
- arity_to_int (ArityExactly n) = n
- arity_to_int _ = panic "Check.getIntArity: Unknown arity"
-
\end{code}
This equation makes the same thing that tidy in Match.lhs, the
simplify_pat pat@(WildPat gt) = pat
simplify_pat (VarPat id) = WildPat (idType id)
-simplify_pat (LazyPat p) = simplify_pat p
-
-simplify_pat (AsPat id p) = simplify_pat p
-
-simplify_pat (ConPat id ty ps) = ConPat id ty (map simplify_pat ps)
+simplify_pat (LazyPat p) = simplify_pat p
+simplify_pat (AsPat id p) = simplify_pat p
-simplify_pat (ConOpPat p1 id p2 ty) = ConPat id ty (map simplify_pat [p1,p2])
+simplify_pat (ConPat id ty tvs dicts ps) = ConPat id ty tvs dicts (map simplify_pat ps)
-simplify_pat (ListPat ty ps) = foldr (\ x -> \y -> ConPat consDataCon list_ty [x, y])
- (ConPat nilDataCon list_ty [])
+simplify_pat (ListPat ty ps) = foldr (\ x -> \y -> ConPat consDataCon list_ty [] [] [x, y])
+ (ConPat nilDataCon list_ty [] [] [])
(map simplify_pat ps)
where list_ty = mkListTy ty
-simplify_pat (TuplePat ps) = ConPat (tupleCon arity)
- (mkTupleTy arity (map outPatType ps))
- (map simplify_pat ps)
+simplify_pat (TuplePat ps True) = ConPat (tupleCon arity)
+ (mkTupleTy arity (map outPatType ps)) [] []
+ (map simplify_pat ps)
where
arity = length ps
-simplify_pat (RecPat id ty []) = ConPat id ty [wild_pat]
- where
- wild_pat = WildPat gt
- gt = panic "Check.symplify_pat: gessing gt"
-simplify_pat (RecPat id ty idps) = ConPat id ty pats
- where
- pats = map (\ (id,p,_)-> simplify_pat p) idps
+simplify_pat (TuplePat ps False)
+ = ConPat (unboxedTupleCon arity)
+ (mkUnboxedTupleTy arity (map outPatType ps)) [] []
+ (map simplify_pat ps)
+ where
+ arity = length ps
+
+simplify_pat (RecPat id ty tvs dicts [])
+ = ConPat id ty tvs dicts [wild_pat]
+ where
+ wild_pat = WildPat gt
+ gt = panic "Check.symplify_pat: gessing gt"
+
+simplify_pat (RecPat id ty tvs dicts idps)
+ = ConPat id ty tvs dicts pats
+ where
+ pats = map (\ (id,p,_)-> simplify_pat p) idps
simplify_pat pat@(LitPat lit lit_ty)
| isUnboxedType lit_ty = pat
- | lit_ty == charTy = ConPat charDataCon charTy [LitPat (mk_char lit) charPrimTy]
+ | lit_ty == charTy = ConPat charDataCon charTy [] [] [LitPat (mk_char lit) charPrimTy]
| otherwise = pprPanic "Check.simplify_pat: LitPat:" (ppr pat)
where
simplify_pat (NPat lit lit_ty hsexpr) = better_pat
where
better_pat
- | lit_ty == charTy = ConPat charDataCon lit_ty [LitPat (mk_char lit) charPrimTy]
- | lit_ty == intTy = ConPat intDataCon lit_ty [LitPat (mk_int lit) intPrimTy]
- | lit_ty == wordTy = ConPat wordDataCon lit_ty [LitPat (mk_word lit) wordPrimTy]
- | lit_ty == addrTy = ConPat addrDataCon lit_ty [LitPat (mk_addr lit) addrPrimTy]
- | lit_ty == floatTy = ConPat floatDataCon lit_ty [LitPat (mk_float lit) floatPrimTy]
- | lit_ty == doubleTy = ConPat doubleDataCon lit_ty [LitPat (mk_double lit) doublePrimTy]
-
- -- Convert the literal pattern "" to the constructor pattern [].
- | null_str_lit lit = ConPat nilDataCon lit_ty []
-
+ | lit_ty == charTy = ConPat charDataCon lit_ty [] [] [LitPat (mk_char lit) charPrimTy]
+ | lit_ty == intTy = ConPat intDataCon lit_ty [] [] [LitPat (mk_int lit) intPrimTy]
+ | lit_ty == wordTy = ConPat wordDataCon lit_ty [] [] [LitPat (mk_word lit) wordPrimTy]
+ | lit_ty == addrTy = ConPat addrDataCon lit_ty [] [] [LitPat (mk_addr lit) addrPrimTy]
+ | lit_ty == floatTy = ConPat floatDataCon lit_ty [] [] [LitPat (mk_float lit) floatPrimTy]
+ | lit_ty == doubleTy = ConPat doubleDataCon lit_ty [] [] [LitPat (mk_double lit) doublePrimTy]
+
+ -- Convert the literal pattern "" to the constructor pattern [].
+ | null_str_lit lit = ConPat nilDataCon lit_ty [] [] []
| lit_ty == stringTy =
- foldr (\ x -> \y -> ConPat consDataCon list_ty [x, y])
- (ConPat nilDataCon list_ty [])
+ foldr (\ x -> \y -> ConPat consDataCon list_ty [] [] [x, y])
+ (ConPat nilDataCon list_ty [] [] [])
(mk_string lit)
-
| otherwise = NPat lit lit_ty hsexpr
list_ty = mkListTy lit_ty
mk_head_char (HsString s) = HsCharPrim (_HEAD_ s)
mk_string (HsString s) =
- map (\ c -> ConPat charDataCon charTy
+ map (\ c -> ConPat charDataCon charTy [] []
[LitPat (HsCharPrim c) charPrimTy])
(_UNPK_ s)
simplify_pat (DictPat dicts methods) =
case num_of_d_and_ms of
- 0 -> simplify_pat (TuplePat [])
+ 0 -> simplify_pat (TuplePat [] True)
1 -> simplify_pat (head dict_and_method_pats)
- _ -> simplify_pat (TuplePat dict_and_method_pats)
+ _ -> simplify_pat (TuplePat dict_and_method_pats True)
where
num_of_d_and_ms = length dicts + length methods
dict_and_method_pats = map VarPat (dicts ++ methods)