summaryrefslogtreecommitdiff
path: root/ghc/compiler/reader/PrefixToHs.lhs
blob: 2f229553f88106c6e214ab00788134beb411329e (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
%
% (c) The GRASP/AQUA Project, Glasgow University, 1992-1996
%
\section[PrefixToHS]{Support routines for converting ``prefix form'' to Haskell abstract syntax}

Support routines for reading prefix-form from the Lex/Yacc parser.

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

module PrefixToHs (
	cvValSig,
	cvClassOpSig,
	cvInstDeclSig,
	cvBinds,
	cvMatches,
	cvMonoBinds,
	cvSepdBinds,
	sepDeclsForTopBinds,
	sepDeclsIntoSigsAndBinds
    ) where

IMP_Ubiq(){-uitous-}

import PrefixSyn	-- and various syntaxen.
import HsSyn
import RdrHsSyn
import HsPragmas	( noGenPragmas, noClassOpPragmas )

import SrcLoc		( mkSrcLoc2 )
import Util		( mapAndUnzip, panic, assertPanic )
\end{code}

%************************************************************************
%*									*
\subsection[cvDecls]{Convert various top-level declarations}
%*									*
%************************************************************************

We make a point not to throw any user-pragma ``sigs'' at
these conversion functions:
\begin{code}
cvValSig, cvClassOpSig, cvInstDeclSig :: SigConverter

cvValSig (RdrTySig vars poly_ty src_loc)
  = [ Sig v poly_ty noGenPragmas src_loc | v <- vars ]

cvClassOpSig (RdrTySig vars poly_ty src_loc)
  = [ ClassOpSig v poly_ty noClassOpPragmas src_loc | v <- vars ]

cvInstDeclSig (RdrSpecValSig        sigs) = sigs
cvInstDeclSig (RdrInlineValSig      sig)  = [ sig ]
cvInstDeclSig (RdrDeforestSig	    sig)  = [ sig ]
cvInstDeclSig (RdrMagicUnfoldingSig sig)  = [ sig ]
\end{code}

%************************************************************************
%*									*
\subsection[cvBinds-etc]{Converting to @HsBinds@, @MonoBinds@, etc.}
%*									*
%************************************************************************

Function definitions are restructured here. Each is assumed to be recursive
initially, and non recursive definitions are discovered by the dependency
analyser.

\begin{code}
cvBinds :: SrcFile -> SigConverter -> RdrBinding -> RdrNameHsBinds
cvBinds sf sig_cvtr raw_binding
  = cvSepdBinds sf sig_cvtr (sepDeclsForBinds raw_binding)

cvSepdBinds :: SrcFile -> SigConverter -> [RdrBinding] -> RdrNameHsBinds
cvSepdBinds sf sig_cvtr bindings
  = case (mkMonoBindsAndSigs sf sig_cvtr bindings) of { (mbs, sigs) ->
    if (null sigs)
    then SingleBind (RecBind mbs)
    else BindWith   (RecBind mbs) sigs
    }

cvMonoBinds :: SrcFile -> [RdrBinding] -> RdrNameMonoBinds
cvMonoBinds sf bindings
  = case (mkMonoBindsAndSigs sf bottom bindings) of { (mbs,sigs) ->
    if (null sigs)
    then mbs
    else panic "cvMonoBinds: some sigs present"
    }
  where
    bottom = panic "cvMonoBinds: sig converter!"
\end{code}

\begin{code}
mkMonoBindsAndSigs :: SrcFile
		   -> SigConverter
		   -> [RdrBinding]
		   -> (RdrNameMonoBinds, [RdrNameSig])

mkMonoBindsAndSigs sf sig_cvtr fbs
  = foldl mangle_bind (EmptyMonoBinds, []) fbs
  where
    -- If the function being bound has at least one argument, then the
    -- guarded right hand sides of each pattern binding are knitted
    -- into a series of patterns, each matched with its corresponding
    -- guarded right hand side (which may contain several
    -- alternatives). This series is then paired with the name of the
    -- function. Otherwise there is only one pattern, which is paired
    -- with a guarded right hand side.

    mangle_bind (b_acc, s_acc) sig@(RdrTySig _ _ _)
      = (b_acc, s_acc ++ sig_cvtr sig)

    mangle_bind (b_acc, s_acc) (RdrSpecValSig	     sig) = (b_acc, sig ++ s_acc)
    mangle_bind (b_acc, s_acc) (RdrInlineValSig      sig) = (b_acc, sig : s_acc)
    mangle_bind (b_acc, s_acc) (RdrDeforestSig       sig) = (b_acc, sig : s_acc)
    mangle_bind (b_acc, s_acc) (RdrMagicUnfoldingSig sig) = (b_acc, sig : s_acc)

    mangle_bind (b_acc, s_acc)
		(RdrPatternBinding lousy_srcline [patbinding])
      -- WDP: the parser has trouble getting a good line-number on RdrPatternBindings.
      = case (cvPatMonoBind sf patbinding) of { (pat, grhss, binds) ->
	let
	    src_loc = mkSrcLoc2 sf good_srcline
	in
	(b_acc `AndMonoBinds`
	 PatMonoBind pat (GRHSsAndBindsIn grhss binds) src_loc, s_acc)
	}
      where
	good_srcline = case patbinding of
			 RdrMatch_NoGuard ln _ _ _ _ -> ln
			 RdrMatch_Guards  ln _ _ _ _ -> ln


    mangle_bind _ (RdrPatternBinding _ _)
      = panic "mangleBinding: more than one pattern on a RdrPatternBinding"

    mangle_bind (b_acc, s_acc) (RdrFunctionBinding srcline patbindings)
	    -- must be a function binding...
      = case (cvFunMonoBind sf patbindings) of { (var, inf, matches) ->
	(b_acc `AndMonoBinds`
	 FunMonoBind var inf matches (mkSrcLoc2 sf srcline), s_acc)
	}
\end{code}

\begin{code}
cvPatMonoBind :: SrcFile -> RdrMatch -> (RdrNamePat, [RdrNameGRHS], RdrNameHsBinds)

cvPatMonoBind sf (RdrMatch_NoGuard srcline srcfun pat expr binding)
  = (pat, [OtherwiseGRHS expr (mkSrcLoc2 sf srcline)], cvBinds sf cvValSig binding)

cvPatMonoBind sf (RdrMatch_Guards srcline srcfun pat guardedexprs binding)
  = (pat, map (cvGRHS sf srcline) guardedexprs, cvBinds sf cvValSig binding)

cvFunMonoBind :: SrcFile -> [RdrMatch] -> (RdrName {-VarName-}, Bool {-InfixDefn-}, [RdrNameMatch])

cvFunMonoBind sf matches
  = (head srcfuns, head infixdefs, cvMatches sf False matches)
  where
    (srcfuns, infixdefs) = mapAndUnzip get_mdef matches
    -- ToDo: Check for consistent srcfun and infixdef

    get_mdef (RdrMatch_NoGuard _ sfun pat _ _) = get_pdef pat
    get_mdef (RdrMatch_Guards  _ sfun pat _ _) = get_pdef pat

    get_pdef (ConPatIn fn _)     = (fn, False)
    get_pdef (ConOpPatIn _ op _) = (op, True)
    get_pdef (ParPatIn pat)	 = get_pdef pat


cvMatches :: SrcFile -> Bool -> [RdrMatch] -> [RdrNameMatch]
cvMatch	  :: SrcFile -> Bool -> RdrMatch   -> RdrNameMatch

cvMatches sf is_case matches = map (cvMatch sf is_case) matches

cvMatch sf is_case rdr_match
  = foldr PatMatch
	  (GRHSMatch (GRHSsAndBindsIn guarded_exprs (cvBinds sf cvValSig binding)))

	  -- For a FunMonoBinds, the first flattened "pattern" is
	  -- just the function name, and we don't want to keep it.
	  -- For a case expr, it's (presumably) a constructor name -- and
	  -- we most certainly want to keep it!	 Hence the monkey busines...

	  (if is_case then -- just one pattern: leave it untouched...
	      [pat]
	   else		   -- function pattern; extract arg patterns...
	      case pat of ConPatIn fn pats    -> pats
			  ConOpPatIn p1 op p2 -> [p1,p2]
			  ParPatIn pat	      -> panic "PrefixToHs.cvMatch:ParPatIn"
	  )
  where
    (pat, binding, guarded_exprs)
      = case rdr_match of
	  RdrMatch_NoGuard ln b c expr    d -> (c,d, [OtherwiseGRHS expr (mkSrcLoc2 sf ln)])
	  RdrMatch_Guards  ln b c gd_exps d -> (c,d, map (cvGRHS sf ln) gd_exps)

cvGRHS :: SrcFile -> SrcLine -> (RdrNameHsExpr, RdrNameHsExpr) -> RdrNameGRHS
cvGRHS sf sl (g, e) = GRHS g e (mkSrcLoc2 sf sl)
\end{code}

%************************************************************************
%*									*
\subsection[PrefixToHS-utils]{Utilities for conversion}
%*									*
%************************************************************************

Separate declarations into all the various kinds:
\begin{display}
tys		RdrTyDecl
ty "sigs" 	RdrSpecDataSig
classes		RdrClassDecl
insts		RdrInstDecl
inst "sigs" 	RdrSpecInstSig
defaults	RdrDefaultDecl
binds		RdrFunctionBinding RdrPatternBinding RdrTySig
		RdrSpecValSig RdrInlineValSig RdrDeforestSig
		RdrMagicUnfoldingSig
\end{display}

This function isn't called directly; some other function calls it,
then checks that what it got is appropriate for that situation.
(Those functions follow...)

\begin{code}
sepDecls (RdrTyDecl a)
	 tys tysigs classes insts instsigs defaults binds
 = (a:tys,tysigs,classes,insts,instsigs,defaults,binds)

sepDecls a@(RdrFunctionBinding _ _)
	 tys tysigs classes insts instsigs defaults binds
 = (tys,tysigs,classes,insts,instsigs,defaults,a:binds)

sepDecls a@(RdrPatternBinding _ _)
	 tys tysigs classes insts instsigs defaults binds
 = (tys,tysigs,classes,insts,instsigs,defaults,a:binds)

-- RdrAndBindings catered for below...

sepDecls (RdrClassDecl a)
	 tys tysigs classes insts instsigs defaults binds
  = (tys,tysigs,a:classes,insts,instsigs,defaults,binds)

sepDecls (RdrInstDecl a)
	 tys tysigs classes insts instsigs defaults binds
  = (tys,tysigs,classes,a:insts,instsigs,defaults,binds)

sepDecls (RdrDefaultDecl a)
	 tys tysigs classes insts instsigs defaults binds
  = (tys,tysigs,classes,insts,instsigs,a:defaults,binds)

sepDecls a@(RdrTySig _ _ _)
	 tys tysigs classes insts instsigs defaults binds
  = (tys,tysigs,classes,insts,instsigs,defaults,a:binds)

sepDecls a@(RdrSpecValSig _)
	 tys tysigs classes insts instsigs defaults binds
  = (tys,tysigs,classes,insts,instsigs,defaults,a:binds)

sepDecls a@(RdrInlineValSig _)
	 tys tysigs classes insts instsigs defaults binds
  = (tys,tysigs,classes,insts,instsigs,defaults,a:binds)

sepDecls a@(RdrDeforestSig _)
	 tys tysigs classes insts instsigs defaults binds
  = (tys,tysigs,classes,insts,instsigs,defaults,a:binds)

sepDecls a@(RdrMagicUnfoldingSig _)
	 tys tysigs classes insts instsigs defaults binds
  = (tys,tysigs,classes,insts,instsigs,defaults,a:binds)

sepDecls (RdrSpecInstSig a)
	 tys tysigs classes insts instsigs defaults binds
  = (tys,tysigs,classes,insts,a:instsigs,defaults,binds)

sepDecls (RdrSpecDataSig a)
	 tys tysigs classes insts instsigs defaults binds
  = (tys,a:tysigs,classes,insts,instsigs,defaults,binds)

sepDecls RdrNullBind
	 tys tysigs classes insts instsigs defaults binds
  = (tys,tysigs,classes,insts,instsigs,defaults,binds)

sepDecls (RdrAndBindings bs1 bs2)
	 tys tysigs classes insts instsigs defaults binds
  = case (sepDecls bs2 tys tysigs classes insts instsigs defaults binds) of {
      (tys,tysigs,classes,insts,instsigs,defaults,binds) ->
	  sepDecls bs1 tys tysigs classes insts instsigs defaults binds
    }
\end{code}

\begin{code}
sepDeclsForTopBinds binding
  = sepDecls binding [] [] [] [] [] [] []

sepDeclsForBinds binding
  = case (sepDecls binding [] [] [] [] [] [] [])
	of { (tys,tysigs,classes,insts,instsigs,defaults,binds) ->
    ASSERT ((null tys)
	 && (null tysigs)
	 && (null classes)
	 && (null insts)
	 && (null instsigs)
	 && (null defaults))
    binds
    }

sepDeclsIntoSigsAndBinds binding
  = case (sepDeclsForBinds binding) of { sigs_and_binds ->
    foldr sep_stuff ([],[]) sigs_and_binds
    }
  where
    sep_stuff s@(RdrTySig _ _ _)         (sigs,defs) = (s:sigs,defs)
    sep_stuff s@(RdrSpecValSig _)        (sigs,defs) = (s:sigs,defs)
    sep_stuff s@(RdrInlineValSig _)      (sigs,defs) = (s:sigs,defs)
    sep_stuff s@(RdrDeforestSig  _)      (sigs,defs) = (s:sigs,defs)
    sep_stuff s@(RdrMagicUnfoldingSig _) (sigs,defs) = (s:sigs,defs)
    sep_stuff d@(RdrFunctionBinding _ _) (sigs,defs) = (sigs,d:defs)
    sep_stuff d@(RdrPatternBinding  _ _) (sigs,defs) = (sigs,d:defs)


\end{code}