X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Fcompiler%2FdeSugar%2FDsListComp.lhs;h=1f20f59f1f83210b8b5805b7ad1a111ecfa05776;hb=706ebc799fd9db83ac6a2e2b701a6413b1867049;hp=ac712c70abaf0e9ac2379cd9f9d886a14a5cbb35;hpb=e7498a3ee1d0484d02a9e86633cc179c76ebf36e;p=ghc-hetmet.git diff --git a/ghc/compiler/deSugar/DsListComp.lhs b/ghc/compiler/deSugar/DsListComp.lhs index ac712c7..1f20f59 100644 --- a/ghc/compiler/deSugar/DsListComp.lhs +++ b/ghc/compiler/deSugar/DsListComp.lhs @@ -1,33 +1,38 @@ % -% (c) The GRASP/AQUA Project, Glasgow University, 1992-1996 +% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998 % -\section[DsListComp]{Desugaring list comprehensions} +\section[DsListComp]{Desugaring list comprehensions and array comprehensions} \begin{code} -#include "HsVersions.h" +module DsListComp ( dsListComp, dsPArrComp ) where -module DsListComp ( dsListComp ) where +#include "HsVersions.h" -IMP_Ubiq() -IMPORT_DELOOPER(DsLoop) -- break dsExpr-ish loop +import {-# SOURCE #-} DsExpr ( dsLExpr, dsLet ) -import HsSyn ( Qual(..), HsExpr, HsBinds ) -import TcHsSyn ( TypecheckedQual(..), TypecheckedHsExpr(..) , TypecheckedHsBinds(..) ) -import DsHsSyn ( outPatType ) +import BasicTypes ( Boxity(..) ) +import HsSyn +import TcHsSyn ( hsPatType ) import CoreSyn import DsMonad -- the monadery used in the desugarer import DsUtils -import CmdLineOpts ( opt_FoldrBuildOn ) -import CoreUtils ( coreExprType, mkCoreIfThenElse ) -import PrelVals ( mkBuild, foldrId ) -import Type ( mkTyVarTy, mkForAllTy, mkFunTys ) -import TysPrim ( alphaTy ) -import TysWiredIn ( nilDataCon, consDataCon, listTyCon ) -import TyVar ( alphaTyVar ) +import CmdLineOpts ( DynFlag(..), dopt, opt_RulesOff ) +import CoreUtils ( exprType, mkIfThenElse ) +import Id ( idType ) +import Var ( Id ) +import Type ( mkTyVarTy, mkFunTys, mkFunTy, Type, + splitTyConApp_maybe ) +import TysPrim ( alphaTyVar ) +import TysWiredIn ( nilDataCon, consDataCon, trueDataConId, falseDataConId, + unitDataConId, unitTy, mkListTy, parrTyCon ) import Match ( matchSimply ) -import Util ( panic ) +import PrelNames ( foldrName, buildName, replicatePName, mapPName, + filterPName, zipPName, crossPName ) +import PrelInfo ( pAT_ERROR_ID ) +import SrcLoc ( noLoc, unLoc ) +import Panic ( panic ) \end{code} List comprehensions may be desugared in one of two ways: ``ordinary'' @@ -37,39 +42,38 @@ turned on'' (if you read Gill {\em et al.}'s paper on the subject). There will be at least one ``qualifier'' in the input. \begin{code} -dsListComp :: CoreExpr -> [TypecheckedQual] -> DsM CoreExpr - -dsListComp expr quals - = let - expr_ty = coreExprType expr +dsListComp :: [LStmt Id] + -> Type -- Type of list elements + -> DsM CoreExpr +dsListComp lquals elt_ty + = getDOptsDs `thenDs` \dflags -> + let + quals = map unLoc lquals in - if not opt_FoldrBuildOn then -- be boring - deListComp expr quals (nIL_EXPR expr_ty) - - else -- foldr/build lives! - new_alpha_tyvar `thenDs` \ (n_tyvar, n_ty) -> - let - alpha_to_alpha = mkFunTys [alphaTy] alphaTy - - c_ty = mkFunTys [expr_ty, n_ty] n_ty - g_ty = mkForAllTy alphaTyVar ( - (mkFunTys [expr_ty, alpha_to_alpha] alpha_to_alpha)) - in - newSysLocalsDs [c_ty,n_ty,g_ty] `thenDs` \ [c, n, g] -> - - dfListComp expr expr_ty - c_ty c - n_ty n - quals `thenDs` \ result -> - - returnDs (mkBuild expr_ty n_tyvar c n g result) - where - nIL_EXPR ty = mkCon nilDataCon [] [ty] [] - - new_alpha_tyvar :: DsM (TyVar, Type) - new_alpha_tyvar - = newTyVarsDs [alphaTyVar] `thenDs` \ [new_ty] -> - returnDs (new_ty, mkTyVarTy new_ty) + if opt_RulesOff || dopt Opt_IgnoreInterfacePragmas dflags + -- Either rules are switched off, or we are ignoring what there are; + -- Either way foldr/build won't happen, so use the more efficient + -- Wadler-style desugaring + || isParallelComp quals + -- Foldr-style desugaring can't handle + -- parallel list comprehensions + then deListComp quals (mkNilExpr elt_ty) + + else -- Foldr/build should be enabled, so desugar + -- into foldrs and builds + newTyVarsDs [alphaTyVar] `thenDs` \ [n_tyvar] -> + let + n_ty = mkTyVarTy n_tyvar + c_ty = mkFunTys [elt_ty, n_ty] n_ty + in + newSysLocalsDs [c_ty,n_ty] `thenDs` \ [c, n] -> + dfListComp c n quals `thenDs` \ result -> + dsLookupGlobalId buildName `thenDs` \ build_id -> + returnDs (Var build_id `App` Type elt_ty + `App` mkLams [n_tyvar, c, n] result) + + where isParallelComp (ParStmt bndrstmtss : _) = True + isParallelComp _ = False \end{code} %************************************************************************ @@ -115,66 +119,153 @@ TQ << [ e | p <- L1, qs ] ++ L2 >> = is the TE translation scheme. Note that we carry around the @L@ list already desugared. @dsListComp@ does the top TE rule mentioned above. +To the above, we add an additional rule to deal with parallel list +comprehensions. The translation goes roughly as follows: + [ e | p1 <- e11, let v1 = e12, p2 <- e13 + | q1 <- e21, let v2 = e22, q2 <- e23] + => + [ e | ((x1, .., xn), (y1, ..., ym)) <- + zip [(x1,..,xn) | p1 <- e11, let v1 = e12, p2 <- e13] + [(y1,..,ym) | q1 <- e21, let v2 = e22, q2 <- e23]] +where (x1, .., xn) are the variables bound in p1, v1, p2 + (y1, .., ym) are the variables bound in q1, v2, q2 + +In the translation below, the ParStmt branch translates each parallel branch +into a sub-comprehension, and desugars each independently. The resulting lists +are fed to a zip function, we create a binding for all the variables bound in all +the comprehensions, and then we hand things off the the desugarer for bindings. +The zip function is generated here a) because it's small, and b) because then we +don't have to deal with arbitrary limits on the number of zip functions in the +prelude, nor which library the zip function came from. +The introduced tuples are Boxed, but only because I couldn't get it to work +with the Unboxed variety. + \begin{code} -deListComp :: CoreExpr -> [TypecheckedQual] -> CoreExpr -> DsM CoreExpr +deListComp :: [Stmt Id] -> CoreExpr -> DsM CoreExpr -deListComp expr [] list -- Figure 7.4, SLPJ, p 135, rule C above - = mkConDs consDataCon [coreExprType expr] [expr, list] +deListComp (ParStmt stmtss_w_bndrs : quals) list + = mappM do_list_comp stmtss_w_bndrs `thenDs` \ exps -> + mkZipBind qual_tys `thenDs` \ (zip_fn, zip_rhs) -> -deListComp expr (FilterQual filt : quals) list -- rule B above - = dsExpr filt `thenDs` \ core_filt -> - deListComp expr quals list `thenDs` \ core_rest -> - returnDs ( mkCoreIfThenElse core_filt core_rest list ) + -- Deal with [e | pat <- zip l1 .. ln] in example above + deBindComp pat (Let (Rec [(zip_fn, zip_rhs)]) (mkApps (Var zip_fn) exps)) + quals list -deListComp expr (LetQual binds : quals) list - = panic "deListComp:LetQual" + where + bndrs_s = map snd stmtss_w_bndrs -deListComp expr ((GeneratorQual pat list1):quals) core_list2 -- rule A' above - = dsExpr list1 `thenDs` \ core_list1 -> - let - u3_ty@u1_ty = coreExprType core_list1 -- two names, same thing + -- pat is the pattern ((x1,..,xn), (y1,..,ym)) in the example above + pat = noLoc (TuplePat pats Boxed) + pats = map mk_hs_tuple_pat bndrs_s + + -- Types of (x1,..,xn), (y1,..,yn) etc + qual_tys = map mk_bndrs_tys bndrs_s + + do_list_comp (stmts, bndrs) + = dsListComp (stmts ++ [noLoc $ ResultStmt (mk_hs_tuple_expr bndrs)]) + (mk_bndrs_tys bndrs) + + mk_bndrs_tys bndrs = mkCoreTupTy (map idType bndrs) + + -- Last: the one to return +deListComp [ResultStmt expr] list -- Figure 7.4, SLPJ, p 135, rule C above + = dsLExpr expr `thenDs` \ core_expr -> + returnDs (mkConsExpr (exprType core_expr) core_expr list) + + -- Non-last: must be a guard +deListComp (ExprStmt guard ty : quals) list -- rule B above + = dsLExpr guard `thenDs` \ core_guard -> + deListComp quals list `thenDs` \ core_rest -> + returnDs (mkIfThenElse core_guard core_rest list) + +-- [e | let B, qs] = let B in [e | qs] +deListComp (LetStmt binds : quals) list + = deListComp quals list `thenDs` \ core_rest -> + dsLet binds core_rest + +deListComp (BindStmt pat list1 : quals) core_list2 -- rule A' above + = dsLExpr list1 `thenDs` \ core_list1 -> + deBindComp pat core_list1 quals core_list2 +\end{code} + + +\begin{code} +deBindComp pat core_list1 quals core_list2 + = let + u3_ty@u1_ty = exprType core_list1 -- two names, same thing -- u1_ty is a [alpha] type, and u2_ty = alpha - u2_ty = outPatType pat + u2_ty = hsPatType pat + + res_ty = exprType core_list2 + h_ty = u1_ty `mkFunTy` res_ty + in + newSysLocalsDs [h_ty, u1_ty, u2_ty, u3_ty] `thenDs` \ [h, u1, u2, u3] -> - res_ty = coreExprType core_list2 - h_ty = mkFunTys [u1_ty] res_ty + -- the "fail" value ... + let + core_fail = App (Var h) (Var u3) + letrec_body = App (Var h) core_list1 in - newSysLocalsDs [h_ty, u1_ty, u2_ty, u3_ty] - `thenDs` \ [h', u1, u2, u3] -> - {- - Make the function h unfoldable by the deforester. - Since it only occurs once in the body, we can't get - an increase in code size by unfolding it. - -} + deListComp quals core_fail `thenDs` \ rest_expr -> + matchSimply (Var u2) (StmtCtxt ListComp) pat + rest_expr core_fail `thenDs` \ core_match -> let - h = if False -- LATER: sw_chkr DoDeforest??? - then panic "deListComp:deforest" - -- replaceIdInfo h' (addInfo (getIdInfo h') DoDeforest) - else h' + rhs = Lam u1 $ + Case (Var u1) u1 res_ty + [(DataAlt nilDataCon, [], core_list2), + (DataAlt consDataCon, [u2, u3], core_match)] + -- Increasing order of tag in - -- the "fail" value ... - mkAppDs (Var h) [] [Var u3] `thenDs` \ core_fail -> - - deListComp expr quals core_fail `thenDs` \ rest_expr -> - - matchSimply (Var u2) pat res_ty rest_expr core_fail `thenDs` \ core_match -> + returnDs (Let (Rec [(h, rhs)]) letrec_body) +\end{code} - mkAppDs (Var h) [] [core_list1] `thenDs` \ letrec_body -> - returnDs ( - mkCoLetrecAny [ - ( h, - (Lam (ValBinder u1) - (Case (Var u1) - (AlgAlts - [(nilDataCon, [], core_list2), - (consDataCon, [u2, u3], core_match)] - NoDefault))) - )] letrec_body - ) +\begin{code} +mkZipBind :: [Type] -> DsM (Id, CoreExpr) +-- mkZipBind [t1, t2] +-- = (zip, \as1:[t1] as2:[t2] +-- -> case as1 of +-- [] -> [] +-- (a1:as'1) -> case as2 of +-- [] -> [] +-- (a2:as'2) -> (a2,a2) : zip as'1 as'2)] + +mkZipBind elt_tys + = mappM newSysLocalDs list_tys `thenDs` \ ass -> + mappM newSysLocalDs elt_tys `thenDs` \ as' -> + mappM newSysLocalDs list_tys `thenDs` \ as's -> + newSysLocalDs zip_fn_ty `thenDs` \ zip_fn -> + let + inner_rhs = mkConsExpr ret_elt_ty + (mkCoreTup (map Var as')) + (mkVarApps (Var zip_fn) as's) + zip_body = foldr mk_case inner_rhs (zip3 ass as' as's) + in + returnDs (zip_fn, mkLams ass zip_body) + where + list_tys = map mkListTy elt_tys + ret_elt_ty = mkCoreTupTy elt_tys + list_ret_ty = mkListTy ret_elt_ty + zip_fn_ty = mkFunTys list_tys list_ret_ty + + mk_case (as, a', as') rest + = Case (Var as) as list_ret_ty + [(DataAlt nilDataCon, [], mkNilExpr ret_elt_ty), + (DataAlt consDataCon, [a', as'], rest)] + -- Increasing order of tag +-- Helper functions that makes an HsTuple only for non-1-sized tuples +mk_hs_tuple_expr :: [Id] -> LHsExpr Id +mk_hs_tuple_expr [] = nlHsVar unitDataConId +mk_hs_tuple_expr [id] = nlHsVar id +mk_hs_tuple_expr ids = noLoc $ ExplicitTuple [ nlHsVar i | i <- ids ] Boxed + +mk_hs_tuple_pat :: [Id] -> LPat Id +mk_hs_tuple_pat [b] = nlVarPat b +mk_hs_tuple_pat bs = noLoc $ TuplePat (map nlVarPat bs) Boxed \end{code} + %************************************************************************ %* * \subsection[DsListComp-foldr-build]{Foldr/Build desugaring of list comprehensions} @@ -182,65 +273,240 @@ deListComp expr ((GeneratorQual pat list1):quals) core_list2 -- rule A' above %************************************************************************ @dfListComp@ are the rules used with foldr/build turned on: + \begin{verbatim} -TE < [ e | ] >> c n = c e n -TE << [ e | b , q ] >> c n = if b then TE << [ e | q ] >> c n else n -TE << [ e | p <- l , q ] c n = foldr - (\ TE << p >> b -> TE << [ e | q ] >> c b - _ b -> b) n l +TE[ e | ] c n = c e n +TE[ e | b , q ] c n = if b then TE[ e | q ] c n else n +TE[ e | p <- l , q ] c n = let + f = \ x b -> case x of + p -> TE[ e | q ] c b + _ -> b + in + foldr f n l \end{verbatim} + \begin{code} -dfListComp :: CoreExpr -- the inside of the comp - -> Type -- the type of the inside - -> Type -> Id -- 'c'; its type and id - -> Type -> Id -- 'n'; its type and id - -> [TypecheckedQual] -- the rest of the qual's +dfListComp :: Id -> Id -- 'c' and 'n' + -> [Stmt Id] -- the rest of the qual's -> DsM CoreExpr -dfListComp expr expr_ty c_ty c_id n_ty n_id [] - = mkAppDs (Var c_id) [] [expr, Var n_id] + -- Last: the one to return +dfListComp c_id n_id [ResultStmt expr] + = dsLExpr expr `thenDs` \ core_expr -> + returnDs (mkApps (Var c_id) [core_expr, Var n_id]) -dfListComp expr expr_ty c_ty c_id n_ty n_id (FilterQual filt : quals) - = dsExpr filt `thenDs` \ core_filt -> - dfListComp expr expr_ty c_ty c_id n_ty n_id quals - `thenDs` \ core_rest -> - returnDs (mkCoreIfThenElse core_filt core_rest (Var n_id)) + -- Non-last: must be a guard +dfListComp c_id n_id (ExprStmt guard ty : quals) + = dsLExpr guard `thenDs` \ core_guard -> + dfListComp c_id n_id quals `thenDs` \ core_rest -> + returnDs (mkIfThenElse core_guard core_rest (Var n_id)) -dfListComp expr expr_ty c_ty c_id n_ty n_id (LetQual binds : quals) - = panic "dfListComp:LetQual" +dfListComp c_id n_id (LetStmt binds : quals) + -- new in 1.3, local bindings + = dfListComp c_id n_id quals `thenDs` \ core_rest -> + dsLet binds core_rest -dfListComp expr expr_ty c_ty c_id n_ty n_id (GeneratorQual pat list1 : quals) +dfListComp c_id n_id (BindStmt pat list1 : quals) -- evaluate the two lists - = dsExpr list1 `thenDs` \ core_list1 -> + = dsLExpr list1 `thenDs` \ core_list1 -> -- find the required type - - let p_ty = outPatType pat - b_ty = n_ty -- alias b_ty to n_ty - fn_ty = mkFunTys [p_ty, b_ty] b_ty - lst_ty = coreExprType core_list1 + let x_ty = hsPatType pat + b_ty = idType n_id in -- create some new local id's - - newSysLocalsDs [b_ty,p_ty,fn_ty,lst_ty] `thenDs` \ [b,p,fn,lst] -> + newSysLocalsDs [b_ty,x_ty] `thenDs` \ [b,x] -> -- build rest of the comprehesion + dfListComp c_id b quals `thenDs` \ core_rest -> - dfListComp expr expr_ty c_ty c_id b_ty b quals `thenDs` \ core_rest -> -- build the pattern match - - matchSimply (Var p) pat b_ty core_rest (Var b) `thenDs` \ core_expr -> + matchSimply (Var x) (StmtCtxt ListComp) + pat core_rest (Var b) `thenDs` \ core_expr -> -- now build the outermost foldr, and return - + dsLookupGlobalId foldrName `thenDs` \ foldr_id -> returnDs ( - mkCoLetsAny - [NonRec fn (mkValLam [p, b] core_expr), - NonRec lst core_list1] - (mkFoldr p_ty n_ty fn n_id lst) + Var foldr_id `App` Type x_ty + `App` Type b_ty + `App` mkLams [x, b] core_expr + `App` Var n_id + `App` core_list1 ) +\end{code} + +%************************************************************************ +%* * +\subsection[DsPArrComp]{Desugaring of array comprehensions} +%* * +%************************************************************************ + +\begin{code} + +-- entry point for desugaring a parallel array comprehension +-- +-- [:e | qss:] = <<[:e | qss:]>> () [:():] +-- +dsPArrComp :: [Stmt Id] + -> Type -- Don't use; called with `undefined' below + -> DsM CoreExpr +dsPArrComp qs _ = + dsLookupGlobalId replicatePName `thenDs` \repP -> + let unitArray = mkApps (Var repP) [Type unitTy, + mkIntExpr 1, + mkCoreTup []] + in + dePArrComp qs (mkTuplePat []) unitArray -mkFoldr a b f z xs - = mkValApp (mkTyApp (Var foldrId) [a,b]) [VarArg f, VarArg z, VarArg xs] +-- the work horse +-- +dePArrComp :: [Stmt Id] + -> LPat Id -- the current generator pattern + -> CoreExpr -- the current generator expression + -> DsM CoreExpr +-- +-- <<[:e' | :]>> pa ea = mapP (\pa -> e') ea +-- +dePArrComp [ResultStmt e'] pa cea = + dsLookupGlobalId mapPName `thenDs` \mapP -> + let ty = parrElemType cea + in + deLambda ty pa e' `thenDs` \(clam, + ty'e') -> + returnDs $ mkApps (Var mapP) [Type ty, Type ty'e', clam, cea] +-- +-- <<[:e' | b, qs:]>> pa ea = <<[:e' | qs:]>> pa (filterP (\pa -> b) ea) +-- +dePArrComp (ExprStmt b _ : qs) pa cea = + dsLookupGlobalId filterPName `thenDs` \filterP -> + let ty = parrElemType cea + in + deLambda ty pa b `thenDs` \(clam,_) -> + dePArrComp qs pa (mkApps (Var filterP) [Type ty, clam, cea]) +-- +-- <<[:e' | p <- e, qs:]>> pa ea = +-- let ef = filterP (\x -> case x of {p -> True; _ -> False}) e +-- in +-- <<[:e' | qs:]>> (pa, p) (crossP ea ef) +-- +dePArrComp (BindStmt p e : qs) pa cea = + dsLookupGlobalId filterPName `thenDs` \filterP -> + dsLookupGlobalId crossPName `thenDs` \crossP -> + dsLExpr e `thenDs` \ce -> + let ty'cea = parrElemType cea + ty'ce = parrElemType ce + false = Var falseDataConId + true = Var trueDataConId + in + newSysLocalDs ty'ce `thenDs` \v -> + matchSimply (Var v) (StmtCtxt PArrComp) p true false `thenDs` \pred -> + let cef = mkApps (Var filterP) [Type ty'ce, mkLams [v] pred, ce] + ty'cef = ty'ce -- filterP preserves the type + pa' = mkTuplePat [pa, p] + in + dePArrComp qs pa' (mkApps (Var crossP) [Type ty'cea, Type ty'cef, cea, cef]) +-- +-- <<[:e' | let ds, qs:]>> pa ea = +-- <<[:e' | qs:]>> (pa, (x_1, ..., x_n)) +-- (mapP (\v@pa -> (v, let ds in (x_1, ..., x_n))) ea) +-- where +-- {x_1, ..., x_n} = DV (ds) -- Defined Variables +-- +dePArrComp (LetStmt ds : qs) pa cea = + dsLookupGlobalId mapPName `thenDs` \mapP -> + let xs = map unLoc (collectGroupBinders ds) + ty'cea = parrElemType cea + in + newSysLocalDs ty'cea `thenDs` \v -> + dsLet ds (mkCoreTup (map Var xs)) `thenDs` \clet -> + newSysLocalDs (exprType clet) `thenDs` \let'v -> + let projBody = mkDsLet (NonRec let'v clet) $ + mkCoreTup [Var v, Var let'v] + errTy = exprType projBody + errMsg = "DsListComp.dePArrComp: internal error!" + in + mkErrorAppDs pAT_ERROR_ID errTy errMsg `thenDs` \cerr -> + matchSimply (Var v) (StmtCtxt PArrComp) pa projBody cerr`thenDs` \ccase -> + let pa' = mkTuplePat [pa, mkTuplePat (map nlVarPat xs)] + proj = mkLams [v] ccase + in + dePArrComp qs pa' (mkApps (Var mapP) [Type ty'cea, proj, cea]) +-- +-- <<[:e' | qs | qss:]>> pa ea = +-- <<[:e' | qss:]>> (pa, (x_1, ..., x_n)) +-- (zipP ea <<[:(x_1, ..., x_n) | qs:]>>) +-- where +-- {x_1, ..., x_n} = DV (qs) +-- +dePArrComp (ParStmt qss : qs) pa cea = + dsLookupGlobalId crossPName `thenDs` \crossP -> + deParStmt qss `thenDs` \(pQss, + ceQss) -> + let ty'cea = parrElemType cea + ty'ceQss = parrElemType ceQss + pa' = mkTuplePat [pa, pQss] + in + dePArrComp qs pa' (mkApps (Var crossP) [Type ty'cea, Type ty'ceQss, + cea, ceQss]) + where + deParStmt [] = + -- empty parallel statement lists have not source representation + panic "DsListComp.dePArrComp: Empty parallel list comprehension" + deParStmt ((qs, xs):qss) = -- first statement + let resStmt = ResultStmt $ mkExplicitTuple (map nlHsVar xs) + in + dsPArrComp (map unLoc qs ++ [resStmt]) undefined `thenDs` \cqs -> + parStmts qss (mkTuplePat (map nlVarPat xs)) cqs + --- + parStmts [] pa cea = return (pa, cea) + parStmts ((qs, xs):qss) pa cea = -- subsequent statements (zip'ed) + dsLookupGlobalId zipPName `thenDs` \zipP -> + let pa' = mkTuplePat [pa, mkTuplePat (map nlVarPat xs)] + ty'cea = parrElemType cea + resStmt = ResultStmt $ mkExplicitTuple (map nlHsVar xs) + in + dsPArrComp (map unLoc qs ++ [resStmt]) undefined `thenDs` \cqs -> + let ty'cqs = parrElemType cqs + cea' = mkApps (Var zipP) [Type ty'cea, Type ty'cqs, cea, cqs] + in + parStmts qss pa' cea' + +-- generate Core corresponding to `\p -> e' +-- +deLambda :: Type -- type of the argument + -> LPat Id -- argument pattern + -> LHsExpr Id -- body + -> DsM (CoreExpr, Type) +deLambda ty p e = + newSysLocalDs ty `thenDs` \v -> + dsLExpr e `thenDs` \ce -> + let errTy = exprType ce + errMsg = "DsListComp.deLambda: internal error!" + in + mkErrorAppDs pAT_ERROR_ID errTy errMsg `thenDs` \cerr -> + matchSimply (Var v) (StmtCtxt PArrComp) p ce cerr `thenDs` \res -> + returnDs (mkLams [v] res, errTy) + +-- obtain the element type of the parallel array produced by the given Core +-- expression +-- +parrElemType :: CoreExpr -> Type +parrElemType e = + case splitTyConApp_maybe (exprType e) of + Just (tycon, [ty]) | tycon == parrTyCon -> ty + _ -> panic + "DsListComp.parrElemType: not a parallel array type" + +-- Smart constructor for source tuple patterns +-- +mkTuplePat :: [LPat id] -> LPat id +mkTuplePat [lpat] = lpat +mkTuplePat lpats = noLoc $ TuplePat lpats Boxed + +-- Smart constructor for source tuple expressions +-- +mkExplicitTuple :: [LHsExpr id] -> LHsExpr id +mkExplicitTuple [lexp] = lexp +mkExplicitTuple lexps = noLoc $ ExplicitTuple lexps Boxed \end{code}