[project @ 1996-01-08 20:28:12 by partain]
[ghc-hetmet.git] / ghc / compiler / abstractSyn / HsBinds.lhs
diff --git a/ghc/compiler/abstractSyn/HsBinds.lhs b/ghc/compiler/abstractSyn/HsBinds.lhs
new file mode 100644 (file)
index 0000000..c0716d2
--- /dev/null
@@ -0,0 +1,329 @@
+%
+% (c) The GRASP/AQUA Project, Glasgow University, 1992-1995
+%
+\section[HsBinds]{Abstract syntax: top-level bindings and signatures}
+
+Datatype for: @Binds@, @Bind@, @Sig@, @MonoBinds@.
+
+\begin{code}
+#include "HsVersions.h"
+
+module HsBinds where
+
+import AbsUniType      ( pprUniType, TyVar, UniType
+                         IF_ATTACK_PRAGMAS(COMMA cmpTyVar)
+                         IF_ATTACK_PRAGMAS(COMMA cmpUniType)
+                       )
+import HsExpr          ( Expr )
+import HsMatches       ( pprMatches, pprGRHSsAndBinds, Match, GRHSsAndBinds )
+import HsPat           ( ProtoNamePat(..), RenamedPat(..),
+                         TypecheckedPat, InPat
+                         IF_ATTACK_PRAGMAS(COMMA typeOfPat)
+                       )
+import HsPragmas       ( GenPragmas, ClassOpPragmas )
+import HsTypes         ( PolyType )
+import Id              ( Id, DictVar(..) )
+import IdInfo          ( UnfoldingGuidance )
+import Inst            ( Inst )
+import Name            ( Name )
+import Outputable
+import Pretty
+import ProtoName       ( ProtoName(..) ) -- .. for pragmas only
+import SrcLoc          ( SrcLoc )
+import Unique          ( Unique )
+import Util
+\end{code}
+
+%************************************************************************
+%*                                                                     *
+\subsection[AbsSyn-Binds]{Bindings: @Binds@}
+%*                                                                     *
+%************************************************************************
+
+The following syntax may produce new syntax which is not part of the input,
+and which is instead a translation of the input to the typechecker.
+Syntax translations are marked TRANSLATION in comments. New empty
+productions are useful in development but may not appear in the final
+grammar.
+
+Collections of bindings, created by dependency analysis and translation:
+
+\begin{code}
+data Binds bdee pat            -- binders and bindees
+  = EmptyBinds
+
+  | ThenBinds  (Binds bdee pat)
+               (Binds bdee pat)
+
+  | SingleBind (Bind  bdee pat)
+
+  | BindWith           -- Bind with a type signature.
+                       -- These appear only on typechecker input
+                       -- (PolyType [in Sigs] can't appear on output)
+               (Bind bdee pat)         -- really ProtoNameBind, but...
+                                       -- (see "really" comment below)
+               [Sig bdee]
+
+  | AbsBinds                   -- Binds abstraction; TRANSLATION
+               [TyVar]
+               [DictVar]
+               [(Id, Id)]              -- (old, new) pairs
+               [(Inst, Expr bdee pat)] -- local dictionaries
+               (Bind bdee pat)         -- "the business end"
+
+       -- Creates bindings for *new* (polymorphic, overloaded) locals
+       -- in terms of *old* (monomorphic, non-overloaded) ones.
+       --
+       -- See section 9 of static semantics paper for more details.
+       -- (You can get a PhD for explaining the True Meaning
+       --  of this last construct.)
+\end{code}
+
+The corresponding unparameterised synonyms:
+
+\begin{code}
+type ProtoNameBinds    = Binds ProtoName ProtoNamePat
+type RenamedBinds       = Binds Name     RenamedPat
+type TypecheckedBinds  = Binds Id        TypecheckedPat
+\end{code}
+
+\begin{code}
+nullBinds :: Binds bdee pat -> Bool
+nullBinds EmptyBinds           = True
+nullBinds (ThenBinds b1 b2)    = (nullBinds b1) && (nullBinds b2)
+nullBinds (SingleBind b)       = nullBind b
+nullBinds (BindWith b _)       = nullBind b
+nullBinds (AbsBinds _ _ _ ds b)        = (null ds) && (nullBind b)
+\end{code}
+
+ToDo: make this recursiveness checking also require that
+there be something there, i.e., not null ?
+\begin{code}
+{- UNUSED:
+bindsAreRecursive :: TypecheckedBinds -> Bool
+
+bindsAreRecursive EmptyBinds           = False
+bindsAreRecursive (ThenBinds b1 b2)
+  = (bindsAreRecursive b1) || (bindsAreRecursive b2)
+bindsAreRecursive (SingleBind b)       = bindIsRecursive b
+bindsAreRecursive (BindWith b _)       = bindIsRecursive b
+bindsAreRecursive (AbsBinds _ _ _ ds b)
+  = (bindsAreRecursive d) || (bindIsRecursive b)
+-}
+\end{code}
+
+\begin{code}
+instance (NamedThing bdee, Outputable bdee,
+            NamedThing pat, Outputable pat) =>
+               Outputable (Binds bdee pat) where
+
+    ppr sty EmptyBinds = ppNil
+    ppr sty (ThenBinds binds1 binds2)
+     = ppAbove (ppr sty binds1) (ppr sty binds2)
+    ppr sty (SingleBind bind) = ppr sty bind
+    ppr sty (BindWith bind sigs)
+     = ppAbove (if null sigs then ppNil else ppr sty sigs) (ppr sty bind)
+    ppr sty (AbsBinds tyvars dictvars local_pairs dict_binds val_binds)
+     = ppAbove (ppSep [ppPStr SLIT("AbsBinds"),
+                     ppBesides[ppLbrack, interpp'SP sty tyvars, ppRbrack],
+                     ppBesides[ppLbrack, interpp'SP sty dictvars, ppRbrack],
+                     ppBesides[ppLbrack, interpp'SP sty local_pairs, ppRbrack]])
+           (ppNest 4 (ppAbove (ppAboves (map (ppr sty) dict_binds)) (ppr sty val_binds)))
+\end{code}
+
+%************************************************************************
+%*                                                                     *
+\subsection[AbsSyn-Sig]{@Sig@: type signatures and value-modifying user pragmas}
+%*                                                                     *
+%************************************************************************
+
+It is convenient to lump ``value-modifying'' user-pragmas (e.g.,
+``specialise this function to these four types...'') in with type
+signatures.  Then all the machinery to move them into place, etc.,
+serves for both.
+
+\begin{code}
+data Sig name
+  = Sig                name            -- a bog-std type signature
+               (PolyType name)
+               (GenPragmas name) -- only interface ones have pragmas
+               SrcLoc
+
+  | ClassOpSig name            -- class-op sigs have different pragmas
+               (PolyType name)
+               (ClassOpPragmas name)   -- only interface ones have pragmas
+               SrcLoc
+
+  | SpecSig    name            -- specialise a function or datatype ...
+               (PolyType name) -- ... to these types
+               (Maybe name)    -- ... maybe using this as the code for it
+               SrcLoc
+
+  | InlineSig  name              -- INLINE f [howto]
+               UnfoldingGuidance -- "howto": how gung-ho we are about inlining
+               SrcLoc
+
+  -- ToDo: strictly speaking, could omit based on -DOMIT_DEFORESTER
+  | DeforestSig name            -- Deforest using this function definition
+               SrcLoc
+  | MagicUnfoldingSig
+               name            -- Associate the "name"d function with
+               FAST_STRING     -- the compiler-builtin unfolding (known
+               SrcLoc          -- by the String name)
+                     
+type ProtoNameSig  = Sig ProtoName
+type RenamedSig    = Sig Name
+
+type ProtoNameClassOpSig  = Sig ProtoName
+type RenamedClassOpSig    = Sig Name
+\end{code}
+
+\begin{code}
+instance (Outputable name) => Outputable (Sig name) where
+    ppr sty (Sig var ty pragmas _)
+      = ppHang (ppCat [ppr sty var, ppPStr SLIT("::")])
+            4 (ppAbove (ppr sty ty)
+                       (ifnotPprForUser sty (ppr sty pragmas)))
+
+    ppr sty (ClassOpSig var ty pragmas _)
+      = ppHang (ppCat [ppr sty var, ppPStr SLIT("::")])
+            4 (ppAbove (ppr sty ty)
+                       (ifnotPprForUser sty (ppr sty pragmas)))
+
+    ppr sty (DeforestSig var _)
+      = ppHang (ppCat [ppStr "{-# DEFOREST", ppr sty var])
+                   4 (ppStr "#-}")
+
+    ppr sty (SpecSig var ty using _)
+      = ppHang (ppCat [ppPStr SLIT("{-# SPECIALIZE"), ppr sty var, ppPStr SLIT("::")])
+            4 (ppCat [ppr sty ty, pp_using using, ppPStr SLIT("#-}")])
+      where
+       pp_using Nothing   = ppNil
+       pp_using (Just me) = ppCat [ppChar '=', ppr sty me]
+
+    ppr sty (InlineSig var _ _)
+      = ppHang (ppCat [ppPStr SLIT("{-# INLINE"), ppr sty var])
+            4 (ppCat [ppPStr SLIT("<enthusiasm not done yet>"), ppPStr SLIT("#-}")])
+
+    ppr sty (MagicUnfoldingSig var str _)
+      = ppCat [ppPStr SLIT("{-# MAGIC_UNFOLDING"), ppr sty var, ppPStr str, ppPStr SLIT("#-}")]
+\end{code}
+
+%************************************************************************
+%*                                                                     *
+\subsection[AbsSyn-Bind]{Binding: @Bind@}
+%*                                                                     *
+%************************************************************************
+
+\begin{code}
+data Bind bdee pat             -- binders and bindees
+  = EmptyBind  -- because it's convenient when parsing signatures
+  | NonRecBind (MonoBinds bdee pat)
+  | RecBind    (MonoBinds bdee pat)
+\end{code}
+
+The corresponding unparameterised synonyms:
+
+\begin{code}
+type ProtoNameBind             = Bind ProtoName ProtoNamePat
+type RenamedBind        = Bind Name RenamedPat
+type TypecheckedBind   = Bind Id          TypecheckedPat
+\end{code}
+
+\begin{code}
+nullBind :: Bind bdee pat -> Bool
+nullBind EmptyBind             = True
+nullBind (NonRecBind bs)       = nullMonoBinds bs
+nullBind (RecBind bs)          = nullMonoBinds bs
+\end{code}
+
+\begin{code}
+bindIsRecursive :: TypecheckedBind -> Bool
+bindIsRecursive EmptyBind      = False
+bindIsRecursive (NonRecBind _) = False
+bindIsRecursive (RecBind _)    = True
+\end{code}
+
+\begin{code}
+instance (NamedThing bdee, Outputable bdee,
+             NamedThing pat, Outputable pat) =>
+               Outputable (Bind bdee pat) where
+    ppr sty EmptyBind = ppNil
+    ppr sty (NonRecBind binds)
+     = ppAbove (ifnotPprForUser sty (ppStr "{- nonrec -}"))
+              (ppr sty binds)
+    ppr sty (RecBind binds)
+     = ppAbove (ifnotPprForUser sty (ppStr "{- rec -}"))
+              (ppr sty binds)
+\end{code}
+
+%************************************************************************
+%*                                                                     *
+\subsection[AbsSyn-MonoBinds]{Bindings: @MonoBinds@}
+%*                                                                     *
+%************************************************************************
+
+Global bindings (where clauses)
+
+\begin{code}
+data MonoBinds bdee pat                -- binders and bindees
+  = EmptyMonoBinds                     -- TRANSLATION
+  | AndMonoBinds    (MonoBinds bdee pat)
+                   (MonoBinds bdee pat)
+  | PatMonoBind     pat
+                   (GRHSsAndBinds bdee pat)
+                   SrcLoc
+  | VarMonoBind            Id                  -- TRANSLATION
+                   (Expr bdee pat)
+  | FunMonoBind     bdee
+                   [Match bdee pat]    -- must have at least one Match
+                   SrcLoc
+\end{code}
+
+The corresponding unparameterised synonyms:
+\begin{code}
+type ProtoNameMonoBinds            = MonoBinds ProtoName ProtoNamePat
+type RenamedMonoBinds      = MonoBinds Name      RenamedPat
+type TypecheckedMonoBinds   = MonoBinds Id        TypecheckedPat
+\end{code}
+
+\begin{code}
+nullMonoBinds :: MonoBinds bdee pat -> Bool
+nullMonoBinds EmptyMonoBinds           = True
+nullMonoBinds (AndMonoBinds bs1 bs2)   = (nullMonoBinds bs1) && (nullMonoBinds bs2)
+nullMonoBinds other_monobind           = False
+\end{code}
+
+\begin{code}
+instance (NamedThing bdee, Outputable bdee,
+             NamedThing pat, Outputable pat) =>
+               Outputable (MonoBinds bdee pat) where
+    ppr sty EmptyMonoBinds = ppNil
+    ppr sty (AndMonoBinds binds1 binds2)
+     = ppAbove (ppr sty binds1) (ppr sty binds2)
+
+    ppr sty (PatMonoBind pat grhss_n_binds locn)
+     = ppAboves [
+           ifPprShowAll sty (ppr sty locn),
+           (if (hasType pat) then
+               ppHang (ppCat [ppr sty pat, ppStr "::"]) 4 (pprUniType sty (getType pat))
+           else
+               ppNil
+           ),
+           (ppHang (ppr sty pat) 4 (pprGRHSsAndBinds sty False grhss_n_binds)) ]
+
+    ppr sty (FunMonoBind fun matches locn)
+     = ppAboves [
+           ifPprShowAll sty (ppr sty locn),
+           if (hasType fun) then
+               ppHang (ppCat [pprNonOp sty fun, ppStr "::"]) 4 
+                      (pprUniType sty (getType fun))
+           else
+               ppNil,
+          pprMatches sty (False, pprNonOp sty fun) matches
+       ]
+
+    ppr sty (VarMonoBind name expr)
+     = ppHang (ppCat [pprNonOp sty name, ppEquals]) 4 (ppr sty expr)
+\end{code}