{-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE ScopedTypeVariables #-} module Nes.FlagRegister (FlagRegister (..), getFlag, setFlag, clearFlag, setFlag') where import Data.Bits import Data.Kind (Type) import Nes.Memory class FlagRegister a where type Flag a :: Type fromByte :: Byte -> a toByte :: a -> Byte flagToBitOffset :: Flag a -> Int setFlag :: (FlagRegister a) => Flag a -> a -> a setFlag :: forall a. FlagRegister a => Flag a -> a -> a setFlag Flag a flag = Flag a -> Bool -> a -> a forall a. FlagRegister a => Flag a -> Bool -> a -> a setFlag' Flag a flag Bool True clearFlag :: (FlagRegister a) => Flag a -> a -> a clearFlag :: forall a. FlagRegister a => Flag a -> a -> a clearFlag Flag a flag = Flag a -> Bool -> a -> a forall a. FlagRegister a => Flag a -> Bool -> a -> a setFlag' Flag a flag Bool False setFlag' :: forall a. (FlagRegister a) => Flag a -> Bool -> a -> a setFlag' :: forall a. FlagRegister a => Flag a -> Bool -> a -> a setFlag' Flag a flag Bool bool a r = let byte :: Byte byte = a -> Byte forall a. FlagRegister a => a -> Byte toByte a r in Byte -> a forall a. FlagRegister a => Byte -> a fromByte (Byte -> a) -> Byte -> a forall a b. (a -> b) -> a -> b $ (if Bool bool then Byte -> Int -> Byte forall a. Bits a => a -> Int -> a setBit else Byte -> Int -> Byte forall a. Bits a => a -> Int -> a clearBit) Byte byte (forall a. FlagRegister a => Flag a -> Int flagToBitOffset @a Flag a flag) getFlag :: forall a. (FlagRegister a) => Flag a -> a -> Bool getFlag :: forall a. FlagRegister a => Flag a -> a -> Bool getFlag Flag a f a r = Byte -> Int -> Bool forall a. Bits a => a -> Int -> Bool testBit (a -> Byte forall a. FlagRegister a => a -> Byte toByte a r) (forall a. FlagRegister a => Flag a -> Int flagToBitOffset @a Flag a f)