Record the type in TuplePat (necessary for GADTs)
[ghc-hetmet.git] / ghc / compiler / hsSyn / HsPat.lhs
index 5cb26fa..eca7dd1 100644 (file)
 %
-% (c) The GRASP/AQUA Project, Glasgow University, 1992-1996
+% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
 %
 \section[PatSyntax]{Abstract Haskell syntax---patterns}
 
 \begin{code}
-#include "HsVersions.h"
-
 module HsPat (
-       InPat(..),
-       OutPat(..),
-
-       irrefutablePat, irrefutablePats,
-       failureFreePat,
-       patsAreAllCons, isConPat,
-       patsAreAllLits, isLitPat,
-       collectPatBinders
+       Pat(..), InPat, OutPat, LPat,
+       
+       HsConDetails(..), hsConArgs,
+
+       mkPrefixConPat, mkCharLitPat, mkNilPat, 
+
+       isWildPat, 
+       patsAreAllCons, isConPat, isSigPat,
+       patsAreAllLits, isLitPat, isIrrefutableHsPat
     ) where
 
-IMP_Ubiq()
+#include "HsVersions.h"
 
--- friends:
-import HsLit           ( HsLit )
-IMPORT_DELOOPER(HsLoop)                ( HsExpr )
 
+import {-# SOURCE #-} HsExpr           ( SyntaxExpr )
+
+-- friends:
+import HsBinds         ( DictBinds, emptyLHsBinds, pprLHsBinds )
+import HsLit           ( HsLit(HsCharPrim), HsOverLit )
+import HsTypes         ( LHsType, PostTcType )
+import BasicTypes      ( Boxity, tupleParens )
 -- others:
-import Id              ( dataConTyCon, GenId )
-import Maybes          ( maybeToBool )
-import Name            ( pprSym, pprNonSym )
-import Outputable      ( interppSP, interpp'SP, ifPprShowAll )
-import PprStyle                ( PprStyle(..) )
-import Pretty
-import TyCon           ( maybeTyConSingleCon )
-import PprType         ( GenType )
+import PprCore         ( {- instance OutputableBndr TyVar -} )
+import TysWiredIn      ( nilDataCon, charDataCon, charTy )
+import Var             ( TyVar )
+import DataCon         ( DataCon, dataConTyCon )
+import TyCon           ( isProductTyCon )
+import Outputable      
+import Type            ( Type )
+import SrcLoc          ( Located(..), unLoc, noLoc )
 \end{code}
 
-Patterns come in distinct before- and after-typechecking flavo(u)rs.
-\begin{code}
-data InPat name
-  = WildPatIn                          -- wild card
-  | VarPatIn       name                -- variable
-  | LitPatIn       HsLit               -- literal
-  | LazyPatIn      (InPat name)        -- lazy pattern
-  | AsPatIn        name                -- as pattern
-                   (InPat name)
-  | ConPatIn       name                -- constructed type
-                   [InPat name]
-  | ConOpPatIn     (InPat name)
-                   name
-                   (InPat name)
-
-  -- We preserve prefix negation and parenthesis for the precedence parser.
-
-  | NegPatIn       (InPat name)        -- negated pattern
-  | ParPatIn        (InPat name)       -- parenthesised pattern
-
-  | ListPatIn      [InPat name]        -- syntactic list
-                                       -- must have >= 1 elements
-  | TuplePatIn     [InPat name]        -- tuple
-
-  | RecPatIn       name                -- record
-                   [(name, InPat name, Bool)]  -- True <=> source used punning
-
-data OutPat tyvar uvar id
-  = WildPat        (GenType tyvar uvar)        -- wild card
-
-  | VarPat         id                          -- variable (type is in the Id)
-
-  | LazyPat        (OutPat tyvar uvar id)      -- lazy pattern
-
-  | AsPat          id                          -- as pattern
-                   (OutPat tyvar uvar id)
-
-  | ConPat         Id                          -- Constructor is always an Id
-                   (GenType tyvar uvar)        -- the type of the pattern
-                   [OutPat tyvar uvar id]
-
-  | ConOpPat       (OutPat tyvar uvar id)      -- just a special case...
-                   Id
-                   (OutPat tyvar uvar id)
-                   (GenType tyvar uvar)
-  | ListPat                                    -- syntactic list
-                   (GenType tyvar uvar)        -- the type of the elements
-                   [OutPat tyvar uvar id]
-
-  | TuplePat       [OutPat tyvar uvar id]      -- tuple
-                                               -- UnitPat is TuplePat []
-
-  | RecPat         Id                          -- record constructor
-                   (GenType tyvar uvar)        -- the type of the pattern
-                   [(Id, OutPat tyvar uvar id, Bool)]  -- True <=> source used punning
-
-  | LitPat         -- Used for *non-overloaded* literal patterns:
-                   -- Int#, Char#, Int, Char, String, etc.
-                   HsLit
-                   (GenType tyvar uvar)        -- type of pattern
-
-  | NPat           -- Used for *overloaded* literal patterns
-                   HsLit                       -- the literal is retained so that
-                                               -- the desugarer can readily identify
-                                               -- equations with identical literal-patterns
-                   (GenType tyvar uvar)        -- type of pattern, t
-                   (HsExpr tyvar uvar id (OutPat tyvar uvar id))
-                                               -- of type t -> Bool; detects match
 
+\begin{code}
+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
+  | 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
+
+       ------------ Lists, tuples, arrays ---------------
+  | ListPat    [LPat id]               -- Syntactic list
+               PostTcType              -- The type of the elements
+                   
+  | TuplePat   [LPat id]               -- Tuple
+               Boxity                  -- UnitPat is TuplePat []
+               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   (Located id)
+               (HsConDetails id (LPat id))
+
+  | 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.
+
+  | 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        (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       (LPat id)           -- Pattern with a type signature
+                   (LHsType id)
+
+  | SigPatOut      (LPat id)           -- Pattern with a type signature
+                   Type
+
+       ------------ Dictionary patterns (translation only) ---------------
   | DictPat        -- Used when destructing Dictionaries with an explicit case
                    [id]                        -- superclass dicts
                    [id]                        -- methods
 \end{code}
 
+HsConDetails is use both for patterns and for data type declarations
+
 \begin{code}
-instance (Outputable name, NamedThing name) => Outputable (InPat name) where
-    ppr = pprInPat
-
-pprInPat :: (Outputable name, NamedThing name) => PprStyle -> InPat name -> Pretty
-
-pprInPat sty (WildPatIn)       = ppStr "_"
-pprInPat sty (VarPatIn var)    = pprNonSym sty var
-pprInPat sty (LitPatIn s)      = ppr sty s
-pprInPat sty (LazyPatIn pat)   = ppBeside (ppChar '~') (ppr sty pat)
-pprInPat sty (AsPatIn name pat)
-    = ppBesides [ppLparen, ppr sty name, ppChar '@', ppr sty pat, ppRparen]
-
-pprInPat sty (ConPatIn c pats)
- = if null pats then
-      ppr sty c
-   else
-      ppCat [ppr sty c, interppSP sty pats] -- ParPats put in the parens
-
-pprInPat sty (ConOpPatIn pat1 op pat2)
- = ppCat [ppr sty pat1, ppr sty op, ppr sty 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)
-
-pprInPat sty (NegPatIn pat)
-  = let
-       pp_pat = pprInPat sty pat
-    in
-    ppBeside (ppChar '-') (
-    case pat of
-      LitPatIn _ -> pp_pat
-      _          -> ppParens pp_pat
-    )
-
-pprInPat sty (ParPatIn pat)
-  = ppParens (pprInPat sty pat)
-
-pprInPat sty (ListPatIn pats)
-  = ppBesides [ppLbrack, interpp'SP sty pats, ppRbrack]
-pprInPat sty (TuplePatIn pats)
-  = ppParens (interpp'SP sty pats)
-
-pprInPat sty (RecPatIn con rpats)
-  = ppBesides [ppr sty con, ppSP, ppChar '{', ppInterleave ppComma (map (pp_rpat sty) rpats), ppChar '}']
-  where
-    pp_rpat PprForUser (v, _, True) = ppr PprForUser v
-    pp_rpat sty        (v, p, _)    = ppCat [ppr sty v, ppStr "=", ppr sty p]
+data HsConDetails id arg
+  = PrefixCon [arg]                    -- C p1 p2 p3
+  | RecCon    [(Located id, arg)]      -- C { x = p1, y = p2 }
+  | InfixCon  arg arg                  -- p1 `C` p2
+
+hsConArgs :: HsConDetails id arg -> [arg]
+hsConArgs (PrefixCon ps)   = ps
+hsConArgs (RecCon fs)      = map snd fs
+hsConArgs (InfixCon p1 p2) = [p1,p2]
 \end{code}
 
+
+%************************************************************************
+%*                                                                     *
+%*             Printing patterns
+%*                                                                     *
+%************************************************************************
+
 \begin{code}
-instance (Eq tyvar, Outputable tyvar, Eq uvar, Outputable uvar,
-         NamedThing id, Outputable id)
-       => Outputable (OutPat tyvar uvar id) where
-    ppr = pprOutPat
+instance (OutputableBndr name) => Outputable (Pat name) where
+    ppr = pprPat
+
+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
+                                               -- but is it worth it?
+    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 (AsPat name pat)     = parens (hcat [ppr name, char '@', ppr pat])
+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 (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
+--
+pabrackets   :: SDoc -> SDoc
+pabrackets p  = ptext SLIT("[:") <> p <> ptext SLIT(":]")
 \end{code}
 
-\begin{code}
-pprOutPat sty (WildPat ty)     = ppChar '_'
-pprOutPat sty (VarPat var)     = pprNonSym sty var
-pprOutPat sty (LazyPat pat)    = ppBesides [ppChar '~', ppr sty pat]
-pprOutPat sty (AsPat name pat)
-  = ppBesides [ppLparen, ppr sty name, ppChar '@', ppr sty pat, ppRparen]
-
-pprOutPat sty (ConPat name ty [])
-  = ppBeside (ppr sty name)
-       (ifPprShowAll sty (pprConPatTy sty ty))
-
-pprOutPat sty (ConPat name ty pats)
-  = ppBesides [ppLparen, ppr sty name, ppSP,
-        interppSP sty pats, ppRparen,
-        ifPprShowAll sty (pprConPatTy sty ty) ]
-
-pprOutPat sty (ConOpPat pat1 op pat2 ty)
-  = ppBesides [ppLparen, ppr sty pat1, ppSP, pprSym sty op, ppSP, ppr sty pat2, ppRparen]
-
-pprOutPat sty (ListPat ty pats)
-  = ppBesides [ppLbrack, interpp'SP sty pats, ppRbrack]
-pprOutPat sty (TuplePat pats)
-  = ppParens (interpp'SP sty pats)
-
-pprOutPat sty (RecPat con ty rpats)
-  = ppBesides [ppr sty con, ppChar '{', ppInterleave ppComma (map (pp_rpat sty) rpats), ppChar '}']
-  where
-    pp_rpat PprForUser (v, _, True) = ppr PprForUser v
-    pp_rpat sty (v, p, _)           = ppCat [ppr sty v, ppStr "=", ppr sty p]
 
-pprOutPat sty (LitPat l ty)    = ppr sty l     -- ToDo: print more
-pprOutPat sty (NPat   l ty e)  = ppr sty l     -- ToDo: print more
+%************************************************************************
+%*                                                                     *
+%*             Building patterns
+%*                                                                     *
+%************************************************************************
+
+\begin{code}
+mkPrefixConPat :: DataCon -> [OutPat id] -> Type -> OutPat id
+-- Make a vanilla Prefix constructor pattern
+mkPrefixConPat dc pats ty = noLoc $ ConPatOut (noLoc dc) [] [] emptyLHsBinds (PrefixCon pats) ty
 
-pprOutPat sty (DictPat dicts methods)
- = ppSep [ppBesides [ppLparen, ppPStr SLIT("{-dict-}")],
-         ppBracket (interpp'SP sty dicts),
-         ppBesides [ppBracket (interpp'SP sty methods), ppRparen]]
+mkNilPat :: Type -> OutPat id
+mkNilPat ty = mkPrefixConPat nilDataCon [] ty
 
-pprConPatTy sty ty
- = ppParens (ppr sty ty)
+mkCharLitPat :: Char -> OutPat id
+mkCharLitPat c = mkPrefixConPat charDataCon [noLoc $ LitPat (HsCharPrim c)] charTy
 \end{code}
 
+
 %************************************************************************
 %*                                                                     *
-%* predicates for checking things about pattern-lists in EquationInfo  *
+%* Predicates for checking things about pattern-lists in EquationInfo  *
 %*                                                                     *
 %************************************************************************
+
 \subsection[Pat-list-predicates]{Look for interesting things in patterns}
 
 Unlike in the Wadler chapter, where patterns are either ``variables''
@@ -236,71 +254,65 @@ patterns are treated specially, of course.
 
 The 1.3 report defines what ``irrefutable'' and ``failure-free'' patterns are.
 \begin{code}
-irrefutablePats :: [OutPat a b c] -> Bool
-irrefutablePats pat_list = all irrefutablePat pat_list
-
-irrefutablePat (AsPat  _ pat)  = irrefutablePat pat
-irrefutablePat (WildPat        _)      = True
-irrefutablePat (VarPat _)      = True
-irrefutablePat (LazyPat        _)      = True
-irrefutablePat (DictPat ds ms) = (length ds + length ms) <= 1
-irrefutablePat other           = False
-
-failureFreePat :: OutPat a b c -> Bool
-
-failureFreePat (WildPat _)               = True
-failureFreePat (VarPat _)                = True
-failureFreePat (LazyPat        _)                = True
-failureFreePat (AsPat _ pat)             = failureFreePat pat
-failureFreePat (ConPat con tys pats)     = only_con con && all failureFreePat pats
-failureFreePat (ConOpPat pat1 con pat2 _) = only_con con && failureFreePat pat1 && failureFreePat pat1
-failureFreePat (RecPat con _ fields)     = only_con con && and [ failureFreePat pat | (_,pat,_) <- fields ]
-failureFreePat (ListPat _ _)             = False
-failureFreePat (TuplePat pats)           = all failureFreePat pats
-failureFreePat (DictPat _ _)             = True
-failureFreePat other_pat                 = False   -- Literals, NPat
-
-only_con con = maybeToBool (maybeTyConSingleCon (dataConTyCon con))
-\end{code}
+isWildPat (WildPat _) = True
+isWildPat other              = False
 
-\begin{code}
-patsAreAllCons :: [OutPat a b c] -> Bool
+patsAreAllCons :: [Pat id] -> Bool
 patsAreAllCons pat_list = all isConPat pat_list
 
-isConPat (AsPat _ pat)         = isConPat pat
-isConPat (ConPat _ _ _)                = True
-isConPat (ConOpPat _ _ _ _)    = True
-isConPat (ListPat _ _)         = True
-isConPat (TuplePat _)          = True
-isConPat (RecPat _ _ _)                = 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
 
-patsAreAllLits :: [OutPat a b c] -> Bool
+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 (LitPat _ _)  = True
-isLitPat (NPat   _ _ _)        = True
-isLitPat other         = False
+isLitPat (AsPat _ pat)         = isLitPat (unLoc pat)
+isLitPat (LitPat _)            = True
+isLitPat (NPat _ _ _ _)                = True
+isLitPat (NPlusKPat _ _ _ _)    = True
+isLitPat other                 = 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 (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}
 
-This function @collectPatBinders@ works with the ``collectBinders''
-functions for @HsBinds@, etc.  The order in which the binders are
-collected is important; see @HsBinds.lhs@.
-\begin{code}
-collectPatBinders :: InPat a -> [a]
-
-collectPatBinders WildPatIn          = []
-collectPatBinders (VarPatIn var)      = [var]
-collectPatBinders (LitPatIn _)       = []
-collectPatBinders (LazyPatIn pat)     = collectPatBinders pat
-collectPatBinders (AsPatIn a pat)     = a : collectPatBinders pat
-collectPatBinders (ConPatIn c pats)   = concat (map collectPatBinders pats)
-collectPatBinders (ConOpPatIn p1 c p2)= collectPatBinders p1 ++ collectPatBinders p2
-collectPatBinders (NegPatIn  pat)     = collectPatBinders pat
-collectPatBinders (ParPatIn  pat)     = collectPatBinders pat
-collectPatBinders (ListPatIn pats)    = concat (map collectPatBinders pats)
-collectPatBinders (TuplePatIn pats)   = concat (map collectPatBinders pats)
-collectPatBinders (RecPatIn c fields) = concat (map (\ (f,pat,_) -> collectPatBinders pat) fields)
-\end{code}