Skip to content

Instantly share code, notes, and snippets.

@L8D
Last active December 31, 2015 15:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save L8D/8007803 to your computer and use it in GitHub Desktop.
Save L8D/8007803 to your computer and use it in GitHub Desktop.
Mini and incomplete RL interpreter in Haskell
{-# LANGUAGE LambdaCase #-}
import Control.Monad ((>=>))
import Data.Maybe (listToMaybe, fromMaybe)
import Data.Char (toLower)
import Data.List (intercalate)
type Item = Int
type Stack = [Item]
maybeRead :: Read a => String -> Maybe a
maybeRead = fmap fst . listToMaybe . reads
execWord :: String -> Stack -> IO Stack
execWord = fromMaybe (return . (0:)) . (`lookup` wordDict)
wordDict =
[ "." ~> \(x:xs) -> print x >> return xs
] ++ map (\(a, b) -> (a, return . b)) -- wrapper for pure functions
[ "dup" ~> \(x:xs) -> x:x:xs
, "null" ~> \case (x:[]) -> -1:x:[]; xs -> 0:xs
, "!" ~> \case (0:xs) -> -1:xs; (x:xs) -> 0:xs
, "," ~> tail
, "+" ~> op (+)
, "-" ~> op (-)
, "*" ~> op (*)
, "/" ~> op div
, "^" ~> op (^)
, "%" ~> op mod
, ">" ~> bop (>)
, "<" ~> bop (<)
, "<=" ~> bop (<=)
, ">=" ~> bop (>=)
, "=" ~> bop (==)
, "&" ~> tbop (&&)
, "|" ~> tbop (||)
-- more words here...
]
where
op f (x':x:xs) = f x x':xs
bop f (x':x:xs) = fromB (f x x'):xs
tbop f (x':x:xs) = fromB (f (toB x) (toB x')):xs
fromB = negate . fromEnum
toB = (/= 0)
(~>) = (,)
interpret :: [String] -> Stack -> IO Stack
interpret [] = return
interpret (w:ws) = maybe (execWord $ map toLower w)
(fmap return . (:))
(maybeRead w)
>=> interpret ws
run :: String -> IO Stack
run = (`interpret` [error "stack underflow"]) . words
main = getContents >>= run >>= putStrLn
. ('[':) . (++ "]")
. intercalate " "
. map show
. init
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment