Skip to content

Commit

Permalink
Better REPL! Also, move pretty printing to Syntax
Browse files Browse the repository at this point in the history
  • Loading branch information
SophieBosio committed May 3, 2024
1 parent 6107916 commit 65c2036
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 46 deletions.
5 changes: 1 addition & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,14 +83,11 @@ Like a normal programming language, you can also execute Contra programs. By def
contra <program-name>.con
```

This prototype also comes with a rudimentary REPL. Start a blank interactive session by typing just `contra` or load a program's functions into the REPL with `--load <program-name>.con`.
This prototype also comes with a rudimentary REPL. Start a blank interactive session by typing just `contra`. Load files into the REPL with `:l <filename>.con` and quit with `:q`.

```shell
# blank REPL session
contra

# load program into REPL
contra --load <program-name>.con
```


Expand Down
14 changes: 6 additions & 8 deletions app/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import Core.Parser
)
import Analysis.TypeInferrer (inferProgram)
import Semantics.Interpreter (runMain)
import Semantics.REPL (evalLoop)
import Validation.PropertyChecker (check, redStr)
import Semantics.REPL (loop)
import Validation.PropertyChecker (check)
import Validation.Formula (defaultRecDepth)

import System.Environment (getArgs)
Expand Down Expand Up @@ -52,7 +52,6 @@ action ["--check", file] = PropertyCheckDefault
action ["--check", n, file] = PropertyCheckCustom (read n)
<$> (parse file >>= typecheck)
action ["--type", file] = TypeCheck <$> parse file
action ["--load", file] = REPL <$> (parse file >>= typecheck)
action ["--version" ] = return $ Version versionInfo
action ["--help" ] = return $ Fail useInfo
action [ file] = Execute <$> (parse file >>= typecheck)
Expand All @@ -77,7 +76,7 @@ typecheck program =
repl :: Program Type -> IO ()
repl program =
do putStrLn "✦ Contra REPL! ✦\n"
evalLoop program
loop program

execute :: Program Type -> IO ()
execute program =
Expand Down Expand Up @@ -105,10 +104,9 @@ useInfo =
"How to use:\n\
\ contra --check <filename>.con - Check all properties in program\n\
\ contra --check n <filename.con> - Check properties with max. recursion depth 'n'\n\
\ contra <filename>.con - Execute 'main' function in program\n\
\ contra --type <filename>.con - Type-check and print program\n\
\Rudimentary REPL:\n\
\ contra - Start blank interactive REPL session\n\
\ contra --load <filename>.con - Load program into REPL\n\
\ contra <filename>.con - Execute 'main' function in program\n\
\ contra - Start an interactive REPL session\n\
\Load file into REPL with ':l <filename.con>'\n\
\Exit REPL with ':q'"

20 changes: 20 additions & 0 deletions src/Core/Syntax.hs
Original file line number Diff line number Diff line change
Expand Up @@ -422,3 +422,23 @@ instance Show (Value a) where
show (Boolean b _) = show b
show (VConstructor c vs _) = c ++
" {" ++ intercalate ", " (map show vs) ++ "}"


-- Pretty printing in the terminal
redStr :: String -> String
redStr s = "\ESC[31m\STX" ++ s ++ "\ESC[m\STX"

yellowStr :: String -> String
yellowStr s = "\ESC[33m\STX" ++ s ++ "\ESC[m\STX"

greenStr :: String -> String
greenStr s = "\ESC[32m\STX" ++ s ++ "\ESC[m\STX"

putStrLnRed :: String -> IO ()
putStrLnRed = putStrLn . redStr

putStrLnYellow :: String -> IO ()
putStrLnYellow = putStrLn . yellowStr

putStrLnGreen :: String -> IO ()
putStrLnGreen = putStrLn . greenStr
46 changes: 33 additions & 13 deletions src/Semantics/REPL.hs
Original file line number Diff line number Diff line change
Expand Up @@ -12,35 +12,55 @@
This is a rudimentary REPL (Read-Eval-Print Loop) for Contra.
It can be used to interact with the core language and the function definitions
in a program text. Load a program in the terminal using the
'--load <program-name>.con' option and call functions interactively.
in a program text. After starting the REPL, load a program in the terminal
with ':l <filename.con>' and start calling functions interactively.
-}

module Semantics.REPL where

import Core.Syntax
import Core.Parser
import Core.Parser hiding (program)
import Analysis.TypeInferrer
import Semantics.PartialEvaluator

import System.IO (hFlush, stdout)
import System.IO (hFlush, stdout)
import System.Exit (die)


-- Export
evalLoop :: Program Type -> IO ()
evalLoop p =
loop :: Program Type -> IO ()
loop p =
do input <- readLine
if input == ":q"
then return ()
else do parsed <- parseLine input
typed <- typeCheck parsed
let (interpreted, residual) = eval p typed
print interpreted
evalLoop residual
case input of
":q" -> return ()
(':':'l':' ': file) -> do program <- loadProgram file
putStrLn $ "Loaded file " ++ show file
loop program
command -> do parsed <- parseLine command
typed <- typeCheck parsed
let (interpreted, residual) = eval p typed
print interpreted
loop residual


-- Utility
loadProgram :: String -> IO (Program Type)
loadProgram file = parse file >>= typecheck

parse :: String -> IO (Program String)
parse file =
do result <- parseProgram file
case result of
Left problems -> die $ redStr $ report problems
Right program -> return program

typecheck :: Program String -> IO (Program Type)
typecheck program =
case inferProgram program of
Left err -> die $ redStr err
Right tp -> return tp

readLine :: IO String
readLine = putStr "contra> "
>> hFlush stdout
Expand Down
21 changes: 0 additions & 21 deletions src/Validation/PropertyChecker.hs
Original file line number Diff line number Diff line change
Expand Up @@ -104,24 +104,3 @@ realise sv =
"Unexpected error: Property should translate to a\
\Boolean formula, but was a " ++ show other


-- Pretty printing
-- printCounterExample :: SMTModel -> IO ()

redStr :: String -> String
redStr s = "\ESC[31m\STX" ++ s ++ "\ESC[m\STX"

yellowStr :: String -> String
yellowStr s = "\ESC[33m\STX" ++ s ++ "\ESC[m\STX"

greenStr :: String -> String
greenStr s = "\ESC[32m\STX" ++ s ++ "\ESC[m\STX"

putStrLnRed :: String -> IO ()
putStrLnRed = putStrLn . redStr

putStrLnYellow :: String -> IO ()
putStrLnYellow = putStrLn . yellowStr

putStrLnGreen :: String -> IO ()
putStrLnGreen = putStrLn . greenStr

0 comments on commit 65c2036

Please sign in to comment.