2021-03-26 12:31:55 -07:00
|
|
|
import Ivo
|
2021-03-16 17:19:50 -07:00
|
|
|
|
2019-12-11 18:29:28 -08:00
|
|
|
import Test.Tasty
|
|
|
|
import Test.Tasty.HUnit
|
2019-12-11 19:21:54 -08:00
|
|
|
|
2020-11-02 15:59:35 -08:00
|
|
|
-- These are terms which have complex reduction steps and
|
|
|
|
-- are likely to catch bugs in the substitution function, if there are any.
|
|
|
|
-- However, they don't have any particular computational *meaning*,
|
|
|
|
-- so the names for them are somewhat arbitrary.
|
|
|
|
|
|
|
|
-- This should evaluate to `y y`.
|
2021-03-16 17:19:50 -07:00
|
|
|
dfi :: EvalExpr
|
|
|
|
dfi = App d (App f i)
|
2021-03-05 19:04:06 -08:00
|
|
|
where
|
2021-03-16 17:19:50 -07:00
|
|
|
d = Abs "x" $ App (Var "x") (Var "x")
|
|
|
|
f = Abs "f" $ App (Var "f") (App (Var "f") (Var "y"))
|
|
|
|
i = Abs "x" $ Var "x"
|
2019-12-11 18:29:28 -08:00
|
|
|
|
2020-11-02 15:59:35 -08:00
|
|
|
-- This should evalaute to `y`.
|
2021-03-16 17:19:50 -07:00
|
|
|
ttttt :: EvalExpr
|
|
|
|
ttttt = App (App (App f t) (Abs "x" (Var "x"))) (Var "y")
|
2021-03-05 19:04:06 -08:00
|
|
|
where
|
2021-03-16 17:19:50 -07:00
|
|
|
t = Abs "f" $ Abs "x" $
|
|
|
|
App (Var "f") (App (Var "f") (Var "x"))
|
|
|
|
f = Abs "T" $ Abs "f" $ Abs "x" $
|
|
|
|
App
|
|
|
|
(App
|
|
|
|
(App (Var "T")
|
|
|
|
(App (Var "T")
|
|
|
|
(App (Var "T")
|
|
|
|
(App (Var "T")
|
|
|
|
(Var "T")))))
|
|
|
|
(Var "f"))
|
|
|
|
(Var "x")
|
2019-12-11 18:29:28 -08:00
|
|
|
|
2021-03-05 23:38:21 -08:00
|
|
|
-- | A simple divergent expression.
|
2021-03-16 17:19:50 -07:00
|
|
|
omega :: EvalExpr
|
|
|
|
omega = App x x
|
|
|
|
where x = Abs "x" (App (Var "x") (Var "x"))
|
2021-03-05 23:38:21 -08:00
|
|
|
|
2021-03-16 17:19:50 -07:00
|
|
|
cc1 :: EvalExpr
|
2021-03-18 00:00:43 -07:00
|
|
|
cc1 = App CallCCE (Abs "k" (App omega (App (Var "k") (Var "z"))))
|
2021-03-05 23:38:21 -08:00
|
|
|
|
2021-03-16 17:19:50 -07:00
|
|
|
cc2 :: EvalExpr
|
2021-03-18 00:00:43 -07:00
|
|
|
cc2 = App (Var "y") (App CallCCE (Abs "k" (App (Var "z") (App (Var "k") (Var "x")))))
|
2019-12-11 18:29:28 -08:00
|
|
|
|
|
|
|
main :: IO ()
|
|
|
|
main = defaultMain $
|
|
|
|
testGroup "Tests"
|
|
|
|
[ testGroup "Evaluator tests"
|
2021-03-16 17:19:50 -07:00
|
|
|
[ testCase "capture test 1: DFI" $ eval dfi @?= App (Var "y") (Var "y")
|
|
|
|
, testCase "capture test 2: ttttt" $ eval ttttt @?= Var "y"
|
|
|
|
, testCase "invoking a continuation replaces the current continuation" $ eval cc1 @?= Var "z"
|
|
|
|
, testCase "callcc actually captures the current continuation" $ eval cc2 @?= App (Var "y") (Var "x")
|
2019-12-11 18:29:28 -08:00
|
|
|
]
|
|
|
|
, testGroup "Parser tests"
|
|
|
|
[ testGroup "Unit tests"
|
2021-03-16 17:19:50 -07:00
|
|
|
[ testCase "identity" $ parseEval "\\x.x" @?= Right (Abs "x" $ Var "x")
|
|
|
|
, testCase "unary application" $ parseEval "(x)" @?= Right (Var "x")
|
|
|
|
, testCase "application shorthand" $ parseEval "a b c d" @?= Right (App (App (App (Var "a") (Var "b")) (Var "c")) (Var "d"))
|
|
|
|
, testCase "let" $ parseEval "let x = \\y.y in x" @?= Right (App (Abs "x" (Var "x")) (Abs "y" (Var "y")))
|
|
|
|
, testCase "multi-let" $ parseEval "let x = y; y = z in x y" @?= Right (App (Abs "x" (App (Abs "y" (App (Var "x") (Var "y"))) (Var "z"))) (Var "y"))
|
|
|
|
, testCase "ttttt" $ parseEval "(\\T f x.(T (T (T (T T)))) f x) (\\f x.f (f x)) (\\x.x) y"
|
2019-12-11 18:29:28 -08:00
|
|
|
@?= Right ttttt
|
2020-11-02 15:59:35 -08:00
|
|
|
, testGroup "Redundant whitespace"
|
2021-03-16 17:19:50 -07:00
|
|
|
[ testCase "around variable" $ parseEval " x " @?= Right (Var "x")
|
|
|
|
, testCase "around lambda" $ parseEval " \\ x y . x " @?= Right (Abs "x" $ Abs "y" $ Var "x")
|
|
|
|
, testCase "around application" $ parseEval " ( x (y ) ) " @?= Right (App (Var "x") (Var "y"))
|
|
|
|
, testCase "around let" $ parseEval " let x=(y)in x " @?= Right (App (Abs "x" (Var "x")) (Var "y"))
|
2020-11-02 15:59:35 -08:00
|
|
|
]
|
2019-12-11 18:29:28 -08:00
|
|
|
]
|
|
|
|
]
|
|
|
|
]
|