summaryrefslogtreecommitdiff
path: root/ghc/compiler/hsSyn/HsExpr.lhs
blob: 936c61225a3e9366ec39621711eca661203e8320 (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
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
%
% (c) The GRASP/AQUA Project, Glasgow University, 1992-1994
%
\section[HsExpr]{Abstract Haskell syntax: expressions}

\begin{code}
#include "HsVersions.h"

module HsExpr where

IMP_Ubiq(){-uitous-}
IMPORT_DELOOPER(HsLoop) -- for paranoia checking

-- friends:
import HsBinds		( HsBinds )
import HsBasic		( HsLit, Fixity(..), FixityDirection(..) )
import HsMatches	( pprMatches, pprMatch, Match )
import HsTypes		( HsType )

-- others:
import Id		( SYN_IE(DictVar), GenId, SYN_IE(Id) )
import Name		( pprNonSym, pprSym )
import Outputable	( interppSP, interpp'SP, ifnotPprForUser )
import PprType		( pprGenType, pprParendGenType, GenType{-instance-} )
import Pretty
import PprStyle		( PprStyle(..) )
import SrcLoc		( SrcLoc )
import Usage		( GenUsage{-instance-} )
--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:
  -- NB Bracketed ops such as (+) come out as Vars.

  -- NB We need an expr for the operator in an OpApp/Section since
  -- the typechecker may need to apply the operator to a few types.

  | OpApp	(HsExpr tyvar uvar id pat)	-- left operand
		(HsExpr tyvar uvar id pat)	-- operator
		Fixity				-- Renamer adds fixity; bottom until then
		(HsExpr tyvar uvar id pat)	-- right operand

  -- We preserve prefix negation and parenthesis for the precedence parser.
  -- They are eventually removed by the type checker.

  | NegApp	(HsExpr tyvar uvar id pat)	-- negated expr
		(HsExpr tyvar uvar id pat)	-- the negate id (in a HsVar)

  | HsPar	(HsExpr tyvar uvar id pat)	-- parenthesised expr

  | 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	DoOrListComp
		[Stmt tyvar uvar id pat]	-- "do":one or more stmts
		SrcLoc

  | HsDoOut	DoOrListComp
		[Stmt   tyvar uvar id pat]	-- "do":one or more stmts
		id				-- id for return
		id				-- id for >>=
		id				-- id for zero
		(GenType tyvar uvar)		-- Type of the whole expression
		SrcLoc

  | 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

	-- Record construction
  | RecordCon	(HsExpr tyvar uvar id pat)	-- Always (HsVar id) until type checker,
						-- but the latter adds its type args too
		(HsRecordBinds tyvar uvar id pat)

	-- Record update
  | RecordUpd	(HsExpr tyvar uvar id pat)
		(HsRecordBinds tyvar uvar id pat)

  | RecordUpdOut (HsExpr tyvar uvar id pat)	-- TRANSLATION
		 [id]				-- Dicts needed for construction
		 (HsRecordBinds tyvar uvar id pat)

  | ExprWithTySig		-- signature binding
		(HsExpr tyvar uvar id pat)
		(HsType 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

type HsRecordBinds tyvar uvar id pat
  = [(id, HsExpr tyvar uvar id pat, Bool)]
	-- True <=> source code used "punning",
	-- i.e. {op1, op2} rather than {op1=e1, op2=e2}
\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) = ppr sty v

pprExpr sty (HsLit    lit)   = ppr sty lit
pprExpr sty (HsLitOut lit _) = ppr sty lit

pprExpr sty (HsLam match)
  = ppCat [ppChar '\\', ppNest 2 (pprMatch sty True match)]

pprExpr sty expr@(HsApp e1 e2)
  = let (fun, args) = collect_args expr [] in
    ppHang (pprExpr sty fun) 4 (ppSep (map (pprExpr 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 fixity e2)
  = case op of
      HsVar v -> pp_infixly v
      _	      -> pp_prefixly
  where
    pp_e1 = pprParendExpr sty e1		-- Add parens to make precedence clear
    pp_e2 = pprParendExpr sty e2

    pp_prefixly
      = ppHang (pprExpr sty op) 4 (ppSep [pp_e1, pp_e2])

    pp_infixly v
      = ppSep [pp_e1, ppCat [ppr sty v, pp_e2]]

pprExpr sty (NegApp e _)
  = ppBeside (ppChar '-') (pprParendExpr sty e)

pprExpr sty (HsPar e)
  = ppParens (pprExpr sty e)

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, ppPStr SLIT("x_ )")])
    pp_infixly v
      = ppSep [ ppBeside ppLparen pp_expr,
	    	ppBeside (ppr 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 (ppr sty v),
		ppBeside pp_expr  ppRparen ]

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 (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)]

-- 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 do_or_list_comp stmts _)            = pprDo do_or_list_comp sty stmts
pprExpr sty (HsDoOut do_or_list_comp stmts _ _ _ _ _) = pprDo do_or_list_comp sty stmts

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 (pprGenType sty ty))) ]

pprExpr sty (ExplicitTuple exprs)
  = ppParens (ppInterleave ppComma (map (pprExpr sty) exprs))

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 (RecordUpdOut aexp _ rbinds)
  = pp_rbinds sty (pprParendExpr sty aexp) rbinds

pprExpr sty (ExprWithTySig expr sig)
  = ppHang (ppBeside (ppNest 2 (pprExpr sty expr)) (ppPStr SLIT(" ::")))
	 4 (ppr sty sig)

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), ppSP, ppr sty info, ppRbrack]

pprExpr sty (CCall fun args _ is_asm result_ty)
  = ppHang (if is_asm
	    then ppBesides [ppPStr SLIT("_casm_ ``"), ppPStr fun, ppPStr SLIT("''")]
	    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 (TyLam tyvars expr)
  = ppHang (ppCat [ppPStr SLIT("/\\"), interppSP sty tyvars, ppPStr SLIT("->")])
	 4 (pprExpr sty expr)

pprExpr sty (TyApp expr [ty])
  = ppHang (pprExpr sty expr) 4 (pprParendGenType sty ty)

pprExpr sty (TyApp expr tys)
  = ppHang (pprExpr sty expr)
	 4 (ppBracket (interpp'SP sty tys))

pprExpr sty (DictLam dictvars expr)
  = ppHang (ppCat [ppPStr SLIT("\\{-dict-}"), interppSP sty dictvars, ppPStr SLIT("->")])
	 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 [ppPStr SLIT("\\{-classdict-}"),
		   ppBracket (interppSP sty dicts),
		   ppBracket (interppSP sty methods),
		   ppPStr SLIT("->")])
	 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
      HsPar _		    -> pp_as_was

      _			    -> ppParens pp_as_was
\end{code}

%************************************************************************
%*									*
\subsection{Record binds}
%*									*
%************************************************************************

\begin{code}
pp_rbinds :: (NamedThing id, Outputable id, Outputable pat,
		  Eq tyvar, Outputable tyvar, Eq uvar, Outputable uvar)
	      => PprStyle -> Pretty 
	      -> HsRecordBinds tyvar uvar id pat -> Pretty

pp_rbinds sty thing rbinds
  = ppHang thing 
	 4 (ppCurlies (ppIntersperse pp'SP (map (pp_rbind sty) rbinds)))
  where
    pp_rbind PprForUser (v, _, True) = ppr PprForUser v
    pp_rbind sty        (v, e, _)    = ppCat [ppr sty v, ppChar '=', ppr sty e]
\end{code}

%************************************************************************
%*									*
\subsection{Do stmts and list comprehensions}
%*									*
%************************************************************************

\begin{code}
data DoOrListComp = DoStmt | ListComp

pprDo DoStmt sty stmts
  = ppHang (ppPStr SLIT("do")) 2 (ppAboves (map (ppr sty) stmts))
pprDo ListComp sty stmts
  = ppHang (ppCat [ppLbrack, pprExpr sty expr, ppChar '|'])
	 4 (ppSep [interpp'SP sty quals, ppRbrack])
  where
    ReturnStmt expr = last stmts	-- Last stmt should be a ReturnStmt for list comps
    quals	    = init stmts
\end{code}

\begin{code}
data Stmt tyvar uvar id pat
  = BindStmt	pat
		(HsExpr  tyvar uvar id pat)
		SrcLoc

  | LetStmt	(HsBinds tyvar uvar id pat)

  | GuardStmt	(HsExpr  tyvar uvar id pat)		-- List comps only
		SrcLoc

  | ExprStmt	(HsExpr  tyvar uvar id pat)		-- Do stmts only
		SrcLoc

  | ReturnStmt	(HsExpr  tyvar uvar id pat)		-- List comps only, at the end
\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, ppPStr SLIT("<-"), ppr sty expr]
    ppr sty (LetStmt binds)
     = ppCat [ppPStr SLIT("let"), ppr sty binds]
    ppr sty (ExprStmt expr _)
     = ppr sty expr
    ppr sty (GuardStmt expr _)
     = ppr sty expr
    ppr sty (ReturnStmt expr)
     = ppCat [ppPStr SLIT("return"), 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}