2024-11-17 18:33:14 -08:00
|
|
|
module Repl (repl, showEnvEntry) where
|
2024-11-15 18:39:44 -08:00
|
|
|
|
2024-11-22 19:44:31 -08:00
|
|
|
import Check (findType)
|
|
|
|
|
import Data.List (stripPrefix)
|
|
|
|
|
import qualified Data.Map.Strict as M
|
|
|
|
|
import Data.Text (pack)
|
2024-11-30 23:43:17 -08:00
|
|
|
import Elaborator
|
2024-11-22 10:36:51 -08:00
|
|
|
import Errors (Result)
|
2024-11-17 18:33:14 -08:00
|
|
|
import Eval
|
2024-11-15 18:39:44 -08:00
|
|
|
import Expr
|
|
|
|
|
import Parser
|
2024-11-30 23:43:17 -08:00
|
|
|
import Program
|
2024-11-15 18:39:44 -08:00
|
|
|
import System.Console.Haskeline
|
|
|
|
|
import System.Directory (createDirectoryIfMissing, getHomeDirectory)
|
|
|
|
|
import System.FilePath ((</>))
|
|
|
|
|
|
2024-11-22 10:36:51 -08:00
|
|
|
data ReplCommand
|
|
|
|
|
= Quit
|
|
|
|
|
| DumpEnv
|
|
|
|
|
| TypeQuery String
|
|
|
|
|
| ValueQuery String
|
|
|
|
|
| Normalize String
|
|
|
|
|
| WeakNormalize String
|
|
|
|
|
| Input String
|
|
|
|
|
| LoadFile String
|
2024-12-04 17:46:50 -08:00
|
|
|
| DumpDebug String
|
2024-11-22 10:36:51 -08:00
|
|
|
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
|
2024-11-22 10:36:51 -08:00
|
|
|
| ":v " `isPrefixOf` input = ValueQuery <$> stripPrefix ":v " input
|
2024-11-18 14:33:21 -08:00
|
|
|
| ":n " `isPrefixOf` input = Normalize <$> stripPrefix ":n " input
|
2024-11-22 10:36:51 -08:00
|
|
|
| ":w " `isPrefixOf` input = WeakNormalize <$> stripPrefix ":w " input
|
|
|
|
|
| ":l " `isPrefixOf` input = LoadFile <$> stripPrefix ":l " input
|
2024-12-04 17:46:50 -08:00
|
|
|
| ":d " `isPrefixOf` input = DumpDebug <$> stripPrefix ":d " input
|
2024-11-17 18:33:14 -08:00
|
|
|
| otherwise = Just $ Input input
|
|
|
|
|
|
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 =
|
2024-11-30 23:43:17 -08:00
|
|
|
case parseDef "repl" (pack input) of
|
|
|
|
|
Left err -> outputStrLn err >> pure env
|
|
|
|
|
Right irDef -> case evalDef env irDef of
|
|
|
|
|
Left err -> outputStrLn (toString err) >> pure env
|
|
|
|
|
Right env' -> pure env'
|
2024-11-15 18:39:44 -08:00
|
|
|
|
2024-11-30 23:43:17 -08:00
|
|
|
actOnParse :: String -> (Expr -> InputT IO ()) -> InputT IO ()
|
2024-12-04 17:46:50 -08:00
|
|
|
actOnParse input action = either outputStrLn (action . elaborate) $ parseExpr "repl" (pack input)
|
2024-11-22 10:36:51 -08:00
|
|
|
|
|
|
|
|
printErrorOrResult :: Env -> (Expr -> ReaderT Env Result Expr) -> Expr -> InputT IO ()
|
2024-12-08 12:40:52 -08:00
|
|
|
printErrorOrResult env action expr = putTextLn $ either toText prettyT $ runReaderT (action expr) env
|
2024-11-22 10:36:51 -08:00
|
|
|
|
|
|
|
|
parseActPrint :: Env -> String -> (Expr -> ReaderT Env Result Expr) -> InputT IO ()
|
2024-11-30 23:43:17 -08:00
|
|
|
parseActPrint env input action = actOnParse input (printErrorOrResult env action)
|
2024-11-22 10:36:51 -08:00
|
|
|
|
2024-11-22 19:44:31 -08:00
|
|
|
lookupAct :: Env -> String -> (Definition -> InputT IO ()) -> InputT IO ()
|
|
|
|
|
lookupAct env input action = maybe (outputStrLn $ "'" ++ input ++ "' unbound") action $ M.lookup (pack input) env
|
2024-11-22 10:36:51 -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-22 10:36:51 -08:00
|
|
|
Just DumpEnv -> lift (dumpEnv env) >> loop env
|
2024-11-22 19:44:31 -08:00
|
|
|
Just (TypeQuery input) -> parseActPrint env input (findType []) >> loop env
|
2024-12-08 12:40:52 -08:00
|
|
|
Just (ValueQuery input) -> lookupAct env input (putTextLn . prettyT . _val) >> loop env
|
2024-11-22 10:36:51 -08:00
|
|
|
Just (Normalize input) -> parseActPrint env input normalize >> loop env
|
|
|
|
|
Just (WeakNormalize input) -> parseActPrint env input whnf >> loop env
|
2024-12-04 17:46:50 -08:00
|
|
|
Just (DumpDebug input) -> either outputStrLn (outputStrLn . show) (parseDef "repl" (pack input)) >> loop env
|
2024-12-01 18:06:03 -08:00
|
|
|
Just (LoadFile filename) -> lift (runExceptT $ handleAndParseFile env filename) >>= either ((>> loop env) . outputStrLn) loop
|
2024-11-22 10:36:51 -08:00
|
|
|
Just (Input input) -> handleInput env input >>= loop
|