[project @ 1996-01-08 20:28:12 by partain]
[ghc-hetmet.git] / ghc / compiler / abstractSyn / HsExpr.lhs
diff --git a/ghc/compiler/abstractSyn/HsExpr.lhs b/ghc/compiler/abstractSyn/HsExpr.lhs
new file mode 100644 (file)
index 0000000..131958c
--- /dev/null
@@ -0,0 +1,506 @@
+%
+% (c) The GRASP/AQUA Project, Glasgow University, 1992-1994
+%
+\section[HsExpr]{Abstract Haskell syntax: expressions}
+
+\begin{code}
+#include "HsVersions.h"
+
+module HsExpr where
+
+import AbsUniType      ( pprUniType, pprParendUniType, TyVar, UniType
+                         IF_ATTACK_PRAGMAS(COMMA cmpTyVar)
+                         IF_ATTACK_PRAGMAS(COMMA cmpUniType)
+                       )
+import Name            ( Name )
+import Unique          ( Unique )
+import HsBinds         ( Binds )
+import HsLit           ( Literal )
+import HsMatches       ( pprMatches, pprMatch, Match )
+import HsPat           ( ProtoNamePat(..), RenamedPat(..),
+                         TypecheckedPat, InPat
+                         IF_ATTACK_PRAGMAS(COMMA typeOfPat)
+                       )
+import HsTypes         ( PolyType )
+import Id              ( Id, DictVar(..), DictFun(..) )
+import Outputable
+import ProtoName       ( ProtoName(..) ) -- .. for pragmas only
+import Pretty
+import Util
+\end{code}
+
+%************************************************************************
+%*                                                                     *
+\subsection[AbsSyn-Expr]{Expressions proper}
+%*                                                                     *
+%************************************************************************
+
+\begin{code}
+data Expr bdee pat
+  = Var                bdee                    -- variable
+  | Lit                Literal                 -- literal
+
+  | Lam                (Match bdee pat)        -- lambda
+  | App                (Expr bdee pat)         -- application
+               (Expr bdee pat)
+
+  -- Operator applications and sections.
+  -- NB Bracketed ops such as (+) come out as Vars.
+
+  | OpApp      (Expr bdee pat) (Expr bdee pat) (Expr bdee pat)
+                                       -- middle expr is the "op"
+
+  -- ADR Question? Why is the "op" in a section an expr when it will
+  -- have to be of the form (Var op) anyway?
+  -- WDP Answer: But when the typechecker gets ahold of it, it may
+  -- apply the var to a few types; it will then be an expression.
+
+  | SectionL   (Expr bdee pat) (Expr bdee pat)
+                                       -- right expr is the "op"
+  | SectionR   (Expr bdee pat) (Expr bdee pat)
+                                       -- left expr is the "op"
+
+  | CCall      FAST_STRING     -- call into the C world; string is
+               [Expr bdee pat] -- the C function; exprs are the
+                               -- arguments to pass.
+               Bool            -- True <=> might cause Haskell
+                               -- garbage-collection (must generate
+                               -- more paranoid code)
+               Bool            -- True <=> it's really a "casm"
+                               -- NOTE: this CCall is the *boxed*
+                               -- version; the desugarer will convert
+                               -- it into the unboxed "ccall#".
+               UniType         -- The result type; will be *bottom*
+                               -- until the typechecker gets ahold of it
+
+  | SCC                FAST_STRING     -- set cost centre annotation
+               (Expr bdee pat) -- expr whose cost is to be measured
+
+  | Case       (Expr bdee pat)
+               [Match bdee pat] -- must have at least one Match
+
+  | If                         -- conditional
+               (Expr bdee pat) --  predicate
+               (Expr bdee pat) --  then part
+               (Expr bdee pat) --  else part
+
+  | Let                (Binds bdee pat) -- let(rec)
+               (Expr bdee pat)
+
+  | ListComp   (Expr bdee pat) -- list comprehension
+               [Qual bdee pat] -- at least one Qual(ifier)
+
+  | ExplicitList               -- syntactic list
+               [Expr bdee pat]
+  | ExplicitListOut            -- TRANSLATION
+               UniType         -- Unitype gives type of components of list
+               [Expr bdee pat]
+
+  | ExplicitTuple              -- tuple
+               [Expr bdee pat]
+                               -- NB: Unit is ExplicitTuple []
+                               -- for tuples, we can get the types
+                               -- direct from the components
+
+  | ExprWithTySig              -- signature binding
+               (Expr bdee pat)
+               (PolyType bdee)
+  | ArithSeqIn                 -- arithmetic sequence
+               (ArithSeqInfo bdee pat)
+  | ArithSeqOut
+               (Expr bdee pat) -- (typechecked, of course)
+               (ArithSeqInfo bdee pat)
+#ifdef DPH
+  | ParallelZF 
+               (Expr bdee pat)
+               (ParQuals bdee pat)
+  | ExplicitPodIn
+               [Expr bdee pat]
+  | ExplicitPodOut
+               UniType         -- Unitype gives type of components of list
+               [Expr bdee pat]
+  | ExplicitProcessor
+               [Expr bdee pat]
+               (Expr bdee pat)
+#endif {- Data Parallel Haskell -} 
+\end{code}
+
+Everything from here on appears only in typechecker output; hence, the
+explicit @Id@s.
+\begin{code}
+  | TyLam                      -- TRANSLATION
+               [TyVar]         -- Not TyVarTemplate, which only occur in a 
+                               -- binding position in a forall type.
+               (Expr bdee pat)
+  | TyApp                      -- TRANSLATION
+               (Expr bdee pat) -- generated by Spec
+               [UniType]
+
+  -- DictLam and DictApp are "inverses"
+  |  DictLam
+               [DictVar]
+               (Expr bdee pat)
+  |  DictApp
+               (Expr bdee pat)
+               [DictVar]               -- dictionary names
+
+  -- ClassDictLam and Dictionary are "inverses" (see note below)
+  |  ClassDictLam
+               [DictVar]
+               [Id]
+               -- The ordering here allows us to do away with dicts and methods
+
+               -- [I don't understand this comment. WDP.  Perhaps a ptr to
+               --  a complete description of what's going on ? ]
+               (Expr bdee pat)
+  |  Dictionary
+               [DictVar]       -- superclass dictionary names
+               [Id]            -- method names
+  |  SingleDict                        -- a simple special case of Dictionary
+               DictVar         -- local dictionary name
+\end{code}
+
+\begin{code}
+type ProtoNameExpr             = Expr ProtoName ProtoNamePat
+
+type RenamedExpr        = Expr Name RenamedPat
+
+type TypecheckedExpr   = Expr Id TypecheckedPat
+\end{code}
+
+A @Dictionary@, unless of length 0 or 1, becomes a tuple.  A
+@ClassDictLam dictvars methods expr@ is, therefore:
+\begin{verbatim}
+\ x -> case x of ( dictvars-and-methods-tuple ) -> expr
+\end{verbatim}
+
+\begin{code}
+instance (NamedThing bdee, Outputable bdee, 
+                                    NamedThing pat, Outputable pat) =>
+               Outputable (Expr bdee pat) where
+    ppr = pprExpr
+\end{code}
+
+\begin{code}
+pprExpr :: (NamedThing bdee, Outputable bdee, 
+                      NamedThing pat, Outputable pat) =>
+               PprStyle -> Expr bdee pat -> Pretty
+
+pprExpr sty (Var v)
+  = if (isOpLexeme v) then
+       ppBesides [ppLparen, ppr sty v, ppRparen]
+    else
+       ppr sty v
+
+pprExpr sty (Lit lit)  = ppr sty lit
+pprExpr sty (Lam match)
+  = ppCat [ppStr "\\", ppNest 2 (pprMatch sty True match)]
+
+pprExpr sty expr@(App e1 e2)
+  = let (fun, args) = collect_args expr [] in
+    ppHang (pprParendExpr sty fun) 4 (ppSep (map (pprParendExpr sty) args))
+  where
+    collect_args (App fun arg) args = collect_args fun (arg:args)
+    collect_args fun          args = (fun, args)
+
+pprExpr sty (OpApp e1 op e2)
+  = case op of
+      Var v -> pp_infixly v
+      _            -> pp_prefixly
+  where
+    pp_e1 = pprParendExpr sty e1
+    pp_e2 = pprParendExpr sty e2
+
+    pp_prefixly
+      = ppHang (pprParendExpr sty op) 4 (ppSep [pp_e1, pp_e2])
+
+    pp_infixly v
+      = ppSep [pp_e1, ppCat [pprOp sty v, pp_e2]]
+
+pprExpr sty (SectionL expr op)
+  = case op of
+      Var v -> pp_infixly v
+      _            -> pp_prefixly
+  where
+    pp_expr = pprParendExpr sty expr
+
+    pp_prefixly = ppHang (ppCat [ppStr "( \\ _x ->", ppr sty op])
+                      4 (ppCat [pp_expr, ppStr "_x )"])
+    pp_infixly v
+      = ppSep [ ppBesides [ppLparen, pp_expr],
+               ppBesides [pprOp sty v, ppRparen] ]
+
+pprExpr sty (SectionR op expr)
+  = case op of
+      Var v -> pp_infixly v
+      _            -> pp_prefixly
+  where
+    pp_expr = pprParendExpr sty expr
+
+    pp_prefixly = ppHang (ppCat [ppStr "( \\ _x ->", ppr sty op, ppStr "_x"])
+                      4 (ppBesides [pp_expr, ppRparen])
+    pp_infixly v
+      = ppSep [ ppBesides [ppLparen, pprOp sty v],
+               ppBesides [pp_expr, ppRparen] ]
+
+pprExpr sty (CCall fun args _ is_asm result_ty)
+  = ppHang (if is_asm
+           then ppBesides [ppStr "_casm_ ``", ppPStr fun, ppStr "''"]
+           else ppCat     [ppStr "_ccall_", ppPStr fun])
+        4 (ppSep (map (pprParendExpr sty) args
+               {-++ [ppCat [ppStr "{-", ppr sty result_ty, ppStr "-}"]]-}))
+       -- printing the result type can give reader panics (ToDo: fix)
+
+pprExpr sty (SCC label expr)
+  = ppSep [ ppBesides [ppStr "scc", ppBesides [ppChar '"', ppPStr label, ppChar '"'] ],
+           pprParendExpr sty expr ]
+
+pprExpr sty (Case expr matches)
+  = ppSep [ ppSep [ppStr "case", ppNest 4 (pprExpr sty expr), ppStr "of"],
+           ppNest 2 (pprMatches sty (True, ppNil) matches) ]
+
+pprExpr sty (ListComp expr quals)
+  = ppHang (ppCat [ppStr "[", pprExpr sty expr, ppStr "|"])
+        4 (ppSep [interpp'SP sty quals, ppRbrack])
+
+-- special case: let ... in let ...
+pprExpr sty (Let binds expr@(Let _ _))
+  = ppSep [ppHang (ppStr "let") 2 (ppCat [ppr sty binds, ppStr "in"]),
+          ppr sty expr]
+
+pprExpr sty (Let binds expr)
+  = ppSep [ppHang (ppStr "let") 2 (ppr sty binds),
+          ppHang (ppStr "in")  2 (ppr sty expr)]
+
+pprExpr sty (ExplicitList exprs)
+  = ppBesides [ppLbrack, ppInterleave ppComma (map (pprExpr sty) exprs), ppRbrack]
+pprExpr sty (ExplicitListOut ty exprs)
+  = ppBesides [ ppLbrack, ppInterleave ppComma (map (pprExpr sty) exprs), ppRbrack,
+               case sty of
+                 PprForUser -> ppNil
+                 _ -> ppBesides [ppStr " (", pprUniType sty ty, ppStr ")"] ]
+
+pprExpr sty (ExplicitTuple exprs)
+  = ppBesides [ppLparen, ppInterleave ppComma (map (pprExpr sty) exprs), ppRparen]
+pprExpr sty (ExprWithTySig expr sig)
+  = ppHang (ppBesides [ppLparen, ppNest 2 (pprExpr sty expr), ppStr " ::"])
+        4 (ppBesides [ppr sty sig, ppRparen])
+
+pprExpr sty (If e1 e2 e3)
+  = ppSep [ppCat [ppStr "if", ppNest 2 (pprExpr sty e1), ppStr "then"],
+          ppNest 4 (pprExpr sty e2),
+          ppStr "else",
+          ppNest 4 (pprExpr sty e3)]
+pprExpr sty (ArithSeqIn info)
+    = ppCat [ppLbrack, ppr sty info, ppRbrack]
+pprExpr sty (ArithSeqOut expr info)
+    = case sty of
+       PprForUser ->
+         ppBesides [ppLbrack, ppr sty info, ppRbrack]
+       _          ->
+         ppBesides [ppLbrack, ppLparen, ppr sty expr, ppRparen, ppr sty info, ppRbrack]
+#ifdef DPH
+pprExpr sty (ParallelZF expr pquals)
+  = ppHang (ppCat [ppStr "<<" , pprExpr sty expr , ppStr "|"])
+        4 (ppSep [ppr sty pquals, ppStr ">>"])
+
+pprExpr sty (ExplicitPodIn exprs)
+  = ppBesides [ppStr "<<", ppInterleave ppComma (map (pprExpr sty) exprs) , 
+              ppStr ">>"]
+
+pprExpr sty (ExplicitPodOut ty exprs)
+  = ppBesides [ppStr "(",ppStr "<<",
+              ppInterleave ppComma (map (pprExpr sty) exprs), 
+              ppStr ">>", ppStr " ::" , ppStr "<<" , pprUniType sty ty , 
+              ppStr ">>" , ppStr ")"]
+
+pprExpr sty (ExplicitProcessor exprs expr)
+  = ppBesides [ppStr "(|", ppInterleave ppComma (map (pprExpr sty) exprs) , 
+              ppSemi , pprExpr sty expr, ppStr "|)"]
+
+#endif {- Data Parallel Haskell -}
+
+-- for these translation-introduced things, we don't show them
+-- if style is PprForUser
+
+pprExpr sty (TyLam tyvars expr)
+  = case sty of
+      PprForUser -> pprExpr sty expr
+      _ -> ppHang (ppCat [ppStr "/\\", interppSP sty tyvars, ppStr "->"])
+               4 (pprExpr sty expr)
+
+pprExpr sty (TyApp expr [ty])
+  = case sty of
+      PprForUser -> pprExpr sty expr
+      _ -> ppHang (ppBeside pp_note (pprExpr sty expr)) 4 (pprParendUniType sty ty)
+  where
+    pp_note = ifPprShowAll sty (ppStr "{-TyApp-} ")
+
+pprExpr sty (TyApp expr tys)
+  = case sty of
+      PprForUser -> pprExpr sty expr
+      _ -> ppHang (ppBeside pp_note (pprExpr sty expr))
+               4 (ppBesides [ppLbrack, interpp'SP sty tys, ppRbrack])
+  where
+    pp_note = ifPprShowAll sty (ppStr "{-TyApp-} ")
+
+pprExpr sty (DictLam dictvars expr)
+  = case sty of
+      PprForUser -> pprExpr sty expr
+      _ -> ppHang (ppCat [ppStr "\\{-dict-}", interppSP sty dictvars, ppStr "->"])
+               4 (pprExpr sty expr)
+
+pprExpr sty (DictApp expr [dname])
+  = case sty of
+      PprForUser -> pprExpr sty expr
+      _ -> ppHang (ppBeside pp_note (pprExpr sty expr)) 4 (ppr sty dname)
+  where
+    pp_note = ifPprShowAll sty (ppStr "{-DictApp-} ")
+
+pprExpr sty (DictApp expr dnames)
+  = case sty of
+      PprForUser -> pprExpr sty expr
+      _ -> ppHang (ppBeside pp_note (pprExpr sty expr))
+               4 (ppBesides [ppLbrack, interpp'SP sty dnames, ppRbrack])
+  where
+    pp_note = ifPprShowAll sty (ppStr "{-DictApp-} ")
+
+pprExpr sty (ClassDictLam dicts methods expr)
+  = case sty of
+      PprForUser -> pprExpr sty expr
+      _ -> ppHang (ppCat [ppStr "\\{-classdict-}",
+                  ppBesides [ppLbrack, interppSP sty dicts,   ppRbrack],
+                  ppBesides [ppLbrack, interppSP sty methods, ppRbrack],
+                  ppStr "->"])
+               4 (pprExpr sty expr)
+
+pprExpr sty (Dictionary dictNames methods)
+ = ppSep [ppBesides [ppLparen, ppStr "{-dict-}"],
+         ppBesides [ppLbrack, interpp'SP sty dictNames, ppRbrack],
+         ppBesides [ppLbrack, interpp'SP sty methods,   ppRbrack, ppRparen]]
+
+pprExpr sty (SingleDict dname)
+ = ppCat [ppStr "{-singleDict-}", ppr sty dname]
+\end{code}
+
+Parenthesize unless very simple:
+\begin{code}
+pprParendExpr :: (NamedThing bdee, Outputable bdee, 
+                     NamedThing pat, Outputable pat) =>
+                   PprStyle -> Expr bdee pat -> Pretty
+pprParendExpr sty e@(Var _)            = pprExpr sty e
+pprParendExpr sty e@(Lit _)            = pprExpr sty e
+pprParendExpr sty other_e      = ppBesides [ppLparen, pprExpr sty other_e, ppRparen]
+\end{code}
+
+%************************************************************************
+%*                                                                     *
+\subsection[AbsSyntax-enums-list-comps]{Enumerations and list comprehensions}
+%*                                                                     *
+%************************************************************************
+
+\begin{code}
+data ArithSeqInfo  bdee pat
+  = From           (Expr bdee pat)
+  | FromThen       (Expr bdee pat) (Expr bdee pat)
+  | FromTo         (Expr bdee pat) (Expr bdee pat)
+  | FromThenTo     (Expr bdee pat) (Expr bdee pat) (Expr bdee pat)
+
+type ProtoNameArithSeqInfo          = ArithSeqInfo ProtoName ProtoNamePat
+type RenamedArithSeqInfo = ArithSeqInfo Name RenamedPat
+type TypecheckedArithSeqInfo = ArithSeqInfo Id          TypecheckedPat
+\end{code}
+
+\begin{code}
+instance (NamedThing bdee, Outputable bdee, 
+                  NamedThing pat, Outputable pat) =>
+               Outputable (ArithSeqInfo bdee pat) where
+    ppr sty (From e1)          = ppBesides [ppr sty e1, ppStr " .. "]
+    ppr sty (FromThen e1 e2)   = ppBesides [ppr sty e1, pp'SP, ppr sty e2, ppStr " .. "]
+    ppr sty (FromTo e1 e3)     = ppBesides [ppr sty e1, ppStr " .. ", ppr sty e3]
+    ppr sty (FromThenTo e1 e2 e3)
+      = ppBesides [ppr sty e1, pp'SP, ppr sty e2, ppStr " .. ", ppr sty e3]
+\end{code}
+
+``Qualifiers'' in list comprehensions:
+\begin{code}
+data Qual bdee pat
+  = GeneratorQual  pat (Expr bdee pat)
+  | FilterQual    (Expr bdee pat)
+
+type ProtoNameQual     = Qual ProtoName ProtoNamePat
+type RenamedQual               = Qual Name      RenamedPat
+type TypecheckedQual   = Qual Id        TypecheckedPat
+\end{code}
+
+\begin{code}
+instance (NamedThing bdee, Outputable bdee, 
+            NamedThing pat, Outputable pat) =>
+               Outputable (Qual bdee pat) where
+    ppr sty (GeneratorQual pat expr)
+     = ppCat [ppr sty pat, ppStr "<-", ppr sty expr]
+    ppr sty (FilterQual expr) = ppr sty expr
+\end{code}
+
+%************************************************************************
+%*                                                                     *
+\subsection[AbsSyntax-parallel-quals]{Parallel Qualifiers for ZF expressions}
+%*                                                                     *
+%************************************************************************
+
+\begin{code}
+#ifdef DPH
+data ParQuals var pat
+  = AndParQuals     (ParQuals var pat)
+                   (ParQuals var pat)
+  | DrawnGenIn     [pat]               
+                   pat
+                   (Expr var pat)      -- (|pat1,...,patN;pat|)<<-exp
+
+  | DrawnGenOut            [pat]               -- Same information as processor
+                   [(Expr var pat)]    -- Conversion fn of type t -> Integer
+                   pat                 -- to keep things together :-)
+                   (Expr var pat)      
+  | IndexGen        [(Expr var pat)]
+                   pat
+                   (Expr var pat)      -- (|exp1,...,expN;pat|)<<-exp
+  | ParFilter       (Expr var pat)
+
+type ProtoNameParQuals         = ParQuals ProtoName ProtoNamePat
+type RenamedParQuals           = ParQuals Name RenamedPat
+type TypecheckedParQuals       = ParQuals Id        TypecheckedPat
+
+instance (NamedThing bdee, Outputable bdee, 
+            NamedThing pat, Outputable pat) =>
+               Outputable (ParQuals bdee pat) where
+    ppr sty (AndParQuals quals1 quals2)
+     = ppBesides [ppr sty quals1, pp'SP, ppr sty quals2]
+    ppr sty (DrawnGenIn pats pat expr)
+     = ppCat [ppStr "(|",
+              ppInterleave ppComma (map (ppr sty) pats),
+             ppSemi, ppr sty pat,ppStr "|)",
+             ppStr "<<-", ppr sty expr]
+
+    ppr sty (DrawnGenOut pats convs pat expr)
+     = case sty of
+          PprForUser -> basic_ppr
+          _          -> ppHang basic_ppr 4 exprs_ppr
+     where
+        basic_ppr = ppCat [ppStr "(|",
+                           ppInterleave ppComma (map (ppr sty) pats),
+                          ppSemi, ppr sty pat,ppStr "|)",
+                          ppStr "<<-", ppr sty expr]
+
+        exprs_ppr = ppBesides [ppStr "{- " ,
+                               ppr sty convs,
+                               ppStr " -}"]
+    ppr sty (IndexGen exprs pat expr)
+     = ppCat [ppStr "(|",
+              ppInterleave ppComma (map (pprExpr sty) exprs),
+             ppSemi, ppr sty pat, ppStr "|)",
+             ppStr "<<=", ppr sty expr]
+
+    ppr sty (ParFilter expr) = ppr sty expr
+#endif {-Data Parallel Haskell -}
+\end{code}