packages feed

Jikka-5.6.0.0: test/Jikka/Core/Language/EtaSpec.hs

{-# LANGUAGE OverloadedStrings #-}

module Jikka.Core.Language.EtaSpec
  ( spec,
  )
where

import Jikka.Common.Alpha
import Jikka.Common.Error
import qualified Jikka.Core.Convert.TypeInfer as TypeInfer
import Jikka.Core.Language.Eta
import Jikka.Core.Language.Expr
import Jikka.Core.Parse (parseExpr)
import Test.Hspec

etaExpand'' :: [(VarName, Type)] -> Expr -> Either Error (Maybe Expr)
etaExpand'' env = flip evalAlphaT 0 . etaExpand' env

parseExpr' :: [(VarName, Type)] -> [String] -> Expr
parseExpr' env = fromSuccess . flip evalAlphaT 100 . (TypeInfer.runExpr env <=< parseExpr . unlines)

spec :: Spec
spec = do
  describe "etaExpand'" $ do
    it "works on sum" $ do
      let env = []
      let e =
            parseExpr'
              env
              [ "sum"
              ]
      let expected =
            parseExpr'
              env
              [ "fun $0 -> sum $0"
              ]
      etaExpand'' env e `shouldBe` Right (Just expected)
    it "works on let" $ do
      let env = []
      let e =
            parseExpr'
              env
              [ "let f = fun x y -> x + y",
                "in f"
              ]
      let expected =
            parseExpr'
              env
              [ "fun $0 $1 ->",
                "    (let f = fun x y -> x + y",
                "    in f) $0 $1"
              ]
      etaExpand'' env e `shouldBe` Right (Just expected)
    it "works on a partial lambda" $ do
      let env = [("f", Fun3Ty IntTy BoolTy UnitTy (ListTy IntTy))]
      let e =
            parseExpr'
              env
              [ "fun (x: int) -> f x"
              ]
      let expected =
            parseExpr'
              env
              [ "fun (x: int) ($0: bool) ($1: unit) -> f x $0 $1"
              ]
      etaExpand'' env e `shouldBe` Right (Just expected)
    it "does nothing on integers" $ do
      let env = []
      let e =
            parseExpr'
              env
              [ "12"
              ]
      etaExpand'' env e `shouldBe` Right Nothing

  describe "etaReduce'" $ do
    it "works on sum" $ do
      let env = []
      let e =
            parseExpr'
              env
              [ "fun $0 -> sum $0"
              ]
      let expected =
            parseExpr'
              env
              [ "sum"
              ]
      etaReduce' e `shouldBe` Just expected
    it "works on an application which is longer than lambda abstraction" $ do
      let env = [("f", Fun3STy IntTy)]
      let e =
            parseExpr'
              env
              [ "fun x y -> f 12 x y"
              ]
      let expected =
            parseExpr'
              env
              [ "f 12"
              ]
      etaReduce' e `shouldBe` Just expected
    it "does nothing on a flipped application" $ do
      let env = [("f", Fun2STy IntTy)]
      let e =
            parseExpr'
              env
              [ "fun x y -> f y x"
              ]
      etaReduce' e `shouldBe` Nothing