{-# LANGUAGE DeriveGeneric, DeriveDataTypeable, MultiParamTypeClasses #-}
module TestRefine (test_refine) where
import Data.Typeable (Typeable)
import GHC.Generics (Generic)
import Unbound.Generics.LocallyNameless
import AlphaAssertions
import Test.Tasty
import Test.Tasty.HUnit
-- Regular variables range over terms
type Var = Name Term
-- Metavariables range over extracts
type MetaVar = Name Extract
data Term
= Var Var
| Hole MetaSubst MetaVar -- Every occurance of a metavariable must subst away fvs of extract
| Lam (Bind Var Term)
| App Term Term
deriving (Generic, Typeable, Show)
-- Extracts represent code extracted via refinement
newtype Extract = Extract { extractTerm :: Term }
deriving (Generic, Typeable, Show)
newtype MetaSubst = MetaSubst { unMetaSubst :: [(Var, Term)] }
deriving (Generic, Typeable, Show)
instance Alpha Term
instance Alpha Extract
instance Alpha MetaSubst
instance Subst Term Term where
isvar (Var x) = Just $ SubstName x
isvar _ = Nothing
instance Subst Extract Term where
isCoerceVar (Hole ms x) = Just $ SubstCoerce x (Just . applyMetaSubst ms)
isCoerceVar _ = Nothing
applyMetaSubst :: MetaSubst -> Extract -> Term
applyMetaSubst (MetaSubst ms) e = substs ms $ extractTerm e
instance Subst Term MetaSubst
instance Subst Extract MetaSubst
test_refine :: TestTree
test_refine =
testCase "subst ?1 x ?0 = ?0"
$ let h0 = s2n "0" :: MetaVar
h1 = s2n "1" :: MetaVar
a = s2n "a" :: Var
x = s2n "x" :: Var
e1 = Hole (MetaSubst [(a, Hole (MetaSubst []) h1)]) h0
e2 = Hole (MetaSubst [(a, Var x)]) h0
in assertAeq (subst h1 (Extract $ Var x) e1) e2