----------------------------------------------------------------------------- -- The fuel monad ----------------------------------------------------------------------------- module Compiler.Hoopl.Fuel ( Fuel , FuelMonad, withFuel, getFuel, setFuel , freshLabel , runWithFuel ) where import Compiler.Hoopl.Label type Fuel = Int newtype FuelMonad a = FM { unFM :: Fuel -> [Label] -> (a, Fuel, [Label]) } instance Monad FuelMonad where return x = FM (\f u -> (x,f,u)) m >>= k = FM (\f u -> case unFM m f u of (r,f',u') -> unFM (k r) f' u') withFuel :: Maybe a -> FuelMonad (Maybe a) withFuel Nothing = return Nothing withFuel (Just r) = FM (\f u -> if f==0 then (Nothing, f, u) else (Just r, f-1, u)) getFuel :: FuelMonad Fuel getFuel = FM (\f u -> (f,f,u)) setFuel :: Fuel -> FuelMonad () setFuel f = FM (\_ u -> ((), f, u)) runWithFuel :: Fuel -> FuelMonad a -> a runWithFuel fuel m = a where (a, _, _) = unFM m fuel allLabels freshLabel :: FuelMonad Label freshLabel = FM (\f (l:ls) -> (l, f, ls))