116 lines
3.3 KiB
Haskell
116 lines
3.3 KiB
Haskell
module APL.Eval_Tests (tests) where
|
|
|
|
import APL.AST (Exp (..))
|
|
import APL.Eval (Val (..), envEmpty, eval)
|
|
import Test.Tasty (TestTree, testGroup)
|
|
import Test.Tasty.HUnit (testCase, (@?=))
|
|
|
|
-- -- Consider this example when you have added the necessary constructors.
|
|
-- -- The Y combinator in a form suitable for strict evaluation.
|
|
yComb :: Exp
|
|
yComb =
|
|
Lambda "f" $
|
|
Apply
|
|
(Lambda "g" (Apply (Var "g") (Var "g")))
|
|
( Lambda
|
|
"g"
|
|
( Apply
|
|
(Var "f")
|
|
(Lambda "a" (Apply (Apply (Var "g") (Var "g")) (Var "a")))
|
|
)
|
|
)
|
|
|
|
fact :: Exp
|
|
fact =
|
|
Apply yComb $
|
|
Lambda "rec" $
|
|
Lambda "n" $
|
|
If
|
|
(Eql (Var "n") (CstInt 0))
|
|
(CstInt 1)
|
|
(Mul (Var "n") (Apply (Var "rec") (Sub (Var "n") (CstInt 1))))
|
|
|
|
tests :: TestTree
|
|
tests =
|
|
testGroup
|
|
"Evaluation"
|
|
[ testCase "Add" $
|
|
eval envEmpty (Add (CstInt 2) (CstInt 5))
|
|
@?= Right (ValInt 7),
|
|
--
|
|
testCase "Add (wrong type)" $
|
|
eval envEmpty (Add (CstInt 2) (CstBool True))
|
|
@?= Left "Non-integer operand",
|
|
--
|
|
testCase "Sub" $
|
|
eval envEmpty (Sub (CstInt 2) (CstInt 5))
|
|
@?= Right (ValInt (-3)),
|
|
--
|
|
testCase "Div" $
|
|
eval envEmpty (Div (CstInt 7) (CstInt 3))
|
|
@?= Right (ValInt 2),
|
|
--
|
|
testCase "Div0" $
|
|
eval envEmpty (Div (CstInt 7) (CstInt 0))
|
|
@?= Left "Division by zero",
|
|
--
|
|
testCase "Pow" $
|
|
eval envEmpty (Pow (CstInt 2) (CstInt 3))
|
|
@?= Right (ValInt 8),
|
|
--
|
|
testCase "Pow0" $
|
|
eval envEmpty (Pow (CstInt 2) (CstInt 0))
|
|
@?= Right (ValInt 1),
|
|
--
|
|
testCase "Pow negative" $
|
|
eval envEmpty (Pow (CstInt 2) (CstInt (-1)))
|
|
@?= Left "Negative exponent",
|
|
--
|
|
testCase "Eql (false)" $
|
|
eval envEmpty (Eql (CstInt 2) (CstInt 3))
|
|
@?= Right (ValBool False),
|
|
--
|
|
testCase "Eql (true)" $
|
|
eval envEmpty (Eql (CstInt 2) (CstInt 2))
|
|
@?= Right (ValBool True),
|
|
--
|
|
testCase "If" $
|
|
eval envEmpty (If (CstBool True) (CstInt 2) (Div (CstInt 7) (CstInt 0)))
|
|
@?= Right (ValInt 2),
|
|
--
|
|
testCase "Let" $
|
|
eval envEmpty (Let "x" (Add (CstInt 2) (CstInt 3)) (Var "x"))
|
|
@?= Right (ValInt 5),
|
|
--
|
|
testCase "Let (shadowing)" $
|
|
eval
|
|
envEmpty
|
|
( Let
|
|
"x"
|
|
(Add (CstInt 2) (CstInt 3))
|
|
(Let "x" (CstBool True) (Var "x"))
|
|
)
|
|
@?= Right (ValBool True),
|
|
testCase "Lambda" $
|
|
eval
|
|
envEmpty
|
|
(
|
|
Lambda "y" (Var "y")
|
|
)
|
|
@?= Right (ValFun [] "y" (Var "y")),
|
|
testCase "Apply" $
|
|
eval [] (Apply (Let "x" (CstInt 2) (Lambda "y" (Add (Var "x") (Var "y")))) (CstInt 3))
|
|
@?= Right (ValInt 5),
|
|
testCase "Apply (fact)" $
|
|
eval envEmpty (Apply fact (CstInt 5)) @?= Right (ValInt 120),
|
|
testCase "Apply (order)" $
|
|
eval envEmpty (Apply (CstInt 1) (Var "missing"))
|
|
@?= Left "Unknown variable: missing",
|
|
testCase "Try" $
|
|
eval envEmpty (TryCatch (CstInt 0) (CstInt 1))
|
|
@?= Right (ValInt 0),
|
|
testCase "Catch" $
|
|
eval envEmpty (TryCatch (Var "missing") (CstInt 1))
|
|
@?= Right (ValInt 1)
|
|
]
|