packages feed

melody-0.2: src/Language/Melody/Interpret/Pop.hs

module Language.Melody.Interpret.Pop (
  push,
  pop,
  topN,
  popWord,
  popFunc,
  popDict,
  popList,
  popNum,
  popStr,
  popBoxed) where
import Language.Melody.Interpret.Types
import Language.Melody.Syntax
import Control.Monad.Error
import Control.Lens

errorMsg :: String -> Expr Compiled -> MelodyM a
errorMsg s e = throwError . TypeMismatch $ "Expected " ++ s ++ " got " ++ show e

push :: Expr NotCompiled -> Melody
push = (stack %=) . (:)

pop :: MelodyM (Expr Compiled)
pop = do
  h <- use (stack.to headMay)
  case h of
    Just x -> stack %= tail >> return x
    Nothing -> lift . throwError $ UnderflowError "Somewhere"
  where headMay []    = Nothing
        headMay (c:_) = Just c

popWord :: MelodyM String
popWord = do
  h <- pop
  case h of
    Word w -> return w
    e      -> errorMsg "word" e

popFunc :: MelodyM (Expr NotCompiled, Maybe Closure)
popFunc = do
  f <- pop
  case f of
    Func exprs clos -> return (exprs, clos)
    e               -> errorMsg "func" e

popDict :: MelodyM [(Expr Compiled, Expr Compiled)]
popDict = do
  h <- pop
  case h of
    Dictionary d   -> return d
    e              -> errorMsg "hash" e

popList :: MelodyM [Expr Compiled]
popList = do
  h <- pop
  case h of
    List w -> return w
    e      -> errorMsg "list" e

popNum :: MelodyM Double
popNum = do
  h <- pop
  case h of
    NumLit n -> return n
    e        -> errorMsg "num" e

popStr :: MelodyM String
popStr = do
  h <- pop
  case h of
    StrLit n -> return n
    e        -> errorMsg "str" e

popBoxed :: MelodyM (String, String, [Expr Compiled])
popBoxed = do
  b <- pop
  case b of
    Boxed t c es -> return (t, c, es)
    e            -> errorMsg "boxed" e

topN :: Int -> MelodyM [Expr Compiled]
topN = flip replicateM pop