{-# LANGUAGE NamedFieldPuns #-}
module Main where
import Data.Functor ((<$))
import Data.List.Split (chunk)
import qualified Data.Vector.Unboxed as V
import Language.ArrayForth.Interpreter (eval, runNativeProgram)
import Language.ArrayForth.Parse (isNumber)
import Language.ArrayForth.Program (toNative, readProgram)
import Language.ArrayForth.State (State (..), setProgram,
startState)
import System.Environment (getArgs)
import System.IO (hFlush, stdout)
import Text.Printf (printf)
main :: IO ()
main = do args <- getArgs
case args of
[] -> repl
[file] -> readFile file >>= print . runNativeProgram startState . read
_ -> putStrLn $ "Too many arguments!"
repl :: IO ()
repl = go 0 startState
where go loc state =
do inp <- putStr "λ>" >> hFlush stdout >> getLine
case inp of
":" -> putStrLn "Please specify a command!" >> go loc state
':' : commands -> let command : args = words commands in
run command args >>= uncurry go
program -> execute $ readProgram program
where execute (Left err) = print err >> go loc state
execute (Right program) = print res >> go p res
where res@State {p} = eval $ setProgram loc (toNative program) state
run "reset" _ = (0, startState) <$ print startState
run "p" args
| null args || not (isNumber $ head args) =
(loc, state) <$ putStrLn "Invalid arguments!"
| otherwise = let n = read $ head args in
(n, state { p = n }) <$ print state { p = n }
run cmd args = (loc, state) <$ continue cmd args
continue "memory" _ = mapM_ print . chunk 8 . V.toList $ memory state
continue cmd _ = printf "Unknown command `%s'!\n" cmd