aboutsummaryrefslogtreecommitdiff
path: root/haskell/Core.hs
diff options
context:
space:
mode:
Diffstat (limited to 'haskell/Core.hs')
-rw-r--r--haskell/Core.hs104
1 files changed, 57 insertions, 47 deletions
diff --git a/haskell/Core.hs b/haskell/Core.hs
index 4bb5517..d1034c1 100644
--- a/haskell/Core.hs
+++ b/haskell/Core.hs
@@ -2,7 +2,9 @@ module Core
( ns )
where
+import System.IO (hFlush, stdout)
import Control.Exception (catch)
+import Control.Monad.Trans (liftIO)
import qualified Data.Map as Map
import Data.Time.Clock.POSIX (getPOSIXTime)
import Data.IORef (IORef, newIORef, readIORef, writeIORef)
@@ -15,23 +17,28 @@ import Printer (_pr_str, _pr_list)
-- General functions
equal_Q [a, b] = return $ if a == b then MalTrue else MalFalse
-equal_Q _ = error $ "illegal arguments to ="
+equal_Q _ = throwStr "illegal arguments to ="
-run_1 :: (MalVal -> MalVal) -> [MalVal] -> IO MalVal
+run_1 :: (MalVal -> MalVal) -> [MalVal] -> IOThrows MalVal
run_1 f (x:[]) = return $ f x
-run_1 _ _ = error $ "function takes a single argument"
+run_1 _ _ = throwStr "function takes a single argument"
-run_2 :: (MalVal -> MalVal -> MalVal) -> [MalVal] -> IO MalVal
+run_2 :: (MalVal -> MalVal -> MalVal) -> [MalVal] -> IOThrows MalVal
run_2 f (x:y:[]) = return $ f x y
-run_2 _ _ = error $ "function takes a two arguments"
+run_2 _ _ = throwStr "function takes a two arguments"
+
+-- Error/Exception functions
+
+throw (mv:[]) = throwMalVal mv
+throw _ = throwStr "illegal arguments to throw"
-- Scalar functions
-symbol (MalString str) = MalSymbol str
-symbol _ = error $ "symbol called with non-string"
+symbol (MalString str:[]) = return $ MalSymbol str
+symbol _ = throwStr "symbol called with non-string"
-keyword (MalString str) = MalString $ "\x029e" ++ str
-keyword _ = error $ "keyword called with non-string"
+keyword (MalString str:[]) = return $ MalString $ "\x029e" ++ str
+keyword _ = throwStr "keyword called with non-string"
-- String functions
@@ -43,37 +50,39 @@ str args = do
return $ MalString $ _pr_list False "" args
prn args = do
- putStrLn $ _pr_list True " " args
+ liftIO $ putStrLn $ _pr_list True " " args
+ liftIO $ hFlush stdout
return Nil
println args = do
- putStrLn $ _pr_list False " " args
+ liftIO $ putStrLn $ _pr_list False " " args
+ liftIO $ hFlush stdout
return Nil
slurp ([MalString path]) = do
- str <- readFile path
+ str <- liftIO $ readFile path
return $ MalString str
-slurp _ = error $ "invalid arguments to slurp"
+slurp _ = throwStr "invalid arguments to slurp"
do_readline ([MalString prompt]) = do
- str <- readline prompt
+ str <- liftIO $ readline prompt
case str of
- Nothing -> error "readline failed"
+ Nothing -> throwStr "readline failed"
Just str -> return $ MalString str
-do_readline _ = error $ "invalid arguments to readline"
+do_readline _ = throwStr "invalid arguments to readline"
-- Numeric functions
num_op op [MalNumber a, MalNumber b] = do
return $ MalNumber $ op a b
-num_op _ _ = error $ "illegal arguments to number operation"
+num_op _ _ = throwStr "illegal arguments to number operation"
cmp_op op [MalNumber a, MalNumber b] = do
return $ if op a b then MalTrue else MalFalse
-cmp_op _ _ = error $ "illegal arguments to comparison operation"
+cmp_op _ _ = throwStr "illegal arguments to comparison operation"
time_ms _ = do
- t <- getPOSIXTime
+ t <- liftIO $ getPOSIXTime
return $ MalNumber $ round (t * 1000)
@@ -87,7 +96,7 @@ vector args = return $ MalVector args Nil
-- Hash Map functions
-_pairup [x] = error "Odd number of elements to _pairup"
+_pairup [x] = throwStr "Odd number of elements to _pairup"
_pairup [] = return []
_pairup (MalString x:y:xs) = do
rest <- _pairup xs
@@ -100,33 +109,33 @@ hash_map args = do
assoc (MalHashMap hm _:kvs) = do
pairs <- _pairup kvs
return $ MalHashMap (Map.union (Map.fromList pairs) hm) Nil
-assoc _ = error $ "invalid call to assoc"
+assoc _ = throwStr "invalid call to assoc"
dissoc (MalHashMap hm _:ks) = do
let remover = (\hm (MalString k) -> Map.delete k hm) in
return $ MalHashMap (foldl remover hm ks) Nil
-dissoc _ = error $ "invalid call to dissoc"
+dissoc _ = throwStr "invalid call to dissoc"
get (MalHashMap hm _:MalString k:[]) = do
case Map.lookup k hm of
Just mv -> return mv
Nothing -> return Nil
get (Nil:MalString k:[]) = return Nil
-get _ = error $ "invalid call to get"
+get _ = throwStr "invalid call to get"
contains_Q (MalHashMap hm _:MalString k:[]) = do
if Map.member k hm then return MalTrue
else return MalFalse
contains_Q (Nil:MalString k:[]) = return MalFalse
-contains_Q _ = error $ "invalid call to contains?"
+contains_Q _ = throwStr "invalid call to contains?"
keys (MalHashMap hm _:[]) = do
return $ MalList (map MalString (Map.keys hm)) Nil
-keys _ = error $ "invalid call to keys"
+keys _ = throwStr "invalid call to keys"
vals (MalHashMap hm _:[]) = do
return $ MalList (Map.elems hm) Nil
-vals _ = error $ "invalid call to vals"
+vals _ = throwStr "invalid call to vals"
-- Sequence functions
@@ -145,11 +154,11 @@ do_concat args = return $ MalList (foldl concat1 [] args) Nil
nth ((MalList lst _):(MalNumber idx):[]) = do
if idx < length lst then return $ lst !! idx
- else error "nth: index out of range"
+ else throwStr "nth: index out of range"
nth ((MalVector lst _):(MalNumber idx):[]) = do
if idx < length lst then return $ lst !! idx
- else error "nth: index out of range"
-nth _ = error "invalid call to nth"
+ else throwStr "nth: index out of range"
+nth _ = throwStr "invalid call to nth"
first (MalList lst _) = if length lst > 0 then lst !! 0 else Nil
first (MalVector lst _) = if length lst > 0 then lst !! 0 else Nil
@@ -162,14 +171,14 @@ empty_Q (MalList [] _) = MalTrue
empty_Q (MalVector [] _) = MalTrue
empty_Q _ = MalFalse
-count Nil = MalNumber 0
-count (MalList lst _) = MalNumber $ length lst
-count (MalVector lst _) = MalNumber $ length lst
-count _ = error $ "non-sequence passed to count"
+count (Nil:[]) = return $ MalNumber 0
+count (MalList lst _:[]) = return $ MalNumber $ length lst
+count (MalVector lst _:[]) = return $ MalNumber $ length lst
+count _ = throwStr $ "non-sequence passed to count"
conj ((MalList lst _):args) = return $ MalList ((reverse args) ++ lst) Nil
conj ((MalVector lst _):args) = return $ MalVector (lst ++ args) Nil
-conj _ = error $ "illegal arguments to conj"
+conj _ = throwStr $ "illegal arguments to conj"
apply args = do
f <- _get_call args
@@ -191,7 +200,7 @@ with_meta ((MalAtom atm _):m:[]) = return $ MalAtom atm m
with_meta ((Func f _):m:[]) = return $ Func f m
with_meta ((MalFunc {fn=f, ast=a, env=e, params=p, macro=mc}):m:[]) = do
return $ MalFunc {fn=f, ast=a, env=e, params=p, macro=mc, meta=m}
-with_meta _ = error $ "invalid with-meta call"
+with_meta _ = throwStr $ "invalid with-meta call"
do_meta ((MalList _ m):[]) = return m
do_meta ((MalVector _ m):[]) = return m
@@ -199,40 +208,41 @@ do_meta ((MalHashMap _ m):[]) = return m
do_meta ((MalAtom _ m):[]) = return m
do_meta ((Func _ m):[]) = return m
do_meta ((MalFunc {meta=m}):[]) = return m
-do_meta _ = error $ "invalid meta call"
+do_meta _ = throwStr $ "invalid meta call"
-- Atom functions
atom (val:[]) = do
- ref <- newIORef val
+ ref <- liftIO $ newIORef val
return $ MalAtom ref Nil
-atom _ = error "invalid atom call"
+atom _ = throwStr "invalid atom call"
deref (MalAtom ref _:[]) = do
- val <- readIORef ref
+ val <- liftIO $ readIORef ref
return val
-deref _ = error "invalid deref call"
+deref _ = throwStr "invalid deref call"
reset_BANG (MalAtom ref _:val:[]) = do
- _ <- writeIORef ref $ val
+ liftIO $ writeIORef ref $ val
return val
-reset_BANG _ = error "invalid deref call"
+reset_BANG _ = throwStr "invalid deref call"
swap_BANG (MalAtom ref _:args) = do
- val <- readIORef ref
+ val <- liftIO $ readIORef ref
f <- _get_call args
new_val <- f $ [val] ++ (tail args)
- _ <- writeIORef ref $ new_val
+ _ <- liftIO $ writeIORef ref $ new_val
return new_val
ns = [
("=", _func equal_Q),
+ ("throw", _func throw),
("nil?", _func $ run_1 $ _nil_Q),
("true?", _func $ run_1 $ _true_Q),
("false?", _func $ run_1 $ _false_Q),
- ("symbol", _func $ run_1 $ symbol),
+ ("symbol", _func $ symbol),
("symbol?", _func $ run_1 $ _symbol_Q),
- ("keyword", _func $ run_1 $ keyword),
+ ("keyword", _func $ keyword),
("keyword?", _func $ run_1 $ _keyword_Q),
("pr-str", _func pr_str),
@@ -273,7 +283,7 @@ ns = [
("first", _func $ run_1 $ first),
("rest", _func $ run_1 $ rest),
("empty?", _func $ run_1 $ empty_Q),
- ("count", _func $ run_1 $ count),
+ ("count", _func $ count),
("conj", _func $ conj),
("apply", _func $ apply),
("map", _func $ do_map),