perga/app/Repl.hs

71 lines
2.5 KiB
Haskell
Raw Normal View History

2024-11-17 18:33:14 -08:00
module Repl (repl, showEnvEntry) where
2024-11-15 18:39:44 -08:00
2024-11-18 14:33:21 -08:00
import Control.Monad.Reader
2024-11-17 18:33:14 -08:00
import Data.Functor (void)
2024-11-18 14:33:21 -08:00
import Data.List (isPrefixOf, stripPrefix)
2024-11-17 01:57:53 -08:00
import qualified Data.Map as M
2024-11-17 18:33:14 -08:00
import qualified Data.Text as T
import Eval
2024-11-15 18:39:44 -08:00
import Expr
import Parser
import System.Console.Haskeline
import System.Directory (createDirectoryIfMissing, getHomeDirectory)
import System.FilePath ((</>))
2024-11-18 14:33:21 -08:00
data ReplCommand = Quit | DumpEnv | TypeQuery String | Normalize String | Input String deriving (Show)
2024-11-15 18:39:44 -08:00
parseCommand :: Maybe String -> Maybe ReplCommand
parseCommand Nothing = Nothing
parseCommand (Just ":q") = Just Quit
2024-11-17 18:33:14 -08:00
parseCommand (Just ":e") = Just DumpEnv
parseCommand (Just input)
2024-11-18 14:33:21 -08:00
| ":t " `isPrefixOf` input = TypeQuery <$> stripPrefix ":t " input
| ":n " `isPrefixOf` input = Normalize <$> stripPrefix ":n " input
2024-11-17 18:33:14 -08:00
| otherwise = Just $ Input input
2024-11-20 07:37:49 -08:00
showEnvEntry :: T.Text -> EnvLine -> String
showEnvEntry k EL{_ty = t} = T.unpack k ++ " : " ++ prettyS t
2024-11-15 18:39:44 -08:00
2024-11-17 18:33:14 -08:00
dumpEnv :: Env -> InputT IO ()
dumpEnv = void . M.traverseWithKey ((outputStrLn .) . showEnvEntry)
2024-11-15 18:39:44 -08:00
2024-11-20 07:37:49 -08:00
handleInput :: Env -> String -> InputT IO Env
2024-11-17 18:33:14 -08:00
handleInput env input =
let (res, env') = parseDefEmpty env (T.pack input)
in case res of
Left err -> outputStrLn err >> pure env'
Right () -> pure env'
2024-11-15 18:39:44 -08:00
2024-11-20 07:37:49 -08:00
repl :: IO Env
2024-11-15 18:39:44 -08:00
repl = do
home <- getHomeDirectory
let basepath = home </> ".cache" </> "perga"
let filepath = basepath </> "history"
createDirectoryIfMissing True basepath
2024-11-20 07:37:49 -08:00
runInputT (defaultSettings{historyFile = Just filepath}) (loop M.empty)
2024-11-15 18:39:44 -08:00
where
2024-11-20 07:37:49 -08:00
loop :: Env -> InputT IO Env
2024-11-17 18:33:14 -08:00
loop env = do
2024-11-15 18:39:44 -08:00
minput <- getInputLine "> "
case parseCommand minput of
2024-11-17 18:33:14 -08:00
Nothing -> pure env
Just Quit -> pure env
2024-11-20 07:37:49 -08:00
Just DumpEnv -> dumpEnv env >> loop env
2024-11-17 18:33:14 -08:00
Just (TypeQuery input) ->
2024-11-20 07:37:49 -08:00
( case M.lookup (T.pack input) env of
2024-11-17 18:33:14 -08:00
Nothing -> outputStrLn (input ++ " unbound")
2024-11-20 07:37:49 -08:00
Just (EL{_ty = t}) -> outputStrLn $ prettyS t
2024-11-17 18:33:14 -08:00
)
>> loop env
2024-11-18 14:33:21 -08:00
Just (Normalize input) ->
( case parseExpr env (T.pack input) of
Left err -> outputStrLn err
2024-11-20 07:37:49 -08:00
Right expr -> case runReaderT (normalize expr) env of
2024-11-18 14:33:21 -08:00
Left err -> outputStrLn $ show err
Right result -> outputStrLn $ prettyS result
)
>> loop env
2024-11-15 18:39:44 -08:00
Just (Input input) -> do
2024-11-17 18:33:14 -08:00
env' <- handleInput env input
loop env'