{-# LANGUAGE MultiParamTypeClasses #-}
module Lazyboy.Control where
import Control.Monad.Trans.RWS
import Data.Word
import Lazyboy.Types
getLabel :: Lazyboy Integer
getLabel = do
label <- get
modify (+ 1)
return label
getLocalLabel :: Lazyboy Label
getLocalLabel = Local <$> getLabel
getGlobalLabel :: Lazyboy Label
getGlobalLabel = Global <$> getLabel
withLabel :: (Label -> Lazyboy ()) -> Lazyboy ()
withLabel block = do
label <- getGlobalLabel
tell [LABEL label]
block label
withLocalLabel :: (Label -> Lazyboy ()) -> Lazyboy ()
withLocalLabel block = do
label <- getLocalLabel
tell [LABEL label]
block label
embedFile :: FilePath -> Lazyboy Label
embedFile file = do
label <- getGlobalLabel
skipLabel <- getGlobalLabel
tell [JP $ Name skipLabel]
tell [LABEL label, INCLUDE file]
tell [LABEL skipLabel]
return label
embedImage = embedFile
embedBytes :: [Word8] -> Lazyboy Label
embedBytes bytes = do
label <- getGlobalLabel
skipLabel <- getGlobalLabel
tell [JP $ Name skipLabel]
tell [LABEL label, BYTES bytes]
tell [LABEL skipLabel]
return label
freeze :: Lazyboy ()
freeze = withLabel $ \label -> do
tell [DI, HALT]
tell [JP $ Name label]
cond :: Condition -> Lazyboy a -> Lazyboy a
cond condition block = do
label <- getLocalLabel
tell [JPif condition (Name label)]
a <- block
tell [LABEL label]
return a
class Comparable a b where
equalTo :: a -> b -> Lazyboy Condition
notEqualTo :: a -> b -> Lazyboy Condition
greaterThan :: a -> b -> Lazyboy Condition
lessThan :: a -> b -> Lazyboy Condition
instance Comparable Register8 Register8 where
equalTo A r = tell [CPr r] >> return NonZero
equalTo r r' = tell [LDrr A r, CPr r'] >> return NonZero
notEqualTo A r = equalTo A r >> return Zero
notEqualTo r r' = equalTo r r' >> return Zero
greaterThan A r = equalTo A r >> return NoCarry
greaterThan r r' = equalTo r r' >> return NoCarry
lessThan A r = equalTo A r >> return Carry
lessThan r r' = equalTo r r' >> return Carry
instance Comparable Register8 Word8 where
equalTo A n = tell [CPn n] >> return NonZero
equalTo r n = tell [LDrr A r, CPn n] >> return NonZero
notEqualTo A n = equalTo A n >> return Zero
notEqualTo r n = equalTo r n >> return Zero
greaterThan A n = equalTo A n >> return NoCarry
greaterThan r n = equalTo r n >> return NoCarry
lessThan A n = equalTo A n >> return Carry
lessThan r n = equalTo r n >> return Carry
instance Comparable Word8 Register8 where
equalTo = flip equalTo
notEqualTo = flip notEqualTo
greaterThan = flip greaterThan
lessThan = flip lessThan
if' :: Lazyboy Condition -> Lazyboy a -> Lazyboy a
if' condition block = do
flag <- condition
cond flag block
not :: Lazyboy Condition -> Lazyboy Condition
not action = do
flag <- action
return $ case flag of
Zero -> NonZero
NonZero -> Zero
Carry -> NoCarry
NoCarry -> Carry
and :: Lazyboy Condition -> Lazyboy Condition -> Lazyboy Condition
and a b = do
a' <- a
cond a' $ do
tell [LDrn L 1]
b' <- b
cond b' $ do
tell [LDrn A 1]
tell [ANDr L]
return Zero
or :: Lazyboy Condition -> Lazyboy Condition -> Lazyboy Condition
or a b = do
a' <- a
cond a' $ do
tell [LDrn L 1]
b' <- b
cond b' $ do
tell [LDrn A 1]
tell [ORr L]
return Zero