summaryrefslogtreecommitdiff
path: root/lambda-calcul/haskell/test/Minilang/Lambda/ParserSpec.hs
diff options
context:
space:
mode:
Diffstat (limited to 'lambda-calcul/haskell/test/Minilang/Lambda/ParserSpec.hs')
-rw-r--r--lambda-calcul/haskell/test/Minilang/Lambda/ParserSpec.hs61
1 files changed, 61 insertions, 0 deletions
diff --git a/lambda-calcul/haskell/test/Minilang/Lambda/ParserSpec.hs b/lambda-calcul/haskell/test/Minilang/Lambda/ParserSpec.hs
index e9cfc6b..08ec661 100644
--- a/lambda-calcul/haskell/test/Minilang/Lambda/ParserSpec.hs
+++ b/lambda-calcul/haskell/test/Minilang/Lambda/ParserSpec.hs
@@ -11,6 +11,7 @@ import qualified Data.Text as Text
import Minilang.Lambda.Eval (Term (Lam))
import qualified Minilang.Lambda.Eval as Eval
import Minilang.Lambda.Parser (AST (..), desugar, initialChars, parse, parseProgram, pretty, restChars)
+import Minilang.Lambda.Eval (normalise)
import Test.Hspec (Spec, describe, it, parallel, shouldBe, shouldSatisfy)
import Test.Hspec.QuickCheck (prop)
import Test.QuickCheck (
@@ -114,6 +115,66 @@ spec = parallel $ do
let spaced = "- " <> Text.pack (show n)
in parse spaced `shouldSatisfy` (/= Right (Lit (negate n)))
+ describe "arithmetic operators" $ do
+ -- Operator names are valid identifiers: they parse as Sym and round-trip.
+ it "parses + as a symbol" $
+ parse "+" `shouldBe` Right (Sym "+")
+
+ it "parses - as a symbol" $
+ parse "-" `shouldBe` Right (Sym "-")
+
+ it "parses * as a symbol" $
+ parse "*" `shouldBe` Right (Sym "*")
+
+ it "parses div as a symbol" $
+ parse "div" `shouldBe` Right (Sym "div")
+
+ it "parses mod as a symbol" $
+ parse "mod" `shouldBe` Right (Sym "mod")
+
+ it "parses = as a symbol" $
+ parse "=" `shouldBe` Right (Sym "=")
+
+ it "parses < as a symbol" $
+ parse "<" `shouldBe` Right (Sym "<")
+
+ it "parses neg as a symbol" $
+ parse "neg" `shouldBe` Right (Sym "neg")
+
+ -- Full expression parses and round-trips
+ it "parses (+ 3 4) and pretty-prints back" $
+ let expr = App (Sym "+") (Lit 3) [Lit 4]
+ in parse "(+ 3 4)" `shouldBe` Right expr
+
+ it "pretty (+ 3 4) round-trips through parse" $
+ let expr = App (Sym "+") (Lit 3) [Lit 4]
+ in parse (pretty expr) `shouldBe` Right expr
+
+ -- desugar of an arithmetic expression produces a normalised integer
+ it "desugar and normalise (+ 3 4) == Num 7" $
+ normalise (desugar (App (Sym "+") (Lit 3) [Lit 4])) `shouldBe` Eval.Num 7
+
+ it "desugar and normalise (* 2 (+ 1 4)) == Num 10" $
+ normalise (desugar (App (Sym "*") (Lit 2) [App (Sym "+") (Lit 1) [Lit 4]]))
+ `shouldBe` Eval.Num 10
+
+ -- Comparison operators produce Church booleans
+ it "desugar and normalise (= 3 3) == Church True" $
+ normalise (desugar (App (Sym "=") (Lit 3) [Lit 3]))
+ `shouldBe` Eval.Lam "f" (Eval.Lam "t" (Eval.Var "t"))
+
+ it "desugar and normalise (= 3 4) == Church False" $
+ normalise (desugar (App (Sym "=") (Lit 3) [Lit 4]))
+ `shouldBe` Eval.Lam "f" (Eval.Lam "t" (Eval.Var "f"))
+
+ it "desugar and normalise (< 2 5) == Church True" $
+ normalise (desugar (App (Sym "<") (Lit 2) [Lit 5]))
+ `shouldBe` Eval.Lam "f" (Eval.Lam "t" (Eval.Var "t"))
+
+ -- A partial application (missing second arg) pretty-prints as an App
+ it "pretty (+ 1) is \"(+ 1)\"" $
+ pretty (App (Sym "+") (Lit 1) []) `shouldBe` "(+ 1)"
+
it "parses multiline program with blank lines" $ do
let program =
"(def id (lam (x) x))\n\