-- |  This is really a hack for benchmarking.
-- Lift global allocations outside of timing loop.s

-- WARNING: seeded with DUPLICATED code from Unariser

module Gibbon.Passes.HoistNewBuf
    (hoistNewBuf) where

import Prelude hiding (exp)
import qualified Data.List as L

import Gibbon.Common
import Gibbon.L3.Syntax

--------------------------------------------------------------------------------

data GcPoint = App | RegAlloc

-- | Strip out the NewBuf bindings up until the point control flow diverges.
hoistNewBuf :: Prog3 -> PassM Prog3
hoistNewBuf :: Prog3 -> PassM Prog3
hoistNewBuf = (Env2 Ty3 -> Exp3 -> PassM Exp3) -> Prog3 -> PassM Prog3
forall (m :: * -> *).
Monad m =>
(Env2 Ty3 -> Exp3 -> m Exp3) -> Prog3 -> m Prog3
mapMExprs Env2 Ty3 -> Exp3 -> PassM Exp3
forall ignored. ignored -> Exp3 -> PassM Exp3
hoistExp

hoistExp :: ignored -> Exp3 -> PassM Exp3
hoistExp :: forall ignored. ignored -> Exp3 -> PassM Exp3
hoistExp ignored
_ Exp3
ex0 = Exp3 -> PassM Exp3
forall a. a -> PassM a
forall (m :: * -> *) a. Monad m => a -> m a
return (Exp3 -> PassM Exp3) -> Exp3 -> PassM Exp3
forall a b. (a -> b) -> a -> b
$ Bool -> Exp3 -> Exp3
gocap Bool
False Exp3
ex0
  where
  -- Returns bindings from shadowstack pushes to pops, including the
  -- region allocation or function call.
  --
  -- assumption: let bindings for shadowstack push and pop ops, and the region
  -- allocation or function call appear one after the other, perhaps with code
  -- that can be hoisted in between.
  fromPushToPop :: (Var,[()],Ty3,Exp3) -> Exp3 -> ([(Var,[()],Ty3,Exp3)], GcPoint, Exp3)
  fromPushToPop :: (Var, [()], Ty3, Exp3)
-> Exp3 -> ([(Var, [()], Ty3, Exp3)], GcPoint, Exp3)
fromPushToPop (Var, [()], Ty3, Exp3)
first_push Exp3
e0 =
    let
        pushes :: [(Var,[()],Ty3,Exp3)] -> Int -> GcPoint -> Exp3
               -> ([(Var,[()],Ty3,Exp3)], GcPoint, Exp3)
        pushes :: [(Var, [()], Ty3, Exp3)]
-> Int
-> GcPoint
-> Exp3
-> ([(Var, [()], Ty3, Exp3)], GcPoint, Exp3)
pushes [(Var, [()], Ty3, Exp3)]
binds Int
n GcPoint
mb_hoist Exp3
e1 =
          case Exp3
e1 of
            LetE b :: (Var, [()], Ty3, Exp3)
b@(Var
_v,[()]
_locs,Ty3
_ty,Exp3
rhs) Exp3
bod ->
              case Exp3
rhs of
                Ext(SSPush{})        -> [(Var, [()], Ty3, Exp3)]
-> Int
-> GcPoint
-> Exp3
-> ([(Var, [()], Ty3, Exp3)], GcPoint, Exp3)
pushes ([(Var, [()], Ty3, Exp3)]
binds [(Var, [()], Ty3, Exp3)]
-> [(Var, [()], Ty3, Exp3)] -> [(Var, [()], Ty3, Exp3)]
forall a. [a] -> [a] -> [a]
++ [(Var, [()], Ty3, Exp3)
b]) (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) GcPoint
mb_hoist Exp3
bod
                Ext(SSPop{})         -> [(Var, [()], Ty3, Exp3)]
-> Int
-> GcPoint
-> Exp3
-> ([(Var, [()], Ty3, Exp3)], GcPoint, Exp3)
pops ([(Var, [()], Ty3, Exp3)]
binds [(Var, [()], Ty3, Exp3)]
-> [(Var, [()], Ty3, Exp3)] -> [(Var, [()], Ty3, Exp3)]
forall a. [a] -> [a] -> [a]
++ [(Var, [()], Ty3, Exp3)
b]) (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) GcPoint
mb_hoist Exp3
bod
                Ext(NewBuffer{})     -> [(Var, [()], Ty3, Exp3)]
-> Int
-> GcPoint
-> Exp3
-> ([(Var, [()], Ty3, Exp3)], GcPoint, Exp3)
pushes ([(Var, [()], Ty3, Exp3)]
binds [(Var, [()], Ty3, Exp3)]
-> [(Var, [()], Ty3, Exp3)] -> [(Var, [()], Ty3, Exp3)]
forall a. [a] -> [a] -> [a]
++ [(Var, [()], Ty3, Exp3)
b]) Int
n GcPoint
RegAlloc Exp3
bod
                Ext(NewParBuffer{})  -> [(Var, [()], Ty3, Exp3)]
-> Int
-> GcPoint
-> Exp3
-> ([(Var, [()], Ty3, Exp3)], GcPoint, Exp3)
pushes ([(Var, [()], Ty3, Exp3)]
binds [(Var, [()], Ty3, Exp3)]
-> [(Var, [()], Ty3, Exp3)] -> [(Var, [()], Ty3, Exp3)]
forall a. [a] -> [a] -> [a]
++ [(Var, [()], Ty3, Exp3)
b]) Int
n GcPoint
RegAlloc Exp3
bod
                Exp3
_                    -> [(Var, [()], Ty3, Exp3)]
-> Int
-> GcPoint
-> Exp3
-> ([(Var, [()], Ty3, Exp3)], GcPoint, Exp3)
pushes ([(Var, [()], Ty3, Exp3)]
binds [(Var, [()], Ty3, Exp3)]
-> [(Var, [()], Ty3, Exp3)] -> [(Var, [()], Ty3, Exp3)]
forall a. [a] -> [a] -> [a]
++ [(Var, [()], Ty3, Exp3)
b]) Int
n GcPoint
mb_hoist Exp3
bod
            Exp3
_ -> [Char] -> ([(Var, [()], Ty3, Exp3)], GcPoint, Exp3)
forall a. HasCallStack => [Char] -> a
error ([Char] -> ([(Var, [()], Ty3, Exp3)], GcPoint, Exp3))
-> [Char] -> ([(Var, [()], Ty3, Exp3)], GcPoint, Exp3)
forall a b. (a -> b) -> a -> b
$ [Char]
"hoistNewBuf: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Exp3 -> [Char]
forall a. Out a => a -> [Char]
sdoc Exp3
e1

        pops :: [(Var,[()],Ty3,Exp3)] -> Int -> GcPoint -> Exp3
             -> ([(Var,[()],Ty3,Exp3)], GcPoint, Exp3)
        pops :: [(Var, [()], Ty3, Exp3)]
-> Int
-> GcPoint
-> Exp3
-> ([(Var, [()], Ty3, Exp3)], GcPoint, Exp3)
pops [(Var, [()], Ty3, Exp3)]
binds Int
0 GcPoint
mb_hoist Exp3
e1 = ([(Var, [()], Ty3, Exp3)]
binds, GcPoint
mb_hoist, Exp3
e1)
        pops [(Var, [()], Ty3, Exp3)]
binds Int
n GcPoint
mb_hoist Exp3
e1 =
          case Exp3
e1 of
            LetE b :: (Var, [()], Ty3, Exp3)
b@(Var
_v,[()]
_locs,Ty3
_ty,Exp3
rhs) Exp3
bod ->
              case Exp3
rhs of
                Ext(SSPop{}) -> [(Var, [()], Ty3, Exp3)]
-> Int
-> GcPoint
-> Exp3
-> ([(Var, [()], Ty3, Exp3)], GcPoint, Exp3)
pops ([(Var, [()], Ty3, Exp3)]
binds [(Var, [()], Ty3, Exp3)]
-> [(Var, [()], Ty3, Exp3)] -> [(Var, [()], Ty3, Exp3)]
forall a. [a] -> [a] -> [a]
++ [(Var, [()], Ty3, Exp3)
b]) (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) GcPoint
mb_hoist Exp3
bod
                Exp3
_ -> [Char] -> ([(Var, [()], Ty3, Exp3)], GcPoint, Exp3)
forall a. HasCallStack => [Char] -> a
error ([Char] -> ([(Var, [()], Ty3, Exp3)], GcPoint, Exp3))
-> [Char] -> ([(Var, [()], Ty3, Exp3)], GcPoint, Exp3)
forall a b. (a -> b) -> a -> b
$ [Char]
"hoistNewBuf: expected pop, got " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Exp3 -> [Char]
forall a. Out a => a -> [Char]
sdoc Exp3
rhs
            Exp3
_ -> [Char] -> ([(Var, [()], Ty3, Exp3)], GcPoint, Exp3)
forall a. HasCallStack => [Char] -> a
error ([Char] -> ([(Var, [()], Ty3, Exp3)], GcPoint, Exp3))
-> [Char] -> ([(Var, [()], Ty3, Exp3)], GcPoint, Exp3)
forall a b. (a -> b) -> a -> b
$ [Char]
"hoistNewBuf: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Exp3 -> [Char]
forall a. Out a => a -> [Char]
sdoc Exp3
e1
    in [(Var, [()], Ty3, Exp3)]
-> Int
-> GcPoint
-> Exp3
-> ([(Var, [()], Ty3, Exp3)], GcPoint, Exp3)
pushes [(Var, [()], Ty3, Exp3)
first_push] Int
1 GcPoint
App Exp3
e0

  gocap :: Bool -> Exp3 -> Exp3
gocap Bool
hoist Exp3
ex =
    if Bool -> Bool
not (Exp3 -> Bool
forall (e :: * -> * -> *) l d. PreExp e l d -> Bool
hasTimeIt Exp3
ex) then Exp3
ex else
      let ([(Var, [()], Ty3, Exp3)]
lets,Exp3
ex') = Bool -> Exp3 -> ([(Var, [()], Ty3, Exp3)], Exp3)
go Bool
hoist Exp3
ex in
        [(Var, [()], Ty3, Exp3)] -> Exp3 -> Exp3
forall loc dec (ext :: * -> * -> *).
[(Var, [loc], dec, PreExp ext loc dec)]
-> PreExp ext loc dec -> PreExp ext loc dec
mkLets [(Var, [()], Ty3, Exp3)]
lets Exp3
ex'

  go :: Bool -> Exp3 -> ([(Var,[()],Ty3,Exp3)], Exp3)
  go :: Bool -> Exp3 -> ([(Var, [()], Ty3, Exp3)], Exp3)
go Bool
hoist Exp3
e0 =
   case Exp3
e0 of
    -- Here's where we lift outside timings!!

    (LetE bnd :: (Var, [()], Ty3, Exp3)
bnd@(Var
_v,[()]
_locs,Ty3
_t,(Ext SSPush{})) Exp3
bod) ->
      if Bool
hoist
        then
          let ([(Var, [()], Ty3, Exp3)]
binds, GcPoint
mb_hoist, Exp3
cont) = (Var, [()], Ty3, Exp3)
-> Exp3 -> ([(Var, [()], Ty3, Exp3)], GcPoint, Exp3)
fromPushToPop (Var, [()], Ty3, Exp3)
bnd Exp3
bod
              ([(Var, [()], Ty3, Exp3)]
lts1,Exp3
cont') = Bool -> Exp3 -> ([(Var, [()], Ty3, Exp3)], Exp3)
go Bool
hoist Exp3
cont
          in case GcPoint
mb_hoist of
               GcPoint
RegAlloc -> ([(Var, [()], Ty3, Exp3)]
binds [(Var, [()], Ty3, Exp3)]
-> [(Var, [()], Ty3, Exp3)] -> [(Var, [()], Ty3, Exp3)]
forall a. [a] -> [a] -> [a]
++ [(Var, [()], Ty3, Exp3)]
lts1, Exp3
cont')
               GcPoint
App      -> ([(Var, [()], Ty3, Exp3)]
lts1, [(Var, [()], Ty3, Exp3)] -> Exp3 -> Exp3
forall loc dec (ext :: * -> * -> *).
[(Var, [loc], dec, PreExp ext loc dec)]
-> PreExp ext loc dec -> PreExp ext loc dec
mkLets [(Var, [()], Ty3, Exp3)]
binds Exp3
cont')
        else let ([(Var, [()], Ty3, Exp3)]
lts, Exp3
bod') = Bool -> Exp3 -> ([(Var, [()], Ty3, Exp3)], Exp3)
go Bool
hoist Exp3
bod
             in ([(Var, [()], Ty3, Exp3)]
lts, (Var, [()], Ty3, Exp3) -> Exp3 -> Exp3
forall (ext :: * -> * -> *) loc dec.
(Var, [loc], dec, PreExp ext loc dec)
-> PreExp ext loc dec -> PreExp ext loc dec
LetE (Var, [()], Ty3, Exp3)
bnd Exp3
bod')

    (LetE (Var
v,[()]
locs,Ty3
ty,(TimeIt Exp3
e Ty3
t Bool
b)) Exp3
bod) ->
      let ([(Var, [()], Ty3, Exp3)]
lts, Exp3
e') = Bool -> Exp3 -> ([(Var, [()], Ty3, Exp3)], Exp3)
go Bool
True Exp3
e
          ([(Var, [()], Ty3, Exp3)]
lts1, Exp3
bod') = Bool -> Exp3 -> ([(Var, [()], Ty3, Exp3)], Exp3)
go Bool
False Exp3
bod
      in ([(Var, [()], Ty3, Exp3)]
lts [(Var, [()], Ty3, Exp3)]
-> [(Var, [()], Ty3, Exp3)] -> [(Var, [()], Ty3, Exp3)]
forall a. [a] -> [a] -> [a]
++ [(Var, [()], Ty3, Exp3)]
lts1, (Var, [()], Ty3, Exp3) -> Exp3 -> Exp3
forall (ext :: * -> * -> *) loc dec.
(Var, [loc], dec, PreExp ext loc dec)
-> PreExp ext loc dec -> PreExp ext loc dec
LetE (Var
v,[()]
locs,Ty3
ty,Exp3 -> Ty3 -> Bool -> Exp3
forall (ext :: * -> * -> *) loc dec.
PreExp ext loc dec -> dec -> Bool -> PreExp ext loc dec
TimeIt Exp3
e' Ty3
t Bool
b) Exp3
bod')

    (TimeIt Exp3
e Ty3
t Bool
b) -> let ([(Var, [()], Ty3, Exp3)]
lts,Exp3
e') = Bool -> Exp3 -> ([(Var, [()], Ty3, Exp3)], Exp3)
go Bool
hoist Exp3
e
                      in ([(Var, [()], Ty3, Exp3)]
lts, Exp3 -> Ty3 -> Bool -> Exp3
forall (ext :: * -> * -> *) loc dec.
PreExp ext loc dec -> dec -> Bool -> PreExp ext loc dec
TimeIt Exp3
e' Ty3
t Bool
b)
    (LetE (Var
v,[()]
locs,Ty3
t, nb :: Exp3
nb@((Ext NewBuffer{}))) Exp3
bod) ->
      if Bool
hoist
      then let ([(Var, [()], Ty3, Exp3)]
lts1,Exp3
bod') = Bool -> Exp3 -> ([(Var, [()], Ty3, Exp3)], Exp3)
go Bool
hoist Exp3
bod
           in ((Var
v,[()]
locs,Ty3
t, Exp3
nb)(Var, [()], Ty3, Exp3)
-> [(Var, [()], Ty3, Exp3)] -> [(Var, [()], Ty3, Exp3)]
forall a. a -> [a] -> [a]
:[(Var, [()], Ty3, Exp3)]
lts1, Exp3
bod')
      else let ([(Var, [()], Ty3, Exp3)]
lts1,Exp3
bod') = Bool -> Exp3 -> ([(Var, [()], Ty3, Exp3)], Exp3)
go Bool
hoist Exp3
bod
           in  ([(Var, [()], Ty3, Exp3)]
lts1, (Var, [()], Ty3, Exp3) -> Exp3 -> Exp3
forall (ext :: * -> * -> *) loc dec.
(Var, [loc], dec, PreExp ext loc dec)
-> PreExp ext loc dec -> PreExp ext loc dec
LetE (Var
v,[()]
locs,Ty3
t,Exp3
nb) Exp3
bod')
    (LetE (Var
v,[()]
locs,Ty3
t, nb :: Exp3
nb@((Ext NewParBuffer{}))) Exp3
bod) ->
      if Bool
hoist
      then let ([(Var, [()], Ty3, Exp3)]
lts1,Exp3
bod') = Bool -> Exp3 -> ([(Var, [()], Ty3, Exp3)], Exp3)
go Bool
hoist Exp3
bod
           in ((Var
v,[()]
locs,Ty3
t, Exp3
nb)(Var, [()], Ty3, Exp3)
-> [(Var, [()], Ty3, Exp3)] -> [(Var, [()], Ty3, Exp3)]
forall a. a -> [a] -> [a]
:[(Var, [()], Ty3, Exp3)]
lts1, Exp3
bod')
      else let ([(Var, [()], Ty3, Exp3)]
lts1,Exp3
bod') = Bool -> Exp3 -> ([(Var, [()], Ty3, Exp3)], Exp3)
go Bool
hoist Exp3
bod
           in  ([(Var, [()], Ty3, Exp3)]
lts1, (Var, [()], Ty3, Exp3) -> Exp3 -> Exp3
forall (ext :: * -> * -> *) loc dec.
(Var, [loc], dec, PreExp ext loc dec)
-> PreExp ext loc dec -> PreExp ext loc dec
LetE (Var
v,[()]
locs,Ty3
t,Exp3
nb) Exp3
bod')
    (LetE (Var
v,[()]
locs,Ty3
t, nb :: Exp3
nb@(Ext EndOfBuffer{})) Exp3
bod) ->
      if Bool
hoist
      then let ([(Var, [()], Ty3, Exp3)]
lts1,Exp3
bod') = Bool -> Exp3 -> ([(Var, [()], Ty3, Exp3)], Exp3)
go Bool
hoist Exp3
bod
           in ((Var
v,[()]
locs,Ty3
t, Exp3
nb)(Var, [()], Ty3, Exp3)
-> [(Var, [()], Ty3, Exp3)] -> [(Var, [()], Ty3, Exp3)]
forall a. a -> [a] -> [a]
:[(Var, [()], Ty3, Exp3)]
lts1, Exp3
bod')
      else let ([(Var, [()], Ty3, Exp3)]
lts1,Exp3
bod') = Bool -> Exp3 -> ([(Var, [()], Ty3, Exp3)], Exp3)
go Bool
hoist Exp3
bod
           in  ([(Var, [()], Ty3, Exp3)]
lts1, (Var, [()], Ty3, Exp3) -> Exp3 -> Exp3
forall (ext :: * -> * -> *) loc dec.
(Var, [loc], dec, PreExp ext loc dec)
-> PreExp ext loc dec -> PreExp ext loc dec
LetE (Var
v,[()]
locs,Ty3
t,Exp3
nb) Exp3
bod')

    -- boilerplate

    (LitE Int
_)      -> ([], Exp3
e0)
    (CharE Char
_)     -> ([], Exp3
e0)
    (FloatE Double
_)    -> ([], Exp3
e0)
    (LitSymE Var
_)   -> ([], Exp3
e0)
    (VarE Var
_)      -> ([], Exp3
e0)
    (AppE Var
_ [()]
_ [Exp3]
_)  -> ([], Exp3
e0)
    (PrimAppE{})  -> ([], Exp3
e0)
    (MapE (Var, Ty3, Exp3)
_ Exp3
_)    -> [Char] -> ([(Var, [()], Ty3, Exp3)], Exp3)
forall a. HasCallStack => [Char] -> a
error [Char]
"hoistExp.go: FINISHME MapE"
    (FoldE (Var, Ty3, Exp3)
_ (Var, Ty3, Exp3)
_ Exp3
_) -> [Char] -> ([(Var, [()], Ty3, Exp3)], Exp3)
forall a. HasCallStack => [Char] -> a
error [Char]
"hoistExp.go: FINISHME FoldE"

    (LetE (Var
v,[()]
locs,Ty3
t,Exp3
rhs) Exp3
bod) ->
        let ([(Var, [()], Ty3, Exp3)]
lts1, Exp3
rhs') = Bool -> Exp3 -> ([(Var, [()], Ty3, Exp3)], Exp3)
go Bool
hoist Exp3
rhs
            ([(Var, [()], Ty3, Exp3)]
lts2, Exp3
bod') = Bool -> Exp3 -> ([(Var, [()], Ty3, Exp3)], Exp3)
go Bool
hoist Exp3
bod
        in ([(Var, [()], Ty3, Exp3)]
lts1[(Var, [()], Ty3, Exp3)]
-> [(Var, [()], Ty3, Exp3)] -> [(Var, [()], Ty3, Exp3)]
forall a. [a] -> [a] -> [a]
++[(Var, [()], Ty3, Exp3)]
lts2, (Var, [()], Ty3, Exp3) -> Exp3 -> Exp3
forall (ext :: * -> * -> *) loc dec.
(Var, [loc], dec, PreExp ext loc dec)
-> PreExp ext loc dec -> PreExp ext loc dec
LetE (Var
v,[()]
locs,Ty3
t,Exp3
rhs') Exp3
bod')

    (IfE Exp3
e1 Exp3
e2 Exp3
e3) ->
         let ([(Var, [()], Ty3, Exp3)]
lts1, Exp3
e1') = Bool -> Exp3 -> ([(Var, [()], Ty3, Exp3)], Exp3)
go Bool
hoist Exp3
e1 in
         ([(Var, [()], Ty3, Exp3)]
lts1, Exp3 -> Exp3 -> Exp3 -> Exp3
forall (ext :: * -> * -> *) loc dec.
PreExp ext loc dec
-> PreExp ext loc dec -> PreExp ext loc dec -> PreExp ext loc dec
IfE Exp3
e1' (Bool -> Exp3 -> Exp3
gocap Bool
hoist Exp3
e2) (Bool -> Exp3 -> Exp3
gocap Bool
hoist Exp3
e3))

    (ProjE Int
i Exp3
e)  -> let ([(Var, [()], Ty3, Exp3)]
lts,Exp3
e') = Bool -> Exp3 -> ([(Var, [()], Ty3, Exp3)], Exp3)
go Bool
hoist Exp3
e in
                    ([(Var, [()], Ty3, Exp3)]
lts, Int -> Exp3 -> Exp3
forall (ext :: * -> * -> *) loc dec.
Int -> PreExp ext loc dec -> PreExp ext loc dec
ProjE Int
i Exp3
e')
    (MkProdE [Exp3]
es) -> let ([[(Var, [()], Ty3, Exp3)]]
ltss,[Exp3]
es') = [([(Var, [()], Ty3, Exp3)], Exp3)]
-> ([[(Var, [()], Ty3, Exp3)]], [Exp3])
forall a b. [(a, b)] -> ([a], [b])
unzip ([([(Var, [()], Ty3, Exp3)], Exp3)]
 -> ([[(Var, [()], Ty3, Exp3)]], [Exp3]))
-> [([(Var, [()], Ty3, Exp3)], Exp3)]
-> ([[(Var, [()], Ty3, Exp3)]], [Exp3])
forall a b. (a -> b) -> a -> b
$ (Exp3 -> ([(Var, [()], Ty3, Exp3)], Exp3))
-> [Exp3] -> [([(Var, [()], Ty3, Exp3)], Exp3)]
forall a b. (a -> b) -> [a] -> [b]
L.map (Bool -> Exp3 -> ([(Var, [()], Ty3, Exp3)], Exp3)
go Bool
hoist) [Exp3]
es in
                    ([[(Var, [()], Ty3, Exp3)]] -> [(Var, [()], Ty3, Exp3)]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[(Var, [()], Ty3, Exp3)]]
ltss, [Exp3] -> Exp3
forall (ext :: * -> * -> *) loc dec.
[PreExp ext loc dec] -> PreExp ext loc dec
MkProdE [Exp3]
es')

    (CaseE Exp3
scrt [([Char], [(Var, ())], Exp3)]
ls) -> let ([(Var, [()], Ty3, Exp3)]
lts,Exp3
scrt') = Bool -> Exp3 -> ([(Var, [()], Ty3, Exp3)], Exp3)
go Bool
hoist Exp3
scrt
                       in ([(Var, [()], Ty3, Exp3)]
lts, Exp3 -> [([Char], [(Var, ())], Exp3)] -> Exp3
forall (ext :: * -> * -> *) loc dec.
PreExp ext loc dec
-> [([Char], [(Var, loc)], PreExp ext loc dec)]
-> PreExp ext loc dec
CaseE Exp3
scrt' [ ([Char]
k,[(Var, ())]
vs, Bool -> Exp3 -> Exp3
gocap Bool
hoist Exp3
e)
                                            | ([Char]
k,[(Var, ())]
vs,Exp3
e) <- [([Char], [(Var, ())], Exp3)]
ls ])
    (DataConE ()
c [Char]
loc [Exp3]
es) -> let ([[(Var, [()], Ty3, Exp3)]]
ltss,[Exp3]
es') = [([(Var, [()], Ty3, Exp3)], Exp3)]
-> ([[(Var, [()], Ty3, Exp3)]], [Exp3])
forall a b. [(a, b)] -> ([a], [b])
unzip ([([(Var, [()], Ty3, Exp3)], Exp3)]
 -> ([[(Var, [()], Ty3, Exp3)]], [Exp3]))
-> [([(Var, [()], Ty3, Exp3)], Exp3)]
-> ([[(Var, [()], Ty3, Exp3)]], [Exp3])
forall a b. (a -> b) -> a -> b
$ (Exp3 -> ([(Var, [()], Ty3, Exp3)], Exp3))
-> [Exp3] -> [([(Var, [()], Ty3, Exp3)], Exp3)]
forall a b. (a -> b) -> [a] -> [b]
L.map (Bool -> Exp3 -> ([(Var, [()], Ty3, Exp3)], Exp3)
go Bool
hoist) [Exp3]
es in
                           ([[(Var, [()], Ty3, Exp3)]] -> [(Var, [()], Ty3, Exp3)]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[(Var, [()], Ty3, Exp3)]]
ltss, () -> [Char] -> [Exp3] -> Exp3
forall (ext :: * -> * -> *) loc dec.
loc -> [Char] -> [PreExp ext loc dec] -> PreExp ext loc dec
DataConE ()
c [Char]
loc [Exp3]
es')

    (SpawnE{})    -> ([], Exp3
e0)

    (Exp3
SyncE)       -> ([], Exp3
e0)

    (WithArenaE Var
v Exp3
e) -> let ([(Var, [()], Ty3, Exp3)]
lts,Exp3
e') = Bool -> Exp3 -> ([(Var, [()], Ty3, Exp3)], Exp3)
go Bool
hoist Exp3
e in
                        ([(Var, [()], Ty3, Exp3)]
lts, Var -> Exp3 -> Exp3
forall (ext :: * -> * -> *) loc dec.
Var -> PreExp ext loc dec -> PreExp ext loc dec
WithArenaE Var
v Exp3
e')

    (Ext E3Ext () Ty3
_) -> ([], Exp3
e0)


    -- (MapE (v,t,e') e) ->
    -- (FoldE (v1,t1,e1) (v2,t2,e2) e3) ->