module TypDefs ( PiProcess (..), Term (..), TermFun , HttpData (..), Condition (..), Value (..), Type (..), Channel (..), BuildType (..), PiError (..), IOThrowsError , ThrowsError , Name , Env ) where import Control.Monad.Trans.Except(ExceptT(..)) import Data.Char (toLower) import Data.ByteString (ByteString) import Data.IORef (IORef) import Data.List (intercalate) import Data.Map (Map) import Network.HTTP.Base (Request, Response) import Network.HTTP.Headers (HasHeaders(..)) import Text.ParserCombinators.Parsec (ParseError) data PiProcess = Null | In Term Term | Out Term Term | New Term | PiProcess `Seq` PiProcess | Conc [PiProcess] | Replicate PiProcess | Let Term Value (Maybe PiProcess) | If Condition PiProcess PiProcess | Atom Term deriving (Eq) data Term = TVar Name (Maybe Type) | TStr String | TNum Integer | TBool Bool | TPair (Term, Term) | TList [Term] | TBS ByteString | TData HttpData | TFun Name [Term] deriving (Eq) data HttpData = Resp (Response String) | Req (Request String) instance HasHeaders HttpData where getHeaders (Resp r) = getHeaders r getHeaders (Req r) = getHeaders r setHeaders (Resp r) = Resp . setHeaders r setHeaders (Req r) = Req . setHeaders r type TermFun = [Term] -> ThrowsError Term type Name = String data Condition = Term `Equals` Term deriving (Eq) data Value = Proc PiProcess | Term Term | Chan Channel | PrimitiveFunc TermFun | Func {params :: [String] , body :: Value, closure :: Env} type IOThrowsError = ExceptT PiError IO type ThrowsError = Either PiError data PiError = NumArgs Name Integer [Value] | TypeMismatch String [Value] | Parser ParseError | UnboundVar String String | NotTerm Name Value | NotFunction String String | NotChannel String | NotProcess String | PatternMatch Term Term | Default String data Type = HttpRequest | HttpResponse deriving (Eq, Read, Show) type Env = IORef (Map Name Value) data Channel = Channel { send :: String -> IO () , receive :: IO String , extra :: [String] } data BuildType = Init | Connect deriving (Eq, Show, Read) instance Show PiProcess where show = showPi instance Show Term where show = showTerm instance Show Value where show = showValue instance Show Condition where show = showCond instance Show PiError where show = showError instance Show HttpData where show = showHttpData showPi :: PiProcess -> String showPi Null = "0" showPi (In c m) = "in(" ++ show c ++ "," ++ show m ++ ")" showPi (Out c m) = "out(" ++ show c ++ "," ++ show m ++ ")" showPi (Replicate proc) = "!(" ++ show proc ++ ")" showPi (Conc procs) = intercalate "|" $ map show procs showPi (p1 `Seq` Null) = show p1 showPi (p1 `Seq` p2) = show p1 ++ ";" ++ show p2 showPi (New n) = "new " ++ show n showPi (If c p1 Null) = "if " ++ show c ++ " then " ++ show p1 showPi (If c p1 p2) = "if " ++ show c ++ " then " ++ show p1 ++ " else " ++ show p2 showPi (Let n t p) = "let " ++ show n ++ " = " ++ show t ++ case p of {Nothing -> "" ; Just x -> " in\n" ++ show x} showPi (Atom t) = show t showTerm :: Term -> String showTerm (TVar x t) = x ++ (case t of Nothing -> "" Just ty -> ": " ++ show ty) showTerm (TStr str) = show str showTerm (TNum num) = show num showTerm (TBool b ) = map toLower $ show b showTerm (TList ls) = "list(" ++ intercalate "," (map show ls) ++ ")" showTerm (TPair (a,b)) = "pair("++ show a ++ ","++ show b ++ ")" showTerm (TData d) = show d showTerm (TBS bs) = show bs showTerm (TFun n ts) = n ++ "(" ++ intercalate "," (map show ts) ++ ")" showValue :: Value -> String showValue (Proc p) = show p showValue (Term t) = show t showValue (Chan c) = show $ convert c where convert ch = TFun "" (map TStr ex) where ex = extra ch showValue (PrimitiveFunc _) = "" showValue (Func {}) = "" showCond :: Condition -> String showCond (t1 `Equals` t2) = show t1 ++ " == " ++ show t2 showError :: PiError -> String showError (UnboundVar message var) = message ++ ": " ++ var showError (NotFunction message fun) = message ++ ": " ++ fun showError (NotChannel chan) = "Not a channel: " ++ chan showError (NotProcess proc) = "Not a Process: " ++ proc showError (NotTerm name var) = "Expecting " ++ name ++ " to be a Term, found: " ++ show var showError (NumArgs name expected found) = "Expected " ++ show name ++ show expected ++ " args; found values " ++ unwordsList found showError (TypeMismatch expected found) = "Invalid type: expected " ++ expected ++ ", found " ++ show found showError (Parser parseErr) = "Parse error at " ++ show parseErr showError (PatternMatch t1 t2) = "Pattern match failure: cannot match " ++ show t1 ++ " and \n" ++ show t2 showError (Default msg) = msg showHttpData :: HttpData -> String showHttpData (Resp r) = show r showHttpData (Req r) = show r instance Eq Value where (==) = eqvVal instance Eq HttpData where (==) = eqHttpData eqHttpData :: HttpData -> HttpData -> Bool eqHttpData _ _ = False eqvVal :: Value -> Value -> Bool eqvVal (Proc p1) (Proc p2) = p1 == p2 eqvVal (Term t1) (Term t2) = t1 == t2 eqvVal _ _ = False unwordsList :: [Value] -> String unwordsList = unwords . map show