shentong-0.3.2: Shentong/Core/Utils.hs
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE OverloadedStrings #-}
module Core.Utils where
import Control.Applicative
import Control.Monad.Except
import Control.Monad.State
import Data.HashMap as HM
import Data.IORef
import Data.Maybe
import Data.Monoid
import qualified Data.Vector as V
import qualified Data.Text as T
import qualified Data.Text.IO as T
import Prelude as P
import Core.Types
exceptionV :: ErrorMsg -> KLValue -> KLContext s a
exceptionV e v = throwError e'
where e' = e <> " " <> (T.pack $ show v)
stubFunction :: Symbol -> KLContext s ApplContext
stubFunction name = return (Malformed msg)
where msg = "function " <> name <> " is not defined"
functionRef :: Symbol -> KLContext Env (IORef ApplContext)
functionRef name = do
st <- get
case HM.lookup name (functionTable st) of
Just ref -> return ref
Nothing -> do
stubFunction name >>= insertFunction name
functionRef name
symbolRef :: Symbol -> KLContext Env KLValue
symbolRef name = do
st <- get
case HM.lookup name (symbolTable st) of
Just v -> return v
Nothing -> throwError "name not found in symbol table."
insertFunction :: Symbol -> ApplContext -> KLContext Env ()
insertFunction name f = do
st <- get
case HM.lookup name (functionTable st) of
Just ref -> liftIO $ writeIORef ref $! f
Nothing -> do
ref <- liftIO $ newIORef $! f
put $ st { functionTable = HM.insert name ref (functionTable st) }
insertSymbol :: Symbol -> KLValue -> KLContext Env ()
insertSymbol name v = do
st <- get
put $ st { symbolTable = HM.insert name v (symbolTable st) }
addVal :: Int -> Bindings -> KLValue -> Bindings
addVal i vals v = replace vals
where replace (p@(i',_) : is')
| i == i' = (i,v) : is'
| otherwise = p : replace is'
replace [] = [(i,v)]
lookupVal :: DeBruijn -> Bindings -> KLContext Env KLValue
lookupVal i vals = maybe err return (P.lookup i vals)
where err = throwError "value not found in bindings list"
fromIORef :: MonadIO m => IORef a -> m a
fromIORef = liftIO . readIORef
{-# SPECIALISE fromIORef :: IORef ApplContext -> KLContext Env ApplContext #-}
applyStep :: Function -> KLValue -> ApplContext
applyStep (PartialApp f) v = Func "curried" (f v)
applyStep (Context f) v = PL "thunk" (f v)
mapM' :: Monad m => (a -> m b) -> [a] -> m [b]
mapM' _ [] = return []
mapM' f (x:xs) = do
y <- f x
ys <- y `seq` mapM' f xs
return (y:ys)
{-# SPECIALISE mapM' :: (RSExpr -> KLContext Env KLValue) -> [RSExpr] -> KLContext Env [KLValue] #-}
checkForBooleans :: Atom -> KLValue
checkForBooleans (UnboundSym "true") = Atom (B True)
checkForBooleans (UnboundSym "false") = Atom (B False)
checkForBooleans a = Atom a
apply :: ApplContext -> [KLValue] -> KLContext Env KLValue
apply (Malformed e) _ = throwError e
apply (PL _ c) [] = c
apply f [] = return (ApplC f)
apply (Func _ f) (v:vs) = apply (applyStep f v) vs
apply f _
| Func name _ <- f = throwError $ name <> ": too many arguments"
| PL name _ <- f = throwError $ name <> ": too many arguments"