shentong-0.3.1: Shentong/Types.hs
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE Rank2Types #-}
module Types where
import Control.Applicative
import Control.Monad.Except
import Control.Monad.State
import Data.Data
import Data.Generics.Uniplate.Data
import Data.HashMap as HM
import Data.IORef
import qualified Data.Text as T
import Data.Vector as V hiding ((++))
import System.IO
type Symbol = T.Text
type ErrorMsg = T.Text
type ParamList = [Symbol]
data SExpr = Lit !Atom
| Sym {-# UNPACK #-} !Symbol
| Freeze !SExpr
| Let !Symbol !SExpr !SExpr
| Lambda {-# UNPACK #-} !Symbol !SExpr
| If !SExpr !SExpr !SExpr
| And !SExpr !SExpr
| Or !SExpr !SExpr
| Cond ![(SExpr,SExpr)]
| Appl ![SExpr]
| TrapError !SExpr !SExpr
| EmptyList
deriving (Data, Show, Typeable)
type DeBruijn = Int
type Bindings = [(DeBruijn, KLValue)]
data RSExpr = RLit !Atom
| RDeBruijn {-# UNPACK #-} !DeBruijn
| RFreeze !RSExpr
| RLambda {-# UNPACK #-} !DeBruijn !RSExpr
| RIf !RSExpr !RSExpr !RSExpr
| RApplDir !(IORef ApplContext) ![RSExpr]
| RApplForm !RSExpr ![RSExpr]
| RTrapError !RSExpr !RSExpr
| REmptyList
data KLNumber = KI !Integer
| KD {-# UNPACK #-} !Double
deriving (Data, Show, Typeable)
instance Eq KLNumber where
(KI n1) == (KI n2) = n1 == n2
(KI n1) == (KD n2) = realToFrac n1 == n2
(KD n1) == (KI n2) = n1 == realToFrac n2
(KD n1) == (KD n2) = n1 == n2
instance Ord KLNumber where
compare (KI n1) (KI n2) = compare n1 n2
compare (KI n1) (KD n2) = compare (realToFrac n1) n2
compare (KD n1) (KI n2) = compare n1 (realToFrac n2)
compare (KD n1) (KD n2) = compare n1 n2
instance Num KLNumber where
(KI n1) + (KI n2) = KI $ n1 + n2
(KD n1) + (KD n2) = KD $ n1 + n2
(KD n1) + (KI n2) = KD $ n1 + realToFrac n2
(KI n1) + (KD n2) = KD $ realToFrac n1 + n2
(KI n1) * (KI n2) = KI $ n1 * n2
(KD n1) * (KD n2) = KD $ n1 * n2
(KD n1) * (KI n2) = KD $ n1 * realToFrac n2
(KI n1) * (KD n2) = KD $ realToFrac n1 * n2
(KI n1) - (KI n2) = KI $ n1 - n2
(KD n1) - (KD n2) = KD $ n1 - n2
(KD n1) - (KI n2) = KD $ n1 - realToFrac n2
(KI n1) - (KD n2) = KD $ realToFrac n1 - n2
abs (KI n) = KI $ abs n
abs (KD n) = KD $ abs n
signum (KI n) = KI $ signum n
signum (KD n) = KD $ signum n
fromInteger = KI
instance Fractional KLNumber where
(KI n1) / (KI n2) = KD $ realToFrac n1 / realToFrac n2
(KD n1) / (KD n2) = KD $ n1 / n2
(KD n1) / (KI n2) = KD $ n1 / realToFrac n2
(KI n1) / (KD n2) = KD $ realToFrac n1 / n2
fromRational r = KD $ fromRational r
data Atom = UnboundSym {-# UNPACK #-} !Symbol
| B !Bool
| Nil
| N !KLNumber
| Str {-# UNPACK #-} !T.Text
deriving (Data, Eq, Show, Typeable)
data TopLevel = Defun {-# UNPACK #-} !Symbol !ParamList !SExpr
| SE !SExpr
deriving Show
data KLValue = Atom !Atom
| Cons !KLValue !KLValue
| Excep {-# UNPACK #-} !ErrorMsg
| ApplC !ApplContext
| InStream !Handle
| OutStream !Handle
| Vec {-# UNPACK #-} !(Vector KLValue)
deriving (Show)
data ApplContext = Func Symbol Function
| PL Symbol (KLContext Env KLValue)
| Malformed ErrorMsg
instance Show ApplContext where
show (Func name _) = "<function " ++ T.unpack name ++ ">"
show (PL name _) = "<function " ++ T.unpack name ++ ">"
show (Malformed e) = "<function, malformed, message : " ++ T.unpack e ++ ">"
data Function = Context (KLValue -> KLContext Env KLValue)
| PartialApp (KLValue -> Function)
data Env = Env { symbolTable :: Map Symbol KLValue
, functionTable :: Map Symbol (IORef ApplContext) }
newtype KLContext s a = KLContext {
runKLC :: forall r. (a -> s -> IO r)
-> (ErrorMsg -> s -> IO r)
-> s
-> IO r
}
instance Monad (KLContext s) where
(>>=) = klcBind
return = klcReturn
klcBind :: KLContext s a -> (a -> KLContext s b) -> KLContext s b
klcBind m f = KLContext go
where go sk fk s = runKLC m (\a s' -> runKLC (f a) sk fk s') fk s
klcReturn :: a -> KLContext s a
klcReturn a = KLContext go
where go sk _ s = sk a s
instance Applicative (KLContext s) where
pure = return
(<*>) = ap
instance Functor (KLContext s) where
fmap f (KLContext m) = KLContext (\sk fk s -> m (sk . f) fk s)
instance MonadState s (KLContext s) where
get = KLContext (\sk _ s -> sk s s)
put s = KLContext (\sk _ _ -> sk () s)
liftIO' m = KLContext $ \sk fk s -> do
x <- m
sk x s
{-# INLINE liftIO' #-}
instance MonadIO (KLContext s) where
liftIO = liftIO'
instance MonadError ErrorMsg (KLContext s) where
throwError e = KLContext (\_ fk s -> fk e s)
catchError m h = KLContext (\sk fk s -> runKLC m sk (h' sk fk) s)
where h' sk fk e s = let KLContext m = h e in m sk fk s