[project @ 1999-07-14 14:40:20 by simonpj]
[ghc-hetmet.git] / ghc / compiler / coreSyn / CoreSyn.lhs
index 1cdba66..c1eb1f0 100644 (file)
 %
-% (c) The GRASP/AQUA Project, Glasgow University, 1992-1995
+% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
 %
 \section[CoreSyn]{A data type for the Haskell compiler midsection}
 
 \begin{code}
-#include "HsVersions.h"
-
 module CoreSyn (
-       CoreBinding(..), CoreExpr(..), CoreAtom(..),
-       CoreCaseAlternatives(..), CoreCaseDefault(..),
-#ifdef DPH
-       CoreParQuals(..),
-       CoreParCommunicate(..),
-#endif {- Data Parallel Haskell -}
-       mkCoTyApp,
-       pprCoreBinding, pprCoreExpr,
-
-       CoreArg(..), applyToArgs, decomposeArgs, collectArgs,
-
-       -- and to make the interface self-sufficient ...
-       Id, UniType, TyVar, TyCon, PrimOp, BasicLit,
-       PprStyle, PrettyRep, CostCentre, Maybe
+       Expr(..), Alt, Bind(..), Arg(..), Note(..),
+       CoreExpr, CoreAlt, CoreBind, CoreArg, CoreBndr,
+       TaggedExpr, TaggedAlt, TaggedBind, TaggedArg,
+
+       mkLets, mkLams,
+       mkApps, mkTyApps, mkValApps, mkVarApps,
+       mkLit, mkStringLit, mkConApp, mkPrimApp, mkNote,
+       bindNonRec, mkIfThenElse, varToCoreExpr,
+
+       bindersOf, bindersOfBinds, rhssOfBind, rhssOfAlts, isDeadBinder, isTyVar, isId,
+       collectBinders, collectTyBinders, collectValBinders, collectTyAndValBinders,
+       collectArgs, collectBindersIgnoringNotes,
+       coreExprCc,
+       flattenBinds, 
+
+       isValArg, isTypeArg, valArgCount, valBndrCount,
+
+       -- Seq stuff
+       seqRules, seqExpr, seqExprs, 
+
+       -- Size
+       coreBindsSize,
+
+       -- Annotated expressions
+       AnnExpr, AnnExpr'(..), AnnBind(..), AnnAlt, deAnnotate,
+
+       -- Core rules
+       CoreRules(..),  -- Representation needed by friends
+       CoreRule(..),   -- CoreSubst, CoreTidy, CoreFVs, PprCore only
+       emptyCoreRules, isEmptyCoreRules, rulesRhsFreeVars, rulesRules
     ) where
 
-import AbsPrel         ( PrimOp, PrimKind
-                         IF_ATTACK_PRAGMAS(COMMA tagOf_PrimOp)
-                         IF_ATTACK_PRAGMAS(COMMA pprPrimOp)
-                       )
-import AbsUniType      ( isPrimType, pprParendUniType, TyVar, TyCon, UniType
-                         IF_ATTACK_PRAGMAS(COMMA cmpTyCon COMMA cmpTyVar)
-                         IF_ATTACK_PRAGMAS(COMMA cmpUniType)
-                       )
-import BasicLit                ( BasicLit )
-import Id              ( getIdUniType, isBottomingId, Id
-                         IF_ATTACK_PRAGMAS(COMMA bottomIsGuaranteed)
-                       )
+#include "HsVersions.h"
+
+import TysWiredIn      ( boolTy, stringTy, nilDataCon )
+import CostCentre      ( CostCentre, isDupdCC, noCostCentre )
+import Var             ( Var, Id, TyVar, IdOrTyVar, isTyVar, isId, idType )
+import VarEnv
+import Id              ( mkWildId, getInlinePragma, idInfo )
+import Type            ( Type, UsageAnn, mkTyVarTy, isUnLiftedType, seqType )
+import IdInfo          ( InlinePragInfo(..), megaSeqIdInfo )
+import Const           ( Con(..), DataCon, Literal(NoRepStr), PrimOp )
+import TysWiredIn      ( trueDataCon, falseDataCon )
+import VarSet
 import Outputable
-import Pretty
-import CostCentre      ( showCostCentre, CostCentre )
-import Util
 \end{code}
 
 %************************************************************************
 %*                                                                     *
-\subsection[CoreTopBinding_and_CoreBinding]{@CoreTopBinding@ and @CoreBinding@}
+\subsection{The main data types}
 %*                                                                     *
 %************************************************************************
 
-Core programs, bindings, expressions, etc., are parameterised with
-respect to the information kept about binding and bound occurrences of
-variables, called {\em binders} and {\em bindees}, respectively.  [I
-don't really like the pair of names; I prefer {\em binder} and {\em
-bounder}.  Or {\em binder} and {\em var}.]
+These data types are the heart of the compiler
 
-A @CoreBinding@ is either a single non-recursive binding of a
-``binder'' to an expression, or a mutually-recursive blob of same.
 \begin{code}
-data CoreBinding binder bindee
-  = CoNonRec   binder (CoreExpr binder bindee)
-  | CoRec      [(binder, CoreExpr binder bindee)]
+infixl 8 `App` -- App brackets to the left
+
+data Expr b    -- "b" for the type of binders, 
+  = Var          Id
+  | Con   Con [Arg b]          -- Guaranteed saturated
+                               -- The Con can be a DataCon, Literal, PrimOP
+                               -- but cannot be DEFAULT
+  | 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 last, if it occurs at all
+  | Note  Note (Expr b)
+  | Type  Type                 -- This should only show up at the top
+                               -- level of an Arg
+
+type Arg b = Expr b            -- Can be a Type
+
+type Alt b = (Con, [b], Expr b)
+       -- (DEFAULT, [], rhs) is the default alternative
+       -- The Con can be a Literal, DataCon, or DEFAULT, but cannot be PrimOp
+
+data Bind b = NonRec b (Expr b)
+             | Rec [(b, (Expr b))]
+
+data Note
+  = SCC CostCentre
+
+  | Coerce     
+       Type            -- The to-type:   type of whole coerce expression
+       Type            -- The from-type: type of enclosed expression
+
+  | InlineCall         -- Instructs simplifier to inline
+                       -- the enclosed call
+
+  | InlineMe           -- Instructs simplifer to treat the enclosed expression
+                       -- as very small, and inline it at its call sites
+
+  | TermUsg             -- A term-level usage annotation
+        UsageAnn        -- (should not be a variable except during UsageSP inference)
 \end{code}
 
+
 %************************************************************************
 %*                                                                     *
-\subsection[CoreAtom]{Core atoms: @CoreAtom@}
+\subsection{Transformation rules}
 %*                                                                     *
 %************************************************************************
 
-Same deal as @StgAtoms@, except that, for @Core@, the atomic object
-may need to be applied to some types.
+The CoreRule type and its friends are dealt with mainly in CoreRules,
+but CoreFVs, Subst, PprCore, CoreTidy also inspect the representation.
 
 \begin{code}
-data CoreAtom bindee
-  = CoVarAtom  bindee
-  | CoLitAtom   BasicLit
+data CoreRules 
+  = Rules [CoreRule]
+         IdOrTyVarSet          -- Locally-defined free vars of RHSs
+
+data CoreRule
+  = Rule FAST_STRING   -- Rule name
+        [CoreBndr]     -- Forall'd variables
+        [CoreExpr]     -- LHS args
+        CoreExpr       -- RHS
+
+emptyCoreRules :: CoreRules
+emptyCoreRules = Rules [] emptyVarSet
+
+isEmptyCoreRules :: CoreRules -> Bool
+isEmptyCoreRules (Rules rs _) = null rs
+
+rulesRhsFreeVars :: CoreRules -> IdOrTyVarSet
+rulesRhsFreeVars (Rules _ fvs) = fvs
+
+rulesRules :: CoreRules -> [CoreRule]
+rulesRules (Rules rules _) = rules
 \end{code}
 
+
 %************************************************************************
 %*                                                                     *
-\subsection[CoreExpr]{Core expressions: @CoreExpr@}
+\subsection{Useful synonyms}
 %*                                                                     *
 %************************************************************************
 
-@CoreExpr@ is the heart of the ``core'' data types; it is
-(more-or-less) boiled-down second-order polymorphic lambda calculus.
-For types in the core world, we just keep using @UniTypes@.
-\begin{code}
-data CoreExpr binder bindee
-     = CoVar    bindee
-     | CoLit    BasicLit       -- literal constants
-\end{code}
+The common case
 
-@CoCons@ and @CoPrims@ are saturated constructor and primitive-op
-applications (see the comment).  Note: @CoCon@s are only set up by the
-simplifier (and by the desugarer when it knows what it's doing).  The
-desugarer sets up constructors as applications of global @CoVars@s.
 \begin{code}
-     | CoCon       Id [UniType] [CoreAtom bindee]
-                   -- saturated constructor application:
-                   -- the constructor is a function of the form:
-                   --  /\ a1 -> ... /\ am -> \ b1 -> ... \ bn ->
-                   -- <expr> where "/\" is a type lambda and "\" the
-                   -- regular kind; there will be "m" UniTypes and
-                   -- "n" bindees in the CoCon args.
-
-     | CoPrim      PrimOp [UniType] [CoreAtom bindee]
-                   -- saturated primitive operation;
-                   -- comment on CoCons applies here, too.
-                   -- The types work the same way
-                   -- (PrimitiveOps may be polymorphic).
+type CoreBndr = IdOrTyVar
+type CoreExpr = Expr CoreBndr
+type CoreArg  = Arg  CoreBndr
+type CoreBind = Bind CoreBndr
+type CoreAlt  = Alt  CoreBndr
+type CoreNote = Note
 \end{code}
 
-Lambdas have multiple binders; this is good for the lambda lifter.
-Single binders may be simulated easily with multiple binders; vice
-versa is a pain.
-\begin{code}
-     | CoLam       [binder]    -- lambda var_1 ... var_n -> CoreExpr
-                   (CoreExpr binder bindee)
-     | CoTyLam     TyVar       -- Lambda TyVar -> CoreExpr
-                   (CoreExpr binder bindee)
-
-     | CoApp       (CoreExpr binder bindee)
-                   (CoreAtom bindee)
-     | CoTyApp      (CoreExpr binder bindee)
-                   UniType     -- type application
-\end{code}
+Binders are ``tagged'' with a \tr{t}:
 
-Case expressions (\tr{case CoreExpr of <List of alternatives>}): there
-are really two flavours masquerading here---those for scrutinising
-{\em algebraic} types and those for {\em primitive} types.  Please see
-under @CoreCaseAlternatives@.
 \begin{code}
-     | CoCase      (CoreExpr binder bindee)
-                   (CoreCaseAlternatives binder bindee)
+type Tagged t = (CoreBndr, 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)
 \end{code}
 
-A Core case expression \tr{case e of v -> ...} implies evaluation of
-\tr{e}; it is not equivalent to \tr{let v = in ...} (as with a Haskell
-\tr{case}).
 
-Non-recursive @CoLets@ only have one binding; having more than one
-doesn't buy you much, and it is an easy way to mess up variable
-scoping.
-\begin{code}
-     | CoLet       (CoreBinding binder bindee)
-                   (CoreExpr binder bindee)
-                   -- both recursive and non-.
-                   -- The "CoreBinding" records that information
-\end{code}
+%************************************************************************
+%*                                                                     *
+\subsection{Core-constructing functions with checking}
+%*                                                                     *
+%************************************************************************
 
-@build@ as a function is a *PAIN*. See Andy's thesis for
-futher details. This is equivalent to:
-@
-       build unitype (/\ tyvar \ c n -> expr)
-@
 \begin{code}
---ANDY:
---   | CoBuild UniType TyVar binder binder (CoreExpr binder bindee)
-\end{code}
+mkApps    :: Expr b -> [Arg b]  -> Expr b
+mkTyApps  :: Expr b -> [Type]   -> Expr b
+mkValApps :: Expr b -> [Expr b] -> Expr b
+mkVarApps :: CoreExpr -> [IdOrTyVar] -> CoreExpr
 
-@CoZfExpr@ exist in the core language, along with their qualifiers. After
-succesive optimisations to the sequential bindings, we desugar the 
-@CoZfExpr@ into a subset of the core language without them - ``podization''.
-\begin{code}
-#ifdef DPH
-     | CoZfExpr     (CoreExpr binder bindee) 
-                   (CoreParQuals binder bindee)
-#endif {- Data Parallel Haskell -}
-\end{code}
+mkApps    f args = foldl App                      f args
+mkTyApps  f args = foldl (\ e a -> App e (Type a)) f args
+mkValApps f args = foldl (\ e a -> App e a)       f args
+mkVarApps f vars = foldl (\ e a -> App e (varToCoreExpr a)) f vars
 
-@CoParCon@ is the parallel equivalent to the sequential @CoCon@ expression. 
-They are introduced into the core syntax by a pass of the compiler that
-removes the parallel ZF expressions, and {\em vectorises} ordinary sequential
-functions.
-\begin{code}
-#ifdef DPH
-      | CoParCon  Id Int [UniType] [CoreExpr binder bindee] --ToDo:DPH: CoreAtom
-#endif {- Data Parallel Haskell -}
-\end{code}
+mkLit       :: Literal -> Expr b
+mkStringLit :: String  -> Expr b
+mkConApp    :: DataCon -> [Arg b] -> Expr b
+mkPrimApp   :: PrimOp  -> [Arg b] -> Expr b
 
-@CoParCommunicate@ constructs are introduced by the desugaring of parallel
-ZF expressions. 
-\begin{code}
-#ifdef DPH
-     | CoParComm
-                    Int
-                   (CoreExpr binder bindee)
-                   (CoreParCommunicate binder bindee)
-#endif {- Data Parallel Haskell -}
-\end{code}
+mkLit lit        = Con (Literal lit) []
+mkStringLit str          = Con (Literal (NoRepStr (_PK_ str) stringTy)) []
+mkConApp con args = Con (DataCon con) args
+mkPrimApp op args = Con (PrimOp op)   args
 
-@CoParZipWith@ constructs are introduced whenever podization fails during the
-desuagring of ZF expressions. These constructs represent zipping the function
-represented by the first @CoreExpr@ with the list of @CoreExpr@'s (hopefully
-we wont see this that often in the resultant program :-).
+varToCoreExpr :: CoreBndr -> CoreExpr
+varToCoreExpr v | isId v    = Var v
+                | otherwise = Type (mkTyVarTy v)
+\end{code}
 
 \begin{code}
-#ifdef DPH
-     | CoParZipWith
-                  Int
-                  (CoreExpr binder bindee)
-                  [CoreExpr binder bindee]
-#endif {- Data Parallel Haskell -}
+mkLams :: [b] -> Expr b -> Expr b
+mkLams binders body = foldr Lam body binders
 \end{code}
 
-For cost centre scc expressions we introduce a new core construct
-@CoSCC@ so transforming passes have to deal with it explicitly. The
-alternative of using a new PrimativeOp may result in a bad
-transformations of which we are unaware.
 \begin{code}
-     | CoSCC       CostCentre                  -- label of scc
-                   (CoreExpr binder bindee)    -- scc expression
+mkLets :: [Bind b] -> Expr b -> Expr b
+mkLets binds body = foldr Let body binds
+
+bindNonRec :: Id -> CoreExpr -> CoreExpr -> CoreExpr
+-- (bindNonRec x r b) produces either
+--     let x = r in b
+-- or
+--     case r of x { _DEFAULT_ -> b }
+--
+-- depending on whether x is unlifted or not
+-- It's used by the desugarer to avoid building bindings
+-- that give Core Lint a heart attack.  Actually the simplifier
+-- deals with them perfectly well.
+bindNonRec bndr rhs body 
+  | isUnLiftedType (idType bndr) = Case rhs bndr [(DEFAULT,[],body)]
+  | otherwise                   = Let (NonRec bndr rhs) body
 
--- end of CoreExpr
+mkIfThenElse :: CoreExpr -> CoreExpr -> CoreExpr -> CoreExpr
+mkIfThenElse guard then_expr else_expr
+  = Case guard (mkWildId boolTy) 
+        [ (DataCon trueDataCon,  [], then_expr),
+          (DataCon falseDataCon, [], else_expr) ]
 \end{code}
 
-
-%************************************************************************
-%*                                                                     *
-\subsection[CoreParQualifiers]{Parallel qualifiers in @CoreExpr@}
-%*                                                                     *
-%************************************************************************
+mkNote removes redundant coercions, and SCCs where possible
 
 \begin{code}
-#ifdef DPH
-data CoreParQuals binder bindee
-   = CoAndQuals  (CoreParQuals binder bindee)
-                (CoreParQuals binder bindee)
-   | CoParFilter (CoreExpr binder bindee)
-   | CoDrawnGen  [binder]
-                (binder)
-                (CoreExpr binder bindee)       
-   | CoIndexGen  [CoreExpr binder bindee]
-                (binder)
-                (CoreExpr binder bindee)       
-#endif {- Data Parallel Haskell -}
-\end{code}
+mkNote :: Note -> Expr b -> Expr b
+mkNote (Coerce to_ty1 from_ty1) (Note (Coerce to_ty2 from_ty2) expr)
+ = ASSERT( from_ty1 == to_ty2 )
+   mkNote (Coerce to_ty1 from_ty2) expr
 
-%************************************************************************
-%*                                                                     *
-\subsection[ParCommunicate]{Parallel Communication primitives}
-%*                                                                     *
-%************************************************************************
-\begin{code}
-#ifdef DPH
-data CoreParCommunicate binder bindee
-  = CoParSend  [CoreExpr binder bindee]     -- fns of form Integer -> Integer
-  | CoParFetch  [CoreExpr binder bindee]     -- to determine where moved
-  | CoToPodized
-  | CoFromPodized
-#endif {- Data Parallel Haskell -}
-\end{code}
+mkNote (SCC cc1) expr@(Note (SCC cc2) _)
+  | isDupdCC cc1       -- Discard the outer SCC provided we don't need
+  = expr               -- to track its entry count
 
-%************************************************************************
-%*                                                                     *
-\subsection[CoreCaseAlternatives]{Case alternatives in @CoreExpr@}
-%*                                                                     *
-%************************************************************************
+mkNote note@(SCC cc1) expr@(Lam x e)   -- Move _scc_ inside lambda
+  = Lam x (mkNote note e)
 
-We have different kinds of @case@s, the differences being reflected in
-the kinds of alternatives a case has.  We maintain a distinction
-between cases for scrutinising algebraic datatypes, as opposed to
-primitive types.  In both cases, we carry around a @TyCon@, as a
-handle with which we can get info about the case (e.g., total number
-of data constructors for this type).
-
-For example:
-\begin{verbatim}
-let# x=e in b
-\end{verbatim}
-becomes
-\begin{verbatim}
-CoCase e [ CoBindDefaultAlt x -> b ]
-\end{verbatim}
+-- Drop trivial InlineMe's
+mkNote InlineMe expr@(Con _ _) = expr
+mkNote InlineMe expr@(Var v)   = expr
 
-\begin{code}
-data CoreCaseAlternatives binder bindee
-
-  = CoAlgAlts  [(Id,                           -- alts: data constructor,
-                 [binder],                     -- constructor's parameters,
-                 CoreExpr binder bindee)]      -- rhs.
-               (CoreCaseDefault binder bindee)
-
-  | CoPrimAlts [(BasicLit,                     -- alts: unboxed literal,
-                 CoreExpr binder bindee)]      -- rhs.
-               (CoreCaseDefault binder bindee)
-#ifdef DPH
-  | CoParAlgAlts 
-               TyCon
-               Int
-               [binder]
-               [(Id,
-                 CoreExpr binder bindee)]
-               (CoreCaseDefault binder bindee)
-
-  | CoParPrimAlts
-               TyCon
-               Int
-               [(BasicLit,
-                 CoreExpr binder bindee)]
-               (CoreCaseDefault binder bindee)
-#endif {- Data Parallel Haskell -}
-
--- obvious things: if there are no alts in the list, then the default
--- can't be CoNoDefault.
-
-data CoreCaseDefault binder bindee
-  = CoNoDefault                                        -- small con family: all
-                                               -- constructor accounted for
-  | CoBindDefault   binder                     -- form: var -> expr;
-                   (CoreExpr binder bindee)    -- "binder" may or may not
-                                               -- be used in RHS.
+-- Slide InlineCall in around the function
+--     No longer necessary I think (SLPJ Apr 99)
+-- mkNote InlineCall (App f a) = App (mkNote InlineCall f) a
+-- mkNote InlineCall (Var v)   = Note InlineCall (Var v)
+-- mkNote InlineCall expr      = expr
+
+mkNote note expr = Note note expr
 \end{code}
 
 %************************************************************************
 %*                                                                     *
-\subsection[CoreSyn-arguments]{Core ``argument'' wrapper type}
+\subsection{Simple access functions}
 %*                                                                     *
 %************************************************************************
 
 \begin{code}
-data CoreArg bindee
-  = TypeArg UniType
-  | ValArg  (CoreAtom bindee)
+bindersOf  :: Bind b -> [b]
+bindersOf (NonRec binder _) = [binder]
+bindersOf (Rec pairs)       = [binder | (binder, _) <- pairs]
 
-instance Outputable bindee => Outputable (CoreArg bindee) where
-  ppr sty (ValArg atom) = ppr sty atom
-  ppr sty (TypeArg ty)  = ppr sty ty
-\end{code}
+bindersOfBinds :: [Bind b] -> [b]
+bindersOfBinds binds = foldr ((++) . bindersOf) [] binds
 
-\begin{code}
-mkCoTyApp expr ty = CoTyApp expr ty
-
-{- OLD: unboxed tyapps now allowed!
-mkCoTyApp expr ty
-#ifdef DEBUG
-  | isPrimType ty && not (error_app expr)
-  = pprPanic "mkCoTyApp:" (ppr PprDebug ty)
-#endif
-  | otherwise = ty_app
-  where
-    ty_app = CoTyApp expr ty
+rhssOfBind :: Bind b -> [Expr b]
+rhssOfBind (NonRec _ rhs) = [rhs]
+rhssOfBind (Rec pairs)    = [rhs | (_,rhs) <- pairs]
 
-    error_app (CoVar id) {-| isBottomingId id-} = True -- debugging
-       -- OOPS! can't do this because it forces
-       -- the bindee type to be Id (ToDo: what?) WDP 95/02
-    error_app _ = False
--}
-\end{code}
+rhssOfAlts :: [Alt b] -> [Expr b]
+rhssOfAlts alts = [e | (_,_,e) <- alts]
 
-\begin{code}
-applyToArgs :: CoreExpr binder bindee
-           -> [CoreArg bindee]
-           -> CoreExpr binder bindee
+isDeadBinder :: CoreBndr -> Bool
+isDeadBinder bndr | isId bndr = case getInlinePragma bndr of
+                                       IAmDead -> True
+                                       other   -> False
+                 | otherwise = False   -- TyVars count as not dead
 
-applyToArgs fun []                 = fun
-applyToArgs fun (ValArg val : args) = applyToArgs (CoApp     fun val) args
-applyToArgs fun (TypeArg ty : args) = applyToArgs (mkCoTyApp fun ty)  args
+flattenBinds :: [Bind b] -> [(b, Expr b)]      -- Get all the lhs/rhs pairs
+flattenBinds (NonRec b r : binds) = (b,r) : flattenBinds binds
+flattenBinds (Rec prs1   : binds) = prs1 ++ flattenBinds binds
+flattenBinds []                          = []
 \end{code}
 
-@decomposeArgs@ just pulls of the contiguous TypeArg-then-ValArg block
-on the front of the args.  Pretty common.
+We often want to strip off leading lambdas before getting down to
+business.  @collectBinders@ is your friend.
+
+We expect (by convention) type-, and value- lambdas in that
+order.
 
 \begin{code}
-decomposeArgs :: [CoreArg bindee]
-             -> ([UniType], [CoreAtom bindee], [CoreArg bindee])
+collectBinders              :: Expr b -> ([b],         Expr b)
+collectBindersIgnoringNotes  :: Expr b -> ([b],         Expr b)
+collectTyBinders                    :: CoreExpr -> ([TyVar],     CoreExpr)
+collectValBinders                   :: CoreExpr -> ([Id],        CoreExpr)
+collectTyAndValBinders              :: CoreExpr -> ([TyVar], [Id], CoreExpr)
 
-decomposeArgs [] = ([],[],[])
+collectBinders expr
+  = go [] expr
+  where
+    go bs (Lam b e) = go (b:bs) e
+    go bs e         = (reverse bs, e)
+
+-- This one ignores notes.  It's used in CoreUnfold and StrAnal
+-- when we aren't going to put the expression back together from
+-- the pieces, so we don't mind losing the Notes
+collectBindersIgnoringNotes expr
+  = go [] expr
+  where
+    go bs (Lam b e)  = go (b:bs) e
+    go bs (Note _ e) = go    bs  e
+    go bs e         = (reverse bs, e)
+
+collectTyAndValBinders expr
+  = (tvs, ids, body)
+  where
+    (tvs, body1) = collectTyBinders expr
+    (ids, body)  = collectValBinders body1
 
-decomposeArgs (TypeArg ty : args)
-  = case (decomposeArgs args) of { (tys, vals, rest) ->
-    (ty:tys, vals, rest) }
+collectTyBinders expr
+  = go [] expr
+  where
+    go tvs (Lam b e) | isTyVar b = go (b:tvs) e
+    go tvs e                    = (reverse tvs, e)
 
-decomposeArgs (ValArg val : args)
-  = case (do_vals args) of { (vals, rest) ->
-    ([], val:vals, rest) }
+collectValBinders expr
+  = go [] expr
   where
-    do_vals (ValArg val : args)
-      = case (do_vals args) of { (vals, rest) ->
-       (val:vals, rest) }
-       
-    do_vals args = ([], args)
+    go ids (Lam b e) | isId b = go (b:ids) e
+    go ids body                      = (reverse ids, body)
 \end{code}
 
+
 @collectArgs@ takes an application expression, returning the function
 and the arguments to which it is applied.
 
 \begin{code}
-collectArgs :: CoreExpr binder bindee
-           -> (CoreExpr binder bindee, [CoreArg bindee])
-
+collectArgs :: Expr b -> (Expr b, [Arg b])
 collectArgs expr
-  = collect expr []
+  = go expr []
   where
-    collect (CoApp fun arg)  args = collect fun (ValArg arg : args)
-    collect (CoTyApp fun ty) args = collect fun (TypeArg ty : args)
-    collect other_expr args      = (other_expr, args)
+    go (App f a) as = go f (a:as)
+    go e        as = (e, as)
+\end{code}
+
+coreExprCc gets the cost centre enclosing an expression, if any.
+It looks inside lambdas because (scc "foo" \x.e) = \x.scc "foo" e
+
+\begin{code}
+coreExprCc :: Expr b -> CostCentre
+coreExprCc (Note (SCC cc) e)   = cc
+coreExprCc (Note other_note e) = coreExprCc e
+coreExprCc (Lam _ e)           = coreExprCc e
+coreExprCc other               = noCostCentre
 \end{code}
 
+
 %************************************************************************
 %*                                                                     *
-\subsection[CoreSyn-output]{Instance declarations for output}
+\subsection{Predicates}
 %*                                                                     *
 %************************************************************************
 
-@pprCoreBinding@ and @pprCoreExpr@ let you give special printing
-function for ``major'' binders (those next to equal signs :-),
-``minor'' ones (lambda-bound, case-bound), and bindees.  They would
-usually be called through some intermediary.
-
 \begin{code}
-pprCoreBinding
-       :: PprStyle
-       -> (PprStyle -> bndr -> Pretty) -- to print "major" binders
-       -> (PprStyle -> bndr -> Pretty) -- to print "minor" binders
-       -> (PprStyle -> bdee -> Pretty) -- to print bindees
-       -> CoreBinding bndr bdee
-       -> Pretty
-
-pprCoreBinding sty pbdr1 pbdr2 pbdee (CoNonRec binder expr)
-  = ppHang (ppCat [pbdr1 sty binder, ppEquals])
-        4 (pprCoreExpr sty pbdr1 pbdr2 pbdee expr)
-
-pprCoreBinding sty pbdr1 pbdr2 pbdee (CoRec binds)
-  = ppAboves [ifPprDebug sty (ppStr "{- CoRec -}"),
-             ppAboves (map ppr_bind binds),
-             ifPprDebug sty (ppStr "{- end CoRec -}")]
-  where
-    ppr_bind (binder, expr)
-      = ppHang (ppCat [pbdr1 sty binder, ppEquals])
-            4 (pprCoreExpr sty pbdr1 pbdr2 pbdee expr)
-\end{code}
+isValArg (Type _) = False
+isValArg other    = True
 
-\begin{code}
-instance (Outputable bndr, Outputable bdee)
-               => Outputable (CoreBinding bndr bdee) where
-    ppr sty bind = pprCoreBinding sty ppr ppr ppr bind
+isTypeArg (Type _) = True
+isTypeArg other    = False
 
-instance (Outputable bndr, Outputable bdee)
-               => Outputable (CoreExpr bndr bdee) where
-    ppr sty expr = pprCoreExpr sty ppr ppr ppr expr
+valBndrCount :: [CoreBndr] -> Int
+valBndrCount []                          = 0
+valBndrCount (b : bs) | isId b    = 1 + valBndrCount bs
+                     | otherwise = valBndrCount bs
 
-instance Outputable bdee => Outputable (CoreAtom bdee) where
-    ppr sty atom = pprCoreAtom sty ppr atom
+valArgCount :: [Arg b] -> Int
+valArgCount []             = 0
+valArgCount (Type _ : args) = valArgCount args
+valArgCount (other  : args) = 1 + valArgCount args
 \end{code}
 
-\begin{code}
-pprCoreAtom
-       :: PprStyle
-       -> (PprStyle -> bdee -> Pretty) -- to print bindees
-       -> CoreAtom bdee
-       -> Pretty
-
-pprCoreAtom sty pbdee (CoLitAtom lit) = ppr sty lit
-pprCoreAtom sty pbdee (CoVarAtom v)   = pbdee sty v
-\end{code}
+
+%************************************************************************
+%*                                                                     *
+\subsection{Seq stuff}
+%*                                                                     *
+%************************************************************************
 
 \begin{code}
-pprCoreExpr, pprParendCoreExpr
-       :: PprStyle
-       -> (PprStyle -> bndr -> Pretty) -- to print "major" binders
-       -> (PprStyle -> bndr -> Pretty) -- to print "minor" binders
-       -> (PprStyle -> bdee -> Pretty) -- to print bindees
-       -> CoreExpr bndr bdee
-       -> Pretty
-
-pprCoreExpr sty pbdr1 pbdr2 pbdee (CoVar name) = pbdee sty name
-
-pprCoreExpr sty pbdr1 pbdr2 pbdee (CoLit literal) = ppr sty literal
-
-pprCoreExpr sty pbdr1 pbdr2 pbdee (CoCon con [] []) = ppr sty con
-
-pprCoreExpr sty pbdr1 pbdr2 pbdee (CoCon con types args)
-  = ppHang (ppBesides [ppr sty con, ppChar '!'])
-        4 (ppSep (  (map (pprParendUniType sty) types)
-                 ++ (map (pprCoreAtom sty pbdee) args)))
-
-pprCoreExpr sty pbdr1 pbdr2 pbdee (CoPrim prim tys args)
-  = ppHang (ppBesides [ppr sty prim, ppChar '!'])
-        4 (ppSep (  (map (pprParendUniType sty) tys)
-                 ++ (map (pprCoreAtom sty pbdee) args) ))
-
-pprCoreExpr sty pbdr1 pbdr2 pbdee (CoLam binders expr)
-  = ppHang (ppCat [ppStr "\\", ppInterleave ppSP (map (pbdr2 sty) binders), ppStr "->"])
-        4 (pprCoreExpr sty pbdr1 pbdr2 pbdee expr)
-
-pprCoreExpr sty pbdr1 pbdr2 pbdee (CoTyLam tyvar expr)
-  = ppHang (ppCat [ppStr "/\\", interppSP sty (tyvar:tyvars),
-                  ppStr "->", pp_varss var_lists])
-          4 (pprCoreExpr sty pbdr1 pbdr2 pbdee expr_after)
-  where
-    (tyvars, var_lists, expr_after) = collect_tyvars expr
-
-    collect_tyvars (CoTyLam tyv e) = ( tyv:tyvs, vs, e_after )
-      where (tyvs, vs, e_after) = collect_tyvars e
-    collect_tyvars e@(CoLam _ _)   = ( [], vss, e_after )
-      where (vss, e_after) = collect_vars e
-    collect_tyvars other_e        = ( [], [], other_e )
-
-    collect_vars (CoLam vars e) = (vars:varss, e_after)
-      where (varss, e_after) = collect_vars e
-    collect_vars other_e          = ( [], other_e )
-
-    pp_varss [] = ppNil
-    pp_varss (vars:varss)
-      = ppCat [ppStr "\\", ppInterleave ppSP (map (pbdr2 sty) vars),
-              ppStr "->", pp_varss varss]
-
-pprCoreExpr sty pbdr1 pbdr2 pbdee expr@(CoApp fun_expr atom)
-  = let
-       (fun, args) = collect_args expr []
-    in
-    ppHang (pprParendCoreExpr sty pbdr1 pbdr2 pbdee fun)
-        4 (ppSep (map (pprCoreAtom sty pbdee) args))
-  where
-    collect_args (CoApp fun arg) args = collect_args fun (arg:args)
-    collect_args fun            args = (fun, args)
+seqExpr :: CoreExpr -> ()
+seqExpr (Var v)       = v `seq` ()
+seqExpr (Con c as)    = seqExprs as
+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
 
-pprCoreExpr sty pbdr1 pbdr2 pbdee (CoTyApp expr ty)
-  = ppHang (ppBeside pp_note (pprParendCoreExpr sty pbdr1 pbdr2 pbdee expr))
-        4 (pprParendUniType sty ty)
-  where
-    pp_note = ifPprShowAll sty (ppStr "{-CoTyApp-} ")
-
-pprCoreExpr sty pbdr1 pbdr2 pbdee (CoCase expr alts)
-  = ppSep [ppSep [ppStr "case", ppNest 4 (pprParendCoreExpr sty pbdr1 pbdr2 pbdee expr),
-                    ppStr "of {"],
-          ppNest 2 (pprCoreCaseAlts sty pbdr1 pbdr2 pbdee alts),
-          ppStr "}"]
-
--- special cases: let ... in let ...
--- ("disgusting" SLPJ)
-
-pprCoreExpr sty pbdr1 pbdr2 pbdee (CoLet bind@(CoNonRec binder rhs@(CoLet _ _)) body)
-  = ppAboves [
-      ppCat [ppStr "let {", pbdr1 sty binder, ppEquals],
-      ppNest 2 (pprCoreExpr sty pbdr1 pbdr2 pbdee rhs),
-      ppStr "} in",
-      pprCoreExpr sty pbdr1 pbdr2 pbdee body ]
-
-pprCoreExpr sty pbdr1 pbdr2 pbdee (CoLet bind@(CoNonRec binder rhs) expr@(CoLet _ _))
-  = ppAbove
-      (ppHang (ppStr "let {")
-           2 (ppCat [ppHang (ppCat [pbdr1 sty binder, ppEquals])
-                          4 (pprCoreExpr sty pbdr1 pbdr2 pbdee rhs),
-       ppStr "} in"]))
-      (pprCoreExpr sty pbdr1 pbdr2 pbdee expr)
-
--- general case (recursive case, too)
-pprCoreExpr sty pbdr1 pbdr2 pbdee (CoLet bind expr)
-  = ppSep [ppHang (ppStr "let {") 2 (pprCoreBinding sty pbdr1 pbdr2 pbdee bind),
-          ppHang (ppStr "} in ") 2 (pprCoreExpr    sty pbdr1 pbdr2 pbdee expr)]
-
-pprCoreExpr sty pbdr1 pbdr2 pbdee (CoSCC cc expr)
-  = ppSep [ ppCat [ppStr "_scc_", ppStr (showCostCentre sty True{-as string-} cc)],
-           pprParendCoreExpr sty pbdr1 pbdr2 pbdee expr ]
-#ifdef DPH
-pprCoreExpr sty pbdr1 pbdr2 pbdee (CoZfExpr expr quals)
-    = ppHang (ppCat [ppStr "<<" , pprCoreExpr sty pbdr1 pbdr2 pbdee expr , ppStr "|"])
-         4 (ppSep [pprParQuals sty pbdr1 pbdr2 pbdee quals, ppStr ">>"])
-
-pprCoreExpr sty pbdr1 pbdr2 pbdee (CoParCon con dim types args)
-  = ppHang (ppBesides [ppr sty con, ppStr "!<<" , ppr sty dim , ppStr ">>"])
-          4 (ppSep (  (map (pprParendUniType sty) types)
-                   ++ (map (pprParendCoreExpr sty pbdr1 pbdr2 pbdee) args) ))
-
-pprCoreExpr sty pbdr1 pbdr2 pbdee (CoParComm dim expr comType)
-  = ppSep [ppSep [ppStr "COMM",
-                 ppNest 2 (pprParendCoreExpr sty pbdr1 pbdr2 pbdee expr),ppStr "{"],
-          ppNest 2 (ppr sty comType),
-          ppStr "}"]
-
-pprCoreExpr sty pbdr1 pbdr2 pbdee (CoParZipWith dim expr exprs)
-  = ppHang (ppBesides [ ppStr "CoParZipWith {" , ppr sty dim , ppStr "}",
-                       pprParendCoreExpr sty pbdr1 pbdr2 pbdee expr])
-          4 (ppr sty exprs)
-#endif {- Data Parallel Haskell -}
-\end{code}
+seqExprs [] = ()
+seqExprs (e:es) = seqExpr e `seq` seqExprs es
 
-\begin{code}
-pprParendCoreExpr sty pbdr1 pbdr2 pbdee e@(CoVar _) = pprCoreExpr sty pbdr1 pbdr2 pbdee e
-pprParendCoreExpr sty pbdr1 pbdr2 pbdee e@(CoLit _) = pprCoreExpr sty pbdr1 pbdr2 pbdee e
-pprParendCoreExpr sty pbdr1 pbdr2 pbdee other_e
-  = ppBesides [ppLparen, pprCoreExpr sty pbdr1 pbdr2 pbdee other_e, ppRparen]
-\end{code}
+seqNote (Coerce t1 t2) = seqType t1 `seq` seqType t2
+seqNote other         = ()
 
-\begin{code}
-instance (Outputable bndr, Outputable bdee)
-               => Outputable (CoreCaseAlternatives bndr bdee) where
-    ppr sty alts = pprCoreCaseAlts sty ppr ppr ppr alts
-\end{code}
+seqBndr b = b `seq` ()
 
-\begin{code}
-pprCoreCaseAlts
-       :: PprStyle
-       -> (PprStyle -> bndr -> Pretty) -- to print "major" binders
-       -> (PprStyle -> bndr -> Pretty) -- to print "minor" binders
-       -> (PprStyle -> bdee -> Pretty) -- to print bindees
-       -> CoreCaseAlternatives bndr bdee
-       -> Pretty
-
-pprCoreCaseAlts sty pbdr1 pbdr2 pbdee (CoAlgAlts alts deflt)
-  = ppAboves [ ppAboves (map ppr_alt alts),
-              pprCoreCaseDefault sty pbdr1 pbdr2 pbdee deflt ]
-  where
-    ppr_alt (con, params, expr)
-      = ppHang (ppCat [ppr_con con,
-                      ppInterleave ppSP (map (pbdr2 sty) params),
-                      ppStr "->"])
-               4 (pprCoreExpr sty pbdr1 pbdr2 pbdee expr)
-      where
-       ppr_con con
-         = if isOpLexeme con
-           then ppBesides [ppLparen, ppr sty con, ppRparen]
-           else ppr sty con
-
-pprCoreCaseAlts sty pbdr1 pbdr2 pbdee (CoPrimAlts alts deflt)
-  = ppAboves [ ppAboves (map ppr_alt alts),
-              pprCoreCaseDefault sty pbdr1 pbdr2 pbdee deflt ]
-  where
-    ppr_alt (lit, expr)
-      = ppHang (ppCat [ppr sty lit, ppStr "->"])
-            4 (pprCoreExpr sty pbdr1 pbdr2 pbdee expr)
-
-#ifdef DPH
--- ToDo: niceties of printing
--- using special binder/bindee printing funs, rather than just "ppr"
-
-pprCoreCaseAlts sty pbdr1 pbdr2 pbdee (CoParAlgAlts tycon dim params alts deflt)
-  = ppAboves [ ifPprShowAll sty (ppr sty tycon),
-              ppBeside (ppCat (map (ppr sty) params))
-                       (ppCat [ppStr "|" , ppr sty dim , ppStr "|"]),
-              ppAboves (map (ppr_alt sty) alts),
-              ppr sty deflt ]
-  where
-    ppr_alt sty (con, expr)
-      = ppHang (ppCat [ppStr "\\/", ppr_con sty con, ppStr "->"])
-               4 (ppr sty expr)
-      where
-       ppr_con sty con
-         = if isOpLexeme con
-           then ppBesides [ppLparen, ppr sty con, ppRparen]
-           else ppr sty con
-
-pprCoreCaseAlts sty pbdr1 pbdr2 pbdee (CoParPrimAlts tycon dim alts deflt)
-  = ppAboves [ ifPprShowAll sty (ppr sty tycon),
-              ppCat [ppStr "|" , ppr sty dim , ppStr "|"],
-              ppAboves (map (ppr_alt sty) alts),
-              ppr sty deflt ]
-  where
-    ppr_alt sty (lit, expr)
-      = ppHang (ppCat [ppStr "\\/", ppr sty lit, ppStr "->"]) 4 (ppr sty expr)
+seqBndrs [] = ()
+seqBndrs (b:bs) = seqBndr b `seq` seqBndrs bs
 
-#endif /* Data Parallel Haskell */
-\end{code}
+seqBind (NonRec b e) = seqBndr b `seq` seqExpr e
+seqBind (Rec prs)    = seqPairs prs
 
-\begin{code}
-instance (Outputable bndr, Outputable bdee)
-               => Outputable (CoreCaseDefault bndr bdee) where
-    ppr sty deflt  = pprCoreCaseDefault sty ppr ppr ppr deflt
+seqPairs [] = ()
+seqPairs ((b,e):prs) = seqBndr b `seq` seqExpr e `seq` seqPairs prs
+
+seqAlts [] = ()
+seqAlts ((c,bs,e):alts) = seqBndrs bs `seq` seqExpr e `seq` seqAlts alts
+
+seqRules :: CoreRules -> ()
+seqRules (Rules rules fvs) = seq_rules rules `seq` seqVarSet fvs
+
+seq_rules [] = ()
+seq_rules (Rule fs bs es e : rules) = seqBndrs bs `seq` seqExprs (e:es) `seq` seq_rules rules
 \end{code}
 
 \begin{code}
-pprCoreCaseDefault
-       :: PprStyle
-       -> (PprStyle -> bndr -> Pretty) -- to print "major" binders
-       -> (PprStyle -> bndr -> Pretty) -- to print "minor" binders
-       -> (PprStyle -> bdee -> Pretty) -- to print bindees
-       -> CoreCaseDefault bndr bdee
-       -> Pretty
-
-pprCoreCaseDefault sty pbdr1 pbdr2 pbdee CoNoDefault = ppNil
-
-pprCoreCaseDefault sty pbdr1 pbdr2 pbdee (CoBindDefault binder expr)
-  = ppHang (ppCat [pbdr2 sty binder, ppStr "->"])
-        4 (pprCoreExpr sty pbdr1 pbdr2 pbdee expr)
+coreBindsSize :: [CoreBind] -> Int
+coreBindsSize bs = foldr ((+) . bindSize) 0 bs
+
+exprSize :: CoreExpr -> Int
+       -- A measure of the size of the expressions
+       -- It also forces the expression pretty drastically as a side effect
+exprSize (Var v)       = varSize v 
+exprSize (Con c as)    = c `seq` exprsSize as
+exprSize (App f a)     = exprSize f + exprSize a
+exprSize (Lam b e)     = varSize b + exprSize e
+exprSize (Let b e)     = bindSize b + exprSize e
+exprSize (Case e b as) = exprSize e + varSize b + foldr ((+) . altSize) 0  as
+exprSize (Note n e)    = exprSize e
+exprSize (Type t)      = seqType t `seq` 1
+
+exprsSize = foldr ((+) . exprSize) 0 
+
+varSize :: IdOrTyVar -> Int
+varSize b | isTyVar b = 1
+         | otherwise = seqType (idType b)              `seq`
+                       megaSeqIdInfo (idInfo b)        `seq`
+                       1
+
+varsSize = foldr ((+) . varSize) 0
+
+bindSize (NonRec b e) = varSize b + exprSize e
+bindSize (Rec prs)    = foldr ((+) . pairSize) 0 prs
+
+pairSize (b,e) = varSize b + exprSize e
+
+altSize (c,bs,e) = c `seq` varsSize bs + exprSize e
 \end{code}
 
+
+%************************************************************************
+%*                                                                     *
+\subsection{Annotated core; annotation at every node in the tree}
+%*                                                                     *
+%************************************************************************
+
 \begin{code}
-#ifdef DPH
-instance (Outputable bndr, Outputable bdee)
-               => Outputable (CoreParQuals bndr bdee) where
-    ppr sty qual = pprParQuals sty ppr ppr ppr qual
-
-pprParQuals sty pbdr1 pbdr2 pbdee (CoAndQuals x y) 
-     = ppAboves [(ppBesides [pprParQuals sty pbdr1 pbdr2 pbdee x , ppComma]) , pprParQuals sty pbdr1 pbdr2 pbdee y]
-
-pprParQuals sty pbdr1 pbdr2 pbdee (CoDrawnGen pats pat expr)
-     = ppCat [ppStr "(|",
-              ppInterleave ppComma (map (ppr sty) pats),
-              ppSemi, ppr sty pat,ppStr "|)",
-              ppStr "<<-", pprCoreExpr sty pbdr1 pbdr2 pbdee expr]
-
-pprParQuals sty pbdr1 pbdr2 pbdee (CoIndexGen exprs pat expr)
-     = ppCat [ppStr "(|",
-              ppInterleave ppComma (map (pprCoreExpr sty pbdr1 pbdr2 pbdee) exprs),
-              ppSemi, ppr sty pat,ppStr "|)",
-              ppStr "<<=", pprCoreExpr sty pbdr1 pbdr2 pbdee expr]
-
-pprParQuals sty pbdr1 pbdr2 pbdee (CoParFilter expr)
-     = pprParendCoreExpr sty pbdr1 pbdr2 pbdee expr
-#endif {- Data Parallel Haskell -}
+type AnnExpr bndr annot = (annot, AnnExpr' bndr annot)
+
+data AnnExpr' bndr annot
+  = AnnVar     Id
+  | AnnCon     Con [AnnExpr bndr annot]
+  | AnnLam     bndr (AnnExpr bndr annot)
+  | AnnApp     (AnnExpr bndr annot) (AnnExpr bndr annot)
+  | AnnCase    (AnnExpr bndr annot) bndr [AnnAlt bndr annot]
+  | AnnLet     (AnnBind bndr annot) (AnnExpr bndr annot)
+  | AnnNote    Note (AnnExpr bndr annot)
+  | AnnType    Type
+
+type AnnAlt bndr annot = (Con, [bndr], AnnExpr bndr annot)
+
+data AnnBind bndr annot
+  = AnnNonRec bndr (AnnExpr bndr annot)
+  | AnnRec    [(bndr, AnnExpr bndr annot)]
 \end{code}
 
 \begin{code}
-#ifdef DPH
-instance (Outputable bndr, Outputable bdee)
-               => Outputable (CoreParCommunicate bndr bdee) where
-    ppr sty c = pprCoreParCommunicate sty ppr ppr ppr c
-
-pprCoreParCommunicate sty pbdr1 pbdr2 pbdee (CoParSend fns)
-  = ppHang 
-       (ppStr "SEND") 
-       4 
-       (ppAboves (zipWith ppSendFns fns ([1..]::[Int])))
-  where
-     ppSendFns expr dim 
-        = ppCat [ppStr "Dim" , ppr sty dim , ppStr "=" , 
-                pprParendCoreExpr sty pbdr1 pbdr2 pbdee expr ]
-
-pprCoreParCommunicate sty pbdr1 pbdr2 pbdee (CoParFetch fns)
-  = ppHang 
-       (ppStr "FETCH") 
-       4 
-       (ppAboves (zipWith ppSendFns fns ([1..]::[Int])))
-  where
-     ppSendFns expr dim 
-        = ppCat [ppStr "Dim" , ppr sty dim , ppStr "=" , 
-                pprParendCoreExpr sty pbdr1 pbdr2 pbdee expr ]
+deAnnotate :: AnnExpr bndr annot -> Expr bndr
 
-pprCoreParCommunicate sty pbdr1 pbdr2 pbdee (CoToPodized)
-  = ppStr "ConvertToPodized"
+deAnnotate (_, AnnType t)          = Type t
+deAnnotate (_, AnnVar  v)          = Var v
+deAnnotate (_, AnnCon  con args)   = Con con (map deAnnotate args)
+deAnnotate (_, AnnLam  binder body)= Lam binder (deAnnotate body)
+deAnnotate (_, AnnApp  fun arg)    = App (deAnnotate fun) (deAnnotate arg)
+deAnnotate (_, AnnNote note body)  = Note note (deAnnotate body)
 
-pprCoreParCommunicate sty pbdr1 pbdr2 pbdee (CoFromPodized)
-  = ppStr "ConvertFromPodized"
-#endif {- Data Parallel Haskell -}
+deAnnotate (_, AnnLet bind body)
+  = Let (deAnnBind bind) (deAnnotate body)
+  where
+    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)
+  where
+    deAnnAlt (con,args,rhs) = (con,args,deAnnotate rhs)
 \end{code}
+