/src/Hummus/Runtime.hs

http://github.com/vito/hummus · Haskell · 90 lines · 73 code · 17 blank · 0 comment · 9 complexity · d0aaf68962fa1a310eaf4fe33db3760b MD5 · raw file

  1. module Hummus.Runtime where
  2. import Control.Monad
  3. import Control.Monad.CC.Dynvar
  4. import Control.Monad.Trans
  5. import Data.Maybe (catMaybes, isJust)
  6. import qualified Data.HashTable.IO as H
  7. import Hummus.Types
  8. evaluate :: Value ans -> Value ans -> VM ans (Value ans)
  9. evaluate env (Pair a b) = do
  10. x <- evaluate env a
  11. if isCombiner x
  12. then apply env x b
  13. else error ("not a combiner: " ++ show x)
  14. evaluate env (Symbol s) = do
  15. mv <- fetch env s
  16. case mv of
  17. Just v -> return v
  18. Nothing -> error ("undefined: " ++ s)
  19. evaluate env o@(Operative { oStaticEnvironment = Nothing }) =
  20. return o { oStaticEnvironment = Just env }
  21. evaluate _ x = return x
  22. evaluateSequence :: Value ans -> [Value ans] -> VM ans (Value ans)
  23. evaluateSequence _ [] = return Inert
  24. evaluateSequence e [s] = evaluate e s
  25. evaluateSequence e (s:ss) = evaluate e s >> evaluateSequence e ss
  26. evaluateAll :: Value ans -> Value ans -> VM ans (Value ans)
  27. evaluateAll env (Pair a b) = do
  28. ea <- evaluate env a
  29. eb <- evaluateAll env b
  30. return (Pair ea eb)
  31. evaluateAll _ x = return x
  32. apply :: Value ans -> Value ans -> Value ans -> VM ans (Value ans)
  33. apply env (CoreOperative f) as = f as env
  34. apply env (Operative fs ef b se) as = do
  35. newEnv <- newEnvironment (catMaybes [se])
  36. define newEnv fs as
  37. define newEnv ef env
  38. evaluate newEnv b
  39. apply env (Applicative x) vs = do
  40. as <- evaluateAll env vs
  41. apply env x as
  42. apply _ (Dynvar d x) _ = liftM (maybe x id) (mdref d)
  43. apply _ v _ = error ("cannot apply: " ++ show v)
  44. define :: Value ans -> Value ans -> Value ans -> VM ans ()
  45. define env@(Environment ht _) p v =
  46. case p of
  47. Ignore -> return ()
  48. Symbol n -> liftIO (H.insert ht n v)
  49. Null ->
  50. case v of
  51. Null -> return ()
  52. _ -> error ("mismatch: " ++ show (p, v))
  53. Pair pa pb ->
  54. case v of
  55. Pair va vb -> do
  56. define env pa va
  57. define env pb vb
  58. _ -> error ("mismatch: " ++ show (p, v))
  59. _ -> error ("unknown pattern: " ++ show p)
  60. define _ _ _ = error "invalid definition target"
  61. binds :: Value ans -> String -> VM ans Bool
  62. binds e n = liftM isJust (fetch e n)
  63. fetch :: Value ans -> String -> VM ans (Maybe (Value ans))
  64. fetch (Environment ht ps) n = do
  65. l <- liftIO (H.lookup ht n)
  66. case l of
  67. Just v -> return (Just v)
  68. Nothing -> do
  69. up <- mapM (flip fetch n) ps
  70. case catMaybes up of
  71. (x:_) -> return (Just x)
  72. [] -> return Nothing
  73. fetch v n = error ("cannot fetch " ++ show n ++ " from " ++ show v)