Add bang patterns
[ghc-hetmet.git] / ghc / compiler / hsSyn / HsPat.lhs
index 71aba6b..953d228 100644 (file)
 
 \begin{code}
 module HsPat (
-       Pat(..), InPat, OutPat, 
+       Pat(..), InPat, OutPat, LPat,
        
        HsConDetails(..), hsConArgs,
 
-       mkPrefixConPat, mkCharLitPat, mkNilPat,
+       mkPrefixConPat, mkCharLitPat, mkNilPat, 
 
-       failureFreePat, isWildPat, 
-       patsAreAllCons, isConPat, isSigPat,
-       patsAreAllLits, isLitPat,
-       collectPatBinders, collectPatsBinders,
-       collectSigTysFromPat, collectSigTysFromPats
+       isBangHsBind,   
+       patsAreAllCons, isConPat, isSigPat, isWildPat,
+       patsAreAllLits, isLitPat, isIrrefutableHsPat
     ) where
 
 #include "HsVersions.h"
 
 
-import {-# SOURCE #-} HsExpr           ( HsExpr )
+import {-# SOURCE #-} HsExpr           ( SyntaxExpr )
 
 -- friends:
+import HsBinds         ( DictBinds, HsBind(..), emptyLHsBinds, pprLHsBinds )
 import HsLit           ( HsLit(HsCharPrim), HsOverLit )
-import HsTypes         ( HsType, SyntaxName, PostTcType )
+import HsTypes         ( LHsType, PostTcType )
 import BasicTypes      ( Boxity, tupleParens )
 -- others:
+import PprCore         ( {- instance OutputableBndr TyVar -} )
 import TysWiredIn      ( nilDataCon, charDataCon, charTy )
 import Var             ( TyVar )
 import DataCon         ( DataCon, dataConTyCon )
-import Maybes          ( maybeToBool )
+import TyCon           ( isProductTyCon )
 import Outputable      
-import TyCon           ( maybeTyConSingleCon )
 import Type            ( Type )
+import SrcLoc          ( Located(..), unLoc, noLoc )
 \end{code}
 
 
 \begin{code}
-type InPat id = Pat id         -- No 'Out' constructors
-type OutPat id = Pat id                -- No 'In' constructors
+type InPat id  = LPat id       -- No 'Out' constructors
+type OutPat id = LPat id       -- No 'In' constructors
+
+type LPat id = Located (Pat id)
 
 data Pat id
   =    ------------ Simple patterns ---------------
     WildPat    PostTcType              -- Wild card
   | VarPat     id                      -- Variable
-  | LazyPat    (Pat id)                -- Lazy pattern
-  | AsPat      id (Pat id)             -- As pattern
-  | ParPat      (Pat id)               -- Parenthesised pattern
+  | VarPatOut  id (DictBinds id)       -- Used only for overloaded Ids; the 
+                                       -- bindings give its overloaded instances
+  | LazyPat    (LPat id)               -- Lazy pattern
+  | AsPat      (Located id) (LPat id)  -- As pattern
+  | ParPat      (LPat id)              -- Parenthesised pattern
+  | BangPat    (LPat id)               -- Bang patterng
 
        ------------ Lists, tuples, arrays ---------------
-  | ListPat    [Pat id]                -- Syntactic list
+  | ListPat    [LPat id]               -- Syntactic list
                PostTcType              -- The type of the elements
                    
-  | TuplePat   [Pat id]                -- Tuple
+  | TuplePat   [LPat id]               -- Tuple
                Boxity                  -- UnitPat is TuplePat []
-
-  | PArrPat    [Pat id]                -- Syntactic parallel array
+               PostTcType
+       -- You might think that the PostTcType was redundant, but it's essential
+       --      data T a where
+       --        T1 :: Int -> T Int
+       --      f :: (T a, a) -> Int
+       --      f (T1 x, z) = z
+       -- When desugaring, we must generate
+       --      f = /\a. \v::a.  case v of (t::T a, w::a) ->
+       --                       case t of (T1 (x::Int)) -> 
+       -- Note the (w::a), NOT (w::Int), because we have not yet
+       -- refined 'a' to Int.  So we must know that the second component
+       -- of the tuple is of type 'a' not Int.  See selectMatchVar
+
+  | PArrPat    [LPat id]               -- Syntactic parallel array
                PostTcType              -- The type of the elements
 
        ------------ Constructor patterns ---------------
-  | ConPatIn   id 
-               (HsConDetails id (Pat id))
+  | ConPatIn   (Located id)
+               (HsConDetails id (LPat id))
 
-  | ConPatOut  DataCon 
-               (HsConDetails id (Pat id))
-               Type                    -- The type of the pattern
+  | ConPatOut  (Located DataCon)
                [TyVar]                 -- Existentially bound type variables
                [id]                    -- Ditto dictionaries
+               (DictBinds id)          -- Bindings involving those dictionaries
+               (HsConDetails id (LPat id))
+               Type                    -- The type of the pattern
 
        ------------ Literal and n+k patterns ---------------
   | LitPat         HsLit               -- Used for *non-overloaded* literal patterns:
                                        -- Int#, Char#, Int, Char, String, etc.
 
-  | NPatIn         HsOverLit           -- Always positive
-                   (Maybe SyntaxName)  -- Just (Name of 'negate') for negative
-                                       -- patterns, Nothing otherwise
-
-  | NPatOut        HsLit               -- Used for literal patterns where there's an equality function to call
-                                       -- The literal is retained so that the desugarer can readily identify
-                                       -- equations with identical literal-patterns
-                                       -- Always HsInteger, HsRat or HsString.
-                                       -- Always HsInteger, HsRat or HsString.
-                                       -- *Unlike* NPatIn, for negative literals, the
-                                       --      literal is acutally negative!
-                   Type                -- Type of pattern, t
-                   (HsExpr id)         -- Of type t -> Bool; detects match
-
-  | NPlusKPatIn            id                  -- n+k pattern
-                   HsOverLit           -- It'll always be an HsIntegral
-                   SyntaxName          -- Name of '-' (see RnEnv.lookupSyntaxName)
-
-  | NPlusKPatOut    id
-                   Integer
-                   (HsExpr id)         -- Of type t -> Bool; detects match
-                   (HsExpr id)         -- Of type t -> t; subtracts k
+  | NPat           (HsOverLit id)              -- ALWAYS positive
+                   (Maybe (SyntaxExpr id))     -- Just (Name of 'negate') for negative
+                                               -- patterns, Nothing otherwise
+                   (SyntaxExpr id)             -- Equality checker, of type t->t->Bool
+                   PostTcType                  -- Type of the pattern
 
+  | NPlusKPat      (Located id)        -- n+k pattern
+                   (HsOverLit id)      -- It'll always be an HsIntegral
+                   (SyntaxExpr id)     -- (>=) function, of type t->t->Bool
+                   (SyntaxExpr id)     -- Name of '-' (see RnEnv.lookupSyntaxName)
 
        ------------ Generics ---------------
-  | TypePat        (HsType id)         -- Type pattern for generic definitions
+  | TypePat        (LHsType id)        -- Type pattern for generic definitions
                                         -- e.g  f{| a+b |} = ...
                                         -- These show up only in class declarations,
                                         -- and should be a top-level pattern
 
        ------------ Pattern type signatures ---------------
-  | SigPatIn       (Pat id)            -- Pattern with a type signature
-                   (HsType id)
+  | SigPatIn       (LPat id)           -- Pattern with a type signature
+                   (LHsType id)
 
-  | SigPatOut      (Pat id)            -- Pattern p
-                   Type                -- Type, t, of the whole pattern
-                   (HsExpr id)         -- Coercion function,
-                                               -- of type t -> typeof(p)
+  | SigPatOut      (LPat id)           -- Pattern with a type signature
+                   Type
 
        ------------ Dictionary patterns (translation only) ---------------
   | DictPat        -- Used when destructing Dictionaries with an explicit case
@@ -124,7 +127,7 @@ HsConDetails is use both for patterns and for data type declarations
 \begin{code}
 data HsConDetails id arg
   = PrefixCon [arg]                    -- C p1 p2 p3
-  | RecCon    [(id, arg)]              -- C { x = p1, y = p2 }
+  | RecCon    [(Located id, arg)]      -- C { x = p1, y = p2 }
   | InfixCon  arg arg                  -- p1 `C` p2
 
 hsConArgs :: HsConDetails id arg -> [arg]
@@ -144,9 +147,8 @@ hsConArgs (InfixCon p1 p2) = [p1,p2]
 instance (OutputableBndr name) => Outputable (Pat name) where
     ppr = pprPat
 
-pprPat :: (OutputableBndr name) => Pat name -> SDoc
-
-pprPat (VarPat var)            -- Print with type info if -dppr-debug is on
+pprPatBndr :: OutputableBndr name => name -> SDoc
+pprPatBndr var                 -- Print with type info if -dppr-debug is on
   = getPprStyle $ \ sty ->
     if debugStyle sty then
        parens (pprBndr LambdaBind var)         -- Could pass the site to pprPat
@@ -154,44 +156,46 @@ pprPat (VarPat var)               -- Print with type info if -dppr-debug is on
     else
        ppr var
 
+pprPat :: (OutputableBndr name) => Pat name -> SDoc
+pprPat (VarPat var)      = pprPatBndr var
+pprPat (VarPatOut var bs) = parens (pprPatBndr var <+> braces (ppr bs))
 pprPat (WildPat _)       = char '_'
 pprPat (LazyPat pat)      = char '~' <> ppr pat
+pprPat (BangPat pat)      = char '!' <> ppr pat
 pprPat (AsPat name pat)   = parens (hcat [ppr name, char '@', ppr pat])
-pprPat (ParPat pat)      = parens (pprPat pat)
-
-pprPat (ListPat pats _)   = brackets (interpp'SP pats)
-pprPat (PArrPat pats _)   = pabrackets (interpp'SP pats)
-pprPat (TuplePat pats bx) = tupleParens bx (interpp'SP pats)
-
-pprPat (ConPatIn c details)       = pprConPat c details
-pprPat (ConPatOut c details _ _ _) = pprConPat c details
+pprPat (ParPat pat)      = parens (ppr pat)
+pprPat (ListPat pats _)     = brackets (interpp'SP pats)
+pprPat (PArrPat pats _)     = pabrackets (interpp'SP pats)
+pprPat (TuplePat pats bx _) = tupleParens bx (interpp'SP pats)
+
+pprPat (ConPatIn con details) = pprUserCon con details
+pprPat (ConPatOut con tvs dicts binds details _) 
+  = getPprStyle $ \ sty ->     -- Tiresome; in TcBinds.tcRhs we print out a 
+    if debugStyle sty then     -- typechecked Pat in an error message, 
+                               -- and we want to make sure it prints nicely
+       ppr con <+> sep [ hsep (map pprPatBndr tvs) <+> hsep (map pprPatBndr dicts),
+                         pprLHsBinds binds, pprConArgs details]
+    else pprUserCon con details
 
 pprPat (LitPat s)            = ppr s
-pprPat (NPatIn l _)          = ppr l
-pprPat (NPatOut l _ _)        = ppr l
-pprPat (NPlusKPatIn n k _)    = hcat [ppr n, char '+', ppr k]
-pprPat (NPlusKPatOut n k _ _) = hcat [ppr n, char '+', integer k]
-
-pprPat (TypePat ty) = ptext SLIT("{|") <> ppr ty <> ptext SLIT("|}")
-
-pprPat (SigPatIn pat ty)    = ppr pat <+> dcolon <+> ppr ty
-pprPat (SigPatOut pat ty _) = ppr pat <+> dcolon <+> ppr ty
-
-pprPat (DictPat dicts methods)
- = parens (sep [ptext SLIT("{-dict-}"),
-                 brackets (interpp'SP dicts),
-                 brackets (interpp'SP methods)])
-
-
-
-pprConPat con (PrefixCon pats)            = ppr con <+> interppSP pats -- inner ParPats supply the necessary parens.
-pprConPat con (InfixCon pat1 pat2) = hsep [ppr pat1, ppr con, ppr pat2] -- ParPats put in parens
-       -- ToDo: use pprSym to print op (but this involves fiddling various
-       -- contexts & I'm lazy...); *PatIns are *rarely* printed anyway... (WDP)
-pprConPat con (RecCon rpats)
-  = ppr con <+> braces (hsep (punctuate comma (map (pp_rpat) rpats)))
-  where
-    pp_rpat (v, p) = hsep [ppr v, char '=', ppr p]
+pprPat (NPat l Nothing  _ _)  = ppr l
+pprPat (NPat l (Just _) _ _)  = char '-' <> ppr l
+pprPat (NPlusKPat n k _ _)    = hcat [ppr n, char '+', ppr k]
+pprPat (TypePat ty)          = ptext SLIT("{|") <> ppr ty <> ptext SLIT("|}")
+pprPat (SigPatIn pat ty)      = ppr pat <+> dcolon <+> ppr ty
+pprPat (SigPatOut pat ty)     = ppr pat <+> dcolon <+> ppr ty
+pprPat (DictPat ds ms)       = parens (sep [ptext SLIT("{-dict-}"),
+                                            brackets (interpp'SP ds),
+                                            brackets (interpp'SP ms)])
+
+pprUserCon c (InfixCon p1 p2) = ppr p1 <+> ppr c <+> ppr p2
+pprUserCon c details          = ppr c <+> pprConArgs details
+
+pprConArgs (PrefixCon pats) = interppSP pats
+pprConArgs (InfixCon p1 p2) = interppSP [p1,p2]
+pprConArgs (RecCon rpats)   = braces (hsep (punctuate comma (map (pp_rpat) rpats)))
+                           where
+                             pp_rpat (v, p) = hsep [ppr v, char '=', ppr p]
 
 
 -- add parallel array brackets around a document
@@ -210,13 +214,13 @@ pabrackets p  = ptext SLIT("[:") <> p <> ptext SLIT(":]")
 \begin{code}
 mkPrefixConPat :: DataCon -> [OutPat id] -> Type -> OutPat id
 -- Make a vanilla Prefix constructor pattern
-mkPrefixConPat dc pats ty = ConPatOut dc (PrefixCon pats) ty [] []
+mkPrefixConPat dc pats ty = noLoc $ ConPatOut (noLoc dc) [] [] emptyLHsBinds (PrefixCon pats) ty
 
 mkNilPat :: Type -> OutPat id
 mkNilPat ty = mkPrefixConPat nilDataCon [] ty
 
-mkCharLitPat :: Int -> OutPat id
-mkCharLitPat c = mkPrefixConPat charDataCon [LitPat (HsCharPrim c)] charTy
+mkCharLitPat :: Char -> OutPat id
+mkCharLitPat c = mkPrefixConPat charDataCon [noLoc $ LitPat (HsCharPrim c)] charTy
 \end{code}
 
 
@@ -250,128 +254,71 @@ patterns are treated specially, of course.
 
 The 1.3 report defines what ``irrefutable'' and ``failure-free'' patterns are.
 \begin{code}
-failureFreePat :: OutPat id -> Bool
-
-failureFreePat (WildPat _)               = True
-failureFreePat (VarPat _)                = True
-failureFreePat (LazyPat        _)                = True
-failureFreePat (ParPat _)                = True
-failureFreePat (AsPat _ pat)             = failureFreePat pat
-
-failureFreePat (ListPat _ _)             = False
-failureFreePat (PArrPat _ _)             = False
-failureFreePat (TuplePat pats _)         = all failureFreePat pats
-
-failureFreePat (ConPatOut con ps _ _ _)   = only_con con && failure_free_con ps
-
-failureFreePat (SigPatOut p _ _)         = failureFreePat p
-
-failureFreePat (DictPat _ _)             = True
-
-failureFreePat other_pat                 = False   -- Literals, NPat
-
-failure_free_con (PrefixCon pats) = all failureFreePat pats
-failure_free_con (InfixCon p1 p2) = failureFreePat p1 && failureFreePat p2
-failure_free_con (RecCon fs)      = all (failureFreePat . snd) fs
-
-only_con con = maybeToBool (maybeTyConSingleCon (dataConTyCon con))
-\end{code}
-
-\begin{code}
 isWildPat (WildPat _) = True
 isWildPat other              = False
 
 patsAreAllCons :: [Pat id] -> Bool
 patsAreAllCons pat_list = all isConPat pat_list
 
-isConPat (AsPat _ pat)         = isConPat pat
-isConPat (ConPatIn _ _)                = True
-isConPat (ConPatOut _ _ _ _ _) = True
-isConPat (ListPat _ _)         = True
-isConPat (PArrPat _ _)         = True
-isConPat (TuplePat _ _)                = True
-isConPat (DictPat ds ms)       = (length ds + length ms) > 1
-isConPat other                 = False
+isConPat (AsPat _ pat)          = isConPat (unLoc pat)
+isConPat (ConPatIn _ _)                 = True
+isConPat (ConPatOut _ _ _ _ _ _) = True
+isConPat (ListPat _ _)          = True
+isConPat (PArrPat _ _)          = True
+isConPat (TuplePat _ _ _)       = True
+isConPat (DictPat ds ms)        = (length ds + length ms) > 1
+isConPat other                  = False
 
-isSigPat (SigPatIn _ _)    = True
-isSigPat (SigPatOut _ _ _) = True
-isSigPat other            = False
+isSigPat (SigPatIn _ _)  = True
+isSigPat (SigPatOut _ _) = True
+isSigPat other          = False
 
 patsAreAllLits :: [Pat id] -> Bool
 patsAreAllLits pat_list = all isLitPat pat_list
 
-isLitPat (AsPat _ pat)         = isLitPat pat
+isLitPat (AsPat _ pat)         = isLitPat (unLoc pat)
 isLitPat (LitPat _)            = True
-isLitPat (NPatIn _ _)          = True
-isLitPat (NPatOut   _ _ _)      = True
-isLitPat (NPlusKPatIn _ _ _)    = True
-isLitPat (NPlusKPatOut _ _ _ _) = True
+isLitPat (NPat _ _ _ _)                = True
+isLitPat (NPlusKPat _ _ _ _)    = True
 isLitPat other                 = False
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-%*             Gathering stuff out of patterns
-%*                                                                     *
-%************************************************************************
-
-This function @collectPatBinders@ works with the ``collectBinders''
-functions for @HsBinds@, etc.  The order in which the binders are
-collected is important; see @HsBinds.lhs@.
-
-It collects the bounds *value* variables in renamed patterns; type variables
-are *not* collected.
 
-\begin{code}
-collectPatBinders :: Pat a -> [a]
-collectPatBinders pat = collect pat []
-
-collectPatsBinders :: [Pat a] -> [a]
-collectPatsBinders pats = foldr collect [] pats
-
-collect (WildPat _)             bndrs = bndrs
-collect (VarPat var)            bndrs = var : bndrs
-collect (LazyPat pat)           bndrs = collect pat bndrs
-collect (AsPat a pat)           bndrs = a : collect pat bndrs
-collect (ParPat  pat)           bndrs = collect pat bndrs
-
-collect (ListPat pats _)        bndrs = foldr collect bndrs pats
-collect (PArrPat pats _)        bndrs = foldr collect bndrs pats
-collect (TuplePat pats _)       bndrs = foldr collect bndrs pats
-
-collect (ConPatIn c ps)         bndrs = foldr collect bndrs (hsConArgs ps)
-collect (ConPatOut c ps _ _ ds)         bndrs = ds ++ foldr collect bndrs (hsConArgs ps)
-
-collect (LitPat _)              bndrs = bndrs
-collect (NPatIn _ _)            bndrs = bndrs
-collect (NPatOut _ _ _)                 bndrs = bndrs
-
-collect (NPlusKPatIn n _ _)      bndrs = n : bndrs
-collect (NPlusKPatOut n _ _ _)   bndrs = n : bndrs
-
-collect (SigPatIn pat _)        bndrs = collect pat bndrs
-collect (SigPatOut pat _ _)     bndrs = collect pat bndrs
-collect (TypePat ty)             bndrs = bndrs
-collect (DictPat ids1 ids2)      bndrs = ids1 ++ ids2 ++ bndrs
-\end{code}
-
-\begin{code}
-collectSigTysFromPats :: [InPat name] -> [HsType name]
-collectSigTysFromPats pats = foldr collect_pat [] pats
-
-collectSigTysFromPat :: InPat name -> [HsType name]
-collectSigTysFromPat pat = collect_pat pat []
-
-collect_pat (SigPatIn pat ty)  acc = collect_pat pat (ty:acc)
-collect_pat (TypePat ty)       acc = ty:acc
-
-collect_pat (LazyPat pat)      acc = collect_pat pat acc
-collect_pat (AsPat a pat)      acc = collect_pat pat acc
-collect_pat (ParPat  pat)      acc = collect_pat pat acc
-collect_pat (ListPat pats _)   acc = foldr collect_pat acc pats
-collect_pat (PArrPat pats _)   acc = foldr collect_pat acc pats
-collect_pat (TuplePat pats _)  acc = foldr collect_pat acc pats
-collect_pat (ConPatIn c ps)    acc = foldr collect_pat acc (hsConArgs ps)
-collect_pat other             acc = acc        -- Literals, vars, wildcard
+isBangHsBind :: HsBind id -> Bool
+-- In this module because HsPat is above HsBinds in the import graph
+isBangHsBind (PatBind { pat_lhs = L _ (BangPat p) }) = True
+isBangHsBind bind                                   = False
+
+isIrrefutableHsPat :: LPat id -> Bool
+-- This function returns False if it's in doubt; specifically
+-- on a ConPatIn it doesn't know the size of the constructor family
+-- But if it returns True, the pattern is definitely irrefutable
+isIrrefutableHsPat pat
+  = go pat
+  where
+    go (L _ pat)        = go1 pat
+
+    go1 (WildPat _)         = True
+    go1 (VarPat _)          = True
+    go1 (VarPatOut _ _)     = True
+    go1 (LazyPat pat)       = True
+    go1 (BangPat pat)       = go pat
+    go1 (ParPat pat)        = go pat
+    go1 (AsPat _ pat)       = go pat
+    go1 (SigPatIn pat _)    = go pat
+    go1 (SigPatOut pat _)   = go pat
+    go1 (TuplePat pats _ _) = all go pats
+    go1 (ListPat pats _)    = False
+    go1 (PArrPat pats _)    = False    -- ?
+
+    go1 (ConPatIn _ _) = False -- Conservative
+    go1 (ConPatOut (L _ con) _ _ _ details _) 
+       =  isProductTyCon (dataConTyCon con)
+       && all go (hsConArgs details)
+
+    go1 (LitPat _)        = False
+    go1 (NPat _ _ _ _)    = False
+    go1 (NPlusKPat _ _ _ _) = False
+
+    go1 (TypePat _)   = panic "isIrrefutableHsPat: type pattern"
+    go1 (DictPat _ _) = panic "isIrrefutableHsPat: type pattern"
 \end{code}