+-- 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' = noLoc (TuplePat [pa, p] Boxed)
+ 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' = noLoc $ TuplePat [pa, noLoc (TuplePat (map nlVarPat xs) Boxed)] Boxed
+ 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 [] : qss2) pa cea = dePArrComp qss2 pa cea
+dePArrComp (ParStmt ((qs, xs):qss) : qss2) pa cea =
+ dsLookupGlobalId zipPName `thenDs` \zipP ->
+ let pa' = noLoc $ TuplePat [pa, noLoc (TuplePat (map nlVarPat xs) Boxed)] Boxed
+ ty'cea = parrElemType cea
+ resStmt = ResultStmt (noLoc $ ExplicitTuple (map nlHsVar xs) Boxed)
+ 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
+ dePArrComp (ParStmt qss : qss2) 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"
+\end{code}