Skip to content

Commit 12af478

Browse files
committed
Make buildScoped take a second continuation to consume the decls from below.
That is, instead of returning an `Abs decls result`, it accepts a continuation that takes `decls` and `e` as arguments, with the decls in scope in the env. This avoids having to use `refreshAbs`. It wasn't a problem previously because decls only appeared in blocks, so there was only an Atom beneath them. But that will change when we add decls to binders.
1 parent 360cd31 commit 12af478

File tree

5 files changed

+95
-72
lines changed

5 files changed

+95
-72
lines changed

src/lib/Builder.hs

Lines changed: 64 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,17 @@ class (EnvReader m, EnvExtender m, Fallible1 m, IRRep r)
4343
rawEmitDecl :: Emits n => NameHint -> LetAnn -> Expr r n -> m n (AtomVar r n)
4444

4545
class Builder r m => ScopableBuilder (r::IR) (m::MonadKind1) | m -> r where
46-
buildScoped
46+
buildScopedAndThen
4747
:: SinkableE e
4848
=> (forall l. (Emits l, DExt n l) => m l (e l))
49-
-> m n (Abs (Nest (Decl r)) e n)
49+
-> (forall l. DExt n l => Nest (Decl r) n l -> e l -> m l a)
50+
-> m n a
51+
52+
buildScoped
53+
:: (ScopableBuilder r m, SinkableE e)
54+
=> (forall l. (Emits l, DExt n l) => m l (e l))
55+
-> m n (Abs (Nest (Decl r)) e n)
56+
buildScoped cont = buildScopedAndThen cont \decls body -> return $ Abs decls body
5057

5158
type SBuilder = Builder SimpIR
5259
type CBuilder = Builder CoreIR
@@ -208,21 +215,26 @@ instance ( RenameB frag, HoistableB frag, OutFrag frag
208215
, ExtOutMap Env frag, Fallible m, IRRep r)
209216
=> ScopableBuilder r (DoubleBuilderT r frag m) where
210217
-- TODO: find a safe API for DoubleInplaceT sufficient to implement this
211-
buildScoped cont = DoubleBuilderT do
212-
(ans, decls) <- UnsafeMakeDoubleInplaceT $
218+
buildScopedAndThen cont1 cont2 = DoubleBuilderT do
219+
(ans, topDecls) <- UnsafeMakeDoubleInplaceT $
213220
StateT \s@(topScope, _) -> do
214-
Abs rdecls (PairE e (LiftE topDecls)) <-
215-
locallyMutableInplaceT do
216-
(e, (_, topDecls)) <- flip runStateT (topScope, emptyOutFrag) $
217-
unsafeRunDoubleInplaceT $ runDoubleBuilderT' do
218-
Emits <- fabricateEmitsEvidenceM
219-
Distinct <- getDistinct
220-
cont
221-
return $ PairE e $ LiftE topDecls
222-
return ((Abs (unRNest rdecls) e, topDecls), s)
223-
unsafeEmitDoubleInplaceTHoisted decls
221+
(ans, topDecls) <- locallyMutableInplaceT
222+
(do (e, s') <- flip runStateT (topScope, emptyOutFrag) $
223+
unsafeRunDoubleInplaceT $ runDoubleBuilderT' do
224+
Emits <- fabricateEmitsEvidenceM
225+
Distinct <- getDistinct
226+
cont1
227+
return $ PairE e $ LiftE s')
228+
(\rdecls (PairE e (LiftE s')) -> do
229+
(ans, (_, topDecls)) <- flip runStateT s' $
230+
unsafeRunDoubleInplaceT $ runDoubleBuilderT' do
231+
Distinct <- getDistinct
232+
cont2 (unRNest rdecls) e
233+
return (ans, topDecls))
234+
return ((ans, topDecls), s)
235+
unsafeEmitDoubleInplaceTHoisted topDecls
224236
return ans
225-
{-# INLINE buildScoped #-}
237+
{-# INLINE buildScopedAndThen #-}
226238

227239
-- TODO: derive this instead
228240
instance ( IRRep r, RenameB frag, HoistableB frag, OutFrag frag
@@ -385,7 +397,7 @@ instance Fallible m => TopBuilder (TopBuilderT m) where
385397
{-# INLINE emitNamelessEnv #-}
386398

387399
localTopBuilder cont = TopBuilderT $
388-
locallyMutableInplaceT $ runTopBuilderT' cont
400+
locallyMutableInplaceT (runTopBuilderT' cont) (\d e -> return $ Abs d e)
389401
{-# INLINE localTopBuilder #-}
390402

391403
instance (SinkableV v, TopBuilder m) => TopBuilder (SubstReaderT v m i) where
@@ -470,14 +482,12 @@ liftEmitBuilder cont = do
470482
emitDecls $ Abs (unsafeCoerceB $ unRNest decls) result
471483

472484
instance (IRRep r, Fallible m) => ScopableBuilder r (BuilderT r m) where
473-
buildScoped cont = BuilderT do
474-
Abs rdecls e <- locallyMutableInplaceT $
475-
runBuilderT' do
476-
Emits <- fabricateEmitsEvidenceM
477-
Distinct <- getDistinct
478-
cont
479-
return $ Abs (unRNest rdecls) e
480-
{-# INLINE buildScoped #-}
485+
buildScopedAndThen cont1 cont2 = BuilderT $ locallyMutableInplaceT
486+
(runBuilderT' do
487+
Emits <- fabricateEmitsEvidenceM
488+
cont1 )
489+
(\rdecls e -> runBuilderT' $ cont2 (unRNest rdecls) e)
490+
{-# INLINE buildScopedAndThen #-}
481491

482492
newtype BuilderDeclEmission (r::IR) (n::S) (l::S) = BuilderDeclEmission (Decl r n l)
483493
instance IRRep r => ExtOutMap Env (BuilderDeclEmission r) where
@@ -504,33 +514,41 @@ instance (IRRep r, Fallible m) => EnvExtender (BuilderT r m) where
504514
{-# INLINE refreshAbs #-}
505515

506516
instance (SinkableV v, ScopableBuilder r m) => ScopableBuilder r (SubstReaderT v m i) where
507-
buildScoped cont = SubstReaderT $ ReaderT \env ->
508-
buildScoped $
509-
runReaderT (runSubstReaderT' cont) (sink env)
510-
{-# INLINE buildScoped #-}
517+
buildScopedAndThen cont1 cont2 = SubstReaderT $ ReaderT \env ->
518+
buildScopedAndThen
519+
(runReaderT (runSubstReaderT' cont1) (sink env))
520+
(\d e -> runReaderT (runSubstReaderT' $ cont2 d e) (sink env))
521+
{-# INLINE buildScopedAndThen #-}
511522

512523
instance (SinkableV v, Builder r m) => Builder r (SubstReaderT v m i) where
513524
rawEmitDecl hint ann expr = SubstReaderT $ lift $ emitDecl hint ann expr
514525
{-# INLINE rawEmitDecl #-}
515526

516527
instance (SinkableE e, ScopableBuilder r m) => ScopableBuilder r (OutReaderT e m) where
517-
buildScoped cont = OutReaderT $ ReaderT \env ->
518-
buildScoped do
519-
env' <- sinkM env
520-
runReaderT (runOutReaderT' cont) env'
521-
{-# INLINE buildScoped #-}
528+
buildScopedAndThen cont1 cont2 = OutReaderT $ ReaderT \env ->
529+
buildScopedAndThen
530+
(do env' <- sinkM env
531+
runReaderT (runOutReaderT' cont1) env')
532+
(\d e -> do
533+
env' <- sinkM env
534+
runReaderT (runOutReaderT' $ cont2 d e) env')
535+
{-# INLINE buildScopedAndThen #-}
522536

523537
instance (SinkableE e, Builder r m) => Builder r (OutReaderT e m) where
524538
rawEmitDecl hint ann expr =
525539
OutReaderT $ lift $ emitDecl hint ann expr
526540
{-# INLINE rawEmitDecl #-}
527541

528542
instance (SinkableE e, ScopableBuilder r m) => ScopableBuilder r (ReaderT1 e m) where
529-
buildScoped cont = ReaderT1 $ ReaderT \env ->
530-
buildScoped do
531-
env' <- sinkM env
532-
runReaderT (runReaderT1' cont) env'
533-
{-# INLINE buildScoped #-}
543+
buildScopedAndThen cont1 cont2 = ReaderT1 $ ReaderT \env ->
544+
buildScopedAndThen
545+
(do env' <- sinkM env
546+
runReaderT (runReaderT1' cont1) env')
547+
(\d e -> do
548+
env' <- sinkM env
549+
runReaderT (runReaderT1' $ cont2 d e) env')
550+
551+
{-# INLINE buildScopedAndThen #-}
534552

535553
instance (SinkableE e, Builder r m) => Builder r (ReaderT1 e m) where
536554
rawEmitDecl hint ann expr =
@@ -542,11 +560,14 @@ instance (SinkableE e, HoistableState e, Builder r m) => Builder r (StateT1 e m)
542560
{-# INLINE rawEmitDecl #-}
543561

544562
instance (SinkableE e, HoistableState e, ScopableBuilder r m) => ScopableBuilder r (StateT1 e m) where
545-
buildScoped cont = StateT1 \s -> do
546-
Abs decls (e `PairE` s') <- buildScoped $ liftM toPairE $ runStateT1 cont =<< sinkM s
547-
let s'' = hoistState s decls s'
548-
return (Abs decls e, s'')
549-
{-# INLINE buildScoped #-}
563+
buildScopedAndThen cont1 cont2 = StateT1 \s1 -> do
564+
buildScopedAndThen
565+
(liftM toPairE $ runStateT1 cont1 =<< sinkM s1)
566+
(\decls (PairE e s2) -> do
567+
let s3 = hoistState s1 decls s2
568+
(ans, s4) <- runStateT1 (cont2 decls e) (sink s3)
569+
let s5 = hoistState s3 decls s4
570+
return (ans, s5))
550571

551572
instance (SinkableE e, HoistableState e, HoistingTopBuilder frag m)
552573
=> HoistingTopBuilder frag (StateT1 e m) where

src/lib/Imp.hs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -230,14 +230,15 @@ instance ImpBuilder ImpM where
230230

231231
buildScopedImp cont = ImpM $ WriterT1 \w ->
232232
liftM (, w) do
233-
Abs rdecls e <- locallyMutableInplaceT do
234-
Emits <- fabricateEmitsEvidenceM
235-
(result, (ListE ptrs)) <- runWriterT1 $ runImpM' do
236-
Distinct <- getDistinct
237-
cont
238-
_ <- runWriterT1 $ runImpM' do
239-
forM ptrs \ptr -> emitStatement $ Free ptr
240-
return result
233+
Abs rdecls e <- locallyMutableInplaceT
234+
(do Emits <- fabricateEmitsEvidenceM
235+
(result, (ListE ptrs)) <- runWriterT1 $ runImpM' do
236+
Distinct <- getDistinct
237+
cont
238+
_ <- runWriterT1 $ runImpM' do
239+
forM ptrs \ptr -> emitStatement $ Free ptr
240+
return result)
241+
(\d e -> return $ Abs d e)
241242
return $ Abs (unRNest rdecls) e
242243

243244
extendAllocsToFree ptr = ImpM $ tell $ ListE [ptr]

src/lib/Inference.hs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -453,10 +453,11 @@ runLocalInfererM
453453
=> (forall l. (EmitsInf l, DExt n l) => InfererM i l (e l))
454454
-> InfererM i n (Abs InfOutFrag e n)
455455
runLocalInfererM cont = InfererM $ SubstReaderT $ ReaderT \env -> do
456-
locallyMutableInplaceT do
456+
locallyMutableInplaceT (do
457457
Distinct <- getDistinct
458458
EmitsInf <- fabricateEmitsInfEvidenceM
459-
runSubstReaderT (sink env) $ runInfererM' cont
459+
runSubstReaderT (sink env) $ runInfererM' cont)
460+
(\d e -> return $ Abs d e)
460461
{-# INLINE runLocalInfererM #-}
461462

462463
initInfOutMap :: Env n -> InfOutMap n
@@ -517,21 +518,23 @@ formatAmbiguousVarErr infVar ty = \case
517518
instance InfBuilder (InfererM i) where
518519
buildDeclsInfUnzonked cont = do
519520
InfererM $ SubstReaderT $ ReaderT \env -> do
520-
Abs frag result <- locallyMutableInplaceT do
521+
Abs frag result <- locallyMutableInplaceT (do
521522
Emits <- fabricateEmitsEvidenceM
522523
EmitsInf <- fabricateEmitsInfEvidenceM
523-
runSubstReaderT (sink env) $ runInfererM' cont
524+
runSubstReaderT (sink env) $ runInfererM' cont)
525+
(\d e -> return $ Abs d e)
524526
extendInplaceT =<< hoistThroughDecls frag result
525527

526528
buildAbsInf hint expl ty cont = do
527529
ab <- InfererM $ SubstReaderT $ ReaderT \env -> do
528530
extendInplaceT =<< withFreshBinder hint ty \bWithTy@(b:>_) -> do
529-
ab <- locallyMutableInplaceT do
531+
ab <- locallyMutableInplaceT (do
530532
v <- sinkM $ binderVar bWithTy
531533
extendInplaceTLocal (extendSynthCandidatesInf expl $ atomVarName v) do
532534
EmitsInf <- fabricateEmitsInfEvidenceM
533535
-- zonking is needed so that dceInfFrag works properly
534-
runSubstReaderT (sink env) (runInfererM' $ cont v >>= zonk)
536+
runSubstReaderT (sink env) (runInfererM' $ cont v >>= zonk))
537+
(\d e -> return $ Abs d e)
535538
ab' <- dceInfFrag ab
536539
refreshAbs ab' \infFrag result -> do
537540
case exchangeBs $ PairB b infFrag of
@@ -2330,10 +2333,10 @@ instance Solver SolverM where
23302333
{-# INLINE emitSolver #-}
23312334

23322335
solveLocal cont = SolverM do
2333-
results <- locallyMutableInplaceT do
2336+
results <- locallyMutableInplaceT (do
23342337
Distinct <- getDistinct
23352338
EmitsInf <- fabricateEmitsInfEvidenceM
2336-
runSolverM' cont
2339+
runSolverM' cont) (\d e -> return $ Abs d e)
23372340
Abs (SolverOutFrag unsolvedInfNames _) result <- return results
23382341
case unsolvedInfNames of
23392342
REmpty -> return result

src/lib/Name.hs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1465,15 +1465,18 @@ freshExtendSubInplaceT hint build =
14651465
{-# INLINE freshExtendSubInplaceT #-}
14661466

14671467
locallyMutableInplaceT
1468-
:: forall m b d n e.
1468+
:: forall m b d n e a.
14691469
(ExtOutMap b d, OutFrag d, Monad m, SinkableE e)
1470-
=> (forall l. (Mut l, DExt n l) => InplaceT b d m l (e l))
1471-
-> InplaceT b d m n (Abs d e n)
1472-
locallyMutableInplaceT cont = do
1470+
=> (forall l. (Mut l, DExt n l) => InplaceT b d m l (e l))
1471+
-> (forall l. DExt n l => d n l -> e l -> InplaceT b d m l a)
1472+
-> InplaceT b d m n a
1473+
locallyMutableInplaceT cont1 cont2 = do
14731474
UnsafeMakeInplaceT \env decls -> do
1474-
(e, d, _) <- withFabricatedMut @n $
1475-
unsafeRunInplaceT cont env emptyOutFrag
1476-
return (Abs (unsafeCoerceB d) e, decls, unsafeCoerceE env)
1475+
(e, d, env') <- withFabricatedMut @n $
1476+
unsafeRunInplaceT cont1 env emptyOutFrag
1477+
withFabricatedDistinct @UnsafeS do
1478+
(ans, _, _) <- unsafeRunInplaceT (cont2 @n (unsafeCoerceB d) (unsafeCoerceE e)) (unsafeCoerceE env') emptyOutFrag
1479+
return (ans, decls, unsafeCoerceE env)
14771480
{-# INLINE locallyMutableInplaceT #-}
14781481

14791482
liftBetweenInplaceTs

src/lib/Simplify.hs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -236,12 +236,7 @@ liftDoubleBuilderToSimplifyM :: DoubleBuilder SimpIR o a -> SimplifyM i o a
236236
liftDoubleBuilderToSimplifyM cont = SimplifyM $ liftSubstReaderT cont
237237

238238
instance Simplifier SimplifyM
239-
240-
-- TODO: figure out why we can't derive this one (here and elsewhere)
241-
instance ScopableBuilder SimpIR (SimplifyM i) where
242-
buildScoped cont = SimplifyM $ SubstReaderT $ ReaderT \env ->
243-
buildScoped $ runSubstReaderT (sink env) (runSimplifyM' cont)
244-
{-# INLINE buildScoped #-}
239+
deriving instance ScopableBuilder SimpIR (SimplifyM i)
245240

246241
-- === Top-level API ===
247242

0 commit comments

Comments
 (0)