diff --git a/colorless.cabal b/colorless.cabal
--- a/colorless.cabal
+++ b/colorless.cabal
@@ -3,7 +3,7 @@
 -- see: https://github.com/sol/hpack
 
 name:           colorless
-version:        2.0.0
+version:        2.1.0
 synopsis:       Colorless
 description:    Colorless
 category:       Web
@@ -40,10 +40,10 @@
     , vector
   exposed-modules:
       Colorless.Endpoint
-      Colorless.Runtime.Ast
-      Colorless.Runtime.Expr
-      Colorless.Runtime.Types
-      Colorless.Runtime.Val
+      Colorless.Server.Ast
+      Colorless.Server.Expr
+      Colorless.Server.Types
+      Colorless.Server.Val
       Colorless.Types
   default-language: Haskell2010
 
diff --git a/library/Colorless/Runtime/Ast.hs b/library/Colorless/Runtime/Ast.hs
deleted file mode 100644
--- a/library/Colorless/Runtime/Ast.hs
+++ /dev/null
@@ -1,212 +0,0 @@
-{-# LANGUAGE DeriveGeneric #-}
-module Colorless.Runtime.Ast
-  ( Ast(..)
-  , Ref(..)
-  , If(..)
-  , Get(..)
-  , Define(..)
-  , Lambda(..)
-  , List(..)
-  , Begin(..)
-  , FnCall(..)
-  , Enumeral(..)
-  , Struct(..)
-  , Wrap(..)
-  , StructCall(..)
-  , WrapCall(..)
-  , EnumerationCall(..)
-  , HollowCall(..)
-  , Const(..)
-  ) where
-
-import qualified Data.HashMap.Lazy as HML
-import qualified Data.Vector as V
-import Control.Monad (mzero)
-import Control.Applicative ((<|>))
-import Data.Text (Text)
-import Data.Aeson
-import Data.Map (Map)
-import GHC.Generics (Generic)
-
-import Colorless.Runtime.Types
-
-data Ast
-  = Ast'Ref Ref
-  | Ast'If If
-  | Ast'Get Get
-  | Ast'Define Define
-  | Ast'Lambda Lambda
-  | Ast'List List
-  | Ast'Begin Begin
-  | Ast'FnCall FnCall
-  | Ast'WrapCall WrapCall
-  | Ast'StructCall StructCall
-  | Ast'EnumerationCall EnumerationCall
-  | Ast'HollowCall HollowCall
-  | Ast'Enumeral Enumeral
-  | Ast'Struct Struct
-  | Ast'Wrap Wrap
-  | Ast'Const Const
-  deriving (Show, Eq)
-
-instance FromJSON Ast where
-  parseJSON v
-    =   (Ast'Ref <$> parseJSON v)
-    <|> (Ast'If <$> parseJSON v)
-    <|> (Ast'Get <$> parseJSON v)
-    <|> (Ast'Define <$> parseJSON v)
-    <|> (Ast'Lambda <$> parseJSON v)
-    <|> (Ast'List <$> parseJSON v)
-    <|> (Ast'Begin <$> parseJSON v)
-    <|> (Ast'FnCall <$> parseJSON v)
-    <|> (Ast'EnumerationCall <$> parseJSON v)
-    <|> (Ast'WrapCall <$> parseJSON v)
-    <|> (Ast'StructCall <$> parseJSON v)
-    <|> (Ast'HollowCall <$> parseJSON v)
-    <|> (Ast'Enumeral <$> parseJSON v)
-    <|> (Ast'Struct <$> parseJSON v)
-    <|> (Ast'Wrap <$> parseJSON v)
-    <|> (Ast'Const <$> parseJSON v)
-
-data Ref = Ref
-  { symbol :: Symbol
-  } deriving (Show, Eq)
-
-instance FromJSON Ref where
-  parseJSON (Object o) = Ref <$> o .: "@"
-  parseJSON _ = mzero
-
-data If = If
-  { cond :: Ast
-  , true :: Ast
-  , false :: Ast
-  } deriving (Show, Eq)
-
-instance FromJSON If where
-  parseJSON (Array arr) = case V.toList arr of
-    ["if", cond, true, false] -> If <$> parseJSON cond <*> parseJSON true <*> parseJSON false
-    _ -> mzero
-  parseJSON _ = mzero
-
-data Get = Get
-  { path :: [Text]
-  , val :: Ast
-  } deriving (Show, Eq)
-
-instance FromJSON Get where
-  parseJSON (Array arr) = case V.toList arr of
-    ["get", path, val] -> Get <$> parseJSON path <*> parseJSON val
-    _ -> mzero
-  parseJSON _ = mzero
-
-data Define = Define
-  { var :: Symbol
-  , expr :: Ast
-  } deriving (Show, Eq)
-
-instance FromJSON Define where
-  parseJSON (Array arr) = case V.toList arr of
-    ["def", var, expr] -> Define <$> parseJSON var <*> parseJSON expr
-    _ -> mzero
-  parseJSON _ = mzero
-
-data Lambda = Lambda
-  { args :: [(Symbol, Type)]
-  , expr :: Ast
-  } deriving (Show, Eq)
-
-instance FromJSON Lambda where
-  parseJSON (Array arr) = case V.toList arr of
-    ["fn", Array params, expr] -> Lambda <$> mapM parseParam (V.toList params) <*> parseJSON expr
-    _ -> mzero
-    where
-      parseParam = \case
-        Object o -> case HML.toList o of
-          [(key,val)] -> (Symbol key,) <$> parseJSON val
-          _ -> mzero
-        _ -> mzero
-  parseJSON _ = mzero
-
-data List = List
-  { list :: [Ast]
-  } deriving (Show, Eq)
-
-instance FromJSON List where
-  parseJSON (Object o) = List <$> o .: "List"
-  parseJSON _ = mzero
-
-data Begin = Begin
-  { vals :: [Ast]
-  } deriving (Show, Eq)
-
-instance FromJSON Begin where
-  parseJSON (Array arr) = case V.toList arr of
-    "begin":xs -> Begin <$> mapM parseJSON xs
-    _ -> mzero
-  parseJSON _ = mzero
-
-data FnCall = FnCall
-  { fn :: Ast
-  , args :: [Ast]
-  } deriving (Show, Eq)
-
-instance FromJSON FnCall where
-  parseJSON (Array arr) = case V.toList arr of
-    ((String x):xs) -> FnCall <$> pure (Ast'Ref $ Ref $ Symbol x) <*> mapM parseJSON xs
-    (x:xs) -> FnCall <$> parseJSON x <*> mapM parseJSON xs
-    _ -> mzero
-  parseJSON _ = mzero
-
-data EnumerationCall = EnumerationCall
-  { n :: TypeName
-  , e :: Ast
-  } deriving (Show, Eq, Generic)
-
-instance FromJSON EnumerationCall
-
-data WrapCall = WrapCall
-  { n :: TypeName
-  , w :: Ast
-  } deriving (Show, Eq, Generic)
-
-instance FromJSON WrapCall
-
-data StructCall = StructCall
-  { n :: TypeName
-  , m :: Map MemberName Ast
-  } deriving (Show, Eq, Generic)
-
-instance FromJSON StructCall
-
-data HollowCall = HollowCall
-  { n :: TypeName
-  } deriving (Show, Eq, Generic)
-
-instance FromJSON HollowCall
-
-data Enumeral = Enumeral
-  { tag :: EnumeralName
-  , m :: Maybe (Map MemberName Ast)
-  } deriving (Show, Eq, Generic)
-
-instance FromJSON Enumeral where
-  parseJSON (Object o) = do
-    tag <- o .: "tag"
-    let tagless = HML.delete "tag" o
-    if HML.size o == 1
-      then pure $ Enumeral tag Nothing
-      else Enumeral tag <$> (Just <$> parseJSON (Object tagless))
-  parseJSON _ = mzero
-
-data Struct = Struct
-  { m :: Map MemberName Ast
-  } deriving (Show, Eq, Generic)
-
-instance FromJSON Struct where
-  parseJSON v = Struct <$> parseJSON v
-
-data Wrap = Wrap
-  { w :: Ast
-  } deriving (Show, Eq, Generic)
-
-instance FromJSON Wrap
diff --git a/library/Colorless/Runtime/Expr.hs b/library/Colorless/Runtime/Expr.hs
deleted file mode 100644
--- a/library/Colorless/Runtime/Expr.hs
+++ /dev/null
@@ -1,658 +0,0 @@
-{-# LANGUAGE RankNTypes #-}
-module Colorless.Runtime.Expr
-  ( Expr(..)
-  , EvalConfig(..)
-  --
-  , Ref(..)
-  , UnVal(..)
-  , UnEnumeral(..)
-  , UnWrap(..)
-  , UnStruct(..)
-  , If(..)
-  , Get(..)
-  , Define(..)
-  , Lambda(..)
-  , Fn(..)
-  , List(..)
-  , Begin(..)
-  , FnCall(..)
-  , ApiUnCall(..)
-  , HollowUnCall(..)
-  , WrapUnCall(..)
-  , StructUnCall(..)
-  , EnumerationUnCall(..)
-  , Val(..)
-  , ApiVal(..)
-  , Wrap(..)
-  , Struct(..)
-  , Enumeral(..)
-  , ApiCall(..)
-  --
-  , jsonToExpr
-  , apiCallName
-  , fromAst
-  --
-  , ApiParser(..)
-  , parseApiCall
-  --
-  , eval
-  , forceVal
-  , runEval
-  , emptyEnv
-  ) where
-
-import qualified Data.Map as Map
-import Control.Monad (when, join)
-import Control.Monad.IO.Class (MonadIO(..))
-import Control.Monad.Reader (MonadReader(..), ReaderT(..), asks, lift)
-import Data.Map (Map)
-import Data.Int
-import Data.Word
-import Data.Aeson (parseJSON, Value)
-import Data.Aeson.Types (parseMaybe)
-import Data.IORef (IORef, readIORef, newIORef, writeIORef)
-import Data.Scientific (toBoundedInteger, Scientific)
-import Data.Text (Text)
-
-import qualified Colorless.Runtime.Ast as Ast
-import Colorless.Types
-import Colorless.Runtime.Types
-import Colorless.Runtime.Val
-import Colorless.Runtime.Ast (Ast(..))
-
-data EvalConfig m = EvalConfig
-  { options :: Options
-  , apiCall :: ApiCall -> m Val
-  }
-
-jsonToExpr :: (Monad m) => Value -> Maybe (Expr m)
-jsonToExpr = fmap fromAst . parseMaybe parseJSON
-
-newtype Eval m a = Eval (ReaderT (EvalConfig m) m a)
-  deriving (Functor, Applicative, Monad, MonadReader (EvalConfig m), MonadIO)
-
-instance RuntimeThrower m => RuntimeThrower (Eval m) where
-  runtimeThrow err = Eval (lift $ runtimeThrow err)
-
-getOptions :: Monad m => Eval m Options
-getOptions = asks options
-
-type Env m = Map Symbol (IORef (Expr m))
-
-runEval :: MonadIO m => Eval m a -> EvalConfig m -> m a
-runEval (Eval r) = runReaderT r
-
-data Expr m
-  = Expr'Ref Ref
-  | Expr'UnVal (UnVal m)
-  | Expr'Val Val
-  | Expr'If (If m)
-  | Expr'Get (Get m)
-  | Expr'Define (Define m)
-  | Expr'Lambda (Lambda m)
-  | Expr'List (List m)
-  | Expr'Fn (Fn m)
-  | Expr'FnCall (FnCall m)
-  | Expr'Begin (Begin m)
-  | Expr'ApiUnCall (ApiUnCall m)
-  deriving (Show, Eq)
-
-data UnVal m
-  = UnVal'Const Const
-  | UnVal'UnWrap (UnWrap m)
-  | UnVal'UnStruct (UnStruct m)
-  | UnVal'UnEnumeral (UnEnumeral m)
-  deriving (Show, Eq)
-
-data UnWrap m = UnWrap
-  { w :: Expr m
-  } deriving (Show, Eq)
-
-data UnStruct m = UnStruct
-  { m :: Map MemberName (Expr m)
-  } deriving (Show, Eq)
-
-data UnEnumeral m = UnEnumeral
-  { tag :: EnumeralName
-  , m :: Maybe (Map MemberName (Expr m))
-  } deriving (Show, Eq)
-
-data Ref = Ref
-  { symbol :: Symbol
-  } deriving (Show, Eq)
-
-data If m = If
-  { cond :: Expr m
-  , true :: Expr m
-  , false :: Expr m
-  } deriving (Show, Eq)
-
-data Get m = Get
-  { path :: [Text]
-  , expr :: Expr m
-  } deriving (Show, Eq)
-
-data Define m = Define
-  { var :: Symbol
-  , expr :: Expr m
-  } deriving (Show, Eq)
-
-data Lambda m = Lambda
-  { params :: [(Symbol, Type)]
-  , expr :: Expr m
-  } deriving (Show, Eq)
-
-newtype Fn m = Fn ([Expr m] -> Eval m (Expr m))
-
-instance Show (Fn m) where
-  show _ = "<Fn>"
-
-instance Eq (Fn m) where
-  (==) _ _ = False
-
-data List m = List
-  { list :: [Expr m]
-  } deriving (Show, Eq)
-
-data Begin m = Begin
-  { exprs :: [Expr m]
-  } deriving (Show, Eq)
-
-data FnCall m = FnCall
-  { fn :: Expr m
-  , args :: [Expr m]
-  } deriving (Show, Eq)
-
-data ApiUnCall m
-  = ApiUnCall'HollowUnCall HollowUnCall
-  | ApiUnCall'WrapUnCall (WrapUnCall m)
-  | ApiUnCall'StructUnCall (StructUnCall m)
-  | ApiUnCall'EnumerationUnCall (EnumerationUnCall m)
-  deriving (Show, Eq)
-
-data HollowUnCall = HollowUnCall
-  { n :: TypeName
-  } deriving (Show, Eq)
-
-data WrapUnCall m = WrapUnCall
-  { n :: TypeName
-  , w :: Expr m
-  } deriving (Show, Eq)
-
-data StructUnCall m = StructUnCall
-  { n :: TypeName
-  , m :: Map MemberName (Expr m)
-  } deriving (Show, Eq)
-
-data EnumerationUnCall m = EnumerationUnCall
-  { n :: TypeName
-  , e :: Expr m
-  } deriving (Show, Eq)
-
-data ApiCall
-  = ApiCall'Hollow TypeName
-  | ApiCall'Struct TypeName Struct
-  | ApiCall'Enumeration TypeName Enumeral
-  | ApiCall'Wrap TypeName Wrap
-  deriving (Show, Eq)
-
-apiCallName :: ApiCall -> TypeName
-apiCallName = \case
-  ApiCall'Hollow n -> n
-  ApiCall'Struct n _ -> n
-  ApiCall'Enumeration n _ -> n
-  ApiCall'Wrap n _ -> n
-
---
-
-fromAst :: Monad m => Ast -> Expr m
-fromAst = \case
-  Ast'Ref Ast.Ref{symbol} -> Expr'Ref $ Ref symbol
-  Ast'If Ast.If{cond,true,false} -> Expr'If $ If (fromAst cond) (fromAst true) (fromAst false)
-  Ast'Get Ast.Get{path,val} -> Expr'Get $ Get path (fromAst val)
-  Ast'Define Ast.Define{var,expr} -> Expr'Define $ Define var (fromAst expr)
-  Ast'Lambda Ast.Lambda{args,expr} -> Expr'Lambda $ Lambda args (fromAst expr)
-  Ast'List Ast.List{list} -> Expr'List $ List $ map fromAst list
-  Ast'Begin Ast.Begin{vals} -> Expr'Begin $ Begin $ map fromAst vals
-  Ast'FnCall Ast.FnCall{fn,args} -> Expr'FnCall $ FnCall (fromAst fn) (map fromAst args)
-  Ast'WrapCall Ast.WrapCall{n,w} -> Expr'ApiUnCall $ ApiUnCall'WrapUnCall $ WrapUnCall n (fromAst w)
-  Ast'HollowCall Ast.HollowCall{n} -> Expr'ApiUnCall $ ApiUnCall'HollowUnCall $ HollowUnCall n
-  Ast'StructCall Ast.StructCall{n,m} -> Expr'ApiUnCall $ ApiUnCall'StructUnCall $ StructUnCall n (fromAst <$> m)
-  Ast'EnumerationCall Ast.EnumerationCall{n,e} -> Expr'ApiUnCall $ ApiUnCall'EnumerationUnCall $ EnumerationUnCall n (fromAst e)
-  Ast'Enumeral Ast.Enumeral{tag,m} -> Expr'UnVal $ UnVal'UnEnumeral $ UnEnumeral tag (fmap fromAst <$> m)
-  Ast'Struct Ast.Struct{m} -> Expr'UnVal $ UnVal'UnStruct $ UnStruct (fromAst <$> m)
-  Ast'Wrap Ast.Wrap{w} -> Expr'UnVal $ UnVal'UnWrap $ UnWrap (fromAst w)
-  Ast'Const c -> Expr'UnVal $ UnVal'Const c
-
---
-
-addEnvToEnv :: (RuntimeThrower m, Ord k, MonadIO m) => Maybe Int -> Map k a -> IORef (Map k a) -> m (IORef (Map k a))
-addEnvToEnv maybeVariableLimit vars envRef = do
-  env <- liftIO $ readIORef envRef
-  let env' = Map.union vars env
-  case maybeVariableLimit of
-    Nothing -> return ()
-    Just limit -> when (Map.size env' > limit) $ runtimeThrow RuntimeError'VariableLimit
-  liftIO $ newIORef env'
-
-addVarToEnv :: (Ord k, MonadIO m, RuntimeThrower m) => Maybe Int -> IORef (Map k a) -> k -> a -> Map k a -> m ()
-addVarToEnv maybeVariableLimit envRef var ref env = do
-  let env' = Map.insert var ref env
-  case maybeVariableLimit of
-    Nothing -> return ()
-    Just limit -> when (Map.size env' > limit) $ runtimeThrow RuntimeError'VariableLimit
-  liftIO $ writeIORef envRef env'
-
-varLookup :: (MonadIO m, RuntimeThrower m) => Map Symbol (IORef a) -> Symbol -> m a
-varLookup env symbol@(Symbol s) = case Map.lookup symbol env of
-  Nothing -> runtimeThrow $ RuntimeError'UnknownVariable s
-  Just var -> liftIO $ readIORef $ var
-
---
-
-eval :: (MonadIO m, RuntimeThrower m) => Expr m -> IORef (Env m) -> Eval m (Expr m)
-eval expr envRef = case expr of
-  Expr'Ref atom -> evalRef atom envRef
-  Expr'If if' -> evalIf if' envRef
-  Expr'UnVal unVal -> evalUnVal unVal envRef
-  Expr'Val val -> return $ Expr'Val val
-  Expr'Get get -> evalGet get envRef
-  Expr'Define define -> evalDefine define envRef
-  Expr'Lambda lambda -> evalLambda lambda envRef
-  Expr'Fn _ -> return expr -- throw error?
-  Expr'List list -> evalList list envRef
-  Expr'FnCall call -> evalFnCall call envRef
-  Expr'Begin begin -> evalBegin begin envRef
-  Expr'ApiUnCall apiUnCall -> evalApiUnCall apiUnCall envRef
-
-forceVal :: (RuntimeThrower m) => Expr m -> Eval m Val
-forceVal (Expr'Val v) = return v
-forceVal _ = runtimeThrow RuntimeError'IncompatibleType
-
-evalRef :: (MonadIO m, RuntimeThrower m) => Ref -> IORef (Env m) -> Eval m (Expr m)
-evalRef Ref{symbol} envRef = do
-  env <- liftIO $ readIORef envRef
-  varLookup env symbol
-
-evalUnVal :: (MonadIO m, RuntimeThrower m) => UnVal m -> IORef (Env m) -> Eval m (Expr m)
-evalUnVal unVal envRef = case unVal of
-  UnVal'Const c -> return $ Expr'Val $ Val'Const c
-
-  UnVal'UnStruct UnStruct{m} -> do
-    members <- mapM (\(name,expr) -> (name,) <$> (forceVal =<< eval expr envRef)) (Map.toList m)
-    return $ Expr'Val $ Val'ApiVal $ ApiVal'Struct $ Struct (Map.fromList members)
-
-  UnVal'UnWrap UnWrap{w} -> do
-    w' <- eval w envRef
-    case w' of
-      Expr'Val (Val'Const c) -> return $ Expr'Val $ Val'ApiVal $ ApiVal'Wrap $ Wrap c
-      _ -> runtimeThrow RuntimeError'IncompatibleType
-
-  UnVal'UnEnumeral UnEnumeral{tag,m} -> do
-    case m of
-      Nothing -> return $ Expr'Val $ Val'ApiVal $ ApiVal'Enumeral $ Enumeral tag Nothing
-      Just members' -> do
-        members <- mapM (\(name,expr) -> (name,) <$> (forceVal =<< eval expr envRef)) (Map.toList members')
-        return $ Expr'Val $ Val'ApiVal $ ApiVal'Enumeral $ Enumeral tag (Just $ Map.fromList members)
-
-evalIf :: (MonadIO m, RuntimeThrower m) => If m -> IORef (Env m) -> Eval m (Expr m)
-evalIf If{cond, true, false} envRef = do
-  envRef' <- liftIO $ newIORef =<< readIORef envRef
-  v <- eval cond envRef'
-  case v of
-    Expr'Val (Val'Const (Const'Bool cond')) -> do
-      envRef'' <- liftIO $ newIORef =<< readIORef envRef
-      eval (if cond' then true else false) envRef''
-    _ -> runtimeThrow RuntimeError'IncompatibleType
-
-evalGet :: (MonadIO m, RuntimeThrower m) => Get m -> IORef (Env m) -> Eval m (Expr m)
-evalGet Get{path,expr} envRef = getter path =<< eval expr envRef
-
-getter :: (MonadIO m, RuntimeThrower m) => [Text] -> Expr m -> Eval m (Expr m)
-getter [] expr = return expr
-getter path expr =
-  case expr of
-    Expr'Val val -> case val of
-      Val'ApiVal apiVal -> getterApiVal path apiVal
-      _ -> runtimeThrow RuntimeError'IncompatibleType
-    _ -> runtimeThrow RuntimeError'IncompatibleType
-
-getterApiVal :: (MonadIO m, RuntimeThrower m) => [Text] -> ApiVal -> Eval m (Expr m)
-getterApiVal ("w":path) (ApiVal'Wrap (Wrap w)) = getter path (Expr'Val (Val'Const w))
-getterApiVal (mName:path) (ApiVal'Struct Struct{m}) =
-  case Map.lookup (MemberName mName) m of
-    Nothing -> runtimeThrow RuntimeError'IncompatibleType
-    Just member -> getter path (Expr'Val member)
-getterApiVal (mName:path) (ApiVal'Enumeral Enumeral{m})
-  | mName == "tag" = runtimeThrow RuntimeError'IncompatibleType
-  | otherwise = case m >>= Map.lookup (MemberName mName) of
-      Nothing -> runtimeThrow RuntimeError'IncompatibleType
-      Just member -> getter path (Expr'Val member)
-getterApiVal _ _ = runtimeThrow RuntimeError'IncompatibleType
-
-evalDefine :: (MonadIO m, RuntimeThrower m) => Define m -> IORef (Env m) -> Eval m (Expr m)
-evalDefine Define{var, expr} envRef = do
-  expr' <- eval expr envRef
-  env <- liftIO $ readIORef envRef
-  ref <- liftIO $ newIORef expr'
-  limit <- variableLimit <$> getOptions
-  addVarToEnv limit envRef var ref env
-  return expr'
-
-evalLambda :: (MonadIO m, RuntimeThrower m) => Lambda m -> IORef (Env m) -> Eval m (Expr m)
-evalLambda Lambda{params, expr} envRef = do
-  return . Expr'Fn . Fn $ \vals -> do
-    let keys = map fst params
-    let args = zip keys vals
-    let keysLen = length keys
-    let argsLen = length args
-    if keysLen /= argsLen
-      then runtimeThrow $ if keysLen < argsLen
-        then RuntimeError'TooManyArguments
-        else RuntimeError'TooFewArguments
-      else do
-        args' <- liftIO $ mapM newIORef (Map.fromList args)
-        limit <- variableLimit <$> getOptions
-        envRef' <- addEnvToEnv limit args' envRef
-        eval expr envRef'
-
-evalList :: (MonadIO m, RuntimeThrower m) => List m -> IORef (Env m)-> Eval m (Expr m)
-evalList List{list} envRef = do
-  list' <- mapM (\item -> eval item envRef) list
-  return . Expr'List $ List list'
-
-evalBegin :: (MonadIO m, RuntimeThrower m) => Begin m -> IORef (Env m) -> Eval m (Expr m)
-evalBegin Begin{exprs} envRef = case exprs of
-  [] -> return $ Expr'Val $ Val'Const $ Const'Null
-  _ -> last <$> mapM (\expr -> eval expr envRef) exprs
-
-evalFnCall :: (MonadIO m, RuntimeThrower m) => FnCall m -> IORef (Env m) -> Eval m (Expr m)
-evalFnCall FnCall{fn, args} envRef = do
-  val <- eval fn envRef
-  case val of
-    Expr'Fn (Fn fn') -> do
-      args' <- mapM (\arg -> eval arg envRef) args
-      fn' args'
-    Expr'Ref Ref{symbol} -> do
-      env <- liftIO $ readIORef envRef
-      v <- varLookup env symbol
-      case v of
-        Expr'Fn (Fn fn') -> do
-          args' <- mapM (\arg -> eval arg envRef) args
-          fn' args'
-        _ -> runtimeThrow $ RuntimeError'IncompatibleType
-    _ -> runtimeThrow RuntimeError'IncompatibleType
-
-evalApiUnCall :: (MonadIO m, RuntimeThrower m) => ApiUnCall m -> IORef (Env m) -> Eval m (Expr m)
-evalApiUnCall apiUnCall envRef = Expr'Val <$> case apiUnCall of
-  ApiUnCall'HollowUnCall c -> evalHollowUnCall c
-  ApiUnCall'WrapUnCall c -> evalWrapUnCall c envRef
-  ApiUnCall'StructUnCall c -> evalStructUnCall c envRef
-  ApiUnCall'EnumerationUnCall c -> evalEnumerationUnCall c envRef
-
-evalHollowUnCall :: (MonadIO m, RuntimeThrower m) => HollowUnCall -> Eval m Val
-evalHollowUnCall HollowUnCall{n} =
-  Eval . ReaderT $ \cfg ->
-    apiCall cfg $ ApiCall'Hollow n
-
-evalWrapUnCall :: (MonadIO m, RuntimeThrower m) => WrapUnCall m -> IORef (Env m) -> Eval m Val
-evalWrapUnCall WrapUnCall{n,w} envRef = do
-  expr <- eval w envRef
-  case expr of
-    Expr'Val (Val'Const c) -> Eval . ReaderT $ \cfg ->
-      apiCall cfg $ ApiCall'Wrap n (Wrap c)
-    _ -> runtimeThrow RuntimeError'IncompatibleType
-
-evalStructUnCall :: (MonadIO m, RuntimeThrower m) => StructUnCall m -> IORef (Env m) -> Eval m Val
-evalStructUnCall StructUnCall{n,m} envRef = do
-  m' <- mapM eval' m
-  Eval . ReaderT $ \cfg ->
-    apiCall cfg $ ApiCall'Struct n (Struct m')
-  where
-    eval' expr = do
-      expr' <- eval expr envRef
-      case expr' of
-        Expr'Val v -> return v
-        _ -> runtimeThrow RuntimeError'IncompatibleType
-
-evalEnumerationUnCall :: (MonadIO m, RuntimeThrower m) => EnumerationUnCall m -> IORef (Env m) -> Eval m Val
-evalEnumerationUnCall EnumerationUnCall{n,e} envRef = do
-  expr <- eval e envRef
-  case expr of
-    Expr'Val (Val'ApiVal (ApiVal'Enumeral e')) -> Eval . ReaderT $ \cfg ->
-      apiCall cfg $ ApiCall'Enumeration n e'
-    _ -> runtimeThrow RuntimeError'IncompatibleType
-
-emptyEnv :: RuntimeThrower m => IO (IORef (Env m))
-emptyEnv = do
-  eq <- newIORef eqExpr
-  neq <- newIORef neqExpr
-  concat' <- newIORef concatExpr
-  add <- newIORef addExpr
-  sub <- newIORef subExpr
-  mul <- newIORef mulExpr
-  div' <- newIORef divExpr
-  newIORef $ Map.fromList
-    [ ("==", eq)
-    , ("/=", neq)
-    , ("+", add)
-    , ("-", sub)
-    , ("*", mul)
-    , ("/", div')
-    , ("concat", concat')
-    ]
-
-numExpr :: RuntimeThrower m
-  => (Scientific -> Scientific -> Scientific)
-  -> (Int8 -> Int8 -> Int8)
-  -> (Int16 -> Int16 -> Int16)
-  -> (Int32 -> Int32 -> Int32)
-  -> (Int64 -> Int64 -> Int64)
-  -> (Word8 -> Word8 -> Word8)
-  -> (Word16 -> Word16 -> Word16)
-  -> (Word32 -> Word32 -> Word32)
-  -> (Word64 -> Word64 -> Word64)
-  -> Expr m
-numExpr num i8 i16 i32 i64 u8 u16 u32 u64 = Expr'Fn . Fn $ \args ->
-  case args of
-    (_:[]) -> runtimeThrow RuntimeError'TooFewArguments
-    [Expr'Val (Val'Const (Const'Number x)), Expr'Val (Val'Const (Const'Number y))] -> return $
-      Expr'Val $ Val'Const $ Const'Number $ x `num` y
-
-    [Expr'Val (Val'Prim (Prim'I8 x)), Expr'Val (Val'Prim (Prim'I8 y))] -> toExpr $ x `i8` y
-    [Expr'Val (Val'Const (Const'Number x)), Expr'Val (Val'Prim (Prim'I8 y))] -> case toBoundedInteger x of
-      Just x' -> toExpr $ x' `i8` y
-      Nothing -> runtimeThrow RuntimeError'IncompatibleType
-    [Expr'Val (Val'Prim (Prim'I8 x)), Expr'Val (Val'Const (Const'Number y))] -> case toBoundedInteger y of
-      Just y' -> toExpr $ x `i8` y'
-      Nothing -> runtimeThrow RuntimeError'IncompatibleType
-
-    [Expr'Val (Val'Prim (Prim'I16 x)), Expr'Val (Val'Prim (Prim'I16 y))] -> toExpr $ x `i16` y
-    [Expr'Val (Val'Const (Const'Number x)), Expr'Val (Val'Prim (Prim'I16 y))] -> case toBoundedInteger x of
-      Just x' -> toExpr $ x' `i16` y
-      Nothing -> runtimeThrow RuntimeError'IncompatibleType
-    [Expr'Val (Val'Prim (Prim'I16 x)), Expr'Val (Val'Const (Const'Number y))] -> case toBoundedInteger y of
-      Just y' -> toExpr $ x `i16` y'
-      Nothing -> runtimeThrow RuntimeError'IncompatibleType
-
-    [Expr'Val (Val'Prim (Prim'I32 x)), Expr'Val (Val'Prim (Prim'I32 y))] -> toExpr $ x `i32` y
-    [Expr'Val (Val'Const (Const'Number x)), Expr'Val (Val'Prim (Prim'I32 y))] -> case toBoundedInteger x of
-      Just x' -> toExpr $ x' `i32` y
-      Nothing -> runtimeThrow RuntimeError'IncompatibleType
-    [Expr'Val (Val'Prim (Prim'I32 x)), Expr'Val (Val'Const (Const'Number y))] -> case toBoundedInteger y of
-      Just y' -> toExpr $ x `i32` y'
-      Nothing -> runtimeThrow RuntimeError'IncompatibleType
-
-    [Expr'Val (Val'Prim (Prim'I64 x)), Expr'Val (Val'Prim (Prim'I64 y))] -> toExpr $ x `i64` y
-    [Expr'Val (Val'Const (Const'Number x)), Expr'Val (Val'Prim (Prim'I64 y))] -> case toBoundedInteger x of
-      Just x' -> toExpr $ x' `i64` y
-      Nothing -> runtimeThrow RuntimeError'IncompatibleType
-    [Expr'Val (Val'Prim (Prim'I64 x)), Expr'Val (Val'Const (Const'Number y))] -> case toBoundedInteger y of
-      Just y' -> toExpr $ x `i64` y'
-      Nothing -> runtimeThrow RuntimeError'IncompatibleType
-
-    [Expr'Val (Val'Prim (Prim'U8 x)), Expr'Val (Val'Prim (Prim'U8 y))] -> toExpr $ x `u8` y
-    [Expr'Val (Val'Const (Const'Number x)), Expr'Val (Val'Prim (Prim'U8 y))] -> case toBoundedInteger x of
-      Just x' -> toExpr $ x' `u8` y
-      Nothing -> runtimeThrow RuntimeError'IncompatibleType
-    [Expr'Val (Val'Prim (Prim'U8 x)), Expr'Val (Val'Const (Const'Number y))] -> case toBoundedInteger y of
-      Just y' -> toExpr $ x `u8` y'
-      Nothing -> runtimeThrow RuntimeError'IncompatibleType
-
-    [Expr'Val (Val'Prim (Prim'U16 x)), Expr'Val (Val'Prim (Prim'U16 y))] -> toExpr $ x `u16` y
-    [Expr'Val (Val'Const (Const'Number x)), Expr'Val (Val'Prim (Prim'U16 y))] -> case toBoundedInteger x of
-      Just x' -> toExpr $ x' `u16` y
-      Nothing -> runtimeThrow RuntimeError'IncompatibleType
-    [Expr'Val (Val'Prim (Prim'U16 x)), Expr'Val (Val'Const (Const'Number y))] -> case toBoundedInteger y of
-      Just y' -> toExpr $ x `u16` y'
-      Nothing -> runtimeThrow RuntimeError'IncompatibleType
-
-    [Expr'Val (Val'Prim (Prim'U32 x)), Expr'Val (Val'Prim (Prim'U32 y))] -> toExpr $ x `u32` y
-    [Expr'Val (Val'Const (Const'Number x)), Expr'Val (Val'Prim (Prim'U32 y))] -> case toBoundedInteger x of
-      Just x' -> toExpr $ x' `u32` y
-      Nothing -> runtimeThrow RuntimeError'IncompatibleType
-    [Expr'Val (Val'Prim (Prim'U32 x)), Expr'Val (Val'Const (Const'Number y))] -> case toBoundedInteger y of
-      Just y' -> toExpr $ x `u32` y'
-      Nothing -> runtimeThrow RuntimeError'IncompatibleType
-
-    [Expr'Val (Val'Prim (Prim'U64 x)), Expr'Val (Val'Prim (Prim'U64 y))] -> toExpr $ x `u64` y
-    [Expr'Val (Val'Const (Const'Number x)), Expr'Val (Val'Prim (Prim'U64 y))] -> case toBoundedInteger x of
-      Just x' -> toExpr $ x' `u64` y
-      Nothing -> runtimeThrow RuntimeError'IncompatibleType
-    [Expr'Val (Val'Prim (Prim'U64 x)), Expr'Val (Val'Const (Const'Number y))] -> case toBoundedInteger y of
-      Just y' -> toExpr $ x `u64` y'
-      Nothing -> runtimeThrow RuntimeError'IncompatibleType
-
-    (_:_:[]) -> runtimeThrow RuntimeError'IncompatibleType
-    _ -> runtimeThrow RuntimeError'TooManyArguments
-    where
-      toExpr v = return $ Expr'Val (toVal v)
-
-boolExpr :: RuntimeThrower m
-  => (Scientific -> Scientific -> Bool)
-  -> (Int8 -> Int8 -> Bool)
-  -> (Int16 -> Int16 -> Bool)
-  -> (Int32 -> Int32 -> Bool)
-  -> (Int64 -> Int64 -> Bool)
-  -> (Word8 -> Word8 -> Bool)
-  -> (Word16 -> Word16 -> Bool)
-  -> (Word32 -> Word32 -> Bool)
-  -> (Word64 -> Word64 -> Bool)
-  -> Expr m
-boolExpr num i8 i16 i32 i64 u8 u16 u32 u64 = Expr'Fn . Fn $ \args ->
-  case args of
-    (_:[]) -> runtimeThrow RuntimeError'TooManyArguments
-    [Expr'Val (Val'Const (Const'Number x)), Expr'Val (Val'Const (Const'Number y))] -> toExpr $ x `num` y
-
-    [Expr'Val (Val'Prim (Prim'I8 x)), Expr'Val (Val'Prim (Prim'I8 y))] -> toExpr $ x `i8` y
-    [Expr'Val (Val'Const (Const'Number x)), Expr'Val (Val'Prim (Prim'I8 y))] -> case toBoundedInteger x of
-      Just x' -> toExpr $ x' `i8` y
-      Nothing -> runtimeThrow RuntimeError'IncompatibleType
-    [Expr'Val (Val'Prim (Prim'I8 x)), Expr'Val (Val'Const (Const'Number y))] -> case toBoundedInteger y of
-      Just y' -> toExpr $ x `i8` y'
-      Nothing -> runtimeThrow RuntimeError'IncompatibleType
-
-    [Expr'Val (Val'Prim (Prim'I16 x)), Expr'Val (Val'Prim (Prim'I16 y))] -> toExpr $ x `i16` y
-    [Expr'Val (Val'Const (Const'Number x)), Expr'Val (Val'Prim (Prim'I16 y))] -> case toBoundedInteger x of
-      Just x' -> toExpr $ x' `i16` y
-      Nothing -> runtimeThrow RuntimeError'IncompatibleType
-    [Expr'Val (Val'Prim (Prim'I16 x)), Expr'Val (Val'Const (Const'Number y))] -> case toBoundedInteger y of
-      Just y' -> toExpr $ x `i16` y'
-      Nothing -> runtimeThrow RuntimeError'IncompatibleType
-
-    [Expr'Val (Val'Prim (Prim'I32 x)), Expr'Val (Val'Prim (Prim'I32 y))] -> toExpr $ x `i32` y
-    [Expr'Val (Val'Const (Const'Number x)), Expr'Val (Val'Prim (Prim'I32 y))] -> case toBoundedInteger x of
-      Just x' -> toExpr $ x' `i32` y
-      Nothing -> runtimeThrow RuntimeError'IncompatibleType
-    [Expr'Val (Val'Prim (Prim'I32 x)), Expr'Val (Val'Const (Const'Number y))] -> case toBoundedInteger y of
-      Just y' -> toExpr $ x `i32` y'
-      Nothing -> runtimeThrow RuntimeError'IncompatibleType
-
-    [Expr'Val (Val'Prim (Prim'I64 x)), Expr'Val (Val'Prim (Prim'I64 y))] -> toExpr $ x `i64` y
-    [Expr'Val (Val'Const (Const'Number x)), Expr'Val (Val'Prim (Prim'I64 y))] -> case toBoundedInteger x of
-      Just x' -> toExpr $ x' `i64` y
-      Nothing -> runtimeThrow RuntimeError'IncompatibleType
-    [Expr'Val (Val'Prim (Prim'I64 x)), Expr'Val (Val'Const (Const'Number y))] -> case toBoundedInteger y of
-      Just y' -> toExpr $ x `i64` y'
-      Nothing -> runtimeThrow RuntimeError'IncompatibleType
-
-    [Expr'Val (Val'Prim (Prim'U8 x)), Expr'Val (Val'Prim (Prim'U8 y))] -> toExpr $ x `u8` y
-    [Expr'Val (Val'Const (Const'Number x)), Expr'Val (Val'Prim (Prim'U8 y))] -> case toBoundedInteger x of
-      Just x' -> toExpr $ x' `u8` y
-      Nothing -> runtimeThrow RuntimeError'IncompatibleType
-    [Expr'Val (Val'Prim (Prim'U8 x)), Expr'Val (Val'Const (Const'Number y))] -> case toBoundedInteger y of
-      Just y' -> toExpr $ x `u8` y'
-      Nothing -> runtimeThrow RuntimeError'IncompatibleType
-
-    [Expr'Val (Val'Prim (Prim'U16 x)), Expr'Val (Val'Prim (Prim'U16 y))] -> toExpr $ x `u16` y
-    [Expr'Val (Val'Const (Const'Number x)), Expr'Val (Val'Prim (Prim'U16 y))] -> case toBoundedInteger x of
-      Just x' -> toExpr $ x' `u16` y
-      Nothing -> runtimeThrow RuntimeError'IncompatibleType
-    [Expr'Val (Val'Prim (Prim'U16 x)), Expr'Val (Val'Const (Const'Number y))] -> case toBoundedInteger y of
-      Just y' -> toExpr $ x `u16` y'
-      Nothing -> runtimeThrow RuntimeError'IncompatibleType
-
-    [Expr'Val (Val'Prim (Prim'U32 x)), Expr'Val (Val'Prim (Prim'U32 y))] -> toExpr $ x `u32` y
-    [Expr'Val (Val'Const (Const'Number x)), Expr'Val (Val'Prim (Prim'U32 y))] -> case toBoundedInteger x of
-      Just x' -> toExpr $ x' `u32` y
-      Nothing -> runtimeThrow RuntimeError'IncompatibleType
-    [Expr'Val (Val'Prim (Prim'U32 x)), Expr'Val (Val'Const (Const'Number y))] -> case toBoundedInteger y of
-      Just y' -> toExpr $ x `u32` y'
-      Nothing -> runtimeThrow RuntimeError'IncompatibleType
-
-    [Expr'Val (Val'Prim (Prim'U64 x)), Expr'Val (Val'Prim (Prim'U64 y))] -> toExpr $ x `u64` y
-    [Expr'Val (Val'Const (Const'Number x)), Expr'Val (Val'Prim (Prim'U64 y))] -> case toBoundedInteger x of
-      Just x' -> toExpr $ x' `u64` y
-      Nothing -> runtimeThrow RuntimeError'IncompatibleType
-    [Expr'Val (Val'Prim (Prim'U64 x)), Expr'Val (Val'Const (Const'Number y))] -> case toBoundedInteger y of
-      Just y' -> toExpr $ x `u64` y'
-      Nothing -> runtimeThrow RuntimeError'IncompatibleType
-
-    (_:_:[]) -> runtimeThrow RuntimeError'IncompatibleType
-    _ -> runtimeThrow RuntimeError'TooFewArguments
-    where
-      toExpr v = return $ Expr'Val (toVal v)
-
-eqExpr :: RuntimeThrower m => Expr m
-eqExpr = boolExpr (==) (==) (==) (==) (==) (==) (==) (==) (==)
-
-neqExpr :: RuntimeThrower m => Expr m
-neqExpr = boolExpr (/=) (/=) (/=) (/=) (/=) (/=) (/=) (/=) (/=)
-
-concatExpr :: RuntimeThrower m => Expr m
-concatExpr = Expr'Fn . Fn $ \args ->
-  case args of
-    (_:[]) -> runtimeThrow RuntimeError'TooFewArguments
-    [x, y] -> case (x,y) of
-      (Expr'Val (Val'Const (Const'String x')), Expr'Val (Val'Const (Const'String y'))) -> return $
-        Expr'Val . Val'Const . Const'String $ x' `mappend` y'
-      _ -> runtimeThrow RuntimeError'IncompatibleType
-    _ -> runtimeThrow RuntimeError'TooManyArguments
-
-addExpr :: RuntimeThrower m => Expr m
-addExpr = numExpr (+) (+) (+) (+) (+) (+) (+) (+) (+)
-
-subExpr :: RuntimeThrower m => Expr m
-subExpr = numExpr (-) (-) (-) (-) (-) (-) (-) (-) (-)
-
-mulExpr :: RuntimeThrower m => Expr m
-mulExpr = numExpr (*) (*) (*) (*) (*) (*) (*) (*) (*)
-
-divExpr :: RuntimeThrower m => Expr m
-divExpr = numExpr (/) div div div div div div div div
-
---
-
-data ApiParser api = ApiParser
-  { hollow :: Map TypeName api
-  , struct :: Map TypeName (Val -> Maybe api)
-  , enumeration :: Map TypeName (Val -> Maybe api)
-  , wrap :: Map TypeName (Val -> Maybe api)
-  }
-
-parseApiCall :: ApiParser api -> ApiCall -> Maybe api
-parseApiCall ApiParser{hollow, struct, enumeration, wrap} = \case
-  ApiCall'Hollow n -> Map.lookup n hollow
-  ApiCall'Struct n s -> join $ ($ Val'ApiVal (ApiVal'Struct s)) <$> Map.lookup n struct
-  ApiCall'Enumeration n e -> join $ ($ Val'ApiVal (ApiVal'Enumeral e)) <$> Map.lookup n enumeration
-  ApiCall'Wrap n w -> join $ ($ Val'ApiVal (ApiVal'Wrap w)) <$> Map.lookup n wrap
diff --git a/library/Colorless/Runtime/Types.hs b/library/Colorless/Runtime/Types.hs
deleted file mode 100644
--- a/library/Colorless/Runtime/Types.hs
+++ /dev/null
@@ -1,116 +0,0 @@
-module Colorless.Runtime.Types
-  ( Symbol(..)
-  , Type(..)
-  , TypeName(..)
-  , MemberName(..)
-  , EnumeralName(..)
-  , EnumeralType(..)
-  , EnumerationType(..)
-  , StructType(..)
-  , HollowType(..)
-  , Prim(..)
-  , Const(..)
-  ) where
-
-import qualified Data.HashMap.Lazy as HML
-import Control.Monad (mzero)
-import Data.Aeson (FromJSON(..), FromJSONKey, ToJSONKey, Value(..), (.:), ToJSON(..))
-import Data.Text (Text)
-import Data.Map (Map)
-import Data.Int
-import Data.Word
-import Data.Scientific
-import Data.String (IsString)
-
-newtype Symbol = Symbol Text
-  deriving (Show, Eq, Ord, FromJSON, IsString)
-
-data Type = Type
-  { n :: TypeName
-  , p :: Maybe Type
-  } deriving (Show, Eq)
-
-instance FromJSON Type where
-  parseJSON = \case
-    String s -> pure $ Type (TypeName s) Nothing
-    Object o -> do
-      n <- o .: "n"
-      case HML.lookup "p" o of
-        Nothing -> pure $ Type n Nothing
-        Just p -> Type n <$> fmap Just (parseJSON p)
-    _ -> mzero
-
-newtype TypeName = TypeName Text
-  deriving (Show, Eq, Ord, FromJSON, IsString)
-
-newtype EnumeralName = EnumeralName Text
-  deriving (Show, Eq, Ord, FromJSON, ToJSON, IsString)
-
-newtype MemberName = MemberName Text
-  deriving (Show, Eq, Ord, FromJSON, ToJSON, ToJSONKey, FromJSONKey, IsString)
-
-data EnumeralType = EnumeralType
-  { m :: Maybe (Map MemberName Type)
-  } deriving (Show, Eq)
-
-data EnumerationType = EnumerationType
-  { e :: Map EnumeralName EnumeralType
-  , o :: Type
-  } deriving (Show, Eq)
-
-data StructType = StructType
-  { m :: Map MemberName Type
-  , o :: Type
-  } deriving (Show, Eq)
-
-data HollowType = HollowType
-  { o :: Type
-  } deriving (Show, Eq)
-
-data Prim
-  = Prim'Bool Bool
-  | Prim'I8 Int8
-  | Prim'I16 Int16
-  | Prim'I32 Int32
-  | Prim'I64 Int64
-  | Prim'U8 Word8
-  | Prim'U16 Word16
-  | Prim'U32 Word32
-  | Prim'U64 Word64
-  | Prim'String Text
-  deriving (Show, Eq)
-
-instance ToJSON Prim where
-  toJSON = \case
-    Prim'Bool b -> toJSON b
-    Prim'I8 i -> toJSON i
-    Prim'I16 i -> toJSON i
-    Prim'I32 i -> toJSON i
-    Prim'I64 i -> toJSON i
-    Prim'U8 u -> toJSON u
-    Prim'U16 u -> toJSON u
-    Prim'U32 u -> toJSON u
-    Prim'U64 u -> toJSON u
-    Prim'String s -> toJSON s
-
-data Const
-  = Const'Null
-  | Const'Bool Bool
-  | Const'String Text
-  | Const'Number Scientific
-  deriving (Show, Eq)
-
-instance ToJSON Const where
-  toJSON = \case
-    Const'Null -> Null
-    Const'Bool b -> Bool b
-    Const'String s -> String s
-    Const'Number n -> Number n
-
-instance FromJSON Const where
-  parseJSON = \case
-    Null -> pure $ Const'Null
-    Bool b -> pure $ Const'Bool b
-    String s -> pure $ Const'String s
-    Number n -> pure $ Const'Number n
-    _ -> mzero
diff --git a/library/Colorless/Runtime/Val.hs b/library/Colorless/Runtime/Val.hs
deleted file mode 100644
--- a/library/Colorless/Runtime/Val.hs
+++ /dev/null
@@ -1,280 +0,0 @@
-{-# LANGUAGE DeriveGeneric #-}
-module Colorless.Runtime.Val
-  ( Val(..)
-  , ApiVal(..)
-  , Wrap(..)
-  , Struct(..)
-  , Enumeral(..)
-  --
-  , FromVal(..)
-  , ToVal(..)
-  , getMember
-  , fromValFromJson
-  , combineObjects
-  ) where
-
-import qualified Data.HashMap.Lazy as HML
-import qualified Data.Map as Map
-import qualified Data.Vector as V
-import Control.Monad (mzero)
-import Control.Applicative ((<|>))
-import Data.Aeson
-import Data.Aeson.Types (parseMaybe)
-import Data.Map (Map)
-import Data.Text (Text)
-import Data.Int
-import Data.Word
-import Data.Scientific
-import GHC.Generics (Generic)
-
-import Colorless.Runtime.Types
-
-data Val
-  = Val'Const Const
-  | Val'Prim Prim
-  | Val'ApiVal ApiVal
-  | Val'List [Val]
-  deriving (Show, Eq)
-
-instance ToJSON Val where
-  toJSON = \case
-    Val'Const c -> toJSON c
-    Val'ApiVal v -> toJSON v
-    Val'List l -> toJSON l
-    Val'Prim p -> toJSON p
-
-instance FromJSON Val where
-  parseJSON = \case
-    Null -> return $ Val'Const Const'Null
-    Number n -> return $ Val'Const $ Const'Number n
-    String s -> return $ Val'Const $ Const'String s
-    Bool b -> return $ Val'Const $ Const'Bool b
-    Array arr -> Val'List <$> (mapM parseJSON $ V.toList arr)
-    v@Object{} -> Val'ApiVal <$> parseJSON v
-
-data ApiVal
-  = ApiVal'Wrap Wrap
-  | ApiVal'Struct Struct
-  | ApiVal'Enumeral Enumeral
-  deriving (Show, Eq)
-
-instance ToJSON ApiVal where
-  toJSON = \case
-    ApiVal'Wrap w -> toJSON w
-    ApiVal'Struct s -> toJSON s
-    ApiVal'Enumeral e -> toJSON e
-
-instance FromJSON ApiVal where
-  parseJSON v =
-    (ApiVal'Wrap <$> parseJSON v) <|>
-    (ApiVal'Enumeral <$> parseJSON v) <|>
-    (ApiVal'Struct <$> parseJSON v)
-
-data Wrap = Wrap
-  { w :: Const
-  } deriving (Show, Eq, Generic)
-
-instance ToJSON Wrap
-instance FromJSON Wrap
-
-data Struct = Struct
-  { m :: Map MemberName Val
-  } deriving (Show, Eq, Generic)
-
-instance ToJSON Struct where
-  toJSON Struct{m} = toJSON m
-
-instance FromJSON Struct where
-  parseJSON v = Struct <$> parseJSON v
-
-data Enumeral = Enumeral
-  { tag :: EnumeralName
-  , m :: Maybe (Map MemberName Val)
-  } deriving (Show, Eq, Generic)
-
-instance ToJSON Enumeral where
-  toJSON Enumeral{tag,m} = object $ [ "tag" .= tag ] ++ case m of
-    Nothing -> []
-    Just m' -> concatMap (\(MemberName k,v) -> [ k .= v ]) (Map.toList m')
-
-instance FromJSON Enumeral where
-  parseJSON (Object o) = do
-    tag <- o .: "tag"
-    let tagless = HML.delete "tag" o
-    if HML.size o == 1
-      then pure $ Enumeral tag Nothing
-      else Enumeral tag <$> (Just <$> parseJSON (Object tagless))
-  parseJSON _ = mzero
-
---
-
-class ToVal a where
-  toVal :: a -> Val
-
-instance ToVal () where
-  toVal () = Val'Const Const'Null
-
-instance ToVal Bool where
-  toVal b = Val'Const $ Const'Bool b
-
-instance ToVal Text where
-  toVal s = Val'Const $ Const'String s
-
-intToVal :: Integral a => a -> Val
-intToVal n = Val'Const $ Const'Number (fromInteger $ toInteger n)
-
-instance ToVal Int where
-  toVal = intToVal
-
-instance ToVal Int8 where
-  toVal i = Val'Prim $ Prim'I8 i
-
-instance ToVal Int16 where
-  toVal i = Val'Prim $ Prim'I16 i
-
-instance ToVal Int32 where
-  toVal i = Val'Prim $ Prim'I32 i
-
-instance ToVal Int64 where
-  toVal i = Val'Prim $ Prim'I64 i
-
-instance ToVal Word where
-  toVal = intToVal
-
-instance ToVal Word8 where
-  toVal u = Val'Prim $ Prim'U8 u
-
-instance ToVal Word16 where
-  toVal u = Val'Prim $ Prim'U16 u
-
-instance ToVal Word32 where
-  toVal u = Val'Prim $ Prim'U32 u
-
-instance ToVal Word64 where
-  toVal u = Val'Prim $ Prim'U64 u
-
-instance ToVal Float where
-    toVal f = Val'Const $ Const'Number $ fromFloatDigits f
-
-instance ToVal Double where
-    toVal d = Val'Const $ Const'Number $ fromFloatDigits d
-
-instance ToVal a => ToVal (Maybe a) where
-  toVal Nothing = Val'Const Const'Null
-  toVal (Just v) = toVal v
-
-instance (ToVal a, ToVal b) => ToVal (Either a b) where
-  toVal m = Val'ApiVal $ ApiVal'Enumeral $ case m of
-    Left l -> Enumeral "Left" (Just $ Map.singleton "left" (toVal l))
-    Right r -> Enumeral "Right" (Just $ Map.singleton "right" (toVal r))
-
-instance ToVal a => ToVal [a] where
-  toVal list = Val'List $ map toVal list
-
---
-
-class FromVal a where
-  fromVal :: Val -> Maybe a
-
-instance FromVal () where
-  fromVal (Val'Const Const'Null) = Just ()
-  fromVal _ = Nothing
-
-instance FromVal Bool where
-  fromVal (Val'Const (Const'Bool b)) = Just b
-  fromVal _ = Nothing
-
-instance FromVal Text where
-  fromVal (Val'Const (Const'String s)) = Just s
-  fromVal _ = Nothing
-
-intFromVal :: (Bounded i, Integral i) => Val -> Maybe i
-intFromVal (Val'Const (Const'Number n)) = toBoundedInteger n
-intFromVal _ = Nothing
-
-instance FromVal Int where
-  fromVal = intFromVal
-
-instance FromVal Int8 where
-  fromVal = \case
-    Val'Const (Const'Number n) -> toBoundedInteger n
-    Val'Prim (Prim'I8 i) -> Just i
-    _ -> Nothing
-
-instance FromVal Int16 where
-  fromVal = \case
-    Val'Const (Const'Number n) -> toBoundedInteger n
-    Val'Prim (Prim'I16 i) -> Just i
-    _ -> Nothing
-
-instance FromVal Int32 where
-  fromVal = \case
-    Val'Const (Const'Number n) -> toBoundedInteger n
-    Val'Prim (Prim'I32 i) -> Just i
-    _ -> Nothing
-
-instance FromVal Int64 where
-  fromVal = \case
-    Val'Const (Const'Number n) -> toBoundedInteger n
-    Val'Prim (Prim'I64 i) -> Just i
-    _ -> Nothing
-
-instance FromVal Word where
-  fromVal = intFromVal
-
-instance FromVal Word8 where
-  fromVal = \case
-    Val'Const (Const'Number n) -> toBoundedInteger n
-    Val'Prim (Prim'U8 u) -> Just u
-    _ -> Nothing
-
-instance FromVal Word16 where
-  fromVal = \case
-    Val'Const (Const'Number n) -> toBoundedInteger n
-    Val'Prim (Prim'U16 u) -> Just u
-    _ -> Nothing
-
-instance FromVal Word32 where
-  fromVal = \case
-    Val'Const (Const'Number n) -> toBoundedInteger n
-    Val'Prim (Prim'U32 u) -> Just u
-    _ -> Nothing
-
-instance FromVal Word64 where
-  fromVal = \case
-    Val'Const (Const'Number n) -> toBoundedInteger n
-    Val'Prim (Prim'U64 u) -> Just u
-    _ -> Nothing
-
-instance FromVal Float where
-  fromVal (Val'Const (Const'Number n)) = Just $ toRealFloat n
-  fromVal _ = Nothing
-
-instance FromVal Double where
-  fromVal (Val'Const (Const'Number n)) = Just $ toRealFloat n
-  fromVal _ = Nothing
-
-instance FromVal a => FromVal (Maybe a) where
-  fromVal (Val'Const Const'Null) = Just Nothing
-  fromVal v = Just <$> fromVal v
-
-instance (FromVal a, FromVal b) => FromVal (Either a b) where
-  fromVal (Val'ApiVal (ApiVal'Enumeral (Enumeral tag m))) = case (tag,m) of
-    ("Left",Just m') -> Map.lookup "left" m' >>= \l -> Left <$> fromVal l
-    ("Right",Just m') -> Map.lookup "right" m' >>= \r -> Right <$> fromVal r
-    _ -> Nothing
-  fromVal _ = Nothing
-
-instance FromVal a => FromVal [a] where
-  fromVal (Val'List list) = mapM fromVal list
-  fromVal _ = Nothing
-
-getMember :: FromVal a => Map MemberName Val -> MemberName -> Maybe a
-getMember m n = fromVal =<< Map.lookup n m
-
-fromValFromJson :: (FromVal b) => Value -> Maybe b
-fromValFromJson x = fromVal =<< parseMaybe parseJSON x
-
-combineObjects :: Value -> Value -> Value
-combineObjects (Object x) (Object y) = Object $ HML.union x y
-combineObjects _ _ = error "not objects"
diff --git a/library/Colorless/Server/Ast.hs b/library/Colorless/Server/Ast.hs
new file mode 100644
--- /dev/null
+++ b/library/Colorless/Server/Ast.hs
@@ -0,0 +1,223 @@
+{-# LANGUAGE DeriveGeneric #-}
+module Colorless.Server.Ast
+  ( Ast(..)
+  , Ref(..)
+  , If(..)
+  , Get(..)
+  , Define(..)
+  , Lambda(..)
+  , List(..)
+  , Tuple(..)
+  , Begin(..)
+  , FnCall(..)
+  , Enumeral(..)
+  , Struct(..)
+  , Wrap(..)
+  , StructCall(..)
+  , WrapCall(..)
+  , EnumerationCall(..)
+  , HollowCall(..)
+  , Const(..)
+  ) where
+
+import qualified Data.HashMap.Lazy as HML
+import qualified Data.Vector as V
+import Control.Monad (mzero)
+import Control.Applicative ((<|>))
+import Data.Text (Text)
+import Data.Aeson
+import Data.Map (Map)
+import GHC.Generics (Generic)
+
+import Colorless.Server.Types
+
+data Ast
+  = Ast'Ref Ref
+  | Ast'If If
+  | Ast'Get Get
+  | Ast'Define Define
+  | Ast'Lambda Lambda
+  | Ast'List List
+  | Ast'Tuple Tuple
+  | Ast'Begin Begin
+  | Ast'FnCall FnCall
+  | Ast'WrapCall WrapCall
+  | Ast'StructCall StructCall
+  | Ast'EnumerationCall EnumerationCall
+  | Ast'HollowCall HollowCall
+  | Ast'Enumeral Enumeral
+  | Ast'Struct Struct
+  | Ast'Wrap Wrap
+  | Ast'Const Const
+  deriving (Show, Eq)
+
+instance FromJSON Ast where
+  parseJSON v
+    =   (Ast'Ref <$> parseJSON v)
+    <|> (Ast'If <$> parseJSON v)
+    <|> (Ast'Get <$> parseJSON v)
+    <|> (Ast'Define <$> parseJSON v)
+    <|> (Ast'Lambda <$> parseJSON v)
+    <|> (Ast'List <$> parseJSON v)
+    <|> (Ast'Tuple <$> parseJSON v)
+    <|> (Ast'Begin <$> parseJSON v)
+    <|> (Ast'FnCall <$> parseJSON v)
+    <|> (Ast'EnumerationCall <$> parseJSON v)
+    <|> (Ast'WrapCall <$> parseJSON v)
+    <|> (Ast'StructCall <$> parseJSON v)
+    <|> (Ast'HollowCall <$> parseJSON v)
+    <|> (Ast'Enumeral <$> parseJSON v)
+    <|> (Ast'Struct <$> parseJSON v)
+    <|> (Ast'Wrap <$> parseJSON v)
+    <|> (Ast'Const <$> parseJSON v)
+
+data Ref = Ref
+  { symbol :: Symbol
+  } deriving (Show, Eq)
+
+instance FromJSON Ref where
+  parseJSON (Object o) = Ref <$> o .: "@"
+  parseJSON _ = mzero
+
+data If = If
+  { cond :: Ast
+  , true :: Ast
+  , false :: Ast
+  } deriving (Show, Eq)
+
+instance FromJSON If where
+  parseJSON (Array arr) = case V.toList arr of
+    ["if", cond, true, false] -> If <$> parseJSON cond <*> parseJSON true <*> parseJSON false
+    _ -> mzero
+  parseJSON _ = mzero
+
+data Get = Get
+  { path :: [Text]
+  , val :: Ast
+  } deriving (Show, Eq)
+
+instance FromJSON Get where
+  parseJSON (Array arr) = case V.toList arr of
+    ["get", path, val] -> Get <$> parseJSON path <*> parseJSON val
+    _ -> mzero
+  parseJSON _ = mzero
+
+data Define = Define
+  { var :: Symbol
+  , expr :: Ast
+  } deriving (Show, Eq)
+
+instance FromJSON Define where
+  parseJSON (Array arr) = case V.toList arr of
+    ["def", var, expr] -> Define <$> parseJSON var <*> parseJSON expr
+    _ -> mzero
+  parseJSON _ = mzero
+
+data Lambda = Lambda
+  { args :: [(Symbol, Type)]
+  , expr :: Ast
+  } deriving (Show, Eq)
+
+instance FromJSON Lambda where
+  parseJSON (Array arr) = case V.toList arr of
+    ["fn", Array params, expr] -> Lambda <$> mapM parseParam (V.toList params) <*> parseJSON expr
+    _ -> mzero
+    where
+      parseParam = \case
+        Object o -> case HML.toList o of
+          [(key,val)] -> (Symbol key,) <$> parseJSON val
+          _ -> mzero
+        _ -> mzero
+  parseJSON _ = mzero
+
+data List = List
+  { list :: [Ast]
+  } deriving (Show, Eq)
+
+instance FromJSON List where
+  parseJSON (Object o) = List <$> o .: "List"
+  parseJSON _ = mzero
+
+data Tuple = Tuple
+  { tuple :: [Ast]
+  } deriving (Show, Eq)
+
+instance FromJSON Tuple where
+  parseJSON (Object o) = Tuple <$> o .: "Tuple"
+  parseJSON _ = mzero
+
+data Begin = Begin
+  { vals :: [Ast]
+  } deriving (Show, Eq)
+
+instance FromJSON Begin where
+  parseJSON (Array arr) = case V.toList arr of
+    "begin":xs -> Begin <$> mapM parseJSON xs
+    _ -> mzero
+  parseJSON _ = mzero
+
+data FnCall = FnCall
+  { fn :: Ast
+  , args :: [Ast]
+  } deriving (Show, Eq)
+
+instance FromJSON FnCall where
+  parseJSON (Array arr) = case V.toList arr of
+    ((String x):xs) -> FnCall <$> pure (Ast'Ref $ Ref $ Symbol x) <*> mapM parseJSON xs
+    (x:xs) -> FnCall <$> parseJSON x <*> mapM parseJSON xs
+    _ -> mzero
+  parseJSON _ = mzero
+
+data EnumerationCall = EnumerationCall
+  { n :: TypeName
+  , e :: Ast
+  } deriving (Show, Eq, Generic)
+
+instance FromJSON EnumerationCall
+
+data WrapCall = WrapCall
+  { n :: TypeName
+  , w :: Ast
+  } deriving (Show, Eq, Generic)
+
+instance FromJSON WrapCall
+
+data StructCall = StructCall
+  { n :: TypeName
+  , m :: Map MemberName Ast
+  } deriving (Show, Eq, Generic)
+
+instance FromJSON StructCall
+
+data HollowCall = HollowCall
+  { n :: TypeName
+  } deriving (Show, Eq, Generic)
+
+instance FromJSON HollowCall
+
+data Enumeral = Enumeral
+  { tag :: EnumeralName
+  , m :: Maybe (Map MemberName Ast)
+  } deriving (Show, Eq, Generic)
+
+instance FromJSON Enumeral where
+  parseJSON (Object o) = do
+    tag <- o .: "tag"
+    let tagless = HML.delete "tag" o
+    if HML.size o == 1
+      then pure $ Enumeral tag Nothing
+      else Enumeral tag <$> (Just <$> parseJSON (Object tagless))
+  parseJSON _ = mzero
+
+data Struct = Struct
+  { m :: Map MemberName Ast
+  } deriving (Show, Eq, Generic)
+
+instance FromJSON Struct where
+  parseJSON v = Struct <$> parseJSON v
+
+data Wrap = Wrap
+  { w :: Ast
+  } deriving (Show, Eq, Generic)
+
+instance FromJSON Wrap
diff --git a/library/Colorless/Server/Expr.hs b/library/Colorless/Server/Expr.hs
new file mode 100644
--- /dev/null
+++ b/library/Colorless/Server/Expr.hs
@@ -0,0 +1,680 @@
+{-# LANGUAGE RankNTypes #-}
+module Colorless.Server.Expr
+  ( Expr(..)
+  , EvalConfig(..)
+  --
+  , Ref(..)
+  , UnVal(..)
+  , UnEnumeral(..)
+  , UnWrap(..)
+  , UnStruct(..)
+  , If(..)
+  , Get(..)
+  , Define(..)
+  , Lambda(..)
+  , Fn(..)
+  , List(..)
+  , Begin(..)
+  , FnCall(..)
+  , ApiUnCall(..)
+  , HollowUnCall(..)
+  , WrapUnCall(..)
+  , StructUnCall(..)
+  , EnumerationUnCall(..)
+  , Val(..)
+  , ApiVal(..)
+  , Wrap(..)
+  , Struct(..)
+  , Enumeral(..)
+  , ApiCall(..)
+  --
+  , jsonToExpr
+  , apiCallName
+  , fromAst
+  --
+  , ApiParser(..)
+  , parseApiCall
+  --
+  , eval
+  , forceVal
+  , runEval
+  , emptyEnv
+  ) where
+
+import qualified Data.Map as Map
+import Control.Monad (when, join)
+import Control.Monad.IO.Class (MonadIO(..))
+import Control.Monad.Reader (MonadReader(..), ReaderT(..), asks, lift)
+import Data.Map (Map)
+import Data.Int
+import Data.Word
+import Data.Aeson (parseJSON, Value)
+import Data.Aeson.Types (parseMaybe)
+import Data.IORef (IORef, readIORef, newIORef, writeIORef)
+import Data.Scientific (toBoundedInteger, Scientific)
+import Data.Text (Text)
+
+import qualified Colorless.Server.Ast as Ast
+import Colorless.Types
+import Colorless.Server.Types
+import Colorless.Server.Val
+import Colorless.Server.Ast (Ast(..))
+
+data EvalConfig m = EvalConfig
+  { options :: Options
+  , apiCall :: ApiCall -> m Val
+  }
+
+jsonToExpr :: (Monad m) => Value -> Maybe (Expr m)
+jsonToExpr = fmap fromAst . parseMaybe parseJSON
+
+newtype Eval m a = Eval (ReaderT (EvalConfig m) m a)
+  deriving (Functor, Applicative, Monad, MonadReader (EvalConfig m), MonadIO)
+
+instance RuntimeThrower m => RuntimeThrower (Eval m) where
+  runtimeThrow err = Eval (lift $ runtimeThrow err)
+
+getOptions :: Monad m => Eval m Options
+getOptions = asks options
+
+type Env m = Map Symbol (IORef (Expr m))
+
+runEval :: MonadIO m => Eval m a -> EvalConfig m -> m a
+runEval (Eval r) = runReaderT r
+
+data Expr m
+  = Expr'Ref Ref
+  | Expr'UnVal (UnVal m)
+  | Expr'Val Val
+  | Expr'If (If m)
+  | Expr'Get (Get m)
+  | Expr'Define (Define m)
+  | Expr'Lambda (Lambda m)
+  | Expr'List (List m)
+  | Expr'Tuple (Tuple m)
+  | Expr'Fn (Fn m)
+  | Expr'FnCall (FnCall m)
+  | Expr'Begin (Begin m)
+  | Expr'ApiUnCall (ApiUnCall m)
+  deriving (Show, Eq)
+
+data UnVal m
+  = UnVal'Const Const
+  | UnVal'UnWrap (UnWrap m)
+  | UnVal'UnStruct (UnStruct m)
+  | UnVal'UnEnumeral (UnEnumeral m)
+  deriving (Show, Eq)
+
+data UnWrap m = UnWrap
+  { w :: Expr m
+  } deriving (Show, Eq)
+
+data UnStruct m = UnStruct
+  { m :: Map MemberName (Expr m)
+  } deriving (Show, Eq)
+
+data UnEnumeral m = UnEnumeral
+  { tag :: EnumeralName
+  , m :: Maybe (Map MemberName (Expr m))
+  } deriving (Show, Eq)
+
+data Ref = Ref
+  { symbol :: Symbol
+  } deriving (Show, Eq)
+
+data If m = If
+  { cond :: Expr m
+  , true :: Expr m
+  , false :: Expr m
+  } deriving (Show, Eq)
+
+data Get m = Get
+  { path :: [Text]
+  , expr :: Expr m
+  } deriving (Show, Eq)
+
+data Define m = Define
+  { var :: Symbol
+  , expr :: Expr m
+  } deriving (Show, Eq)
+
+data Lambda m = Lambda
+  { params :: [(Symbol, Type)]
+  , expr :: Expr m
+  } deriving (Show, Eq)
+
+newtype Fn m = Fn ([Expr m] -> Eval m (Expr m))
+
+instance Show (Fn m) where
+  show _ = "<Fn>"
+
+instance Eq (Fn m) where
+  (==) _ _ = False
+
+data List m = List
+  { list :: [Expr m]
+  } deriving (Show, Eq)
+
+data Tuple m = Tuple
+  { tuple :: [Expr m]
+  } deriving (Show, Eq)
+
+data Begin m = Begin
+  { exprs :: [Expr m]
+  } deriving (Show, Eq)
+
+data FnCall m = FnCall
+  { fn :: Expr m
+  , args :: [Expr m]
+  } deriving (Show, Eq)
+
+data ApiUnCall m
+  = ApiUnCall'HollowUnCall HollowUnCall
+  | ApiUnCall'WrapUnCall (WrapUnCall m)
+  | ApiUnCall'StructUnCall (StructUnCall m)
+  | ApiUnCall'EnumerationUnCall (EnumerationUnCall m)
+  deriving (Show, Eq)
+
+data HollowUnCall = HollowUnCall
+  { n :: TypeName
+  } deriving (Show, Eq)
+
+data WrapUnCall m = WrapUnCall
+  { n :: TypeName
+  , w :: Expr m
+  } deriving (Show, Eq)
+
+data StructUnCall m = StructUnCall
+  { n :: TypeName
+  , m :: Map MemberName (Expr m)
+  } deriving (Show, Eq)
+
+data EnumerationUnCall m = EnumerationUnCall
+  { n :: TypeName
+  , e :: Expr m
+  } deriving (Show, Eq)
+
+data ApiCall
+  = ApiCall'Hollow TypeName
+  | ApiCall'Struct TypeName Struct
+  | ApiCall'Enumeration TypeName Enumeral
+  | ApiCall'Wrap TypeName Wrap
+  deriving (Show, Eq)
+
+apiCallName :: ApiCall -> TypeName
+apiCallName = \case
+  ApiCall'Hollow n -> n
+  ApiCall'Struct n _ -> n
+  ApiCall'Enumeration n _ -> n
+  ApiCall'Wrap n _ -> n
+
+--
+
+fromAst :: Monad m => Ast -> Expr m
+fromAst = \case
+  Ast'Ref Ast.Ref{symbol} -> Expr'Ref $ Ref symbol
+  Ast'If Ast.If{cond,true,false} -> Expr'If $ If (fromAst cond) (fromAst true) (fromAst false)
+  Ast'Get Ast.Get{path,val} -> Expr'Get $ Get path (fromAst val)
+  Ast'Define Ast.Define{var,expr} -> Expr'Define $ Define var (fromAst expr)
+  Ast'Lambda Ast.Lambda{args,expr} -> Expr'Lambda $ Lambda args (fromAst expr)
+  Ast'List Ast.List{list} -> Expr'List $ List $ map fromAst list
+  Ast'Tuple Ast.Tuple{tuple} -> Expr'Tuple $ Tuple $ map fromAst tuple
+  Ast'Begin Ast.Begin{vals} -> Expr'Begin $ Begin $ map fromAst vals
+  Ast'FnCall Ast.FnCall{fn,args} -> Expr'FnCall $ FnCall (fromAst fn) (map fromAst args)
+  Ast'WrapCall Ast.WrapCall{n,w} -> Expr'ApiUnCall $ ApiUnCall'WrapUnCall $ WrapUnCall n (fromAst w)
+  Ast'HollowCall Ast.HollowCall{n} -> Expr'ApiUnCall $ ApiUnCall'HollowUnCall $ HollowUnCall n
+  Ast'StructCall Ast.StructCall{n,m} -> Expr'ApiUnCall $ ApiUnCall'StructUnCall $ StructUnCall n (fromAst <$> m)
+  Ast'EnumerationCall Ast.EnumerationCall{n,e} -> Expr'ApiUnCall $ ApiUnCall'EnumerationUnCall $ EnumerationUnCall n (fromAst e)
+  Ast'Enumeral Ast.Enumeral{tag,m} -> Expr'UnVal $ UnVal'UnEnumeral $ UnEnumeral tag (fmap fromAst <$> m)
+  Ast'Struct Ast.Struct{m} -> Expr'UnVal $ UnVal'UnStruct $ UnStruct (fromAst <$> m)
+  Ast'Wrap Ast.Wrap{w} -> Expr'UnVal $ UnVal'UnWrap $ UnWrap (fromAst w)
+  Ast'Const c -> Expr'UnVal $ UnVal'Const c
+
+--
+
+addEnvToEnv :: (RuntimeThrower m, Ord k, MonadIO m) => Maybe Int -> Map k a -> IORef (Map k a) -> m (IORef (Map k a))
+addEnvToEnv maybeVariableLimit vars envRef = do
+  env <- liftIO $ readIORef envRef
+  let env' = Map.union vars env
+  case maybeVariableLimit of
+    Nothing -> return ()
+    Just limit -> when (Map.size env' > limit) $ runtimeThrow RuntimeError'VariableLimit
+  liftIO $ newIORef env'
+
+addVarToEnv :: (Ord k, MonadIO m, RuntimeThrower m) => Maybe Int -> IORef (Map k a) -> k -> a -> Map k a -> m ()
+addVarToEnv maybeVariableLimit envRef var ref env = do
+  let env' = Map.insert var ref env
+  case maybeVariableLimit of
+    Nothing -> return ()
+    Just limit -> when (Map.size env' > limit) $ runtimeThrow RuntimeError'VariableLimit
+  liftIO $ writeIORef envRef env'
+
+varLookup :: (MonadIO m, RuntimeThrower m) => Map Symbol (IORef a) -> Symbol -> m a
+varLookup env symbol@(Symbol s) = case Map.lookup symbol env of
+  Nothing -> runtimeThrow $ RuntimeError'UnknownVariable s
+  Just var -> liftIO $ readIORef $ var
+
+--
+
+eval :: (MonadIO m, RuntimeThrower m) => Expr m -> IORef (Env m) -> Eval m (Expr m)
+eval expr envRef = case expr of
+  Expr'Ref atom -> evalRef atom envRef
+  Expr'If if' -> evalIf if' envRef
+  Expr'UnVal unVal -> evalUnVal unVal envRef
+  Expr'Val val -> return $ Expr'Val val
+  Expr'Get get -> evalGet get envRef
+  Expr'Define define -> evalDefine define envRef
+  Expr'Lambda lambda -> evalLambda lambda envRef
+  Expr'Fn _ -> return expr -- throw error?
+  Expr'List list -> evalList list envRef
+  Expr'Tuple tuple -> evalTuple tuple envRef
+  Expr'FnCall call -> evalFnCall call envRef
+  Expr'Begin begin -> evalBegin begin envRef
+  Expr'ApiUnCall apiUnCall -> evalApiUnCall apiUnCall envRef
+
+forceVal :: (RuntimeThrower m) => Expr m -> Eval m Val
+forceVal (Expr'Val v) = return v
+forceVal (Expr'List (List l)) = Val'List <$> mapM forceVal l
+forceVal (Expr'Tuple (Tuple t)) = Val'List <$> mapM forceVal t
+forceVal _ = runtimeThrow RuntimeError'IncompatibleType
+
+evalRef :: (MonadIO m, RuntimeThrower m) => Ref -> IORef (Env m) -> Eval m (Expr m)
+evalRef Ref{symbol} envRef = do
+  env <- liftIO $ readIORef envRef
+  varLookup env symbol
+
+evalUnVal :: (MonadIO m, RuntimeThrower m) => UnVal m -> IORef (Env m) -> Eval m (Expr m)
+evalUnVal unVal envRef = case unVal of
+  UnVal'Const c -> return $ Expr'Val $ Val'Const c
+
+  UnVal'UnStruct UnStruct{m} -> do
+    members <- mapM (\(name,expr) -> (name,) <$> (forceVal =<< eval expr envRef)) (Map.toList m)
+    return $ Expr'Val $ Val'ApiVal $ ApiVal'Struct $ Struct (Map.fromList members)
+
+  UnVal'UnWrap UnWrap{w} -> do
+    w' <- eval w envRef
+    case w' of
+      Expr'Val (Val'Const c) -> return $ Expr'Val $ Val'ApiVal $ ApiVal'Wrap $ Wrap c
+      _ -> runtimeThrow RuntimeError'IncompatibleType
+
+  UnVal'UnEnumeral UnEnumeral{tag,m} -> do
+    case m of
+      Nothing -> return $ Expr'Val $ Val'ApiVal $ ApiVal'Enumeral $ Enumeral tag Nothing
+      Just members' -> do
+        members <- mapM (\(name,expr) -> (name,) <$> (forceVal =<< eval expr envRef)) (Map.toList members')
+        return $ Expr'Val $ Val'ApiVal $ ApiVal'Enumeral $ Enumeral tag (Just $ Map.fromList members)
+
+evalIf :: (MonadIO m, RuntimeThrower m) => If m -> IORef (Env m) -> Eval m (Expr m)
+evalIf If{cond, true, false} envRef = do
+  envRef' <- liftIO $ newIORef =<< readIORef envRef
+  v <- eval cond envRef'
+  case v of
+    Expr'Val (Val'Const (Const'Bool cond')) -> do
+      envRef'' <- liftIO $ newIORef =<< readIORef envRef
+      eval (if cond' then true else false) envRef''
+    _ -> runtimeThrow RuntimeError'IncompatibleType
+
+evalGet :: (MonadIO m, RuntimeThrower m) => Get m -> IORef (Env m) -> Eval m (Expr m)
+evalGet Get{path,expr} envRef = getter path =<< eval expr envRef
+
+getter :: (MonadIO m, RuntimeThrower m) => [Text] -> Expr m -> Eval m (Expr m)
+getter [] expr = return expr
+getter path expr =
+  case expr of
+    Expr'Val val -> case val of
+      Val'ApiVal apiVal -> getterApiVal path apiVal
+      _ -> runtimeThrow RuntimeError'IncompatibleType
+    _ -> runtimeThrow RuntimeError'IncompatibleType
+
+getterApiVal :: (MonadIO m, RuntimeThrower m) => [Text] -> ApiVal -> Eval m (Expr m)
+getterApiVal ("w":path) (ApiVal'Wrap (Wrap w)) = getter path (Expr'Val (Val'Const w))
+getterApiVal (mName:path) (ApiVal'Struct Struct{m}) =
+  case Map.lookup (MemberName mName) m of
+    Nothing -> runtimeThrow RuntimeError'IncompatibleType
+    Just member -> getter path (Expr'Val member)
+getterApiVal (mName:path) (ApiVal'Enumeral Enumeral{m})
+  | mName == "tag" = runtimeThrow RuntimeError'IncompatibleType
+  | otherwise = case m >>= Map.lookup (MemberName mName) of
+      Nothing -> runtimeThrow RuntimeError'IncompatibleType
+      Just member -> getter path (Expr'Val member)
+getterApiVal _ _ = runtimeThrow RuntimeError'IncompatibleType
+
+evalDefine :: (MonadIO m, RuntimeThrower m) => Define m -> IORef (Env m) -> Eval m (Expr m)
+evalDefine Define{var, expr} envRef = do
+  expr' <- eval expr envRef
+  env <- liftIO $ readIORef envRef
+  ref <- liftIO $ newIORef expr'
+  limit <- variableLimit <$> getOptions
+  addVarToEnv limit envRef var ref env
+  return expr'
+
+evalLambda :: (MonadIO m, RuntimeThrower m) => Lambda m -> IORef (Env m) -> Eval m (Expr m)
+evalLambda Lambda{params, expr} envRef = do
+  return . Expr'Fn . Fn $ \vals -> do
+    let keys = map fst params
+    let args = zip keys vals
+    let keysLen = length keys
+    let argsLen = length args
+    if keysLen /= argsLen
+      then runtimeThrow $ if keysLen < argsLen
+        then RuntimeError'TooManyArguments
+        else RuntimeError'TooFewArguments
+      else do
+        args' <- liftIO $ mapM newIORef (Map.fromList args)
+        limit <- variableLimit <$> getOptions
+        envRef' <- addEnvToEnv limit args' envRef
+        eval expr envRef'
+
+evalList :: (MonadIO m, RuntimeThrower m) => List m -> IORef (Env m)-> Eval m (Expr m)
+evalList List{list} envRef = do
+  list' <- mapM (\item -> eval item envRef) list
+  return . Expr'List $ List list'
+
+evalTuple :: (MonadIO m, RuntimeThrower m) => Tuple m -> IORef (Env m)-> Eval m (Expr m)
+evalTuple Tuple{tuple} envRef = do
+  tuple' <- mapM (\item -> eval item envRef) tuple
+  return . Expr'Tuple $ Tuple tuple'
+
+evalBegin :: (MonadIO m, RuntimeThrower m) => Begin m -> IORef (Env m) -> Eval m (Expr m)
+evalBegin Begin{exprs} envRef = case exprs of
+  [] -> return $ Expr'Val $ Val'Const $ Const'Null
+  _ -> last <$> mapM (\expr -> eval expr envRef) exprs
+
+evalFnCall :: (MonadIO m, RuntimeThrower m) => FnCall m -> IORef (Env m) -> Eval m (Expr m)
+evalFnCall FnCall{fn, args} envRef = do
+  val <- eval fn envRef
+  case val of
+    Expr'Fn (Fn fn') -> do
+      args' <- mapM (\arg -> eval arg envRef) args
+      fn' args'
+    Expr'Ref Ref{symbol} -> do
+      env <- liftIO $ readIORef envRef
+      v <- varLookup env symbol
+      case v of
+        Expr'Fn (Fn fn') -> do
+          args' <- mapM (\arg -> eval arg envRef) args
+          fn' args'
+        _ -> runtimeThrow $ RuntimeError'IncompatibleType
+    _ -> runtimeThrow RuntimeError'IncompatibleType
+
+evalApiUnCall :: (MonadIO m, RuntimeThrower m) => ApiUnCall m -> IORef (Env m) -> Eval m (Expr m)
+evalApiUnCall apiUnCall envRef = Expr'Val <$> case apiUnCall of
+  ApiUnCall'HollowUnCall c -> evalHollowUnCall c
+  ApiUnCall'WrapUnCall c -> evalWrapUnCall c envRef
+  ApiUnCall'StructUnCall c -> evalStructUnCall c envRef
+  ApiUnCall'EnumerationUnCall c -> evalEnumerationUnCall c envRef
+
+evalHollowUnCall :: (MonadIO m, RuntimeThrower m) => HollowUnCall -> Eval m Val
+evalHollowUnCall HollowUnCall{n} =
+  Eval . ReaderT $ \cfg ->
+    apiCall cfg $ ApiCall'Hollow n
+
+evalWrapUnCall :: (MonadIO m, RuntimeThrower m) => WrapUnCall m -> IORef (Env m) -> Eval m Val
+evalWrapUnCall WrapUnCall{n,w} envRef = do
+  expr <- eval w envRef
+  case expr of
+    Expr'Val (Val'Const c) -> Eval . ReaderT $ \cfg ->
+      apiCall cfg $ ApiCall'Wrap n (Wrap c)
+    _ -> runtimeThrow RuntimeError'IncompatibleType
+
+evalStructUnCall :: (MonadIO m, RuntimeThrower m) => StructUnCall m -> IORef (Env m) -> Eval m Val
+evalStructUnCall StructUnCall{n,m} envRef = do
+  m' <- mapM eval' m
+  Eval . ReaderT $ \cfg ->
+    apiCall cfg $ ApiCall'Struct n (Struct m')
+  where
+    eval' expr = do
+      expr' <- eval expr envRef
+      case expr' of
+        Expr'Val v -> return v
+        _ -> runtimeThrow RuntimeError'IncompatibleType
+
+evalEnumerationUnCall :: (MonadIO m, RuntimeThrower m) => EnumerationUnCall m -> IORef (Env m) -> Eval m Val
+evalEnumerationUnCall EnumerationUnCall{n,e} envRef = do
+  expr <- eval e envRef
+  case expr of
+    Expr'Val (Val'ApiVal (ApiVal'Enumeral e')) -> Eval . ReaderT $ \cfg ->
+      apiCall cfg $ ApiCall'Enumeration n e'
+    _ -> runtimeThrow RuntimeError'IncompatibleType
+
+emptyEnv :: RuntimeThrower m => IO (IORef (Env m))
+emptyEnv = do
+  eq <- newIORef eqExpr
+  neq <- newIORef neqExpr
+  concat' <- newIORef concatExpr
+  add <- newIORef addExpr
+  sub <- newIORef subExpr
+  mul <- newIORef mulExpr
+  div' <- newIORef divExpr
+  tuple <- newIORef tupleExpr
+  newIORef $ Map.fromList
+    [ ("==", eq)
+    , ("/=", neq)
+    , ("+", add)
+    , ("-", sub)
+    , ("*", mul)
+    , ("/", div')
+    , ("concat", concat')
+    , ("tuple", tuple)
+    ]
+
+numExpr :: RuntimeThrower m
+  => (Scientific -> Scientific -> Scientific)
+  -> (Int8 -> Int8 -> Int8)
+  -> (Int16 -> Int16 -> Int16)
+  -> (Int32 -> Int32 -> Int32)
+  -> (Int64 -> Int64 -> Int64)
+  -> (Word8 -> Word8 -> Word8)
+  -> (Word16 -> Word16 -> Word16)
+  -> (Word32 -> Word32 -> Word32)
+  -> (Word64 -> Word64 -> Word64)
+  -> Expr m
+numExpr num i8 i16 i32 i64 u8 u16 u32 u64 = Expr'Fn . Fn $ \args ->
+  case args of
+    (_:[]) -> runtimeThrow RuntimeError'TooFewArguments
+    [Expr'Val (Val'Const (Const'Number x)), Expr'Val (Val'Const (Const'Number y))] -> return $
+      Expr'Val $ Val'Const $ Const'Number $ x `num` y
+
+    [Expr'Val (Val'Prim (Prim'I8 x)), Expr'Val (Val'Prim (Prim'I8 y))] -> toExpr $ x `i8` y
+    [Expr'Val (Val'Const (Const'Number x)), Expr'Val (Val'Prim (Prim'I8 y))] -> case toBoundedInteger x of
+      Just x' -> toExpr $ x' `i8` y
+      Nothing -> runtimeThrow RuntimeError'IncompatibleType
+    [Expr'Val (Val'Prim (Prim'I8 x)), Expr'Val (Val'Const (Const'Number y))] -> case toBoundedInteger y of
+      Just y' -> toExpr $ x `i8` y'
+      Nothing -> runtimeThrow RuntimeError'IncompatibleType
+
+    [Expr'Val (Val'Prim (Prim'I16 x)), Expr'Val (Val'Prim (Prim'I16 y))] -> toExpr $ x `i16` y
+    [Expr'Val (Val'Const (Const'Number x)), Expr'Val (Val'Prim (Prim'I16 y))] -> case toBoundedInteger x of
+      Just x' -> toExpr $ x' `i16` y
+      Nothing -> runtimeThrow RuntimeError'IncompatibleType
+    [Expr'Val (Val'Prim (Prim'I16 x)), Expr'Val (Val'Const (Const'Number y))] -> case toBoundedInteger y of
+      Just y' -> toExpr $ x `i16` y'
+      Nothing -> runtimeThrow RuntimeError'IncompatibleType
+
+    [Expr'Val (Val'Prim (Prim'I32 x)), Expr'Val (Val'Prim (Prim'I32 y))] -> toExpr $ x `i32` y
+    [Expr'Val (Val'Const (Const'Number x)), Expr'Val (Val'Prim (Prim'I32 y))] -> case toBoundedInteger x of
+      Just x' -> toExpr $ x' `i32` y
+      Nothing -> runtimeThrow RuntimeError'IncompatibleType
+    [Expr'Val (Val'Prim (Prim'I32 x)), Expr'Val (Val'Const (Const'Number y))] -> case toBoundedInteger y of
+      Just y' -> toExpr $ x `i32` y'
+      Nothing -> runtimeThrow RuntimeError'IncompatibleType
+
+    [Expr'Val (Val'Prim (Prim'I64 x)), Expr'Val (Val'Prim (Prim'I64 y))] -> toExpr $ x `i64` y
+    [Expr'Val (Val'Const (Const'Number x)), Expr'Val (Val'Prim (Prim'I64 y))] -> case toBoundedInteger x of
+      Just x' -> toExpr $ x' `i64` y
+      Nothing -> runtimeThrow RuntimeError'IncompatibleType
+    [Expr'Val (Val'Prim (Prim'I64 x)), Expr'Val (Val'Const (Const'Number y))] -> case toBoundedInteger y of
+      Just y' -> toExpr $ x `i64` y'
+      Nothing -> runtimeThrow RuntimeError'IncompatibleType
+
+    [Expr'Val (Val'Prim (Prim'U8 x)), Expr'Val (Val'Prim (Prim'U8 y))] -> toExpr $ x `u8` y
+    [Expr'Val (Val'Const (Const'Number x)), Expr'Val (Val'Prim (Prim'U8 y))] -> case toBoundedInteger x of
+      Just x' -> toExpr $ x' `u8` y
+      Nothing -> runtimeThrow RuntimeError'IncompatibleType
+    [Expr'Val (Val'Prim (Prim'U8 x)), Expr'Val (Val'Const (Const'Number y))] -> case toBoundedInteger y of
+      Just y' -> toExpr $ x `u8` y'
+      Nothing -> runtimeThrow RuntimeError'IncompatibleType
+
+    [Expr'Val (Val'Prim (Prim'U16 x)), Expr'Val (Val'Prim (Prim'U16 y))] -> toExpr $ x `u16` y
+    [Expr'Val (Val'Const (Const'Number x)), Expr'Val (Val'Prim (Prim'U16 y))] -> case toBoundedInteger x of
+      Just x' -> toExpr $ x' `u16` y
+      Nothing -> runtimeThrow RuntimeError'IncompatibleType
+    [Expr'Val (Val'Prim (Prim'U16 x)), Expr'Val (Val'Const (Const'Number y))] -> case toBoundedInteger y of
+      Just y' -> toExpr $ x `u16` y'
+      Nothing -> runtimeThrow RuntimeError'IncompatibleType
+
+    [Expr'Val (Val'Prim (Prim'U32 x)), Expr'Val (Val'Prim (Prim'U32 y))] -> toExpr $ x `u32` y
+    [Expr'Val (Val'Const (Const'Number x)), Expr'Val (Val'Prim (Prim'U32 y))] -> case toBoundedInteger x of
+      Just x' -> toExpr $ x' `u32` y
+      Nothing -> runtimeThrow RuntimeError'IncompatibleType
+    [Expr'Val (Val'Prim (Prim'U32 x)), Expr'Val (Val'Const (Const'Number y))] -> case toBoundedInteger y of
+      Just y' -> toExpr $ x `u32` y'
+      Nothing -> runtimeThrow RuntimeError'IncompatibleType
+
+    [Expr'Val (Val'Prim (Prim'U64 x)), Expr'Val (Val'Prim (Prim'U64 y))] -> toExpr $ x `u64` y
+    [Expr'Val (Val'Const (Const'Number x)), Expr'Val (Val'Prim (Prim'U64 y))] -> case toBoundedInteger x of
+      Just x' -> toExpr $ x' `u64` y
+      Nothing -> runtimeThrow RuntimeError'IncompatibleType
+    [Expr'Val (Val'Prim (Prim'U64 x)), Expr'Val (Val'Const (Const'Number y))] -> case toBoundedInteger y of
+      Just y' -> toExpr $ x `u64` y'
+      Nothing -> runtimeThrow RuntimeError'IncompatibleType
+
+    (_:_:[]) -> runtimeThrow RuntimeError'IncompatibleType
+    _ -> runtimeThrow RuntimeError'TooManyArguments
+    where
+      toExpr v = return $ Expr'Val (toVal v)
+
+boolExpr :: RuntimeThrower m
+  => (Scientific -> Scientific -> Bool)
+  -> (Int8 -> Int8 -> Bool)
+  -> (Int16 -> Int16 -> Bool)
+  -> (Int32 -> Int32 -> Bool)
+  -> (Int64 -> Int64 -> Bool)
+  -> (Word8 -> Word8 -> Bool)
+  -> (Word16 -> Word16 -> Bool)
+  -> (Word32 -> Word32 -> Bool)
+  -> (Word64 -> Word64 -> Bool)
+  -> Expr m
+boolExpr num i8 i16 i32 i64 u8 u16 u32 u64 = Expr'Fn . Fn $ \args ->
+  case args of
+    (_:[]) -> runtimeThrow RuntimeError'TooManyArguments
+    [Expr'Val (Val'Const (Const'Number x)), Expr'Val (Val'Const (Const'Number y))] -> toExpr $ x `num` y
+
+    [Expr'Val (Val'Prim (Prim'I8 x)), Expr'Val (Val'Prim (Prim'I8 y))] -> toExpr $ x `i8` y
+    [Expr'Val (Val'Const (Const'Number x)), Expr'Val (Val'Prim (Prim'I8 y))] -> case toBoundedInteger x of
+      Just x' -> toExpr $ x' `i8` y
+      Nothing -> runtimeThrow RuntimeError'IncompatibleType
+    [Expr'Val (Val'Prim (Prim'I8 x)), Expr'Val (Val'Const (Const'Number y))] -> case toBoundedInteger y of
+      Just y' -> toExpr $ x `i8` y'
+      Nothing -> runtimeThrow RuntimeError'IncompatibleType
+
+    [Expr'Val (Val'Prim (Prim'I16 x)), Expr'Val (Val'Prim (Prim'I16 y))] -> toExpr $ x `i16` y
+    [Expr'Val (Val'Const (Const'Number x)), Expr'Val (Val'Prim (Prim'I16 y))] -> case toBoundedInteger x of
+      Just x' -> toExpr $ x' `i16` y
+      Nothing -> runtimeThrow RuntimeError'IncompatibleType
+    [Expr'Val (Val'Prim (Prim'I16 x)), Expr'Val (Val'Const (Const'Number y))] -> case toBoundedInteger y of
+      Just y' -> toExpr $ x `i16` y'
+      Nothing -> runtimeThrow RuntimeError'IncompatibleType
+
+    [Expr'Val (Val'Prim (Prim'I32 x)), Expr'Val (Val'Prim (Prim'I32 y))] -> toExpr $ x `i32` y
+    [Expr'Val (Val'Const (Const'Number x)), Expr'Val (Val'Prim (Prim'I32 y))] -> case toBoundedInteger x of
+      Just x' -> toExpr $ x' `i32` y
+      Nothing -> runtimeThrow RuntimeError'IncompatibleType
+    [Expr'Val (Val'Prim (Prim'I32 x)), Expr'Val (Val'Const (Const'Number y))] -> case toBoundedInteger y of
+      Just y' -> toExpr $ x `i32` y'
+      Nothing -> runtimeThrow RuntimeError'IncompatibleType
+
+    [Expr'Val (Val'Prim (Prim'I64 x)), Expr'Val (Val'Prim (Prim'I64 y))] -> toExpr $ x `i64` y
+    [Expr'Val (Val'Const (Const'Number x)), Expr'Val (Val'Prim (Prim'I64 y))] -> case toBoundedInteger x of
+      Just x' -> toExpr $ x' `i64` y
+      Nothing -> runtimeThrow RuntimeError'IncompatibleType
+    [Expr'Val (Val'Prim (Prim'I64 x)), Expr'Val (Val'Const (Const'Number y))] -> case toBoundedInteger y of
+      Just y' -> toExpr $ x `i64` y'
+      Nothing -> runtimeThrow RuntimeError'IncompatibleType
+
+    [Expr'Val (Val'Prim (Prim'U8 x)), Expr'Val (Val'Prim (Prim'U8 y))] -> toExpr $ x `u8` y
+    [Expr'Val (Val'Const (Const'Number x)), Expr'Val (Val'Prim (Prim'U8 y))] -> case toBoundedInteger x of
+      Just x' -> toExpr $ x' `u8` y
+      Nothing -> runtimeThrow RuntimeError'IncompatibleType
+    [Expr'Val (Val'Prim (Prim'U8 x)), Expr'Val (Val'Const (Const'Number y))] -> case toBoundedInteger y of
+      Just y' -> toExpr $ x `u8` y'
+      Nothing -> runtimeThrow RuntimeError'IncompatibleType
+
+    [Expr'Val (Val'Prim (Prim'U16 x)), Expr'Val (Val'Prim (Prim'U16 y))] -> toExpr $ x `u16` y
+    [Expr'Val (Val'Const (Const'Number x)), Expr'Val (Val'Prim (Prim'U16 y))] -> case toBoundedInteger x of
+      Just x' -> toExpr $ x' `u16` y
+      Nothing -> runtimeThrow RuntimeError'IncompatibleType
+    [Expr'Val (Val'Prim (Prim'U16 x)), Expr'Val (Val'Const (Const'Number y))] -> case toBoundedInteger y of
+      Just y' -> toExpr $ x `u16` y'
+      Nothing -> runtimeThrow RuntimeError'IncompatibleType
+
+    [Expr'Val (Val'Prim (Prim'U32 x)), Expr'Val (Val'Prim (Prim'U32 y))] -> toExpr $ x `u32` y
+    [Expr'Val (Val'Const (Const'Number x)), Expr'Val (Val'Prim (Prim'U32 y))] -> case toBoundedInteger x of
+      Just x' -> toExpr $ x' `u32` y
+      Nothing -> runtimeThrow RuntimeError'IncompatibleType
+    [Expr'Val (Val'Prim (Prim'U32 x)), Expr'Val (Val'Const (Const'Number y))] -> case toBoundedInteger y of
+      Just y' -> toExpr $ x `u32` y'
+      Nothing -> runtimeThrow RuntimeError'IncompatibleType
+
+    [Expr'Val (Val'Prim (Prim'U64 x)), Expr'Val (Val'Prim (Prim'U64 y))] -> toExpr $ x `u64` y
+    [Expr'Val (Val'Const (Const'Number x)), Expr'Val (Val'Prim (Prim'U64 y))] -> case toBoundedInteger x of
+      Just x' -> toExpr $ x' `u64` y
+      Nothing -> runtimeThrow RuntimeError'IncompatibleType
+    [Expr'Val (Val'Prim (Prim'U64 x)), Expr'Val (Val'Const (Const'Number y))] -> case toBoundedInteger y of
+      Just y' -> toExpr $ x `u64` y'
+      Nothing -> runtimeThrow RuntimeError'IncompatibleType
+
+    (_:_:[]) -> runtimeThrow RuntimeError'IncompatibleType
+    _ -> runtimeThrow RuntimeError'TooManyArguments
+    where
+      toExpr v = return $ Expr'Val (toVal v)
+
+eqExpr :: RuntimeThrower m => Expr m
+eqExpr = boolExpr (==) (==) (==) (==) (==) (==) (==) (==) (==)
+
+neqExpr :: RuntimeThrower m => Expr m
+neqExpr = boolExpr (/=) (/=) (/=) (/=) (/=) (/=) (/=) (/=) (/=)
+
+concatExpr :: RuntimeThrower m => Expr m
+concatExpr = Expr'Fn . Fn $ \args ->
+  case args of
+    (_:[]) -> runtimeThrow RuntimeError'TooFewArguments
+    [x, y] -> case (x,y) of
+      (Expr'Val (Val'Const (Const'String x')), Expr'Val (Val'Const (Const'String y'))) -> return $
+        Expr'Val . Val'Const . Const'String $ x' `mappend` y'
+      _ -> runtimeThrow RuntimeError'IncompatibleType
+    _ -> runtimeThrow RuntimeError'TooManyArguments
+
+addExpr :: RuntimeThrower m => Expr m
+addExpr = numExpr (+) (+) (+) (+) (+) (+) (+) (+) (+)
+
+subExpr :: RuntimeThrower m => Expr m
+subExpr = numExpr (-) (-) (-) (-) (-) (-) (-) (-) (-)
+
+mulExpr :: RuntimeThrower m => Expr m
+mulExpr = numExpr (*) (*) (*) (*) (*) (*) (*) (*) (*)
+
+divExpr :: RuntimeThrower m => Expr m
+divExpr = numExpr (/) div div div div div div div div
+
+tupleExpr :: RuntimeThrower m => Expr m
+tupleExpr = Expr'Fn . Fn $ \args ->
+  case args of
+    (_:[]) -> runtimeThrow RuntimeError'TooFewArguments
+    xs -> return $ Expr'Tuple $ Tuple xs
+
+--
+
+data ApiParser api = ApiParser
+  { hollow :: Map TypeName api
+  , struct :: Map TypeName (Val -> Maybe api)
+  , enumeration :: Map TypeName (Val -> Maybe api)
+  , wrap :: Map TypeName (Val -> Maybe api)
+  }
+
+parseApiCall :: ApiParser api -> ApiCall -> Maybe api
+parseApiCall ApiParser{hollow, struct, enumeration, wrap} = \case
+  ApiCall'Hollow n -> Map.lookup n hollow
+  ApiCall'Struct n s -> join $ ($ Val'ApiVal (ApiVal'Struct s)) <$> Map.lookup n struct
+  ApiCall'Enumeration n e -> join $ ($ Val'ApiVal (ApiVal'Enumeral e)) <$> Map.lookup n enumeration
+  ApiCall'Wrap n w -> join $ ($ Val'ApiVal (ApiVal'Wrap w)) <$> Map.lookup n wrap
diff --git a/library/Colorless/Server/Types.hs b/library/Colorless/Server/Types.hs
new file mode 100644
--- /dev/null
+++ b/library/Colorless/Server/Types.hs
@@ -0,0 +1,116 @@
+module Colorless.Server.Types
+  ( Symbol(..)
+  , Type(..)
+  , TypeName(..)
+  , MemberName(..)
+  , EnumeralName(..)
+  , EnumeralType(..)
+  , EnumerationType(..)
+  , StructType(..)
+  , HollowType(..)
+  , Prim(..)
+  , Const(..)
+  ) where
+
+import qualified Data.HashMap.Lazy as HML
+import Control.Monad (mzero)
+import Data.Aeson (FromJSON(..), FromJSONKey, ToJSONKey, Value(..), (.:), ToJSON(..))
+import Data.Text (Text)
+import Data.Map (Map)
+import Data.Int
+import Data.Word
+import Data.Scientific
+import Data.String (IsString)
+
+newtype Symbol = Symbol Text
+  deriving (Show, Eq, Ord, FromJSON, IsString)
+
+data Type = Type
+  { n :: TypeName
+  , p :: Maybe Type
+  } deriving (Show, Eq)
+
+instance FromJSON Type where
+  parseJSON = \case
+    String s -> pure $ Type (TypeName s) Nothing
+    Object o -> do
+      n <- o .: "n"
+      case HML.lookup "p" o of
+        Nothing -> pure $ Type n Nothing
+        Just p -> Type n <$> fmap Just (parseJSON p)
+    _ -> mzero
+
+newtype TypeName = TypeName Text
+  deriving (Show, Eq, Ord, FromJSON, IsString)
+
+newtype EnumeralName = EnumeralName Text
+  deriving (Show, Eq, Ord, FromJSON, ToJSON, IsString)
+
+newtype MemberName = MemberName Text
+  deriving (Show, Eq, Ord, FromJSON, ToJSON, ToJSONKey, FromJSONKey, IsString)
+
+data EnumeralType = EnumeralType
+  { m :: Maybe (Map MemberName Type)
+  } deriving (Show, Eq)
+
+data EnumerationType = EnumerationType
+  { e :: Map EnumeralName EnumeralType
+  , o :: Type
+  } deriving (Show, Eq)
+
+data StructType = StructType
+  { m :: Map MemberName Type
+  , o :: Type
+  } deriving (Show, Eq)
+
+data HollowType = HollowType
+  { o :: Type
+  } deriving (Show, Eq)
+
+data Prim
+  = Prim'Bool Bool
+  | Prim'I8 Int8
+  | Prim'I16 Int16
+  | Prim'I32 Int32
+  | Prim'I64 Int64
+  | Prim'U8 Word8
+  | Prim'U16 Word16
+  | Prim'U32 Word32
+  | Prim'U64 Word64
+  | Prim'String Text
+  deriving (Show, Eq)
+
+instance ToJSON Prim where
+  toJSON = \case
+    Prim'Bool b -> toJSON b
+    Prim'I8 i -> toJSON i
+    Prim'I16 i -> toJSON i
+    Prim'I32 i -> toJSON i
+    Prim'I64 i -> toJSON i
+    Prim'U8 u -> toJSON u
+    Prim'U16 u -> toJSON u
+    Prim'U32 u -> toJSON u
+    Prim'U64 u -> toJSON u
+    Prim'String s -> toJSON s
+
+data Const
+  = Const'Null
+  | Const'Bool Bool
+  | Const'String Text
+  | Const'Number Scientific
+  deriving (Show, Eq)
+
+instance ToJSON Const where
+  toJSON = \case
+    Const'Null -> Null
+    Const'Bool b -> Bool b
+    Const'String s -> String s
+    Const'Number n -> Number n
+
+instance FromJSON Const where
+  parseJSON = \case
+    Null -> pure $ Const'Null
+    Bool b -> pure $ Const'Bool b
+    String s -> pure $ Const'String s
+    Number n -> pure $ Const'Number n
+    _ -> mzero
diff --git a/library/Colorless/Server/Val.hs b/library/Colorless/Server/Val.hs
new file mode 100644
--- /dev/null
+++ b/library/Colorless/Server/Val.hs
@@ -0,0 +1,280 @@
+{-# LANGUAGE DeriveGeneric #-}
+module Colorless.Server.Val
+  ( Val(..)
+  , ApiVal(..)
+  , Wrap(..)
+  , Struct(..)
+  , Enumeral(..)
+  --
+  , FromVal(..)
+  , ToVal(..)
+  , getMember
+  , fromValFromJson
+  , combineObjects
+  ) where
+
+import qualified Data.HashMap.Lazy as HML
+import qualified Data.Map as Map
+import qualified Data.Vector as V
+import Control.Monad (mzero)
+import Control.Applicative ((<|>))
+import Data.Aeson
+import Data.Aeson.Types (parseMaybe)
+import Data.Map (Map)
+import Data.Text (Text)
+import Data.Int
+import Data.Word
+import Data.Scientific
+import GHC.Generics (Generic)
+
+import Colorless.Server.Types
+
+data Val
+  = Val'Const Const
+  | Val'Prim Prim
+  | Val'ApiVal ApiVal
+  | Val'List [Val]
+  deriving (Show, Eq)
+
+instance ToJSON Val where
+  toJSON = \case
+    Val'Const c -> toJSON c
+    Val'ApiVal v -> toJSON v
+    Val'List l -> toJSON l
+    Val'Prim p -> toJSON p
+
+instance FromJSON Val where
+  parseJSON = \case
+    Null -> return $ Val'Const Const'Null
+    Number n -> return $ Val'Const $ Const'Number n
+    String s -> return $ Val'Const $ Const'String s
+    Bool b -> return $ Val'Const $ Const'Bool b
+    Array arr -> Val'List <$> (mapM parseJSON $ V.toList arr)
+    v@Object{} -> Val'ApiVal <$> parseJSON v
+
+data ApiVal
+  = ApiVal'Wrap Wrap
+  | ApiVal'Struct Struct
+  | ApiVal'Enumeral Enumeral
+  deriving (Show, Eq)
+
+instance ToJSON ApiVal where
+  toJSON = \case
+    ApiVal'Wrap w -> toJSON w
+    ApiVal'Struct s -> toJSON s
+    ApiVal'Enumeral e -> toJSON e
+
+instance FromJSON ApiVal where
+  parseJSON v =
+    (ApiVal'Wrap <$> parseJSON v) <|>
+    (ApiVal'Enumeral <$> parseJSON v) <|>
+    (ApiVal'Struct <$> parseJSON v)
+
+data Wrap = Wrap
+  { w :: Const
+  } deriving (Show, Eq, Generic)
+
+instance ToJSON Wrap
+instance FromJSON Wrap
+
+data Struct = Struct
+  { m :: Map MemberName Val
+  } deriving (Show, Eq, Generic)
+
+instance ToJSON Struct where
+  toJSON Struct{m} = toJSON m
+
+instance FromJSON Struct where
+  parseJSON v = Struct <$> parseJSON v
+
+data Enumeral = Enumeral
+  { tag :: EnumeralName
+  , m :: Maybe (Map MemberName Val)
+  } deriving (Show, Eq, Generic)
+
+instance ToJSON Enumeral where
+  toJSON Enumeral{tag,m} = object $ [ "tag" .= tag ] ++ case m of
+    Nothing -> []
+    Just m' -> concatMap (\(MemberName k,v) -> [ k .= v ]) (Map.toList m')
+
+instance FromJSON Enumeral where
+  parseJSON (Object o) = do
+    tag <- o .: "tag"
+    let tagless = HML.delete "tag" o
+    if HML.size o == 1
+      then pure $ Enumeral tag Nothing
+      else Enumeral tag <$> (Just <$> parseJSON (Object tagless))
+  parseJSON _ = mzero
+
+--
+
+class ToVal a where
+  toVal :: a -> Val
+
+instance ToVal () where
+  toVal () = Val'Const Const'Null
+
+instance ToVal Bool where
+  toVal b = Val'Const $ Const'Bool b
+
+instance ToVal Text where
+  toVal s = Val'Const $ Const'String s
+
+intToVal :: Integral a => a -> Val
+intToVal n = Val'Const $ Const'Number (fromInteger $ toInteger n)
+
+instance ToVal Int where
+  toVal = intToVal
+
+instance ToVal Int8 where
+  toVal i = Val'Prim $ Prim'I8 i
+
+instance ToVal Int16 where
+  toVal i = Val'Prim $ Prim'I16 i
+
+instance ToVal Int32 where
+  toVal i = Val'Prim $ Prim'I32 i
+
+instance ToVal Int64 where
+  toVal i = Val'Prim $ Prim'I64 i
+
+instance ToVal Word where
+  toVal = intToVal
+
+instance ToVal Word8 where
+  toVal u = Val'Prim $ Prim'U8 u
+
+instance ToVal Word16 where
+  toVal u = Val'Prim $ Prim'U16 u
+
+instance ToVal Word32 where
+  toVal u = Val'Prim $ Prim'U32 u
+
+instance ToVal Word64 where
+  toVal u = Val'Prim $ Prim'U64 u
+
+instance ToVal Float where
+    toVal f = Val'Const $ Const'Number $ fromFloatDigits f
+
+instance ToVal Double where
+    toVal d = Val'Const $ Const'Number $ fromFloatDigits d
+
+instance ToVal a => ToVal (Maybe a) where
+  toVal Nothing = Val'Const Const'Null
+  toVal (Just v) = toVal v
+
+instance (ToVal a, ToVal b) => ToVal (Either a b) where
+  toVal m = Val'ApiVal $ ApiVal'Enumeral $ case m of
+    Left l -> Enumeral "Left" (Just $ Map.singleton "left" (toVal l))
+    Right r -> Enumeral "Right" (Just $ Map.singleton "right" (toVal r))
+
+instance ToVal a => ToVal [a] where
+  toVal list = Val'List $ map toVal list
+
+--
+
+class FromVal a where
+  fromVal :: Val -> Maybe a
+
+instance FromVal () where
+  fromVal (Val'Const Const'Null) = Just ()
+  fromVal _ = Nothing
+
+instance FromVal Bool where
+  fromVal (Val'Const (Const'Bool b)) = Just b
+  fromVal _ = Nothing
+
+instance FromVal Text where
+  fromVal (Val'Const (Const'String s)) = Just s
+  fromVal _ = Nothing
+
+intFromVal :: (Bounded i, Integral i) => Val -> Maybe i
+intFromVal (Val'Const (Const'Number n)) = toBoundedInteger n
+intFromVal _ = Nothing
+
+instance FromVal Int where
+  fromVal = intFromVal
+
+instance FromVal Int8 where
+  fromVal = \case
+    Val'Const (Const'Number n) -> toBoundedInteger n
+    Val'Prim (Prim'I8 i) -> Just i
+    _ -> Nothing
+
+instance FromVal Int16 where
+  fromVal = \case
+    Val'Const (Const'Number n) -> toBoundedInteger n
+    Val'Prim (Prim'I16 i) -> Just i
+    _ -> Nothing
+
+instance FromVal Int32 where
+  fromVal = \case
+    Val'Const (Const'Number n) -> toBoundedInteger n
+    Val'Prim (Prim'I32 i) -> Just i
+    _ -> Nothing
+
+instance FromVal Int64 where
+  fromVal = \case
+    Val'Const (Const'Number n) -> toBoundedInteger n
+    Val'Prim (Prim'I64 i) -> Just i
+    _ -> Nothing
+
+instance FromVal Word where
+  fromVal = intFromVal
+
+instance FromVal Word8 where
+  fromVal = \case
+    Val'Const (Const'Number n) -> toBoundedInteger n
+    Val'Prim (Prim'U8 u) -> Just u
+    _ -> Nothing
+
+instance FromVal Word16 where
+  fromVal = \case
+    Val'Const (Const'Number n) -> toBoundedInteger n
+    Val'Prim (Prim'U16 u) -> Just u
+    _ -> Nothing
+
+instance FromVal Word32 where
+  fromVal = \case
+    Val'Const (Const'Number n) -> toBoundedInteger n
+    Val'Prim (Prim'U32 u) -> Just u
+    _ -> Nothing
+
+instance FromVal Word64 where
+  fromVal = \case
+    Val'Const (Const'Number n) -> toBoundedInteger n
+    Val'Prim (Prim'U64 u) -> Just u
+    _ -> Nothing
+
+instance FromVal Float where
+  fromVal (Val'Const (Const'Number n)) = Just $ toRealFloat n
+  fromVal _ = Nothing
+
+instance FromVal Double where
+  fromVal (Val'Const (Const'Number n)) = Just $ toRealFloat n
+  fromVal _ = Nothing
+
+instance FromVal a => FromVal (Maybe a) where
+  fromVal (Val'Const Const'Null) = Just Nothing
+  fromVal v = Just <$> fromVal v
+
+instance (FromVal a, FromVal b) => FromVal (Either a b) where
+  fromVal (Val'ApiVal (ApiVal'Enumeral (Enumeral tag m))) = case (tag,m) of
+    ("Left",Just m') -> Map.lookup "left" m' >>= \l -> Left <$> fromVal l
+    ("Right",Just m') -> Map.lookup "right" m' >>= \r -> Right <$> fromVal r
+    _ -> Nothing
+  fromVal _ = Nothing
+
+instance FromVal a => FromVal [a] where
+  fromVal (Val'List list) = mapM fromVal list
+  fromVal _ = Nothing
+
+getMember :: FromVal a => Map MemberName Val -> MemberName -> Maybe a
+getMember m n = fromVal =<< Map.lookup n m
+
+fromValFromJson :: (FromVal b) => Value -> Maybe b
+fromValFromJson x = fromVal =<< parseMaybe parseJSON x
+
+combineObjects :: Value -> Value -> Value
+combineObjects (Object x) (Object y) = Object $ HML.union x y
+combineObjects _ _ = error "not objects"
diff --git a/library/Colorless/Types.hs b/library/Colorless/Types.hs
--- a/library/Colorless/Types.hs
+++ b/library/Colorless/Types.hs
@@ -38,7 +38,7 @@
 
 data Request = Request
   { meta :: Value
-  , query :: [Value]
+  , query :: Value
   } deriving (Show, Eq)
 
 instance FromJSON Request where
diff --git a/package.yaml b/package.yaml
--- a/package.yaml
+++ b/package.yaml
@@ -1,5 +1,5 @@
 name: colorless
-version: '2.0.0'
+version: '2.1.0'
 category: Web
 synopsis: Colorless
 description: Colorless
diff --git a/tests/AstSpec.hs b/tests/AstSpec.hs
--- a/tests/AstSpec.hs
+++ b/tests/AstSpec.hs
@@ -6,8 +6,8 @@
 import Data.Aeson
 import Data.Aeson.Types
 
-import Colorless.Runtime.Types
-import Colorless.Runtime.Ast
+import Colorless.Server.Types
+import Colorless.Server.Ast
 
 parseAst :: Value -> Maybe Ast
 parseAst = parseMaybe parseJSON
@@ -68,6 +68,15 @@
       it "simple" $ shouldBe
         (parseAst $ object [ "List" .= [String "hello"] ])
         (Just $ Ast'List $ List [Ast'Const $ Const'String "hello"])
+
+    context "Tuple" $ do
+      it "one element (sematically too small)" $ shouldBe
+        (parseAst $ object [ "Tuple" .= [String "hello"] ])
+        (Just $ Ast'Tuple $ Tuple [Ast'Const $ Const'String "hello"])
+
+      it "more than one elements" $ shouldBe
+        (parseAst $ object [ "Tuple" .= [String "hello", String "world"] ])
+        (Just $ Ast'Tuple $ Tuple [Ast'Const $ Const'String "hello", Ast'Const $ Const'String "world"])
 
     context "Begin" $ do
       it "simple" $ shouldBe
diff --git a/tests/ExprSpec.hs b/tests/ExprSpec.hs
--- a/tests/ExprSpec.hs
+++ b/tests/ExprSpec.hs
@@ -3,8 +3,8 @@
 import Test.Hspec
 
 -- import Colorless.Types
--- import Colorless.Runtime.Types
--- import Colorless.Runtime.Expr
+-- import Colorless.Server.Types
+-- import Colorless.Server.Expr
 
 spec :: Spec
 spec = do
diff --git a/tests/ValSpec.hs b/tests/ValSpec.hs
--- a/tests/ValSpec.hs
+++ b/tests/ValSpec.hs
@@ -6,8 +6,8 @@
 import Data.Aeson.Types
 import Data.Text (Text)
 
-import Colorless.Runtime.Types
-import Colorless.Runtime.Val
+import Colorless.Server.Types
+import Colorless.Server.Val
 
 spec :: Spec
 spec = do
