{-# LANGUAGE DataKinds #-}
{-# LANGUAGE OverloadedStrings #-}
module Earthling.Eval where
import qualified Data.Foldable as F
import Data.Sequence (Seq)
import qualified Data.Sequence as S
import Data.Text (Text)
import Earthling.Types
eval :: Seq (Decl 'Raw) -> IO ()
eval decls = case F.find (\ d -> declName d == "main") decls of
Nothing -> putStrLn "no main defined"
Just d -> do
_ <- runInstrs decls (S.viewl (declDefn d)) []
return ()
data Value
= IntValue Integer
| DoubleValue Double
deriving (Eq, Show)
runInstrs :: Seq (Decl 'Raw) -> S.ViewL (Item 'Raw) -> [Value] -> IO [Value]
runInstrs decls instrs stack = case instrs of
S.EmptyL -> return stack
i S.:< is -> do
stack' <- runInstr decls (itemTok i) stack
runInstrs decls (S.viewl is) stack'
builtins :: [(Text, [Value] -> IO [Value])]
builtins =
[ ("+", \ (IntValue x:IntValue y:rs) -> return (IntValue (x + y) : rs))
, ("*", \ (IntValue x:IntValue y:rs) -> return (IntValue (x * y) : rs))
, ("print", \ (val:rs) -> print val >> return rs)
]
runInstr :: Seq (Decl 'Raw) -> Atom -> [Value] -> IO [Value]
runInstr _decls (AtomLiteral (IntLiteral i)) st =
return (IntValue i : st)
runInstr _decls (AtomLiteral (DoubleLiteral d)) st =
return (DoubleValue d : st)
runInstr decls (AtomIdent name) st
| Just cb <- lookup name builtins = cb st
| Just decl <- F.find (\ d -> declName d == name) decls =
runInstrs decls (S.viewl (declDefn decl)) st
| otherwise = do
putStrLn ("No definition named " ++ show name)
return []