[project @ 2005-03-09 16:58:15 by simonpj]
[ghc-hetmet.git] / ghc / compiler / coreSyn / CoreSyn.lhs
index a352829..0a2bd0d 100644 (file)
@@ -7,7 +7,7 @@
 module CoreSyn (
        Expr(..), Alt, Bind(..), AltCon(..), Arg, Note(..),
        CoreExpr, CoreAlt, CoreBind, CoreArg, CoreBndr,
-       TaggedExpr, TaggedAlt, TaggedBind, TaggedArg,
+       TaggedExpr, TaggedAlt, TaggedBind, TaggedArg, TaggedBndr(..),
 
        mkLets, mkLams, 
        mkApps, mkTyApps, mkValApps, mkVarApps,
@@ -15,7 +15,7 @@ module CoreSyn (
        mkConApp, 
        varToCoreExpr,
 
-       isTyVar, isId, 
+       isTyVar, isId, cmpAltCon, cmpAlt, ltAlt,
        bindersOf, bindersOfBinds, rhssOfBind, rhssOfAlts, 
        collectBinders, collectTyBinders, collectValBinders, collectTyAndValBinders,
        collectArgs, 
@@ -26,7 +26,7 @@ module CoreSyn (
 
        -- Unfoldings
        Unfolding(..),  UnfoldingGuidance(..),  -- Both abstract everywhere but in CoreUnfold.lhs
-       noUnfolding, mkOtherCon,
+       noUnfolding, evaldUnfolding, mkOtherCon,
        unfoldingTemplate, maybeUnfoldingTemplate, otherCons, 
        isValueUnfolding, isEvaldUnfolding, isCheapUnfolding, isCompulsoryUnfolding,
        hasUnfolding, hasSomeUnfolding, neverUnfold,
@@ -36,12 +36,12 @@ module CoreSyn (
 
        -- Annotated expressions
        AnnExpr, AnnExpr'(..), AnnBind(..), AnnAlt, 
-       deAnnotate, deAnnotate', deAnnAlt,
+       deAnnotate, deAnnotate', deAnnAlt, collectAnnBndrs,
 
        -- Core rules
        CoreRules(..),  -- Representation needed by friends
        CoreRule(..),   -- CoreSubst, CoreTidy, CoreFVs, PprCore only
-       IdCoreRule,
+       IdCoreRule(..), isOrphanRule,
        RuleName,
        emptyCoreRules, isEmptyCoreRules, rulesRhsFreeVars, rulesRules,
        isBuiltinRule, ruleName
@@ -54,9 +54,10 @@ import CostCentre    ( CostCentre, noCostCentre )
 import Var             ( Var, Id, TyVar, isTyVar, isId )
 import Type            ( Type, mkTyVarTy, seqType )
 import Literal         ( Literal, mkMachInt )
-import DataCon         ( DataCon, dataConId )
+import DataCon         ( DataCon, dataConWorkId, dataConTag )
 import BasicTypes      ( Activation )
 import VarSet
+import FastString
 import Outputable
 \end{code}
 
@@ -77,12 +78,33 @@ data Expr b -- "b" for the type of binders,
   | App   (Expr b) (Arg b)
   | Lam   b (Expr b)
   | Let   (Bind b) (Expr b)
-  | Case  (Expr b) b [Alt b]   -- Binder gets bound to value of scrutinee
-                               -- DEFAULT case must be *first*, if it occurs at all
+  | Case  (Expr b) b Type [Alt b]      -- Binder gets bound to value of scrutinee
+       -- Invariant: The list of alternatives is ALWAYS EXHAUSTIVE,
+       --            meaning that it covers all cases that can occur
+       --            See the example below
+       --
+       -- Invariant: The DEFAULT case must be *first*, if it occurs at all
+       -- Invariant: The remaining cases are in order of increasing 
+       --              tag     (for DataAlts)
+       --              lit     (for LitAlts)
+       --            This makes finding the relevant constructor easy,
+       --            and makes comparison easier too
   | Note  Note (Expr b)
   | Type  Type                 -- This should only show up at the top
                                -- level of an Arg
 
+-- An "exhausive" case does not necessarily mention all constructors:
+--     data Foo = Red | Green | Blue
+--
+--     ...case x of 
+--             Red   -> True
+--             other -> f (case x of 
+--                             Green -> ...
+--                             Blue  -> ... )
+-- The inner case does not need a Red alternative, because x can't be Red at
+-- that program point.
+
+
 type Arg b = Expr b            -- Can be a Type
 
 type Alt b = (AltCon, [b], Expr b)     -- (DEFAULT, [], rhs) is the default alternative
@@ -92,6 +114,7 @@ data AltCon = DataAlt DataCon
            | DEFAULT
         deriving (Eq, Ord)
 
+
 data Bind b = NonRec b (Expr b)
              | Rec [(b, (Expr b))]
 
@@ -108,6 +131,8 @@ data Note
   | InlineMe           -- Instructs simplifer to treat the enclosed expression
                        -- as very small, and inline it at its call sites
 
+  | CoreNote String     -- A generic core annotation, propagated but not used by GHC
+
 -- NOTE: we also treat expressions wrapped in InlineMe as
 -- 'cheap' and 'dupable' (in the sense of exprIsCheap, exprIsDupable)
 -- What this means is that we obediently inline even things that don't
@@ -165,8 +190,13 @@ rulesRules (Rules rules _) = rules
 \end{code}
 
 \begin{code}
-type RuleName = FAST_STRING
-type IdCoreRule = (Id,CoreRule)                -- Rules don't have their leading Id inside them
+type RuleName = FastString
+data IdCoreRule = IdCoreRule Id        -- A rule for this Id
+                            Bool       -- True <=> orphan rule
+                            CoreRule   -- The rule itself
+
+isOrphanRule :: IdCoreRule -> Bool
+isOrphanRule (IdCoreRule _ is_orphan _) = is_orphan
 
 data CoreRule
   = Rule RuleName
@@ -238,8 +268,10 @@ data UnfoldingGuidance
                                -- a context (case (thing args) of ...),
                                -- (where there are the right number of arguments.)
 
-noUnfolding = NoUnfolding
-mkOtherCon  = OtherCon
+noUnfolding    = NoUnfolding
+evaldUnfolding = OtherCon []
+
+mkOtherCon = OtherCon
 
 seqUnfolding :: Unfolding -> ()
 seqUnfolding (CoreUnfolding e top b1 b2 g)
@@ -320,6 +352,26 @@ instance Outputable AltCon where
 
 instance Show AltCon where
   showsPrec p con = showsPrecSDoc p (ppr con)
+
+cmpAlt :: Alt b -> Alt b -> Ordering
+cmpAlt (con1, _, _) (con2, _, _) = con1 `cmpAltCon` con2
+
+ltAlt :: Alt b -> Alt b -> Bool
+ltAlt a1 a2 = case a1 `cmpAlt` a2 of { LT -> True; other -> False }
+
+cmpAltCon :: AltCon -> AltCon -> Ordering
+-- Compares AltCons within a single list of alternatives
+cmpAltCon DEFAULT      DEFAULT    = EQ
+cmpAltCon DEFAULT      con        = LT
+
+cmpAltCon (DataAlt d1) (DataAlt d2) = dataConTag d1 `compare` dataConTag d2
+cmpAltCon (DataAlt _)  DEFAULT      = GT
+cmpAltCon (LitAlt  l1) (LitAlt  l2) = l1 `compare` l2
+cmpAltCon (LitAlt _)   DEFAULT      = GT
+
+cmpAltCon con1 con2 = WARN( True, text "Comparing incomparable AltCons" <+> 
+                                 ppr con1 <+> ppr con2 )
+                     LT
 \end{code}
 
 
@@ -342,12 +394,18 @@ type CoreAlt  = Alt  CoreBndr
 Binders are ``tagged'' with a \tr{t}:
 
 \begin{code}
-type Tagged t = (CoreBndr, t)
+data TaggedBndr t = TB CoreBndr t      -- TB for "tagged binder"
+
+type TaggedBind t = Bind (TaggedBndr t)
+type TaggedExpr t = Expr (TaggedBndr t)
+type TaggedArg  t = Arg  (TaggedBndr t)
+type TaggedAlt  t = Alt  (TaggedBndr t)
 
-type TaggedBind t = Bind (Tagged t)
-type TaggedExpr t = Expr (Tagged t)
-type TaggedArg  t = Arg  (Tagged t)
-type TaggedAlt  t = Alt  (Tagged t)
+instance Outputable b => Outputable (TaggedBndr b) where
+  ppr (TB b l) = char '<' <> ppr b <> comma <> ppr l <> char '>'
+
+instance Outputable b => OutputableBndr (TaggedBndr b) where
+  pprBndr _ b = ppr b  -- Simple
 \end{code}
 
 
@@ -376,7 +434,7 @@ mkLets            :: [Bind b] -> Expr b -> Expr b
 mkLams       :: [b] -> Expr b -> Expr b
 
 mkLit lit        = Lit lit
-mkConApp con args = mkApps (Var (dataConId con)) args
+mkConApp con args = mkApps (Var (dataConWorkId con)) args
 
 mkLams binders body = foldr Lam body binders
 mkLets binds body   = foldr Let body binds
@@ -529,19 +587,21 @@ valArgCount (other  : args) = 1 + valArgCount args
 
 \begin{code}
 seqExpr :: CoreExpr -> ()
-seqExpr (Var v)       = v `seq` ()
-seqExpr (Lit lit)     = lit `seq` ()
-seqExpr (App f a)     = seqExpr f `seq` seqExpr a
-seqExpr (Lam b e)     = seqBndr b `seq` seqExpr e
-seqExpr (Let b e)     = seqBind b `seq` seqExpr e
-seqExpr (Case e b as) = seqExpr e `seq` seqBndr b `seq` seqAlts as
-seqExpr (Note n e)    = seqNote n `seq` seqExpr e
-seqExpr (Type t)      = seqType t
+seqExpr (Var v)         = v `seq` ()
+seqExpr (Lit lit)       = lit `seq` ()
+seqExpr (App f a)       = seqExpr f `seq` seqExpr a
+seqExpr (Lam b e)       = seqBndr b `seq` seqExpr e
+seqExpr (Let b e)       = seqBind b `seq` seqExpr e
+-- gaw 2004
+seqExpr (Case e b t as) = seqExpr e `seq` seqBndr b `seq` seqType t `seq` seqAlts as
+seqExpr (Note n e)      = seqNote n `seq` seqExpr e
+seqExpr (Type t)        = seqType t
 
 seqExprs [] = ()
 seqExprs (e:es) = seqExpr e `seq` seqExprs es
 
 seqNote (Coerce t1 t2) = seqType t1 `seq` seqType t2
+seqNote (CoreNote s)   = s `seq` ()
 seqNote other         = ()
 
 seqBndr b = b `seq` ()
@@ -582,7 +642,8 @@ data AnnExpr' bndr annot
   | AnnLit     Literal
   | AnnLam     bndr (AnnExpr bndr annot)
   | AnnApp     (AnnExpr bndr annot) (AnnExpr bndr annot)
-  | AnnCase    (AnnExpr bndr annot) bndr [AnnAlt bndr annot]
+-- gaw 2004
+  | AnnCase    (AnnExpr bndr annot) bndr Type [AnnAlt bndr annot]
   | AnnLet     (AnnBind bndr annot) (AnnExpr bndr annot)
   | AnnNote    Note (AnnExpr bndr annot)
   | AnnType    Type
@@ -611,10 +672,19 @@ deAnnotate' (AnnLet bind body)
     deAnnBind (AnnNonRec var rhs) = NonRec var (deAnnotate rhs)
     deAnnBind (AnnRec pairs) = Rec [(v,deAnnotate rhs) | (v,rhs) <- pairs]
 
-deAnnotate' (AnnCase scrut v alts)
-  = Case (deAnnotate scrut) v (map deAnnAlt alts)
+-- gaw 2004
+deAnnotate' (AnnCase scrut v t alts)
+  = Case (deAnnotate scrut) v t (map deAnnAlt alts)
 
 deAnnAlt :: AnnAlt bndr annot -> Alt bndr
 deAnnAlt (con,args,rhs) = (con,args,deAnnotate rhs)
 \end{code}
 
+\begin{code}
+collectAnnBndrs :: AnnExpr bndr annot -> ([bndr], AnnExpr bndr annot)
+collectAnnBndrs e
+  = collect [] e
+  where
+    collect bs (_, AnnLam b body) = collect (b:bs) body
+    collect bs body              = (reverse bs, body)
+\end{code}