Skip to content

Commit 8f74ef0

Browse files
committed
Carry the TraversalDef in the monad rather than passing around it everywhere.
1 parent 7b396dc commit 8f74ef0

File tree

8 files changed

+489
-466
lines changed

8 files changed

+489
-466
lines changed

src/lib/Builder.hs

Lines changed: 62 additions & 159 deletions
Original file line numberDiff line numberDiff line change
@@ -1455,177 +1455,80 @@ confuseGHCBuilder :: IRRep r => BuilderM r n (DistinctEvidence n)
14551455
confuseGHCBuilder = getDistinct
14561456
{-# INLINE confuseGHCBuilder #-}
14571457

1458-
-- === Traversal helpers ===
1459-
1460-
-- These traversals work with `TraversableTerm` but they make more assumptions
1461-
-- about the monad you're in.
1462-
1463-
type ForallTraversalDef m r = forall i o. TraversalDef (m i o) r i o
1464-
type ExprTraversalDef m r = forall i o. Expr r i -> m i o (Expr r o)
1465-
type BlockTraversalDef m r = forall i o. Block r i -> m i o (Block r o)
1466-
1467-
traverseExprs
1468-
:: (IRRep r, TraversableTerm e r, EnvExtender2 m, SubstReader Name m)
1469-
=> e i -> ExprTraversalDef m r -> m i o (e o)
1470-
traverseExprs e f = traverseTerm (exprTraversal f) e where
1471-
1472-
exprTraversal
1473-
:: (IRRep r, EnvExtender2 m, SubstReader Name m)
1474-
=> ExprTraversalDef m r -> ForallTraversalDef m r
1475-
exprTraversal f = TraversalDef
1476-
{ handleName = renameM
1477-
, handleType = traverseTypeRename (exprTraversal f)
1478-
, handleAtom = traverseAtomRename (exprTraversal f)
1479-
, handleLam = traverseLam (exprTraversal f) (traverseBlock (exprTraversal f) f)
1480-
, handlePi = traversePi (exprTraversal f) }
1481-
1482-
traverseBlock
1483-
:: (IRRep r, FromName v, SubstReader v m, EnvExtender2 m)
1484-
=> ForallTraversalDef m r
1485-
-> ExprTraversalDef m r
1486-
-> Block r i -> m i o (Block r o)
1487-
traverseBlock f fExpr (Block _ decls result) = do
1488-
absToBlockInferringTypes =<< traverseDecls fExpr decls \decls' -> do
1489-
result' <- handleAtom f result
1490-
return $ Abs decls' result'
1491-
1492-
traverseAtomRename
1493-
:: (IRRep r, SubstReader Name m, EnvExtender2 m)
1494-
=> ForallTraversalDef m r
1495-
-> Atom r i -> m i o (Atom r o)
1496-
traverseAtomRename f = \case
1497-
Var v -> Var <$> renameM v
1498-
SimpInCore x -> SimpInCore <$> renameM x
1499-
ProjectElt i x -> ProjectElt i <$> traverseAtomRename f x
1500-
x -> traverseAtom f x
1501-
1502-
traverseTypeRename
1503-
:: (IRRep r, SubstReader Name m, EnvExtender2 m)
1504-
=> ForallTraversalDef m r
1505-
-> Type r i -> m i o (Type r o)
1506-
traverseTypeRename f = \case
1507-
TyVar v -> TyVar <$> renameM v
1508-
ProjectEltTy i x -> ProjectEltTy i <$> traverseAtomRename f x
1509-
x -> traverseType f x
1510-
1511-
traverseLam
1512-
:: (IRRep r, FromName v, SubstReader v m, EnvExtender2 m)
1513-
=> ForallTraversalDef m r
1514-
-> BlockTraversalDef m r
1515-
-> LamExpr r i -> m i o (LamExpr r o)
1516-
traverseLam f fBlock (LamExpr bs body) =
1517-
traverseBinders f bs \bs' -> LamExpr bs' <$> fBlock body
1518-
1519-
traversePi
1520-
:: (IRRep r, FromName v, SubstReader v m, EnvExtender2 m)
1521-
=> ForallTraversalDef m r -> PiType r i -> m i o (PiType r o)
1522-
traversePi f (PiType bs eff ty) = do
1523-
traverseBinders f bs \bs' -> do
1524-
EffectAndType eff' ty' <- traverseTerm f $ EffectAndType eff ty
1525-
return $ PiType bs' eff' ty'
1526-
1527-
traverseBinders
1528-
:: (IRRep r, FromName v, SubstReader v m, EnvExtender2 m)
1529-
=> ForallTraversalDef m r
1530-
-> Nest (Binder r) i i'
1531-
-> (forall o'. DExt o o' => Nest (Binder r) o o' -> m i' o' a)
1532-
-> m i o a
1533-
traverseBinders _ Empty cont = getDistinct >>= \Distinct -> cont Empty
1534-
traverseBinders f (Nest (b:>ty) bs) cont = do
1535-
ty' <- handleType f ty
1536-
withFreshBinder (getNameHint b) ty' \b' -> do
1537-
extendRenamer (b@>binderName b') do
1538-
traverseBinders f bs \bs' ->
1539-
cont $ Nest b' bs'
1458+
-- === Non-emitting expression visitor ===
1459+
1460+
class Visitor m r i o => ExprVisitorNoEmits m r i o | m -> i, m -> o where
1461+
visitExprNoEmits :: Expr r i -> m (Expr r o)
1462+
1463+
type ExprVisitorNoEmits2 m r = forall i o. ExprVisitorNoEmits (m i o) r i o
15401464

1541-
traverseDecls
1542-
:: (IRRep r, FromName v, SubstReader v m, EnvExtender2 m)
1543-
=> ExprTraversalDef m r
1544-
-> Nest (Decl r) i i'
1465+
visitLamNoEmits
1466+
:: (ExprVisitorNoEmits2 m r, IRRep r, AtomSubstReader v m, EnvExtender2 m)
1467+
=> LamExpr r i -> m i o (LamExpr r o)
1468+
visitLamNoEmits (LamExpr bs body) =
1469+
visitBinders bs \bs' -> LamExpr bs' <$> visitBlockNoEmits body
1470+
1471+
visitBlockNoEmits
1472+
:: (ExprVisitorNoEmits2 m r, IRRep r, AtomSubstReader v m, EnvExtender2 m)
1473+
=> Block r i -> m i o (Block r o)
1474+
visitBlockNoEmits (Block _ decls result) =
1475+
absToBlockInferringTypes =<< visitDeclsNoEmits decls \decls' -> do
1476+
Abs decls' <$> visitAtom result
1477+
1478+
visitDeclsNoEmits
1479+
:: (ExprVisitorNoEmits2 m r, IRRep r, AtomSubstReader v m, EnvExtender2 m)
1480+
=> Nest (Decl r) i i'
15451481
-> (forall o'. DExt o o' => Nest (Decl r) o o' -> m i' o' a)
15461482
-> m i o a
1547-
traverseDecls _ Empty cont = getDistinct >>= \Distinct -> cont Empty
1548-
traverseDecls f (Nest (Let b (DeclBinding ann _ expr)) decls) cont = do
1549-
expr' <- f expr
1483+
visitDeclsNoEmits Empty cont = getDistinct >>= \Distinct -> cont Empty
1484+
visitDeclsNoEmits (Nest (Let b (DeclBinding ann _ expr)) decls) cont = do
1485+
expr' <- visitExprNoEmits expr
15501486
ty <- getType expr'
15511487
withFreshBinder (getNameHint b) ty \(b':>_) -> do
15521488
let decl' = Let b' $ DeclBinding ann ty expr'
15531489
extendRenamer (b@>binderName b') do
1554-
traverseDecls f decls \decls' ->
1490+
visitDeclsNoEmits decls \decls' ->
15551491
cont $ Nest decl' decls'
15561492

1557-
-- === traversal helpers that allow emissions ===
1558-
1559-
type ExprEmitTraversalDef m r = forall i o. Emits o => Expr r i -> m i o (Atom r o)
1560-
1561-
liftAtomSubstBuilder :: (IRRep r, EnvReader m) => AtomSubstBuilder r n n a -> m n a
1562-
liftAtomSubstBuilder cont = liftBuilder $ runSubstReaderT idSubst cont
1563-
1564-
type AtomSubstBuilder r = SubstReaderT AtomSubstVal (BuilderM r)
1565-
1566-
exprEmitTraversal
1567-
:: (IRRep r, ScopableBuilder2 r m, SubstReader AtomSubstVal m)
1568-
=> ExprEmitTraversalDef m r -> ForallTraversalDef m r
1569-
exprEmitTraversal f = TraversalDef
1570-
{ handleName = substM
1571-
, handleType = traverseTypeSubst (exprEmitTraversal f)
1572-
, handleAtom = traverseAtomSubst (exprEmitTraversal f)
1573-
, handleLam = traverseLamEmit (exprEmitTraversal f) f
1574-
, handlePi = traversePi (exprEmitTraversal f) }
1575-
1576-
traverseLamEmit
1577-
:: (IRRep r, SubstReader AtomSubstVal m, ScopableBuilder2 r m)
1578-
=> ForallTraversalDef m r
1579-
-> ExprEmitTraversalDef m r
1580-
-> LamExpr r i -> m i o (LamExpr r o)
1581-
traverseLamEmit f fExpr lam =
1582-
traverseLam f (\b -> buildBlock $ traverseBlockEmit f fExpr b) lam
1583-
1584-
traverseBlockEmit
1585-
:: (Emits o, IRRep r, SubstReader AtomSubstVal m, EnvExtender2 m)
1586-
=> ForallTraversalDef m r
1587-
-> ExprEmitTraversalDef m r
1588-
-> Block r i -> m i o (Atom r o)
1589-
traverseBlockEmit f fExpr (Block _ decls result) = do
1590-
traverseDeclsEmit fExpr decls do
1591-
handleAtom f result
1592-
1593-
traverseDeclsEmit
1594-
:: (IRRep r, SubstReader AtomSubstVal m, EnvExtender2 m, Emits o)
1595-
=> ExprEmitTraversalDef m r
1596-
-> Nest (Decl r) i i'
1493+
-- === Emitting expression visitor ===
1494+
1495+
class Visitor m r i o => ExprVisitorEmits m r i o | m -> i, m -> o where
1496+
visitExprEmits :: Emits o => Expr r i -> m (Atom r o)
1497+
1498+
type ExprVisitorEmits2 m r = forall i o. ExprVisitorEmits (m i o) r i o
1499+
1500+
liftAtomSubstBuilder :: forall tag r m n a. (IRRep r, EnvReader m) => AtomSubstBuilder tag r n n a -> m n a
1501+
liftAtomSubstBuilder cont = liftBuilder $ runSubstReaderT idSubst $ runAtomSubstBuilder cont
1502+
1503+
-- The phantom type `v` is for defining `Visitor` instances. The pattern is to
1504+
-- define a new singleton type, like `data MyTag = MyTag`.
1505+
newtype AtomSubstBuilder v r i o a =
1506+
AtomSubstBuilder { runAtomSubstBuilder :: SubstReaderT AtomSubstVal (BuilderM r) i o a}
1507+
deriving (MonadFail, Fallible, Functor, Applicative, Monad, ScopeReader,
1508+
EnvReader, EnvExtender, Builder r, SubstReader AtomSubstVal,
1509+
ScopableBuilder r)
1510+
1511+
visitLamEmits
1512+
:: (ExprVisitorEmits2 m r, IRRep r, SubstReader AtomSubstVal m, ScopableBuilder2 r m)
1513+
=> LamExpr r i -> m i o (LamExpr r o)
1514+
visitLamEmits (LamExpr bs body) = visitBinders bs \bs' -> LamExpr bs' <$>
1515+
buildBlock (visitBlockEmits body)
1516+
1517+
visitBlockEmits
1518+
:: (ExprVisitorEmits2 m r, SubstReader AtomSubstVal m, EnvExtender2 m, IRRep r, Emits o)
1519+
=> Block r i -> m i o (Atom r o)
1520+
visitBlockEmits (Block _ decls result) = visitDeclsEmits decls $ visitAtom result
1521+
1522+
visitDeclsEmits
1523+
:: (ExprVisitorEmits2 m r, SubstReader AtomSubstVal m, EnvExtender2 m, IRRep r, Emits o)
1524+
=> Nest (Decl r) i i'
15971525
-> m i' o a
15981526
-> m i o a
1599-
traverseDeclsEmit _ Empty cont = cont
1600-
traverseDeclsEmit f (Nest (Let b (DeclBinding _ _ expr)) decls) cont = do
1601-
x <- f expr
1527+
visitDeclsEmits Empty cont = cont
1528+
visitDeclsEmits (Nest (Let b (DeclBinding _ _ expr)) decls) cont = do
1529+
x <- visitExprEmits expr
16021530
extendSubst (b@>SubstVal x) do
1603-
traverseDeclsEmit f decls cont
1604-
1605-
traverseExprsEmit
1606-
:: (IRRep r, ScopableBuilder2 r m, SubstReader AtomSubstVal m
1607-
, TraversableTerm e r)
1608-
=> e i -> ExprEmitTraversalDef m r -> m i o (e o)
1609-
traverseExprsEmit e f = traverseTerm (exprEmitTraversal f) e where
1610-
1611-
traverseAtomSubst
1612-
:: (IRRep r, SubstReader AtomSubstVal m, EnvExtender2 m)
1613-
=> ForallTraversalDef m r
1614-
-> Atom r i -> m i o (Atom r o)
1615-
traverseAtomSubst f = \case
1616-
Var v -> substM $ Var v
1617-
SimpInCore x -> SimpInCore <$> substM x
1618-
ProjectElt i x -> ProjectElt i <$> traverseAtomSubst f x
1619-
x -> traverseAtom f x
1620-
1621-
traverseTypeSubst
1622-
:: (IRRep r, SubstReader AtomSubstVal m, EnvExtender2 m)
1623-
=> ForallTraversalDef m r
1624-
-> Type r i -> m i o (Type r o)
1625-
traverseTypeSubst f = \case
1626-
TyVar v -> substM $ TyVar v
1627-
ProjectEltTy i x -> ProjectEltTy i <$> traverseAtomSubst f x
1628-
x -> traverseType f x
1531+
visitDeclsEmits decls cont
16291532

16301533
-- === Helpers for function evaluation over fixed-width types ===
16311534

0 commit comments

Comments
 (0)