Split the Id related functions out from Var into Id, document Var and some of Id
[ghc-hetmet.git] / compiler / deSugar / DsListComp.lhs
1 %
2 % (c) The University of Glasgow 2006
3 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
4 %
5
6 Desugaring list comprehensions and array comprehensions
7
8 \begin{code}
9 {-# OPTIONS -fno-warn-incomplete-patterns #-}
10 -- The above warning supression flag is a temporary kludge.
11 -- While working on this module you are encouraged to remove it and fix
12 -- any warnings in the module. See
13 --     http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#Warnings
14 -- for details
15
16 module DsListComp ( dsListComp, dsPArrComp ) where
17
18 #include "HsVersions.h"
19
20 import {-# SOURCE #-} DsExpr ( dsLExpr, dsLocalBinds )
21
22 import HsSyn
23 import TcHsSyn
24 import CoreSyn
25
26 import DsMonad          -- the monadery used in the desugarer
27 import DsUtils
28
29 import DynFlags
30 import CoreUtils
31 import Id
32 import Type
33 import TysWiredIn
34 import Match
35 import PrelNames
36 import PrelInfo
37 import SrcLoc
38 import Outputable
39
40 import Control.Monad ( liftM2 )
41 \end{code}
42
43 List comprehensions may be desugared in one of two ways: ``ordinary''
44 (as you would expect if you read SLPJ's book) and ``with foldr/build
45 turned on'' (if you read Gill {\em et al.}'s paper on the subject).
46
47 There will be at least one ``qualifier'' in the input.
48
49 \begin{code}
50 dsListComp :: [LStmt Id] 
51            -> LHsExpr Id
52            -> Type              -- Type of list elements
53            -> DsM CoreExpr
54 dsListComp lquals body elt_ty = do 
55     dflags <- getDOptsDs
56     let quals = map unLoc lquals
57     
58     if not (dopt Opt_RewriteRules dflags) || dopt Opt_IgnoreInterfacePragmas dflags
59        -- Either rules are switched off, or we are ignoring what there are;
60        -- Either way foldr/build won't happen, so use the more efficient
61        -- Wadler-style desugaring
62        || isParallelComp quals
63        -- Foldr-style desugaring can't handle parallel list comprehensions
64         then deListComp quals body (mkNilExpr elt_ty)
65         else mkBuildExpr elt_ty (\(c, _) (n, _) -> dfListComp c n quals body) 
66              -- Foldr/build should be enabled, so desugar 
67              -- into foldrs and builds
68
69   where 
70     -- We must test for ParStmt anywhere, not just at the head, because an extension
71     -- to list comprehensions would be to add brackets to specify the associativity
72     -- of qualifier lists. This is really easy to do by adding extra ParStmts into the
73     -- mix of possibly a single element in length, so we do this to leave the possibility open
74     isParallelComp = any isParallelStmt
75   
76     isParallelStmt (ParStmt _) = True
77     isParallelStmt _           = False
78     
79     
80 -- This function lets you desugar a inner list comprehension and a list of the binders
81 -- of that comprehension that we need in the outer comprehension into such an expression
82 -- and the type of the elements that it outputs (tuples of binders)
83 dsInnerListComp :: ([LStmt Id], [Id]) -> DsM (CoreExpr, Type)
84 dsInnerListComp (stmts, bndrs) = do
85         expr <- dsListComp stmts (mkBigLHsVarTup bndrs) bndrs_tuple_type
86         return (expr, bndrs_tuple_type)
87     where
88         bndrs_types = map idType bndrs
89         bndrs_tuple_type = mkBigCoreTupTy bndrs_types
90         
91         
92 -- This function factors out commonality between the desugaring strategies for TransformStmt.
93 -- Given such a statement it gives you back an expression representing how to compute the transformed
94 -- list and the tuple that you need to bind from that list in order to proceed with your desugaring
95 dsTransformStmt :: Stmt Id -> DsM (CoreExpr, LPat Id)
96 dsTransformStmt (TransformStmt (stmts, binders) usingExpr maybeByExpr) = do
97     (expr, binders_tuple_type) <- dsInnerListComp (stmts, binders)
98     usingExpr' <- dsLExpr usingExpr
99     
100     using_args <- 
101         case maybeByExpr of
102             Nothing -> return [expr]
103             Just byExpr -> do
104                 byExpr' <- dsLExpr byExpr
105                 
106                 us <- newUniqueSupply
107                 [tuple_binder] <- newSysLocalsDs [binders_tuple_type]
108                 let byExprWrapper = mkTupleCase us binders byExpr' tuple_binder (Var tuple_binder)
109                 
110                 return [Lam tuple_binder byExprWrapper, expr]
111
112     let inner_list_expr = mkApps usingExpr' ((Type binders_tuple_type) : using_args)
113     
114     let pat = mkBigLHsVarPatTup binders
115     return (inner_list_expr, pat)
116     
117 -- This function factors out commonality between the desugaring strategies for GroupStmt.
118 -- Given such a statement it gives you back an expression representing how to compute the transformed
119 -- list and the tuple that you need to bind from that list in order to proceed with your desugaring
120 dsGroupStmt :: Stmt Id -> DsM (CoreExpr, LPat Id)
121 dsGroupStmt (GroupStmt (stmts, binderMap) groupByClause) = do
122     let (fromBinders, toBinders) = unzip binderMap
123         
124         fromBindersTypes = map idType fromBinders
125         toBindersTypes = map idType toBinders
126         
127         toBindersTupleType = mkBigCoreTupTy toBindersTypes
128     
129     -- Desugar an inner comprehension which outputs a list of tuples of the "from" binders
130     (expr, fromBindersTupleType) <- dsInnerListComp (stmts, fromBinders)
131     
132     -- Work out what arguments should be supplied to that expression: i.e. is an extraction
133     -- function required? If so, create that desugared function and add to arguments
134     (usingExpr', usingArgs) <- 
135         case groupByClause of
136             GroupByNothing usingExpr -> liftM2 (,) (dsLExpr usingExpr) (return [expr])
137             GroupBySomething usingExpr byExpr -> do
138                 usingExpr' <- dsLExpr (either id noLoc usingExpr)
139                 
140                 byExpr' <- dsLExpr byExpr
141                 
142                 us <- newUniqueSupply
143                 [fromBindersTuple] <- newSysLocalsDs [fromBindersTupleType]
144                 let byExprWrapper = mkTupleCase us fromBinders byExpr' fromBindersTuple (Var fromBindersTuple)
145                 
146                 return (usingExpr', [Lam fromBindersTuple byExprWrapper, expr])
147     
148     -- Create an unzip function for the appropriate arity and element types and find "map"
149     (unzip_fn, unzip_rhs) <- mkUnzipBind fromBindersTypes
150     map_id <- dsLookupGlobalId mapName
151
152     -- Generate the expressions to build the grouped list
153     let -- First we apply the grouping function to the inner list
154         inner_list_expr = mkApps usingExpr' ((Type fromBindersTupleType) : usingArgs)
155         -- Then we map our "unzip" across it to turn the lists of tuples into tuples of lists
156         -- We make sure we instantiate the type variable "a" to be a list of "from" tuples and
157         -- the "b" to be a tuple of "to" lists!
158         unzipped_inner_list_expr = mkApps (Var map_id) 
159             [Type (mkListTy fromBindersTupleType), Type toBindersTupleType, Var unzip_fn, inner_list_expr]
160         -- Then finally we bind the unzip function around that expression
161         bound_unzipped_inner_list_expr = Let (Rec [(unzip_fn, unzip_rhs)]) unzipped_inner_list_expr
162     
163     -- Build a pattern that ensures the consumer binds into the NEW binders, which hold lists rather than single values
164     let pat = mkBigLHsVarPatTup toBinders
165     return (bound_unzipped_inner_list_expr, pat)
166     
167 \end{code}
168
169 %************************************************************************
170 %*                                                                      *
171 \subsection[DsListComp-ordinary]{Ordinary desugaring of list comprehensions}
172 %*                                                                      *
173 %************************************************************************
174
175 Just as in Phil's chapter~7 in SLPJ, using the rules for
176 optimally-compiled list comprehensions.  This is what Kevin followed
177 as well, and I quite happily do the same.  The TQ translation scheme
178 transforms a list of qualifiers (either boolean expressions or
179 generators) into a single expression which implements the list
180 comprehension.  Because we are generating 2nd-order polymorphic
181 lambda-calculus, calls to NIL and CONS must be applied to a type
182 argument, as well as their usual value arguments.
183 \begin{verbatim}
184 TE << [ e | qs ] >>  =  TQ << [ e | qs ] ++ Nil (typeOf e) >>
185
186 (Rule C)
187 TQ << [ e | ] ++ L >> = Cons (typeOf e) TE <<e>> TE <<L>>
188
189 (Rule B)
190 TQ << [ e | b , qs ] ++ L >> =
191     if TE << b >> then TQ << [ e | qs ] ++ L >> else TE << L >>
192
193 (Rule A')
194 TQ << [ e | p <- L1, qs ]  ++  L2 >> =
195   letrec
196     h = \ u1 ->
197           case u1 of
198             []        ->  TE << L2 >>
199             (u2 : u3) ->
200                   (( \ TE << p >> -> ( TQ << [e | qs]  ++  (h u3) >> )) u2)
201                     [] (h u3)
202   in
203     h ( TE << L1 >> )
204
205 "h", "u1", "u2", and "u3" are new variables.
206 \end{verbatim}
207
208 @deListComp@ is the TQ translation scheme.  Roughly speaking, @dsExpr@
209 is the TE translation scheme.  Note that we carry around the @L@ list
210 already desugared.  @dsListComp@ does the top TE rule mentioned above.
211
212 To the above, we add an additional rule to deal with parallel list
213 comprehensions.  The translation goes roughly as follows:
214      [ e | p1 <- e11, let v1 = e12, p2 <- e13
215          | q1 <- e21, let v2 = e22, q2 <- e23]
216      =>
217      [ e | ((x1, .., xn), (y1, ..., ym)) <-
218                zip [(x1,..,xn) | p1 <- e11, let v1 = e12, p2 <- e13]
219                    [(y1,..,ym) | q1 <- e21, let v2 = e22, q2 <- e23]]
220 where (x1, .., xn) are the variables bound in p1, v1, p2
221       (y1, .., ym) are the variables bound in q1, v2, q2
222
223 In the translation below, the ParStmt branch translates each parallel branch
224 into a sub-comprehension, and desugars each independently.  The resulting lists
225 are fed to a zip function, we create a binding for all the variables bound in all
226 the comprehensions, and then we hand things off the the desugarer for bindings.
227 The zip function is generated here a) because it's small, and b) because then we
228 don't have to deal with arbitrary limits on the number of zip functions in the
229 prelude, nor which library the zip function came from.
230 The introduced tuples are Boxed, but only because I couldn't get it to work
231 with the Unboxed variety.
232
233 \begin{code}
234
235 deListComp :: [Stmt Id] -> LHsExpr Id -> CoreExpr -> DsM CoreExpr
236
237 deListComp (ParStmt stmtss_w_bndrs : quals) body list
238   = do
239     exps_and_qual_tys <- mapM dsInnerListComp stmtss_w_bndrs
240     let (exps, qual_tys) = unzip exps_and_qual_tys
241     
242     (zip_fn, zip_rhs) <- mkZipBind qual_tys
243
244         -- Deal with [e | pat <- zip l1 .. ln] in example above
245     deBindComp pat (Let (Rec [(zip_fn, zip_rhs)]) (mkApps (Var zip_fn) exps)) 
246                    quals body list
247
248   where 
249         bndrs_s = map snd stmtss_w_bndrs
250
251         -- pat is the pattern ((x1,..,xn), (y1,..,ym)) in the example above
252         pat  = mkBigLHsPatTup pats
253         pats = map mkBigLHsVarPatTup bndrs_s
254
255         -- Last: the one to return
256 deListComp [] body list = do    -- Figure 7.4, SLPJ, p 135, rule C above
257     core_body <- dsLExpr body
258     return (mkConsExpr (exprType core_body) core_body list)
259
260         -- Non-last: must be a guard
261 deListComp (ExprStmt guard _ _ : quals) body list = do  -- rule B above
262     core_guard <- dsLExpr guard
263     core_rest <- deListComp quals body list
264     return (mkIfThenElse core_guard core_rest list)
265
266 -- [e | let B, qs] = let B in [e | qs]
267 deListComp (LetStmt binds : quals) body list = do
268     core_rest <- deListComp quals body list
269     dsLocalBinds binds core_rest
270
271 deListComp (stmt@(TransformStmt _ _ _) : quals) body list = do
272     (inner_list_expr, pat) <- dsTransformStmt stmt
273     deBindComp pat inner_list_expr quals body list
274
275 deListComp (stmt@(GroupStmt _ _) : quals) body list = do
276     (inner_list_expr, pat) <- dsGroupStmt stmt
277     deBindComp pat inner_list_expr quals body list
278
279 deListComp (BindStmt pat list1 _ _ : quals) body core_list2 = do -- rule A' above
280     core_list1 <- dsLExpr list1
281     deBindComp pat core_list1 quals body core_list2
282 \end{code}
283
284
285 \begin{code}
286 deBindComp :: OutPat Id
287            -> CoreExpr
288            -> [Stmt Id]
289            -> LHsExpr Id
290            -> CoreExpr
291            -> DsM (Expr Id)
292 deBindComp pat core_list1 quals body core_list2 = do
293     let
294         u3_ty@u1_ty = exprType core_list1       -- two names, same thing
295
296         -- u1_ty is a [alpha] type, and u2_ty = alpha
297         u2_ty = hsLPatType pat
298
299         res_ty = exprType core_list2
300         h_ty   = u1_ty `mkFunTy` res_ty
301         
302     [h, u1, u2, u3] <- newSysLocalsDs [h_ty, u1_ty, u2_ty, u3_ty]
303
304     -- the "fail" value ...
305     let
306         core_fail   = App (Var h) (Var u3)
307         letrec_body = App (Var h) core_list1
308         
309     rest_expr <- deListComp quals body core_fail
310     core_match <- matchSimply (Var u2) (StmtCtxt ListComp) pat rest_expr core_fail      
311     
312     let
313         rhs = Lam u1 $
314               Case (Var u1) u1 res_ty
315                    [(DataAlt nilDataCon,  [],       core_list2),
316                     (DataAlt consDataCon, [u2, u3], core_match)]
317                         -- Increasing order of tag
318             
319     return (Let (Rec [(h, rhs)]) letrec_body)
320 \end{code}
321
322 %************************************************************************
323 %*                                                                      *
324 \subsection[DsListComp-foldr-build]{Foldr/Build desugaring of list comprehensions}
325 %*                                                                      *
326 %************************************************************************
327
328 @dfListComp@ are the rules used with foldr/build turned on:
329
330 \begin{verbatim}
331 TE[ e | ]            c n = c e n
332 TE[ e | b , q ]      c n = if b then TE[ e | q ] c n else n
333 TE[ e | p <- l , q ] c n = let 
334                                 f = \ x b -> case x of
335                                                   p -> TE[ e | q ] c b
336                                                   _ -> b
337                            in
338                            foldr f n l
339 \end{verbatim}
340
341 \begin{code}
342 dfListComp :: Id -> Id -- 'c' and 'n'
343         -> [Stmt Id]   -- the rest of the qual's
344         -> LHsExpr Id
345         -> DsM CoreExpr
346
347         -- Last: the one to return
348 dfListComp c_id n_id [] body = do
349     core_body <- dsLExpr body
350     return (mkApps (Var c_id) [core_body, Var n_id])
351
352         -- Non-last: must be a guard
353 dfListComp c_id n_id (ExprStmt guard _ _  : quals) body = do
354     core_guard <- dsLExpr guard
355     core_rest <- dfListComp c_id n_id quals body
356     return (mkIfThenElse core_guard core_rest (Var n_id))
357
358 dfListComp c_id n_id (LetStmt binds : quals) body = do
359     -- new in 1.3, local bindings
360     core_rest <- dfListComp c_id n_id quals body
361     dsLocalBinds binds core_rest
362
363 dfListComp c_id n_id (stmt@(TransformStmt _ _ _) : quals) body = do
364     (inner_list_expr, pat) <- dsTransformStmt stmt
365     -- Anyway, we bind the newly transformed list via the generic binding function
366     dfBindComp c_id n_id (pat, inner_list_expr) quals body
367
368 dfListComp c_id n_id (stmt@(GroupStmt _ _) : quals) body = do
369     (inner_list_expr, pat) <- dsGroupStmt stmt
370     -- Anyway, we bind the newly grouped list via the generic binding function
371     dfBindComp c_id n_id (pat, inner_list_expr) quals body
372     
373 dfListComp c_id n_id (BindStmt pat list1 _ _ : quals) body = do
374     -- evaluate the two lists
375     core_list1 <- dsLExpr list1
376     
377     -- Do the rest of the work in the generic binding builder
378     dfBindComp c_id n_id (pat, core_list1) quals body
379                
380 dfBindComp :: Id -> Id          -- 'c' and 'n'
381        -> (LPat Id, CoreExpr)
382            -> [Stmt Id]                 -- the rest of the qual's
383            -> LHsExpr Id
384            -> DsM CoreExpr
385 dfBindComp c_id n_id (pat, core_list1) quals body = do
386     -- find the required type
387     let x_ty   = hsLPatType pat
388         b_ty   = idType n_id
389
390     -- create some new local id's
391     [b, x] <- newSysLocalsDs [b_ty, x_ty]
392
393     -- build rest of the comprehesion
394     core_rest <- dfListComp c_id b quals body
395
396     -- build the pattern match
397     core_expr <- matchSimply (Var x) (StmtCtxt ListComp)
398                 pat core_rest (Var b)
399
400     -- now build the outermost foldr, and return
401     mkFoldrExpr x_ty b_ty (mkLams [x, b] core_expr) (Var n_id) core_list1
402 \end{code}
403
404 %************************************************************************
405 %*                                                                      *
406 \subsection[DsFunGeneration]{Generation of zip/unzip functions for use in desugaring}
407 %*                                                                      *
408 %************************************************************************
409
410 \begin{code}
411
412 mkZipBind :: [Type] -> DsM (Id, CoreExpr)
413 -- mkZipBind [t1, t2] 
414 -- = (zip, \as1:[t1] as2:[t2] 
415 --         -> case as1 of 
416 --              [] -> []
417 --              (a1:as'1) -> case as2 of
418 --                              [] -> []
419 --                              (a2:as'2) -> (a1, a2) : zip as'1 as'2)]
420
421 mkZipBind elt_tys = do
422     ass  <- mapM newSysLocalDs  elt_list_tys
423     as'  <- mapM newSysLocalDs  elt_tys
424     as's <- mapM newSysLocalDs  elt_list_tys
425     
426     zip_fn <- newSysLocalDs zip_fn_ty
427     
428     let inner_rhs = mkConsExpr elt_tuple_ty 
429                         (mkBigCoreVarTup as')
430                         (mkVarApps (Var zip_fn) as's)
431         zip_body  = foldr mk_case inner_rhs (zip3 ass as' as's)
432     
433     return (zip_fn, mkLams ass zip_body)
434   where
435     elt_list_tys      = map mkListTy elt_tys
436     elt_tuple_ty      = mkBigCoreTupTy elt_tys
437     elt_tuple_list_ty = mkListTy elt_tuple_ty
438     
439     zip_fn_ty         = mkFunTys elt_list_tys elt_tuple_list_ty
440
441     mk_case (as, a', as') rest
442           = Case (Var as) as elt_tuple_list_ty
443                   [(DataAlt nilDataCon,  [],        mkNilExpr elt_tuple_ty),
444                    (DataAlt consDataCon, [a', as'], rest)]
445                         -- Increasing order of tag
446             
447             
448 mkUnzipBind :: [Type] -> DsM (Id, CoreExpr)
449 -- mkUnzipBind [t1, t2] 
450 -- = (unzip, \ys :: [(t1, t2)] -> foldr (\ax :: (t1, t2) axs :: ([t1], [t2])
451 --     -> case ax of
452 --      (x1, x2) -> case axs of
453 --                (xs1, xs2) -> (x1 : xs1, x2 : xs2))
454 --      ([], [])
455 --      ys)
456 -- 
457 -- We use foldr here in all cases, even if rules are turned off, because we may as well!
458 mkUnzipBind elt_tys = do
459     ax  <- newSysLocalDs elt_tuple_ty
460     axs <- newSysLocalDs elt_list_tuple_ty
461     ys  <- newSysLocalDs elt_tuple_list_ty
462     xs  <- mapM newSysLocalDs elt_tys
463     xss <- mapM newSysLocalDs elt_list_tys
464     
465     unzip_fn <- newSysLocalDs unzip_fn_ty
466
467     [us1, us2] <- sequence [newUniqueSupply, newUniqueSupply]
468
469     let nil_tuple = mkBigCoreTup (map mkNilExpr elt_tys)
470         
471         concat_expressions = map mkConcatExpression (zip3 elt_tys (map Var xs) (map Var xss))
472         tupled_concat_expression = mkBigCoreTup concat_expressions
473         
474         folder_body_inner_case = mkTupleCase us1 xss tupled_concat_expression axs (Var axs)
475         folder_body_outer_case = mkTupleCase us2 xs folder_body_inner_case ax (Var ax)
476         folder_body = mkLams [ax, axs] folder_body_outer_case
477         
478     unzip_body <- mkFoldrExpr elt_tuple_ty elt_list_tuple_ty folder_body nil_tuple (Var ys)
479     return (unzip_fn, mkLams [ys] unzip_body)
480   where
481     elt_tuple_ty       = mkBigCoreTupTy elt_tys
482     elt_tuple_list_ty  = mkListTy elt_tuple_ty
483     elt_list_tys       = map mkListTy elt_tys
484     elt_list_tuple_ty  = mkBigCoreTupTy elt_list_tys
485     
486     unzip_fn_ty        = elt_tuple_list_ty `mkFunTy` elt_list_tuple_ty
487             
488     mkConcatExpression (list_element_ty, head, tail) = mkConsExpr list_element_ty head tail
489             
490             
491
492 \end{code}
493
494 %************************************************************************
495 %*                                                                      *
496 \subsection[DsPArrComp]{Desugaring of array comprehensions}
497 %*                                                                      *
498 %************************************************************************
499
500 \begin{code}
501
502 -- entry point for desugaring a parallel array comprehension
503 --
504 --   [:e | qss:] = <<[:e | qss:]>> () [:():]
505 --
506 dsPArrComp :: [Stmt Id] 
507             -> LHsExpr Id
508             -> Type                 -- Don't use; called with `undefined' below
509             -> DsM CoreExpr
510 dsPArrComp [ParStmt qss] body _  =  -- parallel comprehension
511   dePArrParComp qss body
512 dsPArrComp qs            body _  = do -- no ParStmt in `qs'
513     sglP <- dsLookupGlobalId singletonPName
514     let unitArray = mkApps (Var sglP) [Type unitTy, mkCoreTup []]
515     dePArrComp qs body (mkLHsPatTup []) unitArray
516
517
518
519 -- the work horse
520 --
521 dePArrComp :: [Stmt Id] 
522            -> LHsExpr Id
523            -> LPat Id           -- the current generator pattern
524            -> CoreExpr          -- the current generator expression
525            -> DsM CoreExpr
526 --
527 --  <<[:e' | :]>> pa ea = mapP (\pa -> e') ea
528 --
529 dePArrComp [] e' pa cea = do
530     mapP <- dsLookupGlobalId mapPName
531     let ty = parrElemType cea
532     (clam, ty'e') <- deLambda ty pa e'
533     return $ mkApps (Var mapP) [Type ty, Type ty'e', clam, cea]
534 --
535 --  <<[:e' | b, qs:]>> pa ea = <<[:e' | qs:]>> pa (filterP (\pa -> b) ea)
536 --
537 dePArrComp (ExprStmt b _ _ : qs) body pa cea = do
538     filterP <- dsLookupGlobalId filterPName
539     let ty = parrElemType cea
540     (clam,_) <- deLambda ty pa b
541     dePArrComp qs body pa (mkApps (Var filterP) [Type ty, clam, cea])
542
543 --
544 --  <<[:e' | p <- e, qs:]>> pa ea =
545 --    let ef = \pa -> e
546 --    in
547 --    <<[:e' | qs:]>> (pa, p) (crossMap ea ef)
548 --
549 -- if matching again p cannot fail, or else
550 --
551 --  <<[:e' | p <- e, qs:]>> pa ea = 
552 --    let ef = \pa -> filterP (\x -> case x of {p -> True; _ -> False}) e
553 --    in
554 --    <<[:e' | qs:]>> (pa, p) (crossMapP ea ef)
555 --
556 dePArrComp (BindStmt p e _ _ : qs) body pa cea = do
557     filterP <- dsLookupGlobalId filterPName
558     crossMapP <- dsLookupGlobalId crossMapPName
559     ce <- dsLExpr e
560     let ety'cea = parrElemType cea
561         ety'ce  = parrElemType ce
562         false   = Var falseDataConId
563         true    = Var trueDataConId
564     v <- newSysLocalDs ety'ce
565     pred <- matchSimply (Var v) (StmtCtxt PArrComp) p true false
566     let cef | isIrrefutableHsPat p = ce
567             | otherwise            = mkApps (Var filterP) [Type ety'ce, mkLams [v] pred, ce]
568     (clam, _) <- mkLambda ety'cea pa cef
569     let ety'cef = ety'ce                    -- filter doesn't change the element type
570         pa'     = mkLHsPatTup [pa, p]
571
572     dePArrComp qs body pa' (mkApps (Var crossMapP) 
573                                  [Type ety'cea, Type ety'cef, cea, clam])
574 --
575 --  <<[:e' | let ds, qs:]>> pa ea = 
576 --    <<[:e' | qs:]>> (pa, (x_1, ..., x_n)) 
577 --                    (mapP (\v@pa -> let ds in (v, (x_1, ..., x_n))) ea)
578 --  where
579 --    {x_1, ..., x_n} = DV (ds)         -- Defined Variables
580 --
581 dePArrComp (LetStmt ds : qs) body pa cea = do
582     mapP <- dsLookupGlobalId mapPName
583     let xs     = map unLoc (collectLocalBinders ds)
584         ty'cea = parrElemType cea
585     v <- newSysLocalDs ty'cea
586     clet <- dsLocalBinds ds (mkCoreTup (map Var xs))
587     let'v <- newSysLocalDs (exprType clet)
588     let projBody = mkDsLet (NonRec let'v clet) $ 
589                    mkCoreTup [Var v, Var let'v]
590         errTy    = exprType projBody
591         errMsg   = "DsListComp.dePArrComp: internal error!"
592     cerr <- mkErrorAppDs pAT_ERROR_ID errTy errMsg
593     ccase <- matchSimply (Var v) (StmtCtxt PArrComp) pa projBody cerr
594     let pa'    = mkLHsPatTup [pa, mkLHsPatTup (map nlVarPat xs)]
595         proj   = mkLams [v] ccase
596     dePArrComp qs body pa' (mkApps (Var mapP) 
597                                    [Type ty'cea, Type errTy, proj, cea])
598 --
599 -- The parser guarantees that parallel comprehensions can only appear as
600 -- singeltons qualifier lists, which we already special case in the caller.
601 -- So, encountering one here is a bug.
602 --
603 dePArrComp (ParStmt _ : _) _ _ _ = 
604   panic "DsListComp.dePArrComp: malformed comprehension AST"
605
606 --  <<[:e' | qs | qss:]>> pa ea = 
607 --    <<[:e' | qss:]>> (pa, (x_1, ..., x_n)) 
608 --                     (zipP ea <<[:(x_1, ..., x_n) | qs:]>>)
609 --    where
610 --      {x_1, ..., x_n} = DV (qs)
611 --
612 dePArrParComp :: [([LStmt Id], [Id])] -> LHsExpr Id -> DsM CoreExpr
613 dePArrParComp qss body = do
614     (pQss, ceQss) <- deParStmt qss
615     dePArrComp [] body pQss ceQss
616   where
617     deParStmt []             =
618       -- empty parallel statement lists have no source representation
619       panic "DsListComp.dePArrComp: Empty parallel list comprehension"
620     deParStmt ((qs, xs):qss) = do        -- first statement
621       let res_expr = mkLHsVarTup xs
622       cqs <- dsPArrComp (map unLoc qs) res_expr undefined
623       parStmts qss (mkLHsVarPatTup xs) cqs
624     ---
625     parStmts []             pa cea = return (pa, cea)
626     parStmts ((qs, xs):qss) pa cea = do  -- subsequent statements (zip'ed)
627       zipP <- dsLookupGlobalId zipPName
628       let pa'      = mkLHsPatTup [pa, mkLHsVarPatTup xs]
629           ty'cea   = parrElemType cea
630           res_expr = mkLHsVarTup xs
631       cqs <- dsPArrComp (map unLoc qs) res_expr undefined
632       let ty'cqs = parrElemType cqs
633           cea'   = mkApps (Var zipP) [Type ty'cea, Type ty'cqs, cea, cqs]
634       parStmts qss pa' cea'
635
636 -- generate Core corresponding to `\p -> e'
637 --
638 deLambda :: Type                        -- type of the argument
639           -> LPat Id                    -- argument pattern
640           -> LHsExpr Id                 -- body
641           -> DsM (CoreExpr, Type)
642 deLambda ty p e =
643     mkLambda ty p =<< dsLExpr e
644
645 -- generate Core for a lambda pattern match, where the body is already in Core
646 --
647 mkLambda :: Type                        -- type of the argument
648          -> LPat Id                     -- argument pattern
649          -> CoreExpr                    -- desugared body
650          -> DsM (CoreExpr, Type)
651 mkLambda ty p ce = do
652     v <- newSysLocalDs ty
653     let errMsg = do "DsListComp.deLambda: internal error!"
654         ce'ty  = exprType ce
655     cerr <- mkErrorAppDs pAT_ERROR_ID ce'ty errMsg
656     res <- matchSimply (Var v) (StmtCtxt PArrComp) p ce cerr
657     return (mkLams [v] res, ce'ty)
658
659 -- obtain the element type of the parallel array produced by the given Core
660 -- expression
661 --
662 parrElemType   :: CoreExpr -> Type
663 parrElemType e  = 
664   case splitTyConApp_maybe (exprType e) of
665     Just (tycon, [ty]) | tycon == parrTyCon -> ty
666     _                                                     -> panic
667       "DsListComp.parrElemType: not a parallel array type"
668 \end{code}