summaryrefslogtreecommitdiff
path: root/ghc/compiler/hsSyn/HsExpr.lhs
diff options
context:
space:
mode:
Diffstat (limited to 'ghc/compiler/hsSyn/HsExpr.lhs')
-rw-r--r--ghc/compiler/hsSyn/HsExpr.lhs453
1 files changed, 453 insertions, 0 deletions
diff --git a/ghc/compiler/hsSyn/HsExpr.lhs b/ghc/compiler/hsSyn/HsExpr.lhs
new file mode 100644
index 0000000000..2004ddf329
--- /dev/null
+++ b/ghc/compiler/hsSyn/HsExpr.lhs
@@ -0,0 +1,453 @@
+%
+% (c) The GRASP/AQUA Project, Glasgow University, 1992-1994
+%
+\section[HsExpr]{Abstract Haskell syntax: expressions}
+
+\begin{code}
+#include "HsVersions.h"
+
+module HsExpr where
+
+import Ubiq{-uitous-}
+import HsLoop -- for paranoia checking
+
+-- friends:
+import HsBinds ( HsBinds )
+import HsLit ( HsLit )
+import HsMatches ( pprMatches, pprMatch, Match )
+import HsTypes ( PolyType )
+
+-- others:
+import Id ( DictVar(..), GenId, Id(..) )
+import Outputable
+import PprType ( pprType, pprParendType, GenType{-instance-}, GenTyVar{-instance-} )
+import Pretty
+import PprStyle ( PprStyle(..) )
+import SrcLoc ( SrcLoc )
+import TyVar ( GenTyVar{-instances-} )
+import Usage ( GenUsage{-instance-} )
+import Unique ( Unique{-instances-} )
+import Util ( panic{-ToDo:rm eventually-} )
+\end{code}
+
+%************************************************************************
+%* *
+\subsection{Expressions proper}
+%* *
+%************************************************************************
+
+\begin{code}
+data HsExpr tyvar uvar id pat
+ = HsVar id -- variable
+ | HsLit HsLit -- literal
+ | HsLitOut HsLit -- TRANSLATION
+ (GenType tyvar uvar) -- (with its type)
+
+ | HsLam (Match tyvar uvar id pat) -- lambda
+ | HsApp (HsExpr tyvar uvar id pat) -- application
+ (HsExpr tyvar uvar id pat)
+
+ -- Operator applications and sections.
+ -- NB Bracketed ops such as (+) come out as Vars.
+
+ | OpApp (HsExpr tyvar uvar id pat) -- left operand
+ (HsExpr tyvar uvar id pat) -- operator
+ (HsExpr tyvar uvar id pat) -- right operand
+
+ -- ADR Question? Why is the "op" in a section an expr when it will
+ -- have to be of the form (HsVar 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 (HsExpr tyvar uvar id pat) -- operand
+ (HsExpr tyvar uvar id pat) -- operator
+ | SectionR (HsExpr tyvar uvar id pat) -- operator
+ (HsExpr tyvar uvar id pat) -- operand
+
+
+ | HsCase (HsExpr tyvar uvar id pat)
+ [Match tyvar uvar id pat] -- must have at least one Match
+ SrcLoc
+
+ | HsIf (HsExpr tyvar uvar id pat) -- predicate
+ (HsExpr tyvar uvar id pat) -- then part
+ (HsExpr tyvar uvar id pat) -- else part
+ SrcLoc
+
+ | HsLet (HsBinds tyvar uvar id pat) -- let(rec)
+ (HsExpr tyvar uvar id pat)
+
+ | HsDo [Stmt tyvar uvar id pat] -- "do":one or more stmts
+ SrcLoc
+
+ | HsDoOut [Stmt tyvar uvar id pat] -- "do":one or more stmts
+ id id -- Monad and MonadZero dicts
+ SrcLoc
+
+ | ListComp (HsExpr tyvar uvar id pat) -- list comprehension
+ [Qual tyvar uvar id pat] -- at least one Qual(ifier)
+
+ | ExplicitList -- syntactic list
+ [HsExpr tyvar uvar id pat]
+ | ExplicitListOut -- TRANSLATION
+ (GenType tyvar uvar) -- Gives type of components of list
+ [HsExpr tyvar uvar id pat]
+
+ | ExplicitTuple -- tuple
+ [HsExpr tyvar uvar id pat]
+ -- NB: Unit is ExplicitTuple []
+ -- for tuples, we can get the types
+ -- direct from the components
+
+ | RecordCon id -- record construction
+ [(id, Maybe (HsExpr tyvar uvar id pat))]
+
+ | RecordUpd (HsExpr tyvar uvar id pat) -- record update
+ [(id, Maybe (HsExpr tyvar uvar id pat))]
+
+ | ExprWithTySig -- signature binding
+ (HsExpr tyvar uvar id pat)
+ (PolyType id)
+ | ArithSeqIn -- arithmetic sequence
+ (ArithSeqInfo tyvar uvar id pat)
+ | ArithSeqOut
+ (HsExpr tyvar uvar id pat) -- (typechecked, of course)
+ (ArithSeqInfo tyvar uvar id pat)
+
+ | CCall FAST_STRING -- call into the C world; string is
+ [HsExpr tyvar uvar id 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#".
+ (GenType tyvar uvar) -- The result type; will be *bottom*
+ -- until the typechecker gets ahold of it
+
+ | HsSCC FAST_STRING -- "set cost centre" (_scc_) annotation
+ (HsExpr tyvar uvar id pat) -- expr whose cost is to be measured
+\end{code}
+
+Everything from here on appears only in typechecker output.
+
+\begin{code}
+ | TyLam -- TRANSLATION
+ [tyvar]
+ (HsExpr tyvar uvar id pat)
+ | TyApp -- TRANSLATION
+ (HsExpr tyvar uvar id pat) -- generated by Spec
+ [GenType tyvar uvar]
+
+ -- DictLam and DictApp are "inverses"
+ | DictLam
+ [id]
+ (HsExpr tyvar uvar id pat)
+ | DictApp
+ (HsExpr tyvar uvar id pat)
+ [id]
+
+ -- ClassDictLam and Dictionary are "inverses" (see note below)
+ | ClassDictLam
+ [id] -- superclass dicts
+ [id] -- methods
+ (HsExpr tyvar uvar id pat)
+ | Dictionary
+ [id] -- superclass dicts
+ [id] -- methods
+
+ | SingleDict -- a simple special case of Dictionary
+ id -- local dictionary name
+\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 id, Outputable id, Outputable pat,
+ Eq tyvar, Outputable tyvar, Eq uvar, Outputable uvar) =>
+ Outputable (HsExpr tyvar uvar id pat) where
+ ppr = pprExpr
+\end{code}
+
+\begin{code}
+pprExpr sty (HsVar v)
+ = (if (isOpLexeme v) then ppParens else id) (ppr sty v)
+
+pprExpr sty (HsLit lit) = ppr sty lit
+pprExpr sty (HsLitOut lit _) = ppr sty lit
+
+pprExpr sty (HsLam match)
+ = ppCat [ppStr "\\", ppNest 2 (pprMatch sty True match)]
+
+pprExpr sty expr@(HsApp e1 e2)
+ = let (fun, args) = collect_args expr [] in
+ ppHang (pprParendExpr sty fun) 4 (ppSep (map (pprParendExpr sty) args))
+ where
+ collect_args (HsApp fun arg) args = collect_args fun (arg:args)
+ collect_args fun args = (fun, args)
+
+pprExpr sty (OpApp e1 op e2)
+ = case op of
+ HsVar 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
+ HsVar 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 [ ppBeside ppLparen pp_expr,
+ ppBeside (pprOp sty v) ppRparen ]
+
+pprExpr sty (SectionR op expr)
+ = case op of
+ HsVar v -> pp_infixly v
+ _ -> pp_prefixly
+ where
+ pp_expr = pprParendExpr sty expr
+
+ pp_prefixly = ppHang (ppCat [ppStr "( \\ _x ->", ppr sty op, ppPStr SLIT("_x")])
+ 4 (ppBeside pp_expr ppRparen)
+ pp_infixly v
+ = ppSep [ ppBeside ppLparen (pprOp sty v),
+ ppBeside pp_expr ppRparen ]
+
+pprExpr sty (CCall fun args _ is_asm result_ty)
+ = ppHang (if is_asm
+ then ppBesides [ppStr "_casm_ ``", ppPStr fun, ppStr "''"]
+ else ppBeside (ppPStr SLIT("_ccall_ ")) (ppPStr fun))
+ 4 (ppSep (map (pprParendExpr sty) args))
+
+pprExpr sty (HsSCC label expr)
+ = ppSep [ ppBeside (ppPStr SLIT("_scc_ ")) (ppBesides [ppChar '"', ppPStr label, ppChar '"']),
+ pprParendExpr sty expr ]
+
+pprExpr sty (HsCase expr matches _)
+ = ppSep [ ppSep [ppPStr SLIT("case"), ppNest 4 (pprExpr sty expr), ppPStr SLIT("of")],
+ ppNest 2 (pprMatches sty (True, ppNil) matches) ]
+
+pprExpr sty (ListComp expr quals)
+ = ppHang (ppCat [ppLbrack, pprExpr sty expr, ppChar '|'])
+ 4 (ppSep [interpp'SP sty quals, ppRbrack])
+
+-- special case: let ... in let ...
+pprExpr sty (HsLet binds expr@(HsLet _ _))
+ = ppSep [ppHang (ppPStr SLIT("let")) 2 (ppCat [ppr sty binds, ppPStr SLIT("in")]),
+ ppr sty expr]
+
+pprExpr sty (HsLet binds expr)
+ = ppSep [ppHang (ppPStr SLIT("let")) 2 (ppr sty binds),
+ ppHang (ppPStr SLIT("in")) 2 (ppr sty expr)]
+
+pprExpr sty (HsDo stmts _)
+ = ppCat [ppPStr SLIT("do"), ppAboves (map (ppr sty) stmts)]
+
+pprExpr sty (HsIf e1 e2 e3 _)
+ = ppSep [ppCat [ppPStr SLIT("if"), ppNest 2 (pprExpr sty e1), ppPStr SLIT("then")],
+ ppNest 4 (pprExpr sty e2),
+ ppPStr SLIT("else"),
+ ppNest 4 (pprExpr sty e3)]
+
+pprExpr sty (ExplicitList exprs)
+ = ppBracket (ppInterleave ppComma (map (pprExpr sty) exprs))
+pprExpr sty (ExplicitListOut ty exprs)
+ = ppBesides [ ppBracket (ppInterleave ppComma (map (pprExpr sty) exprs)),
+ ifnotPprForUser sty (ppBeside ppSP (ppParens (pprType sty ty))) ]
+
+pprExpr sty (ExplicitTuple exprs)
+ = ppParens (ppInterleave ppComma (map (pprExpr sty) exprs))
+pprExpr sty (ExprWithTySig expr sig)
+ = ppHang (ppBesides [ppLparen, ppNest 2 (pprExpr sty expr), ppPStr SLIT(" ::")])
+ 4 (ppBeside (ppr sty sig) ppRparen)
+
+pprExpr sty (RecordCon con rbinds)
+ = pp_rbinds sty (ppr sty con) rbinds
+
+pprExpr sty (RecordUpd aexp rbinds)
+ = pp_rbinds sty (pprParendExpr sty aexp) rbinds
+
+pprExpr sty (ArithSeqIn info)
+ = ppBracket (ppr sty info)
+pprExpr sty (ArithSeqOut expr info)
+ = case sty of
+ PprForUser ->
+ ppBracket (ppr sty info)
+ _ ->
+ ppBesides [ppLbrack, ppParens (ppr sty expr), ppr sty info, ppRbrack]
+
+pprExpr sty (TyLam tyvars expr)
+ = ppHang (ppCat [ppStr "/\\", interppSP sty tyvars, ppStr "->"])
+ 4 (pprExpr sty expr)
+
+pprExpr sty (TyApp expr [ty])
+ = ppHang (pprExpr sty expr) 4 (pprParendType sty ty)
+
+pprExpr sty (TyApp expr tys)
+ = ppHang (pprExpr sty expr)
+ 4 (ppBracket (interpp'SP sty tys))
+
+pprExpr sty (DictLam dictvars expr)
+ = ppHang (ppCat [ppStr "\\{-dict-}", interppSP sty dictvars, ppStr "->"])
+ 4 (pprExpr sty expr)
+
+pprExpr sty (DictApp expr [dname])
+ = ppHang (pprExpr sty expr) 4 (ppr sty dname)
+
+pprExpr sty (DictApp expr dnames)
+ = ppHang (pprExpr sty expr)
+ 4 (ppBracket (interpp'SP sty dnames))
+
+pprExpr sty (ClassDictLam dicts methods expr)
+ = ppHang (ppCat [ppStr "\\{-classdict-}",
+ ppBracket (interppSP sty dicts),
+ ppBracket (interppSP sty methods),
+ ppStr "->"])
+ 4 (pprExpr sty expr)
+
+pprExpr sty (Dictionary dicts methods)
+ = ppSep [ppBesides [ppLparen, ppPStr SLIT("{-dict-}")],
+ ppBracket (interpp'SP sty dicts),
+ ppBesides [ppBracket (interpp'SP sty methods), ppRparen]]
+
+pprExpr sty (SingleDict dname)
+ = ppCat [ppPStr SLIT("{-singleDict-}"), ppr sty dname]
+\end{code}
+
+Parenthesize unless very simple:
+\begin{code}
+pprParendExpr :: (NamedThing id, Outputable id, Outputable pat,
+ Eq tyvar, Outputable tyvar, Eq uvar, Outputable uvar)
+ => PprStyle -> HsExpr tyvar uvar id pat -> Pretty
+
+pprParendExpr sty expr
+ = let
+ pp_as_was = pprExpr sty expr
+ in
+ case expr of
+ HsLit l -> ppr sty l
+ HsLitOut l _ -> ppr sty l
+ HsVar _ -> pp_as_was
+ ExplicitList _ -> pp_as_was
+ ExplicitListOut _ _ -> pp_as_was
+ ExplicitTuple _ -> pp_as_was
+ _ -> ppParens pp_as_was
+\end{code}
+
+%************************************************************************
+%* *
+\subsection{Record binds}
+%* *
+%************************************************************************
+
+\begin{code}
+pp_rbinds sty thing rbinds
+ = ppHang thing 4
+ (ppBesides [ppChar '{', ppInterleave ppComma (map (pp_rbind sty) rbinds), ppChar '}'])
+
+pp_rbind :: (NamedThing id, Outputable id, Outputable pat,
+ Eq tyvar, Outputable tyvar, Eq uvar, Outputable uvar)
+ => PprStyle -> (id, Maybe (HsExpr tyvar uvar id pat)) -> Pretty
+
+pp_rbind sty (v, Nothing) = ppr sty v
+pp_rbind sty (v, Just e) = ppCat [ppr sty v, ppStr "<-", ppr sty e]
+\end{code}
+
+%************************************************************************
+%* *
+\subsection{Do stmts}
+%* *
+%************************************************************************
+
+\begin{code}
+data Stmt tyvar uvar id pat
+ = BindStmt pat
+ (HsExpr tyvar uvar id pat)
+ SrcLoc
+ | ExprStmt (HsExpr tyvar uvar id pat)
+ SrcLoc
+ | LetStmt (HsBinds tyvar uvar id pat)
+\end{code}
+
+\begin{code}
+instance (NamedThing id, Outputable id, Outputable pat,
+ Eq tyvar, Outputable tyvar, Eq uvar, Outputable uvar) =>
+ Outputable (Stmt tyvar uvar id pat) where
+ ppr sty (BindStmt pat expr _)
+ = ppCat [ppr sty pat, ppStr "<-", ppr sty expr]
+ ppr sty (LetStmt binds)
+ = ppCat [ppPStr SLIT("let"), ppr sty binds]
+ ppr sty (ExprStmt expr _)
+ = ppr sty expr
+\end{code}
+
+%************************************************************************
+%* *
+\subsection{Enumerations and list comprehensions}
+%* *
+%************************************************************************
+
+\begin{code}
+data ArithSeqInfo tyvar uvar id pat
+ = From (HsExpr tyvar uvar id pat)
+ | FromThen (HsExpr tyvar uvar id pat)
+ (HsExpr tyvar uvar id pat)
+ | FromTo (HsExpr tyvar uvar id pat)
+ (HsExpr tyvar uvar id pat)
+ | FromThenTo (HsExpr tyvar uvar id pat)
+ (HsExpr tyvar uvar id pat)
+ (HsExpr tyvar uvar id pat)
+\end{code}
+
+\begin{code}
+instance (NamedThing id, Outputable id, Outputable pat,
+ Eq tyvar, Outputable tyvar, Eq uvar, Outputable uvar) =>
+ Outputable (ArithSeqInfo tyvar uvar id pat) where
+ ppr sty (From e1) = ppBesides [ppr sty e1, pp_dotdot]
+ ppr sty (FromThen e1 e2) = ppBesides [ppr sty e1, pp'SP, ppr sty e2, pp_dotdot]
+ ppr sty (FromTo e1 e3) = ppBesides [ppr sty e1, pp_dotdot, ppr sty e3]
+ ppr sty (FromThenTo e1 e2 e3)
+ = ppBesides [ppr sty e1, pp'SP, ppr sty e2, pp_dotdot, ppr sty e3]
+
+pp_dotdot = ppPStr SLIT(" .. ")
+\end{code}
+
+``Qualifiers'' in list comprehensions:
+\begin{code}
+data Qual tyvar uvar id pat
+ = GeneratorQual pat
+ (HsExpr tyvar uvar id pat)
+ | LetQual (HsBinds tyvar uvar id pat)
+ | FilterQual (HsExpr tyvar uvar id pat)
+\end{code}
+
+\begin{code}
+instance (NamedThing id, Outputable id, Outputable pat,
+ Eq tyvar, Outputable tyvar, Eq uvar, Outputable uvar) =>
+ Outputable (Qual tyvar uvar id pat) where
+ ppr sty (GeneratorQual pat expr)
+ = ppCat [ppr sty pat, ppStr "<-", ppr sty expr]
+ ppr sty (LetQual binds)
+ = ppCat [ppPStr SLIT("let"), ppr sty binds]
+ ppr sty (FilterQual expr)
+ = ppr sty expr
+\end{code}