module System.Log.Data where
import Prelude hiding (lookup, log)
import Control.Monad.IO.Class (MonadIO, liftIO)
import Control.Concurrent (threadDelay)
import Control.Applicative hiding (empty)
import System.Log.Log (MonadLogger, LogFormat, Log(Log), fromLog, appendLog)
import Data.Time.Clock (getCurrentTime, UTCTime)
import Control.Lens
log :: (Show pri, Enum pri, MonadRecord (Data Lvl, (Data Msg, r)) m)
=> RecordBuilder r -> pri -> String -> m ()
log rec pri msg = do
#ifdef NOLOGS
return ()
#else
appendRecord $ appData Lvl (mkLevel pri)
$ appData Msg msg
$ rec
#endif
newtype RecordBuilder a = RecordBuilder { fromRecordBuilder :: a } deriving (Show, Functor)
empty = RecordBuilder ()
class MonadRecord d m where
appendRecord :: RecordBuilder d -> m ()
default appendRecord :: (MonadLogger m, LogBuilder d m) => RecordBuilder d -> m ()
appendRecord d = do
l <- buildLog d
appendLog l
appData :: (a~DataOf base) => base -> a -> RecordBuilder as -> RecordBuilder (Data base, as)
appData base a = fmap (Data base a,)
data Data base = Data { recBase :: base
, recData :: DataOf base
}
deriving instance (Show (DataOf base), Show base) => Show (Data base)
class DataGetter base m where
getData :: m (Data base)
type family DataOf a :: *
class LogBuilderProto a m b where
buildLogProto :: RecordBuilder a -> m (Log b)
type LogBuilder a m = LogBuilderProto a m (LogFormat m)
buildLog :: (Monad m, Applicative m, LogBuilder a m) => RecordBuilder a -> m (Log (LogFormat m))
buildLog = buildLogProto
instance (LogBuilderProto xs m ys, Functor m) => LogBuilderProto (Data x,xs) m (Data x,ys) where
buildLogProto b = (fmap.fmap) (x,) $ buildLogProto $ RecordBuilder xs where
(x,xs) = fromRecordBuilder b
instance (LogBuilderProto (Data x,xs) m ys, LogBuilderProto xs m (Data y,()), Monad m) => LogBuilderProto (Data x,xs) m (Data y,ys) where
buildLogProto b = do
let (x,xs) = fromRecordBuilder b
Log ys <- buildLogProto b
Log (y,()) <- buildLogProto $ RecordBuilder xs
return $ Log (y, ys)
instance Monad m => LogBuilderProto a m () where
buildLogProto _ = return $ Log ()
instance (Functor m, Applicative m, DataGetter y m, LogBuilderProto () m ys) => LogBuilderProto () m (Data y,ys) where
buildLogProto b = fmap Log $ (,) <$> getData <*> (fromLog <$> buildLogProto b)
class Lookup base s where
lookup :: base -> s -> Data base
readData :: Lookup a l => a -> l -> DataOf a
readData a = recData . lookup a
instance LookupDataSet base l => Lookup base (Log l) where
lookup b (fromLog -> s) = lookupDataSet b s
instance LookupDataSet base r => Lookup base (RecordBuilder r) where
lookup b (fromRecordBuilder -> r) = lookupDataSet b r
class LookupDataSet base s where
lookupDataSet :: base -> s -> Data base
instance LookupDataSet base (Data base,as) where
lookupDataSet _ (a,_) = a
instance LookupDataSet base as => LookupDataSet base (Data b,as) where
lookupDataSet b (_, as) = lookupDataSet b as
data Time = Time deriving (Show)
type instance DataOf Time = UTCTime
instance MonadIO m => DataGetter Time m where
getData = do liftIO $ Data Time <$> getCurrentTime
data Msg = Msg deriving (Show)
type instance DataOf Msg = String
data Lvl = Lvl deriving (Show)
type instance DataOf Lvl = LevelData
data LevelData = LevelData Int String deriving (Show, Ord, Eq)
mkLevel a = LevelData (fromEnum a) (show a)
type Pos = (Int, Int)
data LocData = LocData { _filename :: String
, _package :: String
, _module :: String
, _start :: Pos
, _end :: Pos
} deriving Show
mkLoc (f,p,m,s,e) = LocData f p m s e
data Loc = Loc deriving (Show)
type instance DataOf Loc = LocData
makeLenses ''Loc