Advertisement
Guest User

Untitled

a guest
Jul 22nd, 2019
57
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.04 KB | None | 0 0
  1. {-# LANGUAGE FlexibleContexts, LambdaCase #-}
  2.  
  3. module Scheme.Runtime where
  4.  
  5. import Scheme.Core
  6. import Scheme.Parse
  7. import Scheme.Eval
  8.  
  9. import qualified Data.HashMap.Strict as H
  10. import Text.ParserCombinators.Parsec hiding (Parser, State)
  11. import Control.Monad
  12. import Control.Monad.State
  13. import Control.Monad.Except
  14. import Data.Foldable
  15.  
  16. --- ### Helper functions for lifting and lowering
  17.  
  18. lowerBool :: Val -> Bool
  19. lowerBool (Boolean False) = False
  20. lowerBool _ = True
  21.  
  22. lowerInt :: Val -> EvalState Int
  23. lowerInt (Number i) = return i
  24. lowerInt v = throwError $ TypeError v
  25.  
  26. lowerList :: Val -> EvalState [Val]
  27. lowerList (List xx) = return xx
  28. lowerList v = throwError $ TypeError v
  29.  
  30. liftIntVargOp :: (Int -> Int -> Int) -> Int -> Val
  31. liftIntVargOp f c = PrimFunc p where
  32. p [] = return $ Number c
  33. p [x] = Number . f c <$> lowerInt x
  34. p xx = Number . foldl1 f <$> mapM lowerInt xx
  35.  
  36. liftBoolVargOp :: ([Bool] -> Bool) -> Val
  37. liftBoolVargOp f = PrimFunc $ return . Boolean . f . map lowerBool
  38.  
  39. liftIntBinOp :: (Int -> Int -> Int) -> Val
  40. liftIntBinOp f = PrimFunc p where
  41. p [Number x, Number y] = return $ Number $ f x y
  42. p v = throwError $ UnexpectedArgs v
  43.  
  44. liftIntUnaryOp :: (Int -> Int) -> Val
  45. liftIntUnaryOp f = PrimFunc p where
  46. p [Number x] = return $ Number $ f x
  47. p v = throwError $ UnexpectedArgs v
  48.  
  49. liftBoolUnaryOp :: (Bool -> Bool) -> Val
  50. liftBoolUnaryOp f = PrimFunc p where
  51. p [Boolean False] = return $ Boolean $ f False
  52. p [_] = return $ Boolean $ f True
  53. p v = throwError $ UnexpectedArgs v
  54.  
  55. liftCompOp :: (Int -> Int -> Bool) -> Val
  56. liftCompOp f = PrimFunc p where
  57. p [] = return $ Boolean True
  58. p xx = mapM lowerInt xx >>= \nums ->
  59. return . Boolean . and . map (uncurry f) $ zip nums (tail nums)
  60.  
  61. --- ### Primtive operations
  62.  
  63. -- Primitive function `car`
  64. car :: [Val] -> EvalState Val
  65. car [List (x:_)] = return x
  66. car [DottedList (x:_) _] = return x
  67. car vv = throwError $ UnexpectedArgs vv
  68.  
  69. -- Primitive function `cdr`
  70. cdr :: [Val] -> EvalState Val
  71. cdr [List (_:xs)] = return $ List xs
  72. cdr [DottedList [_] y] = return y
  73. cdr [DottedList (_:xs) y] = return $ DottedList xs y
  74. cdr vv = throwError $ UnexpectedArgs vv
  75.  
  76. -- Primitive function `cons`
  77. cons :: [Val] -> EvalState Val
  78. cons [x, y] = return $ DottedList [x] y
  79. cons vv = throwError $ UnexpectedArgs vv
  80.  
  81. -- Primitive function `append`
  82. append :: [Val] -> EvalState Val
  83. append [] = return $ List []
  84. append [x] = return x
  85. append vv = foldlM append' (List []) (map flattenList vv) where
  86. append' (List []) x = return x
  87. append' (List xs) (List ys) = return $ List (xs ++ ys)
  88. append' (List xs) (DottedList ys y) = return $ DottedList (xs ++ ys) y
  89. append' _ acc = throwError $ TypeError acc
  90.  
  91. -- Primitive function `apply`
  92. -- It applies a function to a list of parameters
  93. -- Examples:
  94. -- (apply + '(1 2 3)) => 6
  95. -- (apply car '((1 2 3))) => 1
  96. applyPrim :: [Val] -> EvalState Val
  97. applyPrim [f, args] = case flattenList args of
  98. List xx -> apply f xx
  99. v -> throwError $ TypeError v
  100. applyPrim vv = throwError $ UnexpectedArgs vv
  101.  
  102. -- Primitive function `eval`
  103. -- It evaluates the single argument as an expression
  104. -- All you have to do is to check the number of arguments and
  105. -- feed the single argument to the evaluator!
  106. -- Examples:
  107. -- (eval '(+ 1 2 3)) => 6
  108. evalPrim :: [Val] -> EvalState Val
  109. evalPrim [e] = eval e
  110. evalPrim vv = throwError $ UnexpectedArgs vv
  111.  
  112. -- Primitive function `=`, throwing type error for mismatch
  113. -- `=` is a comparison operator for numbers and booleans
  114. -- Examples:
  115. -- (= 1 1) => #t
  116. -- (= #f #t) => #f
  117. -- (= #f #f) => #t
  118. -- (= 'a 10) => Type error
  119. -- (= 'a 'b) => Type error
  120. equalSign :: [Val] -> EvalState Val
  121. equalSign [] = return $ Boolean True
  122. equalSign [x] = return $ Boolean True
  123. equalSign l@(x:xs) = equalSignTypeValid l >> equalSignVal l
  124. equalSignTypeValid :: [Val] -> EvalState Val
  125. equalSignTypeValid [] = return $ Boolean True
  126. equalSignTypeValid [x] = return $ Boolean True
  127. equalSignTypeValid l@(x:xs) =
  128. let same_type (a,b) = case (a,b) of
  129. ((Number _),(Number _)) -> return $ Boolean True
  130. ((Boolean _),(Boolean _)) -> return $ Boolean True
  131. (x,y) -> throwError $ TypeError y
  132. pairs = zip l (tail l)
  133. check_pairs [] = return $ Boolean True
  134. check_pairs ((a,b):xs) = same_type (a,b) >> check_pairs xs
  135. in check_pairs pairs
  136. equalSignVal :: [Val] -> EvalState Val
  137. equalSignVal [] = return $ Boolean True
  138. equalSignVal [x] = return $ Boolean True
  139. equalSignVal (x:xs) = Boolean <$> foldlM (equal' x) True xs where
  140. equal' _ False _ = return False
  141. equal' (Number a) _ (Number b) = return $ a == b
  142. equal' (Boolean a) _ (Boolean b) = return $ a == b
  143. equal' y _ _ = throwError $ TypeError y
  144.  
  145. -- Primitive function `eq?`, not throwing any error
  146. -- `eq?` is a comparison operator for atom values (numbers, booleans, and symbols)
  147. -- Returns `#f` on type mismatch or unsupported types (functions etc)
  148. -- Examples:
  149. -- (eq? 1 1) => #t
  150. -- (eq? #f #t) => #f
  151. -- (eq? #f #f) => #t
  152. -- (eq? 'a 10) => #f
  153. -- (eq? 'a 'a) => #t
  154. eq :: [Val] -> EvalState Val
  155. eq [] = return $ Boolean True
  156. eq (x:xs) = return $ Boolean $ foldl (eq' x) True xs where
  157. eq' _ False _ = False
  158. eq' (Number a) _ (Number b) = a == b
  159. eq' (Boolean a) _ (Boolean b) = a == b
  160. eq' (Symbol a) _ (Symbol b) = a == b
  161. eq' _ _ _ = False
  162.  
  163. -- Primitive function `symbol?` predicate
  164. isSymbol :: [Val] -> EvalState Val
  165. isSymbol [Symbol _] = return $ Boolean True
  166. isSymbol [_] = return $ Boolean False
  167. isSymbol vv = throwError $ UnexpectedArgs vv
  168.  
  169. -- Primitive function `list?` predicate
  170. isList :: [Val] -> EvalState Val
  171. isList [v] =
  172. return . Boolean $ case flattenList v of
  173. List _ -> True
  174. _ -> False
  175. isList vv = throwError $ UnexpectedArgs vv
  176.  
  177. -- Primitive function `pair?` predicate
  178. isPair :: [Val] -> EvalState Val
  179. isPair [v] =
  180. return . Boolean $ case flattenList v of
  181. List (_:_) -> True
  182. DottedList _ _ -> True
  183. _ -> False
  184. isPair vv = throwError $ UnexpectedArgs vv
  185.  
  186. -- Primitive function `isNumber?` predicate
  187. isNumber :: [Val] -> EvalState Val
  188. isNumber [Number _] = return $ Boolean True
  189. isNumber [_] = return $ Boolean False
  190. isNumber vv = throwError $ UnexpectedArgs vv
  191.  
  192. -- Primitive function `isBoolean?` predicate
  193. isBoolean :: [Val] -> EvalState Val
  194. isBoolean [Boolean _] = return $ Boolean True
  195. isBoolean [_] = return $ Boolean False
  196. isBoolean vv = throwError $ UnexpectedArgs vv
  197.  
  198. -- Primitive function `null?` predicate
  199. isNull :: [Val] -> EvalState Val
  200. isNull [v] =
  201. return . Boolean $ case flattenList v of
  202. List [] -> True
  203. _ -> False
  204. isNull vv = throwError $ UnexpectedArgs vv
  205.  
  206. --- ### Runtime
  207.  
  208. runtime :: Env
  209. runtime = H.fromList [ ("+", liftIntVargOp (+) 0)
  210. , ("-", liftIntVargOp (-) 0)
  211. , ("*", liftIntVargOp (*) 1)
  212. , ("/", liftIntVargOp div 1)
  213. , (">", liftCompOp (>))
  214. , (">=", liftCompOp (>=))
  215. , ("<", liftCompOp (<))
  216. , ("<=", liftCompOp (<=))
  217. , ("or", liftBoolVargOp or)
  218. , ("and", liftBoolVargOp and)
  219. , ("modulo", liftIntBinOp mod)
  220. , ("abs", liftIntUnaryOp abs)
  221. , ("not", liftBoolUnaryOp not)
  222. , ("car", PrimFunc car)
  223. , ("cdr", PrimFunc cdr)
  224. , ("cons", PrimFunc cons)
  225. , ("list", PrimFunc $ return . List)
  226. , ("append", PrimFunc append)
  227. , ("apply", PrimFunc applyPrim)
  228. , ("=", PrimFunc equalSign)
  229. , ("eq?", PrimFunc eq)
  230. , ("symbol?", PrimFunc isSymbol)
  231. , ("list?", PrimFunc isList)
  232. , ("pair?", PrimFunc isPair)
  233. , ("number?", PrimFunc isNumber)
  234. , ("boolean?", PrimFunc isBoolean)
  235. , ("null?", PrimFunc isNull)
  236. , ("eval", PrimFunc evalPrim)
  237. ]
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement