summaryrefslogtreecommitdiff
path: root/ghc/compiler/coreSyn/PprCore.lhs
blob: e77cac841fea5f04c09100fe60d645b989251c9e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
%
% (c) The AQUA Project, Glasgow University, 1996-1998
%
%************************************************************************
%*									*
\section[PprCore]{Printing of Core syntax, including for interfaces}
%*									*
%************************************************************************

\begin{code}
module PprCore (
	pprCoreExpr, pprParendExpr,
	pprCoreBinding, pprCoreBindings, pprIdBndr,
	pprCoreBinding, pprCoreBindings, pprCoreAlt,
	pprCoreRules, pprCoreRule, pprIdCoreRule
    ) where

#include "HsVersions.h"

import CoreSyn
import CostCentre	( pprCostCentreCore )
import Id		( Id, idType, isDataConId_maybe, idLBVarInfo, idArity,
			  idInfo, idInlinePragma, idOccInfo,
#ifdef OLD_STRICTNESS
			  idDemandInfo, 
#endif
			  globalIdDetails, isGlobalId, isExportedId, 
			  isSpecPragmaId, idNewDemandInfo
			)
import Var		( isTyVar )
import IdInfo		( IdInfo, megaSeqIdInfo, 
			  arityInfo, ppArityInfo, 
			  specInfo, ppStrictnessInfo, 
			  workerInfo, ppWorkerInfo,
                          tyGenInfo, ppTyGenInfo,
			  newStrictnessInfo,
#ifdef OLD_STRICTNESS
			  cprInfo, ppCprInfo, 
			  strictnessInfo,
#endif
			)
import DataCon		( dataConTyCon )
import TyCon		( tupleTyConBoxity, isTupleTyCon )
import PprType		( pprParendType, pprTyVarBndr )
import BasicTypes	( tupleParens )
import PprEnv
import Util             ( lengthIs )
import Outputable
\end{code}

%************************************************************************
%*									*
\subsection{Public interfaces for Core printing (excluding instances)}
%*									*
%************************************************************************

@pprCoreBinding@ and @pprCoreExpr@ let you give special printing
function for ``major'' val_bdrs (those next to equal signs :-),
``minor'' ones (lambda-bound, case-bound), and bindees.  They would
usually be called through some intermediary.

The binder/occ printers take the default ``homogenized'' (see
@PprEnv@...) @Doc@ and the binder/occ.  They can either use the
homogenized one, or they can ignore it completely.  In other words,
the things passed in act as ``hooks'', getting the last word on how to
print something.

@pprParendCoreExpr@ puts parens around non-atomic Core expressions.

Un-annotated core dumps
~~~~~~~~~~~~~~~~~~~~~~~
\begin{code}
pprCoreBindings :: [CoreBind] -> SDoc
pprCoreBinding  :: CoreBind   -> SDoc
pprCoreExpr     :: CoreExpr   -> SDoc
pprParendExpr   :: CoreExpr   -> SDoc

pprCoreBindings = pprTopBinds pprCoreEnv
pprCoreBinding  = pprTopBind pprCoreEnv
pprCoreExpr     = ppr_noparend_expr pprCoreEnv
pprParendExpr   = ppr_parend_expr   pprCoreEnv
pprArg 	        = ppr_arg pprCoreEnv
pprCoreAlt      = ppr_alt pprCoreEnv

pprCoreEnv = initCoreEnv pprCoreBinder
\end{code}

Printer for unfoldings in interfaces
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\begin{code}
instance Outputable b => Outputable (Bind b) where
    ppr bind = ppr_bind pprGenericEnv bind

instance Outputable b => Outputable (Expr b) where
    ppr expr = ppr_noparend_expr pprGenericEnv expr

pprGenericEnv :: Outputable b => PprEnv b
pprGenericEnv = initCoreEnv (\site -> ppr)
\end{code}

%************************************************************************
%*									*
\subsection{Instance declarations for Core printing}
%*									*
%************************************************************************


\begin{code}
initCoreEnv pbdr
  = initPprEnv
	(Just pprCostCentreCore)	-- Cost centres

	(Just ppr) 		-- tyvar occs
	(Just pprParendType)    -- types

	(Just pbdr) (Just ppr) -- value vars
	-- Use pprIdBndr for this last one as a debugging device.
\end{code}

%************************************************************************
%*									*
\subsection{The guts}
%*									*
%************************************************************************

\begin{code}
pprTopBinds pe binds = vcat (map (pprTopBind pe) binds)

pprTopBind pe (NonRec binder expr)
 = ppr_binding_pe pe (binder,expr) $$ text ""

pprTopBind pe (Rec binds)
  = vcat [ptext SLIT("Rec {"),
	  vcat (map (ppr_binding_pe pe) binds),
	  ptext SLIT("end Rec }"),
	  text ""]
\end{code}

\begin{code}
ppr_bind :: PprEnv b -> Bind b -> SDoc

ppr_bind pe (NonRec val_bdr expr) = ppr_binding_pe pe (val_bdr, expr)
ppr_bind pe (Rec binds)  	  = vcat (map pp binds)
				  where
				    pp bind = ppr_binding_pe pe bind <> semi

ppr_binding_pe :: PprEnv b -> (b, Expr b) -> SDoc
ppr_binding_pe pe (val_bdr, expr)
  = sep [pBndr pe LetBind val_bdr, 
	 nest 2 (equals <+> ppr_noparend_expr pe expr)]
\end{code}

\begin{code}
ppr_parend_expr   pe expr = ppr_expr parens pe expr
ppr_noparend_expr pe expr = ppr_expr noParens pe expr

noParens :: SDoc -> SDoc
noParens pp = pp
\end{code}

\begin{code}
ppr_expr :: (SDoc -> SDoc) -> PprEnv b -> Expr b -> SDoc
	-- The function adds parens in context that need
	-- an atomic value (e.g. function args)

ppr_expr add_par pe (Type ty)  = add_par (ptext SLIT("TYPE") <+> ppr ty)	-- Wierd
	           
ppr_expr add_par pe (Var name) = pOcc pe name
ppr_expr add_par pe (Lit lit)  = ppr lit

ppr_expr add_par pe expr@(Lam _ _)
  = let
	(bndrs, body) = collectBinders expr
    in
    add_par $
    hang (ptext SLIT("\\") <+> sep (map (pBndr pe LambdaBind) bndrs) <+> arrow)
	 2 (ppr_noparend_expr pe body)

ppr_expr add_par pe expr@(App fun arg)
  = case collectArgs expr of { (fun, args) -> 
    let
	pp_args     = sep (map (ppr_arg pe) args)
	val_args    = dropWhile isTypeArg args	 -- Drop the type arguments for tuples
	pp_tup_args = sep (punctuate comma (map (ppr_arg pe) val_args))
    in
    case fun of
	Var f -> case isDataConId_maybe f of
			-- Notice that we print the *worker*
			-- for tuples in paren'd format.
		   Just dc | saturated && isTupleTyCon tc
			   -> tupleParens (tupleTyConBoxity tc) pp_tup_args
			   where
			     tc	       = dataConTyCon dc
			     saturated = val_args `lengthIs` idArity f

		   other -> add_par (hang (pOcc pe f) 2 pp_args)

	other -> add_par (hang (ppr_parend_expr pe fun) 2 pp_args)
    }

ppr_expr add_par pe (Case expr var [(con,args,rhs)])
  = add_par $
    sep [sep [ptext SLIT("case") <+> ppr_noparend_expr pe expr,
	      hsep [ptext SLIT("of"),
		    ppr_bndr var,
		    char '{',
		    ppr_case_pat pe con args
	  ]],
	 ppr_noparend_expr pe rhs,
	 char '}'
    ]
  where
    ppr_bndr = pBndr pe CaseBind

ppr_expr add_par pe (Case expr var alts)
  = add_par $
    sep [sep [ptext SLIT("case") <+> ppr_noparend_expr pe expr,
	      ptext SLIT("of") <+> ppr_bndr var <+> char '{'],
	 nest 2 (sep (punctuate semi (map (ppr_alt pe) alts))),
	 char '}'
    ]
  where
    ppr_bndr = pBndr pe CaseBind
 

-- special cases: let ... in let ...
-- ("disgusting" SLPJ)

ppr_expr add_par pe (Let bind@(NonRec val_bdr rhs@(Let _ _)) body)
  = add_par $
    vcat [
      hsep [ptext SLIT("let {"), pBndr pe LetBind val_bdr, equals],
      nest 2 (ppr_noparend_expr pe rhs),
      ptext SLIT("} in"),
      ppr_noparend_expr pe body ]

ppr_expr add_par pe (Let bind@(NonRec val_bdr rhs) expr@(Let _ _))
  = add_par
    (hang (ptext SLIT("let {"))
	  2 (hsep [hang (hsep [pBndr pe LetBind val_bdr, equals])
			   2 (ppr_noparend_expr pe rhs),
       ptext SLIT("} in")])
     $$
     ppr_noparend_expr pe expr)

-- general case (recursive case, too)
ppr_expr add_par pe (Let bind expr)
  = add_par $
    sep [hang (ptext keyword) 2 (ppr_bind pe bind),
	 hang (ptext SLIT("} in ")) 2 (ppr_noparend_expr pe expr)]
  where
    keyword = case bind of
		Rec _      -> SLIT("__letrec {")
		NonRec _ _ -> SLIT("let {")

ppr_expr add_par pe (Note (SCC cc) expr)
  = add_par (sep [pSCC pe cc, ppr_noparend_expr pe expr])

#ifdef DEBUG
ppr_expr add_par pe (Note (Coerce to_ty from_ty) expr)
 = add_par $
   getPprStyle $ \ sty ->
   if debugStyle sty then
      sep [ptext SLIT("__coerce") <+> sep [pTy pe to_ty, pTy pe from_ty],
	   ppr_parend_expr pe expr]
   else
      sep [hsep [ptext SLIT("__coerce"), pTy pe to_ty],
	          ppr_parend_expr pe expr]
#else
ppr_expr add_par pe (Note (Coerce to_ty from_ty) expr)
  = add_par $
    sep [sep [ptext SLIT("__coerce"), nest 2 (pTy pe to_ty)],
	 ppr_parend_expr pe expr]
#endif

ppr_expr add_par pe (Note InlineCall expr)
  = add_par (ptext SLIT("__inline_call") <+> ppr_parend_expr pe expr)

ppr_expr add_par pe (Note InlineMe expr)
  = add_par $ ptext SLIT("__inline_me") <+> ppr_parend_expr pe expr

ppr_alt pe (con, args, rhs) 
  = hang (ppr_case_pat pe con args) 2 (ppr_noparend_expr pe rhs)

ppr_case_pat pe con@(DataAlt dc) args
  | isTupleTyCon tc
  = tupleParens (tupleTyConBoxity tc) (hsep (punctuate comma (map ppr_bndr args))) <+> arrow
  where
    ppr_bndr = pBndr pe CaseBind
    tc = dataConTyCon dc

ppr_case_pat pe con args
  = ppr con <+> hsep (map ppr_bndr args) <+> arrow
  where
    ppr_bndr = pBndr pe CaseBind

ppr_arg pe (Type ty) = ptext SLIT("@") <+> pTy pe ty
ppr_arg pe expr      = ppr_parend_expr pe expr

arrow = ptext SLIT("->")
\end{code}

Other printing bits-and-bobs used with the general @pprCoreBinding@
and @pprCoreExpr@ functions.

\begin{code}
-- Used for printing dump info
pprCoreBinder LetBind binder
  = vcat [sig, pprIdDetails binder, pragmas, ppr binder]
  where
    sig     = pprTypedBinder binder
    pragmas = ppIdInfo binder (idInfo binder)

-- Lambda bound type variables are preceded by "@"
pprCoreBinder LambdaBind bndr = pprTypedBinder bndr

-- Case bound things don't get a signature or a herald
pprCoreBinder CaseBind bndr = pprUntypedBinder bndr

pprUntypedBinder binder
  | isTyVar binder = ptext SLIT("@") <+> ppr binder	-- NB: don't print kind
  | otherwise      = pprIdBndr binder

pprTypedBinder binder
  | isTyVar binder  = ptext SLIT("@") <+> pprTyVarBndr binder
  | otherwise	    = pprIdBndr binder <+> dcolon <+> pprParendType (idType binder)
	-- The space before the :: is important; it helps the lexer
	-- when reading inferfaces.  Otherwise it would lex "a::b" as one thing.
	--
	-- It's important that the type is parenthesised too, at least when
	-- printing interfaces, because we get \ x::(a->b) y::(c->d) -> ...

-- pprIdBndr does *not* print the type
-- When printing any Id binder in debug mode, we print its inline pragma and one-shot-ness
pprIdBndr id = ppr id <+> 
	       (megaSeqIdInfo (idInfo id) `seq`
			-- Useful for poking on black holes
	        ifPprDebug (ppr (idInlinePragma id) <+> ppr (idOccInfo id) <+> 
#ifdef OLD_STRICTNESS
			    ppr (idDemandInfo id) <+>
#endif
			    ppr (idNewDemandInfo id) <+>
			    ppr (idLBVarInfo id)))
\end{code}


\begin{code}
pprIdDetails :: Id -> SDoc
pprIdDetails id | isGlobalId id     = ppr (globalIdDetails id)
		| isExportedId id   = ptext SLIT("[Exported]")
		| isSpecPragmaId id = ptext SLIT("[SpecPrag]")
		| otherwise	    = empty

ppIdInfo :: Id -> IdInfo -> SDoc
ppIdInfo b info
  = hsep [  ppArityInfo a,
            ppTyGenInfo g,
	    ppWorkerInfo (workerInfo info),
#ifdef OLD_STRICTNESS
	    ppStrictnessInfo s,
            ppCprInfo m,
#endif
	    ppr (newStrictnessInfo info),
	    pprCoreRules b p
	-- Inline pragma, occ, demand, lbvar info
	-- printed out with all binders (when debug is on); 
	-- see PprCore.pprIdBndr
	]
  where
    a = arityInfo info
    g = tyGenInfo info
#ifdef OLD_STRICTNESS
    s = strictnessInfo info
    m = cprInfo info
#endif
    p = specInfo info
\end{code}


\begin{code}
pprCoreRules :: Id -> CoreRules -> SDoc
pprCoreRules var (Rules rules _) = vcat (map (pprCoreRule (ppr var)) rules)

pprIdCoreRule :: IdCoreRule -> SDoc
pprIdCoreRule (id,rule) = pprCoreRule (ppr id) rule

pprCoreRule :: SDoc -> CoreRule -> SDoc
pprCoreRule pp_fn (BuiltinRule name _)
  = ifPprDebug (ptext SLIT("Built in rule for") <+> pp_fn <> colon <+> doubleQuotes (ptext name))

pprCoreRule pp_fn (Rule name act tpl_vars tpl_args rhs)
  = doubleQuotes (ptext name) <+> ppr act <+>
    sep [
	  ptext SLIT("__forall") <+> braces (sep (map pprTypedBinder tpl_vars)),
	  nest 2 (pp_fn <+> sep (map pprArg tpl_args)),
	  nest 2 (ptext SLIT("=") <+> pprCoreExpr rhs)
    ] <+> semi
\end{code}