packages feed

apple-0.1.0.0: src/Asm/CF.hs

module Asm.CF ( N, FreshM
              , runFreshM
              , getFresh, fm
              , lookupLabel, lC
              , broadcast
              , b3
              , singleton
              , fromList
              ) where

import           Asm.M
import           Class.E                    as E
import           Control.Monad.State.Strict (State, evalState, gets, modify, state)
import           Data.Functor               (($>))
import qualified Data.IntSet                as IS
import qualified Data.Map                   as M
import           Data.Tuple.Extra           (second3, snd3, thd3, third3)

type N=Int

-- map of labels by node
type FreshM = State (N, M.Map Label N, M.Map Label [N])

runFreshM :: FreshM a -> a
runFreshM = flip evalState (0, mempty, mempty)

getFresh :: FreshM N
getFresh = state (\(i,m0,m1) -> (i,(i+1,m0,m1)))

fm :: Label -> FreshM N
fm l = do {st <- gets snd3; case M.lookup l st of {Just i -> pure i; Nothing -> do {i <- getFresh; broadcast i l $> i}}}

lookupLabel :: Label -> FreshM N
lookupLabel l = gets (M.findWithDefault (error "Internal error in control-flow graph: node label not in map.") l . snd3)

lC :: Label -> FreshM [N]
lC l = gets (M.findWithDefault (error "Internal error in CF graph: node label not in map.") l . thd3)

broadcast :: N -> Label -> FreshM ()
broadcast i l = modify (second3 (M.insert l i))

b3 :: N -> Label -> FreshM ()
b3 i l = modify (third3 (M.alter (\k -> Just$case k of {Nothing -> [i]; Just is -> i:is}) l))

singleton :: E reg => reg -> IS.IntSet
singleton = IS.singleton . E.toInt

fromList :: E reg => [reg] -> IS.IntSet
fromList = foldMap singleton