module BruijnSpec (spec) where import Bruijn (toDeBruijn) import Parser (Expr (Abstraction, Application, Variable)) import Test.Hspec spec :: Spec spec = do describe "toDeBruijn" $ do -- Free variables it "leaves a lone free variable unchanged" $ toDeBruijn (Variable "x") `shouldBe` Variable "x" it "leaves free variables in abstraction body unchanged" $ toDeBruijn (Abstraction "x" (Variable "y")) `shouldBe` Abstraction "0" (Variable "y") -- Single abstraction it "converts bound variable in identity" $ toDeBruijn (Abstraction "x" (Variable "x")) `shouldBe` Abstraction "0" (Variable "0") it "leaves free variable in abstraction body unchanged" $ toDeBruijn (Abstraction "x" (Variable "z")) `shouldBe` Abstraction "0" (Variable "z") -- Nested abstractions it "inner binder resolves to depth 1" $ toDeBruijn (Abstraction "x" (Abstraction "y" (Variable "y"))) `shouldBe` Abstraction "0" (Abstraction "1" (Variable "1")) it "outer binder resolves to depth 0 from within nested scope" $ toDeBruijn (Abstraction "x" (Abstraction "y" (Variable "x"))) `shouldBe` Abstraction "0" (Abstraction "1" (Variable "0")) it "outermost of three binders resolves correctly" $ toDeBruijn (Abstraction "x" (Abstraction "y" (Abstraction "z" (Variable "x")))) `shouldBe` Abstraction "0" (Abstraction "1" (Abstraction "2" (Variable "0"))) -- Application it "converts self-application" $ toDeBruijn (Abstraction "x" (Application (Variable "x") (Variable "x"))) `shouldBe` Abstraction "0" (Application (Variable "0") (Variable "0")) it "converts independent scopes in application" $ toDeBruijn (Application (Abstraction "x" (Variable "x")) (Abstraction "y" (Variable "y"))) `shouldBe` Application (Abstraction "0" (Variable "0")) (Abstraction "0" (Variable "0")) -- Alpha equivalence it "alpha-equivalent terms produce identical output" $ toDeBruijn (Abstraction "x" (Variable "x")) `shouldBe` toDeBruijn (Abstraction "y" (Variable "y"))