@@ -48,6 +48,9 @@ type LinRegions = ListE AtomName
4848type TransposeM a = SubstReaderT TransposeSubstVal
4949 (ReaderT1 LinRegions BuilderM ) a
5050
51+ type TransposeM' a = SubstReaderT AtomSubstVal
52+ (ReaderT1 LinRegions BuilderM ) a
53+
5154-- TODO: it might make sense to replace substNonlin/isLin
5255-- with a single `trySubtNonlin :: e i -> Maybe (e o)`.
5356-- But for that we need a way to traverse names, like a monadic
@@ -60,6 +63,22 @@ substNonlin e = do
6063 RenameNonlin v' -> v'
6164 _ -> error " not a nonlinear expression" ) e
6265
66+ -- TODO: Can we generalize onNonLin to accept SubstReaderT Name instead of
67+ -- SubstReaderT AtomSubstVal? For that to work, we need another combinator,
68+ -- that lifts a SubstReader AtomSubstVal into a SubstReader Name, because
69+ -- effectsSubstE is currently typed as SubstReader AtomSubstVal.
70+ -- Then we can presumably recode substNonlin as `onNonLin substM`. We may
71+ -- be able to do that anyway, except we will then need to restrict the type
72+ -- of substNonlin to require `SubstE AtomSubstVal e`; but that may be fine.
73+ onNonLin :: HasCallStack
74+ => TransposeM' i o a -> TransposeM i o a
75+ onNonLin cont = do
76+ subst <- getSubst
77+ let subst' = newSubst (\ v -> case subst ! v of
78+ RenameNonlin v' -> Rename v'
79+ _ -> error " not a nonlinear expression" )
80+ liftSubstReaderT $ runSubstReaderT subst' cont
81+
6382isLin :: HoistableE e => e i -> TransposeM i o Bool
6483isLin e = do
6584 substVals <- mapM lookupSubstM $ freeAtomVarsList e
@@ -123,10 +142,9 @@ substExprIfNonlin expr =
123142 isLin expr >>= \ case
124143 True -> return Nothing
125144 False -> do
126- expr' <- substNonlin expr
127- getEffects expr' >>= isLinEff >>= \ case
145+ onNonLin (getEffectsSubst expr) >>= isLinEff >>= \ case
128146 True -> return Nothing
129- False -> return $ Just expr'
147+ False -> Just <$> substNonlin expr
130148
131149isLinEff :: EffectRow o -> TransposeM i o Bool
132150isLinEff effs@ (EffectRow _ Nothing ) = do
0 commit comments