Nomyx-Language-0.4.0: src/Language/Nomyx/Expression.hs
{-# LANGUAGE FlexibleInstances, GADTs, DeriveDataTypeable, MultiParamTypeClasses,
TemplateHaskell, ScopedTypeVariables, StandaloneDeriving, NamedFieldPuns, EmptyDataDecls #-}
-- | This module containt the type definitions necessary to build a Nomic rule.
module Language.Nomyx.Expression where
import Data.Typeable
import Data.Time
import Control.Applicative hiding (Const)
import Data.Lens.Template
import Control.Monad.Error
type PlayerNumber = Int
type PlayerName = String
type RuleNumber = Int
type RuleName = String
type RuleDesc = String
type RuleText = String
type RuleCode = String
type EventNumber = Int
type EventName = String
type VarName = String
type Code = String
type OutputNumber = Int
-- * Nomyx Expression
-- | A Nomex (Nomyx Expression) allows the players to write rules.
-- within the rules, you can access and modify the state of the game.
data Nomex a where
--Variable management
NewVar :: (Typeable a, Show a, Eq a) => VarName -> a -> Nomex (Maybe (V a))
ReadVar :: (Typeable a, Show a, Eq a) => (V a) -> Nomex (Maybe a)
WriteVar :: (Typeable a, Show a, Eq a) => (V a) -> a -> Nomex Bool
DelVar :: (V a) -> Nomex Bool
--Events management
OnEvent :: (Typeable e, Show e, Eq e) => Event e -> ((EventNumber, EventData e) -> Nomex ()) -> Nomex EventNumber
DelEvent :: EventNumber -> Nomex Bool
DelAllEvents :: (Typeable e, Show e, Eq e) => Event e -> Nomex ()
SendMessage :: (Typeable a, Show a, Eq a) => Event (Message a) -> a -> Nomex ()
--Rules management
ProposeRule :: Rule -> Nomex Bool
ActivateRule :: RuleNumber -> Nomex Bool
RejectRule :: RuleNumber -> Nomex Bool
AddRule :: Rule -> Nomex Bool
ModifyRule :: RuleNumber -> Rule -> Nomex Bool
GetRules :: Nomex [Rule]
--Players management
GetPlayers :: Nomex [PlayerInfo]
SetPlayerName :: PlayerNumber -> PlayerName -> Nomex Bool
DelPlayer :: PlayerNumber -> Nomex Bool
--Output
NewOutput :: (Maybe PlayerNumber) -> String -> Nomex OutputNumber
GetOutput :: OutputNumber -> Nomex (Maybe String)
UpdateOutput :: OutputNumber -> String -> Nomex Bool
DelOutput :: OutputNumber -> Nomex Bool
--Mileacenous
SetVictory :: [PlayerNumber] -> Nomex ()
CurrentTime :: Nomex UTCTime
SelfRuleNumber :: Nomex RuleNumber
--Monadic bindings
Return :: a -> Nomex a
Bind :: Nomex a -> (a -> Nomex b) -> Nomex b
ThrowError :: String -> Nomex a
CatchError :: Nomex a -> (String -> Nomex a) -> Nomex a
deriving (Typeable)
instance Monad Nomex where
return = Return
(>>=) = Bind
instance Functor Nomex where
fmap f e = Bind e $ Return . f
instance Applicative Nomex where
pure = Return
f <*> a = do
f' <- f
a' <- a
return $ f' a'
instance MonadError String Nomex where
throwError = ThrowError
catchError = CatchError
instance Typeable a => Show (Nomex a) where
show e = '<' : (show . typeOf) e ++ ">"
-- * Variables
-- | a container for a variable name and type
data V a = V {varName :: String} deriving (Typeable)
-- * Events
-- | events types
data Player = Arrive | Leave deriving (Typeable, Show, Eq)
data RuleEvent = Proposed | Activated | Rejected | Added | Modified | Deleted deriving (Typeable, Show, Eq)
data Time deriving Typeable
data EvRule deriving Typeable
data Message m deriving Typeable
data Victory deriving Typeable
data Input a = Input PlayerNumber String (InputForm a)
data InputForm a = Radio [(a, String)]
| Text
| TextArea
| Button
| Checkbox [(a, String)]
-- | events names
data Event a where
Player :: Player -> Event Player
RuleEv :: RuleEvent -> Event RuleEvent
Time :: UTCTime -> Event Time
Message :: String -> Event (Message m)
InputEv :: (Eq a, Show a, Typeable a) => Input a -> Event (Input a)
Victory :: Event Victory
-- data sent back by inputs
data InputData a = RadioData a
| CheckboxData [a]
| TextData String
| TextAreaData String
| ButtonData
-- | data associated with each events
data EventData a where
PlayerData :: {playerData :: PlayerInfo} -> EventData Player
RuleData :: {ruleData :: Rule} -> EventData RuleEvent
TimeData :: {timeData :: UTCTime} -> EventData Time
MessageData :: (Show m) => {messageData :: m} -> EventData (Message m)
InputData :: (Show a) => {inputData :: InputData a} -> EventData (Input a)
VictoryData :: {victoryData :: [PlayerInfo]} -> EventData Victory
deriving instance Typeable1 EventData
deriving instance Typeable1 Event
deriving instance Typeable1 Input
deriving instance Typeable1 InputForm
deriving instance (Show a) => Show (Event a)
deriving instance (Show a) => Show (InputForm a)
deriving instance (Show a) => Show (Input a)
deriving instance (Show a) => Show (EventData a)
deriving instance (Show a) => Show (InputData a)
deriving instance (Show a) => Show (Message a)
deriving instance Show Time
deriving instance Show Victory
deriving instance Eq Time
deriving instance Eq Victory
deriving instance Eq EvRule
deriving instance Eq (Message m)
deriving instance (Eq e) => Eq (Event e)
deriving instance (Eq e) => Eq (Input e)
deriving instance (Eq e) => Eq (InputForm e)
type Msg a = Event (Message a)
type MsgData a = EventData (Message a)
-- * Rule
-- | Type of a rule function.
type RuleFunc = Nomex RuleResp
-- | Return type of a rule function.
-- it can be either nothing or another rule.
data RuleResp =
Void
| Meta (Rule -> Nomex BoolResp)
deriving (Typeable)
--An extended type for booleans supporting immediate or delayed response (through a message)
data BoolResp = BoolResp Bool
| MsgResp (Msg Bool)
instance Show RuleResp where
show _ = "RuleResp"
-- | An informationnal structure about a rule
data Rule = Rule { _rNumber :: RuleNumber, -- number of the rule (must be unique) TO CHECK
_rName :: RuleName, -- short name of the rule
_rDescription :: String, -- description of the rule
_rProposedBy :: PlayerNumber, -- player proposing the rule
_rRuleCode :: Code, -- code of the rule as a string
_rRuleFunc :: RuleFunc, -- function representing the rule (interpreted from rRuleCode)
_rStatus :: RuleStatus, -- status of the rule
_rAssessedBy :: Maybe RuleNumber} -- which rule accepted or rejected this rule
deriving (Typeable, Show)
instance Eq Rule where
(Rule {_rNumber=r1}) == (Rule {_rNumber=r2}) = r1 == r2
instance Ord Rule where
(Rule {_rNumber=r1}) <= (Rule {_rNumber=r2}) = r1 <= r2
-- | the status of a rule.
data RuleStatus = Active -- Active rules forms the current Constitution
| Pending -- Proposed rules
| Reject -- Rejected rules
deriving (Eq, Show, Typeable)
-- * Player
-- | informations on players
data PlayerInfo = PlayerInfo { _playerNumber :: PlayerNumber,
_playerName :: String}
deriving (Eq, Typeable, Show)
instance Ord PlayerInfo where
h <= g = (_playerNumber h) <= (_playerNumber g)
partial :: String -> Nomex (Maybe a) -> Nomex a
partial s nm = do
m <- nm
case m of
Just a -> return a
Nothing -> throwError s
$( makeLenses [''Rule, ''PlayerInfo] )