never executed always true always false
1 module HelVM.HelMA.Automaton.Trampoline where
2
3 import Control.Monad.Loops
4 import Control.Type.Operator
5
6 import Prelude hiding (break)
7
8 testMaybeLimit :: LimitMaybe
9 testMaybeLimit = Just $ fromIntegral (maxBound :: Int)
10
11 trampolineMWithLimit :: Monad m => (a -> m $ Same a) -> LimitMaybe -> a -> m a
12 trampolineMWithLimit f Nothing x = trampolineM f x
13 trampolineMWithLimit f (Just n) x = trampolineM (actMWithLimit f) (n , x)
14
15 actMWithLimit :: Monad m => (a -> m $ Same a) -> WithLimit a -> m $ EitherWithLimit a
16 actMWithLimit f (n , x) = checkN n where
17 checkN 0 = pure $ break x
18 checkN _ = next n <$> f x
19
20 next :: Natural -> Same a -> EitherWithLimit a
21 next n a = withLimit n <$> a
22
23 withLimit :: Natural -> a -> WithLimit a
24 withLimit n a = (n - 1 , a)
25
26 trampolineM :: Monad m => (a -> m (Either b a)) -> a -> m b
27 trampolineM f = fmap (fromLeft $ error "unreachable") . iterateUntilM isLeft (either (pure . Left) f) . Right
28
29 trampoline :: (a -> Either b a) -> a -> b
30 trampoline f = fromLeft (error "unreachable") . iterateUntil isLeft (either Left f) . Right
31
32 continue :: a -> Either b a
33 continue = Right
34
35 break :: b -> Either b a
36 break = Left
37
38 type LimitMaybe = Maybe Natural
39
40 type EitherWithLimit a = Either a $ WithLimit a
41
42 type WithLimit a = (Natural , a)
43
44 type Same a = Either a a