/src/Hummus/Prelude.hs

http://github.com/vito/hummus · Haskell · 313 lines · 229 code · 83 blank · 1 comment · 13 complexity · 8a56f99751989632333840ca26ca22a1 MD5 · raw file

  1. {-# LANGUAGE RankNTypes #-}
  2. module Hummus.Prelude where
  3. import Control.Monad
  4. import Control.Monad.CC
  5. import Control.Monad.CC.Dynvar
  6. import Control.Monad.Trans
  7. import Data.Attoparsec
  8. import Data.IORef
  9. import Data.Time
  10. import qualified Data.ByteString as BS
  11. import Hummus.Types
  12. import Hummus.Parser
  13. import Hummus.Runtime
  14. import Paths_hummus
  15. new :: VM ans (Value ans)
  16. new = do
  17. env <- newEnvironment []
  18. defn env "make-encapsulation-type" $ \Null _ -> do
  19. i <- liftIO (newIORef ())
  20. let cons =
  21. Applicative . CoreOperative $ \(Pair a Null) _ -> do
  22. vr <- liftIO (newIORef a)
  23. return Encapsulation { eID = i, eValue = vr }
  24. test =
  25. Applicative . CoreOperative $ \(Pair a Null) _ ->
  26. case a of
  27. Encapsulation { eID = eid } -> return (Boolean (eid == i))
  28. _ -> return (Boolean False)
  29. decons =
  30. Applicative . CoreOperative $ \(Pair a Null) _ ->
  31. case a of
  32. Encapsulation { eID = eid, eValue = vr } | eid == i ->
  33. liftIO (readIORef vr)
  34. _ -> error "encapsulation type mismatch"
  35. return (Pair cons (Pair test (Pair decons Null)))
  36. defn env "reset" $ \(Pair b _) e ->
  37. reset $ \p ->
  38. apply e b (Pair (Prompt p) Null)
  39. defn env "make-dynvar" $ \(Pair a _) _ ->
  40. liftM (flip Dynvar a) dnew
  41. defn env "put!" $ \(Pair (Dynvar d _) (Pair b Null)) _ ->
  42. dset d b
  43. def env "with" $ \(Pair as bs) e -> do
  44. letDyn e (map toList (toList as)) (toList bs)
  45. defn env "shift" $ \(Pair a (Pair b _)) e -> do
  46. Prompt p <- evaluate e a
  47. shift p $ \f ->
  48. let app = Applicative . CoreOperative $ \(Pair x _) _ -> f (return x)
  49. in apply e b (Pair app Null)
  50. defn env "control" $ \(Pair a (Pair b _)) e -> do
  51. Prompt p <- evaluate e a
  52. control p $ \f ->
  53. let app = Applicative . CoreOperative $ \(Pair x _) _ -> f (return x)
  54. in apply e b (Pair app Null)
  55. defn env "shift0" $ \(Pair a (Pair b _)) e -> do
  56. Prompt p <- evaluate e a
  57. shift0 p $ \f ->
  58. let app = Applicative . CoreOperative $ \(Pair x _) _ -> f (return x)
  59. in apply e b (Pair app Null)
  60. defn env "control0" $ \(Pair a (Pair b _)) e -> do
  61. Prompt p <- evaluate e a
  62. control0 p $ \f ->
  63. let app = Applicative . CoreOperative $ \(Pair x _) _ -> f (return x)
  64. in apply e b (Pair app Null)
  65. def env "abort" $ \(Pair a (Pair b _)) e -> do
  66. Prompt p <- evaluate e a
  67. abort p (evaluate e b)
  68. defn env "boolean?" $ \(Pair a _) _ ->
  69. return (Boolean (isBoolean a))
  70. defn env "eq?" $ \(Pair a (Pair b _)) _ ->
  71. return (Boolean (a == b))
  72. evaluate env (Symbol "eq?") >>= define env (Symbol "equal?")
  73. defn env "symbol?" $ \(Pair a _) _ ->
  74. return (Boolean (isSymbol a))
  75. defn env "string?" $ \(Pair a _) _ ->
  76. return (Boolean (isString a))
  77. defn env "subcontinuation?" $ \(Pair a _) _ ->
  78. return (Boolean (isSubContinuation a))
  79. defn env "prompt?" $ \(Pair a _) _ ->
  80. return (Boolean (isPrompt a))
  81. defn env "inert?" $ \(Pair a _) _ ->
  82. return (Boolean (isInert a))
  83. defn env "pair?" $ \(Pair a _) _ ->
  84. return (Boolean (isPair a))
  85. defn env "null?" $ \(Pair a _) _ ->
  86. return (Boolean (isNull a))
  87. defn env "cons" $ \(Pair a (Pair b _)) _ ->
  88. return (Pair a b)
  89. def env "if" $ \(Pair a (Pair b (Pair c _))) e -> do
  90. t <- evaluate e a
  91. case t of
  92. Boolean True ->
  93. evaluate e b
  94. Boolean False ->
  95. evaluate e c
  96. _ -> error ("not a boolean: " ++ show t)
  97. defn env "environment?" $ \(Pair a _) _ ->
  98. return (Boolean (isEnvironment a))
  99. defn env "ignore?" $ \(Pair a _) _ ->
  100. return (Boolean (isIgnore a))
  101. defn env "number?" $ \(Pair a _) _ ->
  102. return (Boolean (isNumber a))
  103. defn env "eval" $ \(Pair a (Pair b _)) _ ->
  104. evaluate b a
  105. defn env "make-environment" $ \parents _ ->
  106. newEnvironment (toList parents)
  107. def env "binds?" $ \(Pair a bs) e -> do
  108. e' <- evaluate e a
  109. ss <- mapM (\(Symbol s) -> binds e' s) (toList bs)
  110. return (Boolean (and ss))
  111. def env "define" $ \(Pair a (Pair b _)) e -> do
  112. v <- evaluate e b
  113. define e a v
  114. return Inert
  115. defn env "operative?" $ \(Pair a _) _ ->
  116. return (Boolean (isOperative a))
  117. defn env "applicative?" $ \(Pair a _) _ ->
  118. return (Boolean (isApplicative a))
  119. defn env "dynvar?" $ \(Pair a _) _ ->
  120. return (Boolean (isDynvar a))
  121. defn env "combiner?" $ \as _ ->
  122. return (Boolean (and (map isCombiner (toList as))))
  123. def env "vau" $ \(Pair a (Pair b (Pair c _))) e ->
  124. return (Operative a b c (Just e))
  125. defn env "wrap" $ \(Pair a _) _ ->
  126. return (Applicative a)
  127. defn env "unwrap" $ \(Pair a _) _ ->
  128. case a of
  129. Applicative c -> return c
  130. _ -> error ("not an applicative: " ++ show a)
  131. defn env "make-prompt" $ \Null _ -> do
  132. x <- newPrompt
  133. return (Prompt x)
  134. def env "push-prompt" $ \(Pair a bs) e -> do
  135. Prompt p <- evaluate e a
  136. pushPrompt p (evaluateSequence e (toList bs))
  137. defn env "with-sub-cont" $ \(Pair (Prompt p) (Pair x Null)) e -> do
  138. withSubCont p $ \s ->
  139. apply e x (Pair (SubContinuation s) Null)
  140. defn env "push-sub-cont" $ \(Pair a bs) e -> do
  141. SubContinuation s <- evaluate e a
  142. pushSubCont s (evaluateSequence e (toList bs))
  143. defn env "=?" $ \as _ ->
  144. let allEq (a:b:cs) = a == b && allEq (b:cs)
  145. allEq _ = True
  146. in return (Boolean (allEq (toList as)))
  147. defn env "max" $ \as _ ->
  148. let nums = map (\(Number n) -> n) (toList as)
  149. in return (Number (maximum nums))
  150. defn env "<?" $ \(Pair (Number a) (Pair (Number b) _)) _ ->
  151. return (Boolean (a < b))
  152. defn env ">?" $ \(Pair (Number a) (Pair (Number b) _)) _ ->
  153. return (Boolean (a > b))
  154. defn env "<=?" $ \(Pair (Number a) (Pair (Number b) _)) _ ->
  155. return (Boolean (a <= b))
  156. defn env ">=?" $ \(Pair (Number a) (Pair (Number b) _)) _ ->
  157. return (Boolean (a >= b))
  158. defn env "+" $ \as _ ->
  159. let nums = map (\(Number n) -> n) (toList as)
  160. in return (Number (sum nums))
  161. defn env "*" $ \as _ ->
  162. let nums = map (\(Number n) -> n) (toList as)
  163. in return (Number (product nums))
  164. defn env "-" $ \(Pair (Number a) (Pair (Number b) _)) _ ->
  165. return (Number (a - b))
  166. defn env "print" $ \(Pair a _) _ -> do
  167. case a of
  168. String s -> liftIO (putStrLn s)
  169. _ -> liftIO (print a)
  170. return Inert
  171. defn env "display" $ \(Pair a _) _ -> do
  172. case a of
  173. String s -> liftIO (putStr s)
  174. _ -> liftIO (putStr (show a))
  175. return Inert
  176. defn env "write" $ \(Pair a _) _ -> do
  177. liftIO (print a)
  178. return Inert
  179. defn env "show" $ \(Pair a _) _ ->
  180. return (String (show a))
  181. def env "time" $ \(Pair a _) e -> do
  182. before <- liftIO getCurrentTime
  183. x <- evaluate e a
  184. after <- liftIO getCurrentTime
  185. liftIO (print x)
  186. liftIO (print (diffUTCTime after before))
  187. return Inert
  188. def env "loop" $ \as e ->
  189. forever $ evaluateSequence e (toList as)
  190. defn env "get-hummus-data-file" $ \(Pair (String fn) _) _ -> do
  191. liftM String (liftIO (getDataFileName fn))
  192. defn env "load" $ \(Pair (String fn) _) e -> do
  193. source <- liftIO (BS.readFile fn)
  194. case parseOnly sexps source of
  195. Right ss ->
  196. evaluateSequence e ss
  197. Left msg ->
  198. error msg
  199. defn env "string->symbol" $ \(Pair (String s) _) _ ->
  200. return (Symbol s)
  201. defn env "symbol->string" $ \(Pair (Symbol s) _) _ ->
  202. return (String s)
  203. defn env "join" $ \as _ ->
  204. return (String (concatMap (\(String s) -> s) (toList as)))
  205. bootFile <- liftIO (getDataFileName "kernel/boot.hms")
  206. boot <- liftIO (BS.readFile bootFile)
  207. case parseOnly sexps boot of
  208. Right ss ->
  209. mapM_ (evaluate env) ss
  210. Left e ->
  211. error e
  212. return env
  213. where
  214. def :: Value ans -> String -> (Value ans -> Value ans -> VM ans (Value ans)) -> VM ans ()
  215. def e n f = define e (Symbol n) (CoreOperative f)
  216. defn :: Value ans -> String -> (Value ans -> Value ans -> VM ans (Value ans)) -> VM ans ()
  217. defn e n f = define e (Symbol n) (Applicative $ CoreOperative f)
  218. letDyn :: Value ans -> [[Value ans]] -> [Value ans] -> VM ans (Value ans)
  219. letDyn e [] bs = evaluateSequence e bs
  220. letDyn e ([a, b]:as) bs = do
  221. Dynvar d _ <- evaluate e a
  222. v <- evaluate e b
  223. dlet d v (letDyn e as bs)
  224. letDyn _ (p:_) _ = error $ "unknown pair: " ++ show p
  225. fromGround :: (Value ans -> VM ans (Value ans)) -> VM ans (Value ans)
  226. fromGround x = do
  227. e <- new
  228. reset $ \root -> do
  229. define e (Symbol "root-prompt") (Prompt root)
  230. x e