{-# LANGUAGE CPP #-}
module Language.Scheme.Variables
(
printEnv
, recPrintEnv
, recExportsFromEnv
, exportsFromEnv
, copyEnv
, extendEnv
, importEnv
, topmostEnv
, nullEnvWithParent
, findNamespacedEnv
, macroNamespace
, varNamespace
, getVar
, getVar'
, getNamespacedVar
, getNamespacedVar'
, getNamespacedRef
, defineVar
, defineNamespacedVar
, setVar
, setNamespacedVar
, updateObject
, updateNamespacedObject
, isBound
, isRecBound
, isNamespacedRecBound
, derefPtr
, recDerefPtrs
, safeRecDerefPtrs
, recDerefToFnc
) where
import Language.Scheme.Types
import Control.Monad.Except
import Data.Array
import Data.IORef
import qualified Data.Map
macroNamespace :: Char
macroNamespace :: Char
macroNamespace = Char
'm'
varNamespace :: Char
varNamespace :: Char
varNamespace = Char
'v'
getVarName :: Char -> String -> String
getVarName :: Char -> String -> String
getVarName Char
namespace String
name = (Char
namespace Char -> String -> String
forall a. a -> [a] -> [a]
: (Char
'_' Char -> String -> String
forall a. a -> [a] -> [a]
: String
name))
printEnv :: Env
-> IO String
printEnv :: Env -> IO String
printEnv Env
env = do
Map String (IORef LispVal)
binds <- IO (Map String (IORef LispVal)) -> IO (Map String (IORef LispVal))
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Map String (IORef LispVal))
-> IO (Map String (IORef LispVal)))
-> IO (Map String (IORef LispVal))
-> IO (Map String (IORef LispVal))
forall a b. (a -> b) -> a -> b
$ IORef (Map String (IORef LispVal))
-> IO (Map String (IORef LispVal))
forall a. IORef a -> IO a
readIORef (IORef (Map String (IORef LispVal))
-> IO (Map String (IORef LispVal)))
-> IORef (Map String (IORef LispVal))
-> IO (Map String (IORef LispVal))
forall a b. (a -> b) -> a -> b
$ Env -> IORef (Map String (IORef LispVal))
bindings Env
env
[String]
l <- ((String, IORef LispVal) -> IO String)
-> [(String, IORef LispVal)] -> IO [String]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (String, IORef LispVal) -> IO String
forall (m :: * -> *) a.
(MonadIO m, Show a) =>
(String, IORef a) -> m String
showVar ([(String, IORef LispVal)] -> IO [String])
-> [(String, IORef LispVal)] -> IO [String]
forall a b. (a -> b) -> a -> b
$ Map String (IORef LispVal) -> [(String, IORef LispVal)]
forall k a. Map k a -> [(k, a)]
Data.Map.toList Map String (IORef LispVal)
binds
String -> IO String
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> IO String) -> String -> IO String
forall a b. (a -> b) -> a -> b
$ [String] -> String
unlines [String]
l
where
showVar :: (String, IORef a) -> m String
showVar (String
name, IORef a
val) = do
a
v <- IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO a -> m a) -> IO a -> m a
forall a b. (a -> b) -> a -> b
$ IORef a -> IO a
forall a. IORef a -> IO a
readIORef IORef a
val
String -> m String
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> m String) -> String -> m String
forall a b. (a -> b) -> a -> b
$ String
"[" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
name String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"]" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
": " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
v
recPrintEnv :: Env -> IO String
recPrintEnv :: Env -> IO String
recPrintEnv Env
env = do
String
envStr <- IO String -> IO String
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO String -> IO String) -> IO String -> IO String
forall a b. (a -> b) -> a -> b
$ Env -> IO String
printEnv Env
env
case Env -> Maybe Env
parentEnv Env
env of
Just Env
par -> do
String
parEnvStr <- IO String -> IO String
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO String -> IO String) -> IO String -> IO String
forall a b. (a -> b) -> a -> b
$ Env -> IO String
recPrintEnv Env
par
String -> IO String
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> IO String) -> String -> IO String
forall a b. (a -> b) -> a -> b
$ String
envStr String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\n" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
parEnvStr
Maybe Env
Nothing -> String -> IO String
forall (m :: * -> *) a. Monad m => a -> m a
return String
envStr
recExportsFromEnv :: Env -> IO [LispVal]
recExportsFromEnv :: Env -> IO [LispVal]
recExportsFromEnv Env
env = do
[LispVal]
xs <- Env -> IO [LispVal]
exportsFromEnv Env
env
case Env -> Maybe Env
parentEnv Env
env of
Just Env
par -> do
[LispVal]
pxs <- IO [LispVal] -> IO [LispVal]
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO [LispVal] -> IO [LispVal]) -> IO [LispVal] -> IO [LispVal]
forall a b. (a -> b) -> a -> b
$ Env -> IO [LispVal]
recExportsFromEnv Env
par
[LispVal] -> IO [LispVal]
forall (m :: * -> *) a. Monad m => a -> m a
return ([LispVal] -> IO [LispVal]) -> [LispVal] -> IO [LispVal]
forall a b. (a -> b) -> a -> b
$ [LispVal]
xs [LispVal] -> [LispVal] -> [LispVal]
forall a. [a] -> [a] -> [a]
++ [LispVal]
pxs
Maybe Env
Nothing -> [LispVal] -> IO [LispVal]
forall (m :: * -> *) a. Monad m => a -> m a
return [LispVal]
xs
exportsFromEnv :: Env
-> IO [LispVal]
exportsFromEnv :: Env -> IO [LispVal]
exportsFromEnv Env
env = do
Map String (IORef LispVal)
binds <- IO (Map String (IORef LispVal)) -> IO (Map String (IORef LispVal))
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Map String (IORef LispVal))
-> IO (Map String (IORef LispVal)))
-> IO (Map String (IORef LispVal))
-> IO (Map String (IORef LispVal))
forall a b. (a -> b) -> a -> b
$ IORef (Map String (IORef LispVal))
-> IO (Map String (IORef LispVal))
forall a. IORef a -> IO a
readIORef (IORef (Map String (IORef LispVal))
-> IO (Map String (IORef LispVal)))
-> IORef (Map String (IORef LispVal))
-> IO (Map String (IORef LispVal))
forall a b. (a -> b) -> a -> b
$ Env -> IORef (Map String (IORef LispVal))
bindings Env
env
[LispVal] -> IO [LispVal]
forall (m :: * -> *) a. Monad m => a -> m a
return ([LispVal] -> IO [LispVal]) -> [LispVal] -> IO [LispVal]
forall a b. (a -> b) -> a -> b
$ [LispVal] -> [String] -> [LispVal]
getExports [] ([String] -> [LispVal]) -> [String] -> [LispVal]
forall a b. (a -> b) -> a -> b
$ ([String], [IORef LispVal]) -> [String]
forall a b. (a, b) -> a
fst (([String], [IORef LispVal]) -> [String])
-> ([String], [IORef LispVal]) -> [String]
forall a b. (a -> b) -> a -> b
$ [(String, IORef LispVal)] -> ([String], [IORef LispVal])
forall a b. [(a, b)] -> ([a], [b])
unzip ([(String, IORef LispVal)] -> ([String], [IORef LispVal]))
-> [(String, IORef LispVal)] -> ([String], [IORef LispVal])
forall a b. (a -> b) -> a -> b
$ Map String (IORef LispVal) -> [(String, IORef LispVal)]
forall k a. Map k a -> [(k, a)]
Data.Map.toList Map String (IORef LispVal)
binds
where
getExports :: [LispVal] -> [String] -> [LispVal]
getExports [LispVal]
acc ((Char
'm':Char
'_':String
b) : [String]
bs) = [LispVal] -> [String] -> [LispVal]
getExports (String -> LispVal
Atom String
bLispVal -> [LispVal] -> [LispVal]
forall a. a -> [a] -> [a]
:[LispVal]
acc) [String]
bs
getExports [LispVal]
acc ((Char
'v':Char
'_':String
b) : [String]
bs) = [LispVal] -> [String] -> [LispVal]
getExports (String -> LispVal
Atom String
bLispVal -> [LispVal] -> [LispVal]
forall a. a -> [a] -> [a]
:[LispVal]
acc) [String]
bs
getExports [LispVal]
acc (String
_ : [String]
bs) = [LispVal] -> [String] -> [LispVal]
getExports [LispVal]
acc [String]
bs
getExports [LispVal]
acc [] = [LispVal]
acc
copyEnv :: Env
-> IO Env
copyEnv :: Env -> IO Env
copyEnv Env
env = do
Map String (IORef [LispVal])
ptrs <- IO (Map String (IORef [LispVal]))
-> IO (Map String (IORef [LispVal]))
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Map String (IORef [LispVal]))
-> IO (Map String (IORef [LispVal])))
-> IO (Map String (IORef [LispVal]))
-> IO (Map String (IORef [LispVal]))
forall a b. (a -> b) -> a -> b
$ IORef (Map String (IORef [LispVal]))
-> IO (Map String (IORef [LispVal]))
forall a. IORef a -> IO a
readIORef (IORef (Map String (IORef [LispVal]))
-> IO (Map String (IORef [LispVal])))
-> IORef (Map String (IORef [LispVal]))
-> IO (Map String (IORef [LispVal]))
forall a b. (a -> b) -> a -> b
$ Env -> IORef (Map String (IORef [LispVal]))
pointers Env
env
IORef (Map String (IORef [LispVal]))
ptrList <- Map String (IORef [LispVal])
-> IO (IORef (Map String (IORef [LispVal])))
forall a. a -> IO (IORef a)
newIORef Map String (IORef [LispVal])
ptrs
Map String (IORef LispVal)
binds <- IO (Map String (IORef LispVal)) -> IO (Map String (IORef LispVal))
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Map String (IORef LispVal))
-> IO (Map String (IORef LispVal)))
-> IO (Map String (IORef LispVal))
-> IO (Map String (IORef LispVal))
forall a b. (a -> b) -> a -> b
$ IORef (Map String (IORef LispVal))
-> IO (Map String (IORef LispVal))
forall a. IORef a -> IO a
readIORef (IORef (Map String (IORef LispVal))
-> IO (Map String (IORef LispVal)))
-> IORef (Map String (IORef LispVal))
-> IO (Map String (IORef LispVal))
forall a b. (a -> b) -> a -> b
$ Env -> IORef (Map String (IORef LispVal))
bindings Env
env
[(String, IORef LispVal)]
bindingListT <- ((String, IORef LispVal) -> IO (String, IORef LispVal))
-> [(String, IORef LispVal)] -> IO [(String, IORef LispVal)]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (String, IORef LispVal) -> IO (String, IORef LispVal)
forall a a. (a, IORef a) -> IO (a, IORef a)
addBinding ([(String, IORef LispVal)] -> IO [(String, IORef LispVal)])
-> [(String, IORef LispVal)] -> IO [(String, IORef LispVal)]
forall a b. (a -> b) -> a -> b
$ Map String (IORef LispVal) -> [(String, IORef LispVal)]
forall k a. Map k a -> [(k, a)]
Data.Map.toList Map String (IORef LispVal)
binds
IORef (Map String (IORef LispVal))
bindingList <- Map String (IORef LispVal)
-> IO (IORef (Map String (IORef LispVal)))
forall a. a -> IO (IORef a)
newIORef (Map String (IORef LispVal)
-> IO (IORef (Map String (IORef LispVal))))
-> Map String (IORef LispVal)
-> IO (IORef (Map String (IORef LispVal)))
forall a b. (a -> b) -> a -> b
$ [(String, IORef LispVal)] -> Map String (IORef LispVal)
forall k a. Ord k => [(k, a)] -> Map k a
Data.Map.fromList [(String, IORef LispVal)]
bindingListT
Env -> IO Env
forall (m :: * -> *) a. Monad m => a -> m a
return (Env -> IO Env) -> Env -> IO Env
forall a b. (a -> b) -> a -> b
$ Maybe Env
-> IORef (Map String (IORef LispVal))
-> IORef (Map String (IORef [LispVal]))
-> Env
Environment (Env -> Maybe Env
parentEnv Env
env) IORef (Map String (IORef LispVal))
bindingList IORef (Map String (IORef [LispVal]))
ptrList
where addBinding :: (a, IORef a) -> IO (a, IORef a)
addBinding (a
name, IORef a
val) = do
a
x <- IO a -> IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO a -> IO a) -> IO a -> IO a
forall a b. (a -> b) -> a -> b
$ IORef a -> IO a
forall a. IORef a -> IO a
readIORef IORef a
val
IORef a
ref <- a -> IO (IORef a)
forall a. a -> IO (IORef a)
newIORef a
x
(a, IORef a) -> IO (a, IORef a)
forall (m :: * -> *) a. Monad m => a -> m a
return (a
name, IORef a
ref)
importEnv
:: Env
-> Env
-> IO Env
importEnv :: Env -> Env -> IO Env
importEnv Env
dEnv Env
sEnv = do
Map String (IORef [LispVal])
sPtrs <- IO (Map String (IORef [LispVal]))
-> IO (Map String (IORef [LispVal]))
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Map String (IORef [LispVal]))
-> IO (Map String (IORef [LispVal])))
-> IO (Map String (IORef [LispVal]))
-> IO (Map String (IORef [LispVal]))
forall a b. (a -> b) -> a -> b
$ IORef (Map String (IORef [LispVal]))
-> IO (Map String (IORef [LispVal]))
forall a. IORef a -> IO a
readIORef (IORef (Map String (IORef [LispVal]))
-> IO (Map String (IORef [LispVal])))
-> IORef (Map String (IORef [LispVal]))
-> IO (Map String (IORef [LispVal]))
forall a b. (a -> b) -> a -> b
$ Env -> IORef (Map String (IORef [LispVal]))
pointers Env
sEnv
Map String (IORef [LispVal])
dPtrs <- IO (Map String (IORef [LispVal]))
-> IO (Map String (IORef [LispVal]))
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Map String (IORef [LispVal]))
-> IO (Map String (IORef [LispVal])))
-> IO (Map String (IORef [LispVal]))
-> IO (Map String (IORef [LispVal]))
forall a b. (a -> b) -> a -> b
$ IORef (Map String (IORef [LispVal]))
-> IO (Map String (IORef [LispVal]))
forall a. IORef a -> IO a
readIORef (IORef (Map String (IORef [LispVal]))
-> IO (Map String (IORef [LispVal])))
-> IORef (Map String (IORef [LispVal]))
-> IO (Map String (IORef [LispVal]))
forall a b. (a -> b) -> a -> b
$ Env -> IORef (Map String (IORef [LispVal]))
pointers Env
dEnv
IORef (Map String (IORef [LispVal]))
-> Map String (IORef [LispVal]) -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef (Env -> IORef (Map String (IORef [LispVal]))
pointers Env
dEnv) (Map String (IORef [LispVal]) -> IO ())
-> Map String (IORef [LispVal]) -> IO ()
forall a b. (a -> b) -> a -> b
$ Map String (IORef [LispVal])
-> Map String (IORef [LispVal]) -> Map String (IORef [LispVal])
forall k a. Ord k => Map k a -> Map k a -> Map k a
Data.Map.union Map String (IORef [LispVal])
sPtrs Map String (IORef [LispVal])
dPtrs
Map String (IORef LispVal)
sBinds <- IO (Map String (IORef LispVal)) -> IO (Map String (IORef LispVal))
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Map String (IORef LispVal))
-> IO (Map String (IORef LispVal)))
-> IO (Map String (IORef LispVal))
-> IO (Map String (IORef LispVal))
forall a b. (a -> b) -> a -> b
$ IORef (Map String (IORef LispVal))
-> IO (Map String (IORef LispVal))
forall a. IORef a -> IO a
readIORef (IORef (Map String (IORef LispVal))
-> IO (Map String (IORef LispVal)))
-> IORef (Map String (IORef LispVal))
-> IO (Map String (IORef LispVal))
forall a b. (a -> b) -> a -> b
$ Env -> IORef (Map String (IORef LispVal))
bindings Env
sEnv
Map String (IORef LispVal)
dBinds <- IO (Map String (IORef LispVal)) -> IO (Map String (IORef LispVal))
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Map String (IORef LispVal))
-> IO (Map String (IORef LispVal)))
-> IO (Map String (IORef LispVal))
-> IO (Map String (IORef LispVal))
forall a b. (a -> b) -> a -> b
$ IORef (Map String (IORef LispVal))
-> IO (Map String (IORef LispVal))
forall a. IORef a -> IO a
readIORef (IORef (Map String (IORef LispVal))
-> IO (Map String (IORef LispVal)))
-> IORef (Map String (IORef LispVal))
-> IO (Map String (IORef LispVal))
forall a b. (a -> b) -> a -> b
$ Env -> IORef (Map String (IORef LispVal))
bindings Env
dEnv
IORef (Map String (IORef LispVal))
-> Map String (IORef LispVal) -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef (Env -> IORef (Map String (IORef LispVal))
bindings Env
dEnv) (Map String (IORef LispVal) -> IO ())
-> Map String (IORef LispVal) -> IO ()
forall a b. (a -> b) -> a -> b
$ Map String (IORef LispVal)
-> Map String (IORef LispVal) -> Map String (IORef LispVal)
forall k a. Ord k => Map k a -> Map k a -> Map k a
Data.Map.union Map String (IORef LispVal)
sBinds Map String (IORef LispVal)
dBinds
case Env -> Maybe Env
parentEnv Env
sEnv of
Just Env
ps -> Env -> Env -> IO Env
importEnv Env
dEnv Env
ps
Maybe Env
Nothing -> Env -> IO Env
forall (m :: * -> *) a. Monad m => a -> m a
return Env
dEnv
extendEnv :: Env
-> [((Char, String), LispVal)]
-> IO Env
extendEnv :: Env -> [((Char, String), LispVal)] -> IO Env
extendEnv Env
envRef [((Char, String), LispVal)]
abindings = do
[(String, IORef LispVal)]
bindinglistT <- ((((Char, String), LispVal) -> IO (String, IORef LispVal))
-> [((Char, String), LispVal)] -> IO [(String, IORef LispVal)]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM ((Char, String), LispVal) -> IO (String, IORef LispVal)
forall a. ((Char, String), a) -> IO (String, IORef a)
addBinding [((Char, String), LispVal)]
abindings)
IORef (Map String (IORef LispVal))
bindinglist <- Map String (IORef LispVal)
-> IO (IORef (Map String (IORef LispVal)))
forall a. a -> IO (IORef a)
newIORef (Map String (IORef LispVal)
-> IO (IORef (Map String (IORef LispVal))))
-> Map String (IORef LispVal)
-> IO (IORef (Map String (IORef LispVal)))
forall a b. (a -> b) -> a -> b
$ [(String, IORef LispVal)] -> Map String (IORef LispVal)
forall k a. Ord k => [(k, a)] -> Map k a
Data.Map.fromList [(String, IORef LispVal)]
bindinglistT
IORef (Map String (IORef [LispVal]))
nullPointers <- Map String (IORef [LispVal])
-> IO (IORef (Map String (IORef [LispVal])))
forall a. a -> IO (IORef a)
newIORef (Map String (IORef [LispVal])
-> IO (IORef (Map String (IORef [LispVal]))))
-> Map String (IORef [LispVal])
-> IO (IORef (Map String (IORef [LispVal])))
forall a b. (a -> b) -> a -> b
$ [(String, IORef [LispVal])] -> Map String (IORef [LispVal])
forall k a. Ord k => [(k, a)] -> Map k a
Data.Map.fromList []
Env -> IO Env
forall (m :: * -> *) a. Monad m => a -> m a
return (Env -> IO Env) -> Env -> IO Env
forall a b. (a -> b) -> a -> b
$ Maybe Env
-> IORef (Map String (IORef LispVal))
-> IORef (Map String (IORef [LispVal]))
-> Env
Environment (Env -> Maybe Env
forall a. a -> Maybe a
Just Env
envRef) IORef (Map String (IORef LispVal))
bindinglist IORef (Map String (IORef [LispVal]))
nullPointers
where addBinding :: ((Char, String), a) -> IO (String, IORef a)
addBinding ((Char
namespace, String
name), a
val) = do IORef a
ref <- a -> IO (IORef a)
forall a. a -> IO (IORef a)
newIORef a
val
(String, IORef a) -> IO (String, IORef a)
forall (m :: * -> *) a. Monad m => a -> m a
return (Char -> String -> String
getVarName Char
namespace String
name, IORef a
ref)
topmostEnv :: Env -> IO Env
topmostEnv :: Env -> IO Env
topmostEnv Env
envRef = do
case Env -> Maybe Env
parentEnv Env
envRef of
Just Env
p -> Env -> IO Env
topmostEnv Env
p
Maybe Env
Nothing -> Env -> IO Env
forall (m :: * -> *) a. Monad m => a -> m a
return Env
envRef
nullEnvWithParent :: Env -> IO Env
nullEnvWithParent :: Env -> IO Env
nullEnvWithParent Env
p = do
Environment Maybe Env
_ IORef (Map String (IORef LispVal))
binds IORef (Map String (IORef [LispVal]))
ptrs <- IO Env
nullEnv
Env -> IO Env
forall (m :: * -> *) a. Monad m => a -> m a
return (Env -> IO Env) -> Env -> IO Env
forall a b. (a -> b) -> a -> b
$ Maybe Env
-> IORef (Map String (IORef LispVal))
-> IORef (Map String (IORef [LispVal]))
-> Env
Environment (Env -> Maybe Env
forall a. a -> Maybe a
Just Env
p) IORef (Map String (IORef LispVal))
binds IORef (Map String (IORef [LispVal]))
ptrs
findNamespacedEnv
:: Env
-> Char
-> String
-> IO (Maybe Env)
findNamespacedEnv :: Env -> Char -> String -> IO (Maybe Env)
findNamespacedEnv Env
envRef Char
namespace String
var = do
Bool
found <- IO Bool -> IO Bool
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Bool -> IO Bool) -> IO Bool -> IO Bool
forall a b. (a -> b) -> a -> b
$ Env -> Char -> String -> IO Bool
isNamespacedBound Env
envRef Char
namespace String
var
if Bool
found
then Maybe Env -> IO (Maybe Env)
forall (m :: * -> *) a. Monad m => a -> m a
return (Env -> Maybe Env
forall a. a -> Maybe a
Just Env
envRef)
else case Env -> Maybe Env
parentEnv Env
envRef of
(Just Env
par) -> Env -> Char -> String -> IO (Maybe Env)
findNamespacedEnv Env
par Char
namespace String
var
Maybe Env
Nothing -> Maybe Env -> IO (Maybe Env)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe Env
forall a. Maybe a
Nothing
isBound :: Env
-> String
-> IO Bool
isBound :: Env -> String -> IO Bool
isBound Env
envRef = Env -> Char -> String -> IO Bool
isNamespacedBound Env
envRef Char
varNamespace
isRecBound :: Env
-> String
-> IO Bool
isRecBound :: Env -> String -> IO Bool
isRecBound Env
envRef = Env -> Char -> String -> IO Bool
isNamespacedRecBound Env
envRef Char
varNamespace
isNamespacedBound
:: Env
-> Char
-> String
-> IO Bool
isNamespacedBound :: Env -> Char -> String -> IO Bool
isNamespacedBound Env
envRef Char
namespace String
var =
IORef (Map String (IORef LispVal))
-> IO (Map String (IORef LispVal))
forall a. IORef a -> IO a
readIORef (Env -> IORef (Map String (IORef LispVal))
bindings Env
envRef) IO (Map String (IORef LispVal))
-> (Map String (IORef LispVal) -> IO Bool) -> IO Bool
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Bool -> IO Bool
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> IO Bool)
-> (Map String (IORef LispVal) -> Bool)
-> Map String (IORef LispVal)
-> IO Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Map String (IORef LispVal) -> Bool
forall k a. Ord k => k -> Map k a -> Bool
Data.Map.member (Char -> String -> String
getVarName Char
namespace String
var)
isNamespacedRecBound
:: Env
-> Char
-> String
-> IO Bool
isNamespacedRecBound :: Env -> Char -> String -> IO Bool
isNamespacedRecBound Env
envRef Char
namespace String
var = do
Maybe Env
env <- Env -> Char -> String -> IO (Maybe Env)
findNamespacedEnv Env
envRef Char
namespace String
var
case Maybe Env
env of
(Just Env
e) -> Env -> Char -> String -> IO Bool
isNamespacedBound Env
e Char
namespace String
var
Maybe Env
Nothing -> Bool -> IO Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
getVar :: Env
-> String
-> IOThrowsError LispVal
getVar :: Env -> String -> IOThrowsError LispVal
getVar Env
envRef = Env -> Char -> String -> IOThrowsError LispVal
getNamespacedVar Env
envRef Char
varNamespace
getVar' :: Env
-> String
-> IOThrowsError (Maybe LispVal)
getVar' :: Env -> String -> IOThrowsError (Maybe LispVal)
getVar' Env
envRef = Env -> Char -> String -> IOThrowsError (Maybe LispVal)
getNamespacedVar' Env
envRef Char
varNamespace
getNamespacedRef :: Env
-> Char
-> String
-> IOThrowsError (IORef LispVal)
getNamespacedRef :: Env -> Char -> String -> IOThrowsError (IORef LispVal)
getNamespacedRef Env
envRef
Char
namespace
String
var = do
Maybe (IORef LispVal)
v <- Env
-> Char
-> String
-> (IORef LispVal -> IO (IORef LispVal))
-> IOThrowsError (Maybe (IORef LispVal))
forall a.
Env
-> Char
-> String
-> (IORef LispVal -> IO a)
-> IOThrowsError (Maybe a)
getNamespacedObj' Env
envRef Char
namespace String
var IORef LispVal -> IO (IORef LispVal)
forall (m :: * -> *) a. Monad m => a -> m a
return
case Maybe (IORef LispVal)
v of
Just IORef LispVal
a -> IORef LispVal -> IOThrowsError (IORef LispVal)
forall (m :: * -> *) a. Monad m => a -> m a
return IORef LispVal
a
Maybe (IORef LispVal)
Nothing -> (LispError -> IOThrowsError (IORef LispVal)
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError (LispError -> IOThrowsError (IORef LispVal))
-> LispError -> IOThrowsError (IORef LispVal)
forall a b. (a -> b) -> a -> b
$ String -> String -> LispError
UnboundVar String
"Getting an unbound variable" String
var)
getNamespacedVar :: Env
-> Char
-> String
-> IOThrowsError LispVal
getNamespacedVar :: Env -> Char -> String -> IOThrowsError LispVal
getNamespacedVar Env
envRef
Char
namespace
String
var = do
Maybe LispVal
v <- Env -> Char -> String -> IOThrowsError (Maybe LispVal)
getNamespacedVar' Env
envRef Char
namespace String
var
case Maybe LispVal
v of
Just LispVal
a -> LispVal -> IOThrowsError LispVal
forall (m :: * -> *) a. Monad m => a -> m a
return LispVal
a
Maybe LispVal
Nothing -> (LispError -> IOThrowsError LispVal
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError (LispError -> IOThrowsError LispVal)
-> LispError -> IOThrowsError LispVal
forall a b. (a -> b) -> a -> b
$ String -> String -> LispError
UnboundVar String
"Getting an unbound variable" String
var)
getNamespacedVar' :: Env
-> Char
-> String
-> IOThrowsError (Maybe LispVal)
getNamespacedVar' :: Env -> Char -> String -> IOThrowsError (Maybe LispVal)
getNamespacedVar' Env
envRef
Char
namespace
String
var = do
Env
-> Char
-> String
-> (IORef LispVal -> IO LispVal)
-> IOThrowsError (Maybe LispVal)
forall a.
Env
-> Char
-> String
-> (IORef LispVal -> IO a)
-> IOThrowsError (Maybe a)
getNamespacedObj' Env
envRef Char
namespace String
var IORef LispVal -> IO LispVal
forall a. IORef a -> IO a
readIORef
getNamespacedObj' :: Env
-> Char
-> String
-> (IORef LispVal -> IO a)
-> IOThrowsError (Maybe a)
getNamespacedObj' :: Env
-> Char
-> String
-> (IORef LispVal -> IO a)
-> IOThrowsError (Maybe a)
getNamespacedObj' Env
envRef
Char
namespace
String
var
IORef LispVal -> IO a
unpackFnc = do
Map String (IORef LispVal)
binds <- IO (Map String (IORef LispVal))
-> ExceptT LispError IO (Map String (IORef LispVal))
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Map String (IORef LispVal))
-> ExceptT LispError IO (Map String (IORef LispVal)))
-> IO (Map String (IORef LispVal))
-> ExceptT LispError IO (Map String (IORef LispVal))
forall a b. (a -> b) -> a -> b
$ IORef (Map String (IORef LispVal))
-> IO (Map String (IORef LispVal))
forall a. IORef a -> IO a
readIORef (IORef (Map String (IORef LispVal))
-> IO (Map String (IORef LispVal)))
-> IORef (Map String (IORef LispVal))
-> IO (Map String (IORef LispVal))
forall a b. (a -> b) -> a -> b
$ Env -> IORef (Map String (IORef LispVal))
bindings Env
envRef
case String -> Map String (IORef LispVal) -> Maybe (IORef LispVal)
forall k a. Ord k => k -> Map k a -> Maybe a
Data.Map.lookup (Char -> String -> String
getVarName Char
namespace String
var) Map String (IORef LispVal)
binds of
(Just IORef LispVal
a) -> do
a
v <- IO a -> ExceptT LispError IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO a -> ExceptT LispError IO a) -> IO a -> ExceptT LispError IO a
forall a b. (a -> b) -> a -> b
$ IORef LispVal -> IO a
unpackFnc IORef LispVal
a
Maybe a -> IOThrowsError (Maybe a)
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe a -> IOThrowsError (Maybe a))
-> Maybe a -> IOThrowsError (Maybe a)
forall a b. (a -> b) -> a -> b
$ a -> Maybe a
forall a. a -> Maybe a
Just a
v
Maybe (IORef LispVal)
Nothing -> case Env -> Maybe Env
parentEnv Env
envRef of
(Just Env
par) -> Env
-> Char
-> String
-> (IORef LispVal -> IO a)
-> IOThrowsError (Maybe a)
forall a.
Env
-> Char
-> String
-> (IORef LispVal -> IO a)
-> IOThrowsError (Maybe a)
getNamespacedObj' Env
par Char
namespace String
var IORef LispVal -> IO a
unpackFnc
Maybe Env
Nothing -> Maybe a -> IOThrowsError (Maybe a)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe a
forall a. Maybe a
Nothing
setVar
:: Env
-> String
-> LispVal
-> IOThrowsError LispVal
setVar :: Env -> String -> LispVal -> IOThrowsError LispVal
setVar Env
envRef = Env -> Char -> String -> LispVal -> IOThrowsError LispVal
setNamespacedVar Env
envRef Char
varNamespace
setNamespacedVar
:: Env
-> Char
-> String
-> LispVal
-> IOThrowsError LispVal
setNamespacedVar :: Env -> Char -> String -> LispVal -> IOThrowsError LispVal
setNamespacedVar Env
envRef
Char
namespace
String
var LispVal
value = do
case LispVal
value of
Pointer String
p Env
_ -> do
if String
p String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
var
then LispVal -> IOThrowsError LispVal
forall (m :: * -> *) a. Monad m => a -> m a
return LispVal
value
else IOThrowsError LispVal
next
LispVal
_ -> IOThrowsError LispVal
next
where
next :: IOThrowsError LispVal
next = do
LispVal
_ <- Env -> Char -> String -> IOThrowsError LispVal
updatePointers Env
envRef Char
namespace String
var
Env -> Char -> String -> LispVal -> IOThrowsError LispVal
_setNamespacedVar Env
envRef Char
namespace String
var LispVal
value
_setNamespacedVar
:: Env
-> Char
-> String
-> LispVal
-> IOThrowsError LispVal
_setNamespacedVar :: Env -> Char -> String -> LispVal -> IOThrowsError LispVal
_setNamespacedVar Env
envRef
Char
namespace
String
var LispVal
value = do
LispVal
valueToStore <- Char -> String -> Env -> LispVal -> IOThrowsError LispVal
getValueToStore Char
namespace String
var Env
envRef LispVal
value
Env -> Char -> String -> LispVal -> IOThrowsError LispVal
_setNamespacedVarDirect Env
envRef Char
namespace String
var LispVal
valueToStore
_setNamespacedVarDirect
:: Env
-> Char
-> String
-> LispVal
-> IOThrowsError LispVal
_setNamespacedVarDirect :: Env -> Char -> String -> LispVal -> IOThrowsError LispVal
_setNamespacedVarDirect Env
envRef
Char
namespace
String
var LispVal
valueToStore = do
Map String (IORef LispVal)
env <- IO (Map String (IORef LispVal))
-> ExceptT LispError IO (Map String (IORef LispVal))
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Map String (IORef LispVal))
-> ExceptT LispError IO (Map String (IORef LispVal)))
-> IO (Map String (IORef LispVal))
-> ExceptT LispError IO (Map String (IORef LispVal))
forall a b. (a -> b) -> a -> b
$ IORef (Map String (IORef LispVal))
-> IO (Map String (IORef LispVal))
forall a. IORef a -> IO a
readIORef (IORef (Map String (IORef LispVal))
-> IO (Map String (IORef LispVal)))
-> IORef (Map String (IORef LispVal))
-> IO (Map String (IORef LispVal))
forall a b. (a -> b) -> a -> b
$ Env -> IORef (Map String (IORef LispVal))
bindings Env
envRef
case String -> Map String (IORef LispVal) -> Maybe (IORef LispVal)
forall k a. Ord k => k -> Map k a -> Maybe a
Data.Map.lookup (Char -> String -> String
getVarName Char
namespace String
var) Map String (IORef LispVal)
env of
(Just IORef LispVal
a) -> do
IO () -> ExceptT LispError IO ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> ExceptT LispError IO ())
-> IO () -> ExceptT LispError IO ()
forall a b. (a -> b) -> a -> b
$ IORef LispVal -> LispVal -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef LispVal
a LispVal
valueToStore
LispVal -> IOThrowsError LispVal
forall (m :: * -> *) a. Monad m => a -> m a
return LispVal
valueToStore
Maybe (IORef LispVal)
Nothing -> case Env -> Maybe Env
parentEnv Env
envRef of
(Just Env
par) -> Env -> Char -> String -> LispVal -> IOThrowsError LispVal
_setNamespacedVarDirect Env
par Char
namespace String
var LispVal
valueToStore
Maybe Env
Nothing -> LispError -> IOThrowsError LispVal
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError (LispError -> IOThrowsError LispVal)
-> LispError -> IOThrowsError LispVal
forall a b. (a -> b) -> a -> b
$ String -> String -> LispError
UnboundVar String
"Setting an unbound variable: " String
var
updatePointers :: Env -> Char -> String -> IOThrowsError LispVal
updatePointers :: Env -> Char -> String -> IOThrowsError LispVal
updatePointers Env
envRef Char
namespace String
var = do
Map String (IORef [LispVal])
ptrs <- IO (Map String (IORef [LispVal]))
-> ExceptT LispError IO (Map String (IORef [LispVal]))
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Map String (IORef [LispVal]))
-> ExceptT LispError IO (Map String (IORef [LispVal])))
-> IO (Map String (IORef [LispVal]))
-> ExceptT LispError IO (Map String (IORef [LispVal]))
forall a b. (a -> b) -> a -> b
$ IORef (Map String (IORef [LispVal]))
-> IO (Map String (IORef [LispVal]))
forall a. IORef a -> IO a
readIORef (IORef (Map String (IORef [LispVal]))
-> IO (Map String (IORef [LispVal])))
-> IORef (Map String (IORef [LispVal]))
-> IO (Map String (IORef [LispVal]))
forall a b. (a -> b) -> a -> b
$ Env -> IORef (Map String (IORef [LispVal]))
pointers Env
envRef
case String -> Map String (IORef [LispVal]) -> Maybe (IORef [LispVal])
forall k a. Ord k => k -> Map k a -> Maybe a
Data.Map.lookup (Char -> String -> String
getVarName Char
namespace String
var) Map String (IORef [LispVal])
ptrs of
(Just IORef [LispVal]
valIORef) -> do
[LispVal]
val <- IO [LispVal] -> ExceptT LispError IO [LispVal]
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO [LispVal] -> ExceptT LispError IO [LispVal])
-> IO [LispVal] -> ExceptT LispError IO [LispVal]
forall a b. (a -> b) -> a -> b
$ IORef [LispVal] -> IO [LispVal]
forall a. IORef a -> IO a
readIORef IORef [LispVal]
valIORef
case [LispVal]
val of
(Pointer String
pVar Env
pEnv : [LispVal]
ps) -> do
IO () -> ExceptT LispError IO ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> ExceptT LispError IO ())
-> IO () -> ExceptT LispError IO ()
forall a b. (a -> b) -> a -> b
$ IORef [LispVal] -> [LispVal] -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef [LispVal]
valIORef []
LispVal
_ <- Env -> Char -> String -> [LispVal] -> IOThrowsError LispVal
movePointers Env
pEnv Char
namespace String
pVar [LispVal]
ps
LispVal
_ <- Env -> Char -> String -> [LispVal] -> IOThrowsError LispVal
pointToNewVar Env
pEnv Char
namespace String
pVar [LispVal]
ps
LispVal
existingValue <- Env -> Char -> String -> IOThrowsError LispVal
getNamespacedVar Env
envRef Char
namespace String
var
Env -> Char -> String -> LispVal -> IOThrowsError LispVal
_setNamespacedVar Env
pEnv Char
namespace String
pVar LispVal
existingValue
[] -> LispVal -> IOThrowsError LispVal
forall (m :: * -> *) a. Monad m => a -> m a
return (LispVal -> IOThrowsError LispVal)
-> LispVal -> IOThrowsError LispVal
forall a b. (a -> b) -> a -> b
$ String -> LispVal
Nil String
""
[LispVal]
_ -> LispError -> IOThrowsError LispVal
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError (LispError -> IOThrowsError LispVal)
-> LispError -> IOThrowsError LispVal
forall a b. (a -> b) -> a -> b
$ String -> LispError
InternalError
String
"non-pointer value found in updatePointers"
Maybe (IORef [LispVal])
Nothing -> LispVal -> IOThrowsError LispVal
forall (m :: * -> *) a. Monad m => a -> m a
return (LispVal -> IOThrowsError LispVal)
-> LispVal -> IOThrowsError LispVal
forall a b. (a -> b) -> a -> b
$ String -> LispVal
Nil String
""
where
movePointers :: Env -> Char -> String -> [LispVal] -> IOThrowsError LispVal
movePointers :: Env -> Char -> String -> [LispVal] -> IOThrowsError LispVal
movePointers Env
envRef' Char
namespace' String
var' [LispVal]
ptrs = do
Map String (IORef [LispVal])
env <- IO (Map String (IORef [LispVal]))
-> ExceptT LispError IO (Map String (IORef [LispVal]))
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Map String (IORef [LispVal]))
-> ExceptT LispError IO (Map String (IORef [LispVal])))
-> IO (Map String (IORef [LispVal]))
-> ExceptT LispError IO (Map String (IORef [LispVal]))
forall a b. (a -> b) -> a -> b
$ IORef (Map String (IORef [LispVal]))
-> IO (Map String (IORef [LispVal]))
forall a. IORef a -> IO a
readIORef (IORef (Map String (IORef [LispVal]))
-> IO (Map String (IORef [LispVal])))
-> IORef (Map String (IORef [LispVal]))
-> IO (Map String (IORef [LispVal]))
forall a b. (a -> b) -> a -> b
$ Env -> IORef (Map String (IORef [LispVal]))
pointers Env
envRef'
case String -> Map String (IORef [LispVal]) -> Maybe (IORef [LispVal])
forall k a. Ord k => k -> Map k a -> Maybe a
Data.Map.lookup (Char -> String -> String
getVarName Char
namespace' String
var') Map String (IORef [LispVal])
env of
Just IORef [LispVal]
ps' -> do
[LispVal]
ps <- IO [LispVal] -> ExceptT LispError IO [LispVal]
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO [LispVal] -> ExceptT LispError IO [LispVal])
-> IO [LispVal] -> ExceptT LispError IO [LispVal]
forall a b. (a -> b) -> a -> b
$ IORef [LispVal] -> IO [LispVal]
forall a. IORef a -> IO a
readIORef IORef [LispVal]
ps'
IO () -> ExceptT LispError IO ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> ExceptT LispError IO ())
-> IO () -> ExceptT LispError IO ()
forall a b. (a -> b) -> a -> b
$ IORef [LispVal] -> [LispVal] -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef [LispVal]
ps' ([LispVal] -> IO ()) -> [LispVal] -> IO ()
forall a b. (a -> b) -> a -> b
$ [LispVal]
ps [LispVal] -> [LispVal] -> [LispVal]
forall a. [a] -> [a] -> [a]
++ [LispVal]
ptrs
LispVal -> IOThrowsError LispVal
forall (m :: * -> *) a. Monad m => a -> m a
return (LispVal -> IOThrowsError LispVal)
-> LispVal -> IOThrowsError LispVal
forall a b. (a -> b) -> a -> b
$ String -> LispVal
Nil String
""
Maybe (IORef [LispVal])
Nothing -> do
IORef [LispVal]
valueRef <- IO (IORef [LispVal]) -> ExceptT LispError IO (IORef [LispVal])
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (IORef [LispVal]) -> ExceptT LispError IO (IORef [LispVal]))
-> IO (IORef [LispVal]) -> ExceptT LispError IO (IORef [LispVal])
forall a b. (a -> b) -> a -> b
$ [LispVal] -> IO (IORef [LispVal])
forall a. a -> IO (IORef a)
newIORef [LispVal]
ptrs
IO () -> ExceptT LispError IO ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> ExceptT LispError IO ())
-> IO () -> ExceptT LispError IO ()
forall a b. (a -> b) -> a -> b
$ IORef (Map String (IORef [LispVal]))
-> Map String (IORef [LispVal]) -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef (Env -> IORef (Map String (IORef [LispVal]))
pointers Env
envRef') (String
-> IORef [LispVal]
-> Map String (IORef [LispVal])
-> Map String (IORef [LispVal])
forall k a. Ord k => k -> a -> Map k a -> Map k a
Data.Map.insert (Char -> String -> String
getVarName Char
namespace String
var') IORef [LispVal]
valueRef Map String (IORef [LispVal])
env)
LispVal -> IOThrowsError LispVal
forall (m :: * -> *) a. Monad m => a -> m a
return (LispVal -> IOThrowsError LispVal)
-> LispVal -> IOThrowsError LispVal
forall a b. (a -> b) -> a -> b
$ String -> LispVal
Nil String
""
pointToNewVar :: Env -> Char -> String -> [LispVal] -> IOThrowsError LispVal
pointToNewVar Env
pEnv Char
namespace' String
pVar' (Pointer String
v Env
e : [LispVal]
ps) = do
LispVal
_ <- Env -> Char -> String -> LispVal -> IOThrowsError LispVal
_setNamespacedVarDirect Env
e Char
namespace' String
v (String -> Env -> LispVal
Pointer String
pVar' Env
pEnv)
Env -> Char -> String -> [LispVal] -> IOThrowsError LispVal
pointToNewVar Env
pEnv Char
namespace' String
pVar' [LispVal]
ps
pointToNewVar Env
_ Char
_ String
_ [] = LispVal -> IOThrowsError LispVal
forall (m :: * -> *) a. Monad m => a -> m a
return (LispVal -> IOThrowsError LispVal)
-> LispVal -> IOThrowsError LispVal
forall a b. (a -> b) -> a -> b
$ String -> LispVal
Nil String
""
pointToNewVar Env
_ Char
_ String
_ [LispVal]
_ = LispError -> IOThrowsError LispVal
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError (LispError -> IOThrowsError LispVal)
-> LispError -> IOThrowsError LispVal
forall a b. (a -> b) -> a -> b
$ String -> LispError
InternalError String
"pointToNewVar"
updateObject :: Env -> String -> LispVal -> IOThrowsError LispVal
updateObject :: Env -> String -> LispVal -> IOThrowsError LispVal
updateObject Env
env =
Env -> Char -> String -> LispVal -> IOThrowsError LispVal
updateNamespacedObject Env
env Char
varNamespace
updateNamespacedObject :: Env
-> Char
-> String
-> LispVal
-> IOThrowsError LispVal
updateNamespacedObject :: Env -> Char -> String -> LispVal -> IOThrowsError LispVal
updateNamespacedObject Env
env Char
namespace String
var LispVal
value = do
LispVal
varContents <- Env -> Char -> String -> IOThrowsError LispVal
getNamespacedVar Env
env Char
namespace String
var
LispVal
obj <- LispVal -> IOThrowsError LispVal
findPointerTo LispVal
varContents
case LispVal
obj of
Pointer String
pVar Env
pEnv -> do
Env -> Char -> String -> LispVal -> IOThrowsError LispVal
_setNamespacedVar Env
pEnv Char
namespace String
pVar LispVal
value
LispVal
_ -> Env -> Char -> String -> LispVal -> IOThrowsError LispVal
_setNamespacedVar Env
env Char
namespace String
var LispVal
value
defineVar
:: Env
-> String
-> LispVal
-> IOThrowsError LispVal
defineVar :: Env -> String -> LispVal -> IOThrowsError LispVal
defineVar Env
envRef = Env -> Char -> String -> LispVal -> IOThrowsError LispVal
defineNamespacedVar Env
envRef Char
varNamespace
defineNamespacedVar
:: Env
-> Char
-> String
-> LispVal
-> IOThrowsError LispVal
defineNamespacedVar :: Env -> Char -> String -> LispVal -> IOThrowsError LispVal
defineNamespacedVar Env
envRef
Char
namespace
String
var LispVal
value = do
Bool
alreadyDefined <- IO Bool -> ExceptT LispError IO Bool
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Bool -> ExceptT LispError IO Bool)
-> IO Bool -> ExceptT LispError IO Bool
forall a b. (a -> b) -> a -> b
$ Env -> Char -> String -> IO Bool
isNamespacedBound Env
envRef Char
namespace String
var
if Bool
alreadyDefined
then Env -> Char -> String -> LispVal -> IOThrowsError LispVal
setNamespacedVar Env
envRef Char
namespace String
var LispVal
value IOThrowsError LispVal
-> IOThrowsError LispVal -> IOThrowsError LispVal
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> LispVal -> IOThrowsError LispVal
forall (m :: * -> *) a. Monad m => a -> m a
return LispVal
value
else do
LispVal
valueToStore <- Char -> String -> Env -> LispVal -> IOThrowsError LispVal
getValueToStore Char
namespace String
var Env
envRef LispVal
value
IO LispVal -> IOThrowsError LispVal
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO LispVal -> IOThrowsError LispVal)
-> IO LispVal -> IOThrowsError LispVal
forall a b. (a -> b) -> a -> b
$ do
IORef LispVal
valueRef <- LispVal -> IO (IORef LispVal)
forall a. a -> IO (IORef a)
newIORef LispVal
valueToStore
Map String (IORef LispVal)
env <- IORef (Map String (IORef LispVal))
-> IO (Map String (IORef LispVal))
forall a. IORef a -> IO a
readIORef (IORef (Map String (IORef LispVal))
-> IO (Map String (IORef LispVal)))
-> IORef (Map String (IORef LispVal))
-> IO (Map String (IORef LispVal))
forall a b. (a -> b) -> a -> b
$ Env -> IORef (Map String (IORef LispVal))
bindings Env
envRef
IORef (Map String (IORef LispVal))
-> Map String (IORef LispVal) -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef (Env -> IORef (Map String (IORef LispVal))
bindings Env
envRef) (String
-> IORef LispVal
-> Map String (IORef LispVal)
-> Map String (IORef LispVal)
forall k a. Ord k => k -> a -> Map k a -> Map k a
Data.Map.insert (Char -> String -> String
getVarName Char
namespace String
var) IORef LispVal
valueRef Map String (IORef LispVal)
env)
LispVal -> IO LispVal
forall (m :: * -> *) a. Monad m => a -> m a
return LispVal
valueToStore
getValueToStore :: Char -> String -> Env -> LispVal -> IOThrowsError LispVal
getValueToStore :: Char -> String -> Env -> LispVal -> IOThrowsError LispVal
getValueToStore Char
namespace String
var Env
env (Pointer String
p Env
pEnv) = do
Char
-> String -> Env -> Char -> String -> Env -> IOThrowsError LispVal
addReversePointer Char
namespace String
p Env
pEnv Char
namespace String
var Env
env
getValueToStore Char
_ String
_ Env
_ LispVal
value = LispVal -> IOThrowsError LispVal
forall (m :: * -> *) a. Monad m => a -> m a
return LispVal
value
addReversePointer :: Char -> String -> Env -> Char -> String -> Env -> IOThrowsError LispVal
addReversePointer :: Char
-> String -> Env -> Char -> String -> Env -> IOThrowsError LispVal
addReversePointer Char
namespace String
var Env
envRef Char
ptrNamespace String
ptrVar Env
ptrEnvRef = do
Map String (IORef LispVal)
env <- IO (Map String (IORef LispVal))
-> ExceptT LispError IO (Map String (IORef LispVal))
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Map String (IORef LispVal))
-> ExceptT LispError IO (Map String (IORef LispVal)))
-> IO (Map String (IORef LispVal))
-> ExceptT LispError IO (Map String (IORef LispVal))
forall a b. (a -> b) -> a -> b
$ IORef (Map String (IORef LispVal))
-> IO (Map String (IORef LispVal))
forall a. IORef a -> IO a
readIORef (IORef (Map String (IORef LispVal))
-> IO (Map String (IORef LispVal)))
-> IORef (Map String (IORef LispVal))
-> IO (Map String (IORef LispVal))
forall a b. (a -> b) -> a -> b
$ Env -> IORef (Map String (IORef LispVal))
bindings Env
envRef
case String -> Map String (IORef LispVal) -> Maybe (IORef LispVal)
forall k a. Ord k => k -> Map k a -> Maybe a
Data.Map.lookup (Char -> String -> String
getVarName Char
namespace String
var) Map String (IORef LispVal)
env of
(Just IORef LispVal
a) -> do
LispVal
v <- IO LispVal -> IOThrowsError LispVal
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO LispVal -> IOThrowsError LispVal)
-> IO LispVal -> IOThrowsError LispVal
forall a b. (a -> b) -> a -> b
$ IORef LispVal -> IO LispVal
forall a. IORef a -> IO a
readIORef IORef LispVal
a
if LispVal -> Bool
isObject LispVal
v
then do
Map String (IORef [LispVal])
ptrs <- IO (Map String (IORef [LispVal]))
-> ExceptT LispError IO (Map String (IORef [LispVal]))
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Map String (IORef [LispVal]))
-> ExceptT LispError IO (Map String (IORef [LispVal])))
-> IO (Map String (IORef [LispVal]))
-> ExceptT LispError IO (Map String (IORef [LispVal]))
forall a b. (a -> b) -> a -> b
$ IORef (Map String (IORef [LispVal]))
-> IO (Map String (IORef [LispVal]))
forall a. IORef a -> IO a
readIORef (IORef (Map String (IORef [LispVal]))
-> IO (Map String (IORef [LispVal])))
-> IORef (Map String (IORef [LispVal]))
-> IO (Map String (IORef [LispVal]))
forall a b. (a -> b) -> a -> b
$ Env -> IORef (Map String (IORef [LispVal]))
pointers Env
envRef
case String -> Map String (IORef [LispVal]) -> Maybe (IORef [LispVal])
forall k a. Ord k => k -> Map k a -> Maybe a
Data.Map.lookup (Char -> String -> String
getVarName Char
namespace String
var) Map String (IORef [LispVal])
ptrs of
(Just IORef [LispVal]
valueRef) -> IO LispVal -> IOThrowsError LispVal
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO LispVal -> IOThrowsError LispVal)
-> IO LispVal -> IOThrowsError LispVal
forall a b. (a -> b) -> a -> b
$ do
[LispVal]
value <- IORef [LispVal] -> IO [LispVal]
forall a. IORef a -> IO a
readIORef IORef [LispVal]
valueRef
IORef [LispVal] -> [LispVal] -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef [LispVal]
valueRef ([LispVal]
value [LispVal] -> [LispVal] -> [LispVal]
forall a. [a] -> [a] -> [a]
++ [String -> Env -> LispVal
Pointer String
ptrVar Env
ptrEnvRef])
LispVal -> IO LispVal
forall (m :: * -> *) a. Monad m => a -> m a
return (LispVal -> IO LispVal) -> LispVal -> IO LispVal
forall a b. (a -> b) -> a -> b
$ String -> Env -> LispVal
Pointer String
var Env
envRef
Maybe (IORef [LispVal])
Nothing -> IO LispVal -> IOThrowsError LispVal
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO LispVal -> IOThrowsError LispVal)
-> IO LispVal -> IOThrowsError LispVal
forall a b. (a -> b) -> a -> b
$ do
IORef [LispVal]
valueRef <- [LispVal] -> IO (IORef [LispVal])
forall a. a -> IO (IORef a)
newIORef [String -> Env -> LispVal
Pointer String
ptrVar Env
ptrEnvRef]
IORef (Map String (IORef [LispVal]))
-> Map String (IORef [LispVal]) -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef (Env -> IORef (Map String (IORef [LispVal]))
pointers Env
envRef) (String
-> IORef [LispVal]
-> Map String (IORef [LispVal])
-> Map String (IORef [LispVal])
forall k a. Ord k => k -> a -> Map k a -> Map k a
Data.Map.insert (Char -> String -> String
getVarName Char
namespace String
var) IORef [LispVal]
valueRef Map String (IORef [LispVal])
ptrs)
LispVal -> IO LispVal
forall (m :: * -> *) a. Monad m => a -> m a
return (LispVal -> IO LispVal) -> LispVal -> IO LispVal
forall a b. (a -> b) -> a -> b
$ String -> Env -> LispVal
Pointer String
var Env
envRef
else LispVal -> IOThrowsError LispVal
forall (m :: * -> *) a. Monad m => a -> m a
return LispVal
v
Maybe (IORef LispVal)
Nothing -> case Env -> Maybe Env
parentEnv Env
envRef of
(Just Env
par) -> Char
-> String -> Env -> Char -> String -> Env -> IOThrowsError LispVal
addReversePointer Char
namespace String
var Env
par Char
ptrNamespace String
ptrVar Env
ptrEnvRef
Maybe Env
Nothing -> LispError -> IOThrowsError LispVal
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError (LispError -> IOThrowsError LispVal)
-> LispError -> IOThrowsError LispVal
forall a b. (a -> b) -> a -> b
$ String -> String -> LispError
UnboundVar String
"Getting an unbound variable: " String
var
derefPtr :: LispVal -> IOThrowsError LispVal
derefPtr :: LispVal -> IOThrowsError LispVal
derefPtr (Pointer String
p Env
env) = do
LispVal
result <- Env -> String -> IOThrowsError LispVal
getVar Env
env String
p
LispVal -> IOThrowsError LispVal
derefPtr LispVal
result
derefPtr LispVal
v = LispVal -> IOThrowsError LispVal
forall (m :: * -> *) a. Monad m => a -> m a
return LispVal
v
recDerefPtrs :: LispVal -> IOThrowsError LispVal
recDerefPtrs :: LispVal -> IOThrowsError LispVal
recDerefPtrs = [LispVal] -> LispVal -> IOThrowsError LispVal
safeRecDerefPtrs []
safeRecDerefPtrs :: [LispVal] -> LispVal -> IOThrowsError LispVal
#ifdef UsePointers
safeRecDerefPtrs :: [LispVal] -> LispVal -> IOThrowsError LispVal
safeRecDerefPtrs [LispVal]
ps (List [LispVal]
l) = do
[LispVal]
result <- (LispVal -> IOThrowsError LispVal)
-> [LispVal] -> ExceptT LispError IO [LispVal]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM ([LispVal] -> LispVal -> IOThrowsError LispVal
safeRecDerefPtrs [LispVal]
ps) [LispVal]
l
LispVal -> IOThrowsError LispVal
forall (m :: * -> *) a. Monad m => a -> m a
return (LispVal -> IOThrowsError LispVal)
-> LispVal -> IOThrowsError LispVal
forall a b. (a -> b) -> a -> b
$ [LispVal] -> LispVal
List [LispVal]
result
safeRecDerefPtrs [LispVal]
ps (DottedList [LispVal]
ls LispVal
l) = do
[LispVal]
ds <- (LispVal -> IOThrowsError LispVal)
-> [LispVal] -> ExceptT LispError IO [LispVal]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM ([LispVal] -> LispVal -> IOThrowsError LispVal
safeRecDerefPtrs [LispVal]
ps) [LispVal]
ls
LispVal
d <- [LispVal] -> LispVal -> IOThrowsError LispVal
safeRecDerefPtrs [LispVal]
ps LispVal
l
LispVal -> IOThrowsError LispVal
forall (m :: * -> *) a. Monad m => a -> m a
return (LispVal -> IOThrowsError LispVal)
-> LispVal -> IOThrowsError LispVal
forall a b. (a -> b) -> a -> b
$ [LispVal] -> LispVal -> LispVal
DottedList [LispVal]
ds LispVal
d
safeRecDerefPtrs [LispVal]
ps (Vector Array Int LispVal
v) = do
let vs :: [LispVal]
vs = Array Int LispVal -> [LispVal]
forall i e. Array i e -> [e]
elems Array Int LispVal
v
[LispVal]
ds <- (LispVal -> IOThrowsError LispVal)
-> [LispVal] -> ExceptT LispError IO [LispVal]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM ([LispVal] -> LispVal -> IOThrowsError LispVal
safeRecDerefPtrs [LispVal]
ps) [LispVal]
vs
LispVal -> IOThrowsError LispVal
forall (m :: * -> *) a. Monad m => a -> m a
return (LispVal -> IOThrowsError LispVal)
-> LispVal -> IOThrowsError LispVal
forall a b. (a -> b) -> a -> b
$ Array Int LispVal -> LispVal
Vector (Array Int LispVal -> LispVal) -> Array Int LispVal -> LispVal
forall a b. (a -> b) -> a -> b
$ (Int, Int) -> [LispVal] -> Array Int LispVal
forall i e. Ix i => (i, i) -> [e] -> Array i e
listArray (Int
0, [LispVal] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [LispVal]
vs Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) [LispVal]
ds
safeRecDerefPtrs [LispVal]
ps (HashTable Map LispVal LispVal
ht) = do
[LispVal]
ks <- (LispVal -> IOThrowsError LispVal)
-> [LispVal] -> ExceptT LispError IO [LispVal]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM ([LispVal] -> LispVal -> IOThrowsError LispVal
safeRecDerefPtrs [LispVal]
ps)([LispVal] -> ExceptT LispError IO [LispVal])
-> [LispVal] -> ExceptT LispError IO [LispVal]
forall a b. (a -> b) -> a -> b
$ ((LispVal, LispVal) -> LispVal)
-> [(LispVal, LispVal)] -> [LispVal]
forall a b. (a -> b) -> [a] -> [b]
map (\ (LispVal
k, LispVal
_) -> LispVal
k) ([(LispVal, LispVal)] -> [LispVal])
-> [(LispVal, LispVal)] -> [LispVal]
forall a b. (a -> b) -> a -> b
$ Map LispVal LispVal -> [(LispVal, LispVal)]
forall k a. Map k a -> [(k, a)]
Data.Map.toList Map LispVal LispVal
ht
[LispVal]
vs <- (LispVal -> IOThrowsError LispVal)
-> [LispVal] -> ExceptT LispError IO [LispVal]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM ([LispVal] -> LispVal -> IOThrowsError LispVal
safeRecDerefPtrs [LispVal]
ps)([LispVal] -> ExceptT LispError IO [LispVal])
-> [LispVal] -> ExceptT LispError IO [LispVal]
forall a b. (a -> b) -> a -> b
$ ((LispVal, LispVal) -> LispVal)
-> [(LispVal, LispVal)] -> [LispVal]
forall a b. (a -> b) -> [a] -> [b]
map (\ (LispVal
_, LispVal
v) -> LispVal
v) ([(LispVal, LispVal)] -> [LispVal])
-> [(LispVal, LispVal)] -> [LispVal]
forall a b. (a -> b) -> a -> b
$ Map LispVal LispVal -> [(LispVal, LispVal)]
forall k a. Map k a -> [(k, a)]
Data.Map.toList Map LispVal LispVal
ht
LispVal -> IOThrowsError LispVal
forall (m :: * -> *) a. Monad m => a -> m a
return (LispVal -> IOThrowsError LispVal)
-> LispVal -> IOThrowsError LispVal
forall a b. (a -> b) -> a -> b
$ Map LispVal LispVal -> LispVal
HashTable (Map LispVal LispVal -> LispVal) -> Map LispVal LispVal -> LispVal
forall a b. (a -> b) -> a -> b
$ [(LispVal, LispVal)] -> Map LispVal LispVal
forall k a. Ord k => [(k, a)] -> Map k a
Data.Map.fromList ([(LispVal, LispVal)] -> Map LispVal LispVal)
-> [(LispVal, LispVal)] -> Map LispVal LispVal
forall a b. (a -> b) -> a -> b
$ [LispVal] -> [LispVal] -> [(LispVal, LispVal)]
forall a b. [a] -> [b] -> [(a, b)]
zip [LispVal]
ks [LispVal]
vs
#endif
safeRecDerefPtrs [LispVal]
ps ptr :: LispVal
ptr@(Pointer String
p Env
env) = do
if [LispVal] -> LispVal -> Bool
containsPtr [LispVal]
ps LispVal
ptr
then LispVal -> IOThrowsError LispVal
forall (m :: * -> *) a. Monad m => a -> m a
return LispVal
ptr
else do
LispVal
result <- Env -> String -> IOThrowsError LispVal
getVar Env
env String
p
[LispVal] -> LispVal -> IOThrowsError LispVal
safeRecDerefPtrs (LispVal
ptr LispVal -> [LispVal] -> [LispVal]
forall a. a -> [a] -> [a]
: [LispVal]
ps) LispVal
result
safeRecDerefPtrs [LispVal]
_ LispVal
v = LispVal -> IOThrowsError LispVal
forall (m :: * -> *) a. Monad m => a -> m a
return LispVal
v
containsPtr :: [LispVal] -> LispVal -> Bool
containsPtr :: [LispVal] -> LispVal -> Bool
containsPtr ((Pointer String
pa Env
ea):[LispVal]
ps) p :: LispVal
p@(Pointer String
pb Env
eb) = do
let found :: Bool
found = (String
pa String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
pb) Bool -> Bool -> Bool
&& ((Env -> IORef (Map String (IORef LispVal))
bindings Env
ea) IORef (Map String (IORef LispVal))
-> IORef (Map String (IORef LispVal)) -> Bool
forall a. Eq a => a -> a -> Bool
== (Env -> IORef (Map String (IORef LispVal))
bindings Env
eb))
Bool
found Bool -> Bool -> Bool
|| [LispVal] -> LispVal -> Bool
containsPtr [LispVal]
ps LispVal
p
containsPtr [LispVal]
_ LispVal
_ = Bool
False
recDerefToFnc :: ([LispVal] -> ThrowsError LispVal) -> [LispVal]
-> IOThrowsError LispVal
recDerefToFnc :: ([LispVal] -> ThrowsError LispVal)
-> [LispVal] -> IOThrowsError LispVal
recDerefToFnc [LispVal] -> ThrowsError LispVal
fnc [LispVal]
lvs = do
List [LispVal]
result <- LispVal -> IOThrowsError LispVal
recDerefPtrs (LispVal -> IOThrowsError LispVal)
-> LispVal -> IOThrowsError LispVal
forall a b. (a -> b) -> a -> b
$ [LispVal] -> LispVal
List [LispVal]
lvs
ThrowsError LispVal -> IOThrowsError LispVal
forall a. ThrowsError a -> IOThrowsError a
liftThrows (ThrowsError LispVal -> IOThrowsError LispVal)
-> ThrowsError LispVal -> IOThrowsError LispVal
forall a b. (a -> b) -> a -> b
$ [LispVal] -> ThrowsError LispVal
fnc [LispVal]
result
isObject :: LispVal -> Bool
isObject :: LispVal -> Bool
isObject (List [LispVal]
_) = Bool
True
isObject (DottedList [LispVal]
_ LispVal
_) = Bool
True
isObject (String String
_) = Bool
True
isObject (Vector Array Int LispVal
_) = Bool
True
isObject (HashTable Map LispVal LispVal
_) = Bool
True
isObject (ByteVector ByteString
_) = Bool
True
isObject (Pointer String
_ Env
_) = Bool
True
isObject LispVal
_ = Bool
False
findPointerTo :: LispVal -> IOThrowsError LispVal
findPointerTo :: LispVal -> IOThrowsError LispVal
findPointerTo ptr :: LispVal
ptr@(Pointer String
p Env
env) = do
LispVal
result <- Env -> String -> IOThrowsError LispVal
getVar Env
env String
p
case LispVal
result of
(Pointer String
_ Env
_) -> LispVal -> IOThrowsError LispVal
findPointerTo LispVal
result
LispVal
_ -> LispVal -> IOThrowsError LispVal
forall (m :: * -> *) a. Monad m => a -> m a
return LispVal
ptr
findPointerTo LispVal
v = LispVal -> IOThrowsError LispVal
forall (m :: * -> *) a. Monad m => a -> m a
return LispVal
v