@@ -16,25 +16,35 @@ import Exprs
1616-- TODO argparse for something like check -i fma.unit
1717-- TODO release packaged binaries on github
1818
19+ -- | Either runs a file or runs the REPL
1920main :: IO ()
2021main = do
2122 args <- getArgs
2223 case args of
24+ -- no file, run the repl
2325 [] -> repl
26+ -- run the file
2427 filePath: _ -> do
2528 source <- readFile filePath
2629 runString filePath source
2730
31+ -- | Run the given file name and string, printing output
2832runString :: String -> String -> IO ()
2933runString filePath source = case parseProgram filePath source of
34+ -- report parse error
3035 Left err -> hPrint stderr err
36+ -- run the program
3137 Right prog ->
3238 case checkProgram prog of
39+ -- report well-formedness/type checking errors
3340 Left errs -> sequence_ (print <$> errs)
41+ -- success! show definitions in their file (don't include the prelude)
3442 Right env -> print (envDifference env (initialEnv dummySS))
3543
44+ -- | Stateful REPL for running statements and viewing definitions
3645type Repl a = HaskelineT (StateT (TyEnv SS ) IO ) a
3746
47+ -- | run the input as a statement and print any new definitions. The environment is maintained throughout the REPL
3848cmd :: String -> Repl ()
3949cmd input = do
4050 env <- get
@@ -47,6 +57,7 @@ cmd input = do
4757 put env'
4858 liftIO (print (envDifference env' env))
4959
60+ -- | (Stateful) Autocomplete based on keywords and names in scope
5061comp :: (Monad m , MonadState (TyEnv SS ) m ) => WordCompleter m
5162comp n = do
5263 env <- get
@@ -57,38 +68,48 @@ comp n = do
5768 ]
5869 return $ filter (isPrefixOf n) names
5970
71+ -- | :help displays help text
6072help :: [String ] -> Repl ()
6173help _ = liftIO $ putStrLn (unlines helpLines)
6274
75+ -- | :quit exits the repl
6376quit :: [String ] -> Repl ()
6477quit _ = abort
6578
79+ -- | :list shows all names and their units
6680listEnv :: [String ] -> Repl ()
6781listEnv _ = do
6882 env <- get
6983 liftIO (print env)
7084
85+ -- | Data for a @:help@-like command
7186data Opt = Opt { synonyms :: [String ]
7287 , arguments :: [String ]
7388 , runOpt :: [String ] -> Repl ()
7489 , usage :: String
7590 }
91+
92+ -- | @:help@-like commands
7693opts :: [Opt ]
7794opts =
7895 [ Opt [" help" , " h" ] [] help " display this help information"
7996 , Opt [" quit" , " q" ] [] quit " exit the repl"
8097 , Opt [" list" , " l" ] [] listEnv " list all names currently in scope"
8198 ]
8299
100+ -- | Help text lines describing available @:help@-like commands
83101helpLines :: [String ]
84102helpLines = " command -> description" : [unwords ((" :" ++ ) <$> synonyms opt)++ " -> " ++ usage opt | opt <- opts]
85103
104+ -- | @:help@-like commands for defining the repl
86105opts' :: [(String , [String ] -> Repl () )]
87106opts' = [(name, runOpt opt) | opt <- opts, name <- synonyms opt]
88107
108+ -- | Welcome message
89109ini :: Repl ()
90110ini = liftIO $ putStrLn " Welcome to UnitChecker!" >> putStrLn " for help, use :h or :help. to quit, use :q or :quit"
91111
112+ -- | Actual repl definition. Evaluating this runs the repl until the user exits
92113repl :: IO ()
93114repl = flip evalStateT (initialEnv dummySS)
94115 $ evalRepl (pure " UnitChecker> " ) cmd opts' (Just ' :' ) (Word comp) ini
0 commit comments