summaryrefslogtreecommitdiff
path: root/lambda-calcul/haskell/test/Minilang/REPLSpec.hs
diff options
context:
space:
mode:
authorArnaud Bailly <arnaud@pankzsoft.com>2025-10-28 20:14:16 +0100
committerArnaud Bailly <arnaud@pankzsoft.com>2025-10-28 20:14:16 +0100
commit1d1f0efc7de1eaa0c8a6b503892c2f950008fde6 (patch)
treebd2e2ea5963d8a208d302854502f580d8ffd73cb /lambda-calcul/haskell/test/Minilang/REPLSpec.hs
parenta210419fd60c00d011f70fb1b968031621e4c01a (diff)
downloadlambda-nantes-1d1f0efc7de1eaa0c8a6b503892c2f950008fde6.tar.gz
wip: port REPL from minilang
Diffstat (limited to 'lambda-calcul/haskell/test/Minilang/REPLSpec.hs')
-rw-r--r--lambda-calcul/haskell/test/Minilang/REPLSpec.hs74
1 files changed, 74 insertions, 0 deletions
diff --git a/lambda-calcul/haskell/test/Minilang/REPLSpec.hs b/lambda-calcul/haskell/test/Minilang/REPLSpec.hs
new file mode 100644
index 0000000..e134810
--- /dev/null
+++ b/lambda-calcul/haskell/test/Minilang/REPLSpec.hs
@@ -0,0 +1,74 @@
+module Minilang.REPLSpec where
+
+import Control.Exception (bracket)
+import Data.Text.IO
+import Minilang.Lambda.Eval (Term (Var))
+import Minilang.REPL
+import Minilang.REPL.Purer
+import Minilang.REPL.Types
+import System.Directory (getTemporaryDirectory, removeFile)
+import System.FilePath ((<.>), (</>))
+import System.IO (IOMode (..), hClose, withFile)
+import System.Posix.Temp (mkstemp)
+import Test.Hspec
+import Prelude hiding (lines, readFile, writeFile)
+
+spec :: Spec
+spec = parallel $
+ describe "MiniLang REPL" $ do
+ it "evaluates MiniLang terms read from pure Monad" $ do
+ let out =
+ withInput
+ [ "rec Nat : U = Sum (zero | succ Nat);",
+ "id : Π A : U . Π _ : A . A = λ A . λ x . x;",
+ "id Nat (succ (succ (succ zero)))"
+ ]
+
+ out
+ `shouldBe` [ "Bye!",
+ "$succ $succ $succ $zero : Sum(zero| succ Nat)",
+ "defined id : Π A : U . A → A",
+ "defined Nat : U"
+ ]
+
+ it "shows error when trying to load a non-existent file" $ do
+ withInput [":load foo"]
+ `shouldBe` [ "Bye!",
+ "REPLError \"cannot load file foo in Pure interpreter\""
+ ]
+
+ around withTempFile $
+ it "evaluates single MiniLang term read from IO" $ \fileName -> do
+ let outputFileName = fileName <> ".out"
+
+ writeFile fileName "rec Nat : U = Sum (zero | succ Nat);\nid : Π A : U . Π _ : A . A = λ A . λ x . x;\nid Nat (succ (succ (succ zero)))"
+
+ _ <- withFile fileName ReadMode $ \hin ->
+ withFile outputFileName AppendMode $ \hout ->
+ withHandles hin hout
+
+ out <- readFile outputFileName
+
+ out
+ `shouldBe` "\955\928> defined Nat : U\n\955\928> defined id : \928 A : U . A \8594 A\n\955\928> succ succ succ zero : Sum(zero| succ Nat)\n\955\928> Bye!\n"
+
+ describe "Purer REPL" $ do
+ it "keeps handling Inputs even when they fail" $ do
+ let inputs =
+ [ In "Unit : U",
+ In "Unit : U = Sum(tt)",
+ Com DumpEnv
+ ]
+
+ env (purerREPL (withInputs initialREPL inputs))
+ `shouldBe` [("Unit", Var "x")]
+
+ outputs (withInputs initialREPL inputs)
+ `shouldContain` [Msg "cannot find \"Unit\" in empty context"]
+
+withTempFile :: (String -> IO ()) -> IO ()
+withTempFile =
+ bracket mkTempFile rmTempFile
+ where
+ mkTempFile = getTemporaryDirectory >>= \dir -> mkstemp (dir </> "test-repl") >>= \(fp, h) -> hClose h >> pure fp
+ rmTempFile fn = removeFile fn >> removeFile (fn <.> "out")