{-# OPTIONS_HADDOCK hide #-}
{-# LANGUAGE RecordWildCards, FlexibleContexts, FlexibleInstances, GADTs, PatternSynonyms, GeneralizedNewtypeDeriving, MultiParamTypeClasses, UndecidableInstances, TemplateHaskell #-}
module QuickSpec.Pruning.UntypedTwee where
import QuickSpec.Testing
import QuickSpec.Pruning
import QuickSpec.Prop
import QuickSpec.Term
import QuickSpec.Type
import QuickSpec.Utils
import qualified Twee
import qualified Twee.Equation as Twee
import qualified Twee.KBO as KBO
import qualified Twee.Base as Twee
import Twee hiding (Config(..))
import Twee.Rule hiding (normalForms)
import Twee.Proof hiding (Config, defaultConfig)
import Twee.Base(Ordered(..), Extended(..), EqualsBonus, pattern F, pattern Empty, unpack)
import Control.Monad.Trans.Reader
import Control.Monad.Trans.State.Strict hiding (State)
import Control.Monad.Trans.Class
import Control.Monad.IO.Class
import QuickSpec.Terminal
import qualified Data.Set as Set
import Data.Set(Set)
data Config =
Config {
cfg_max_term_size :: Int,
cfg_max_cp_depth :: Int }
makeLensAs ''Config
[("cfg_max_term_size", "lens_max_term_size"),
("cfg_max_cp_depth", "lens_max_cp_depth")]
instance (Pretty fun, PrettyTerm fun, Ord fun, Typeable fun, Twee.Sized fun, Arity fun, EqualsBonus fun) => Ordered (Extended fun) where
lessEq = KBO.lessEq
lessIn = KBO.lessIn
newtype Pruner fun m a =
Pruner (ReaderT (Twee.Config (Extended fun)) (StateT (State (Extended fun)) m) a)
deriving (Functor, Applicative, Monad, MonadIO, MonadTester testcase term, MonadTerminal)
instance MonadTrans (Pruner fun) where
lift = Pruner . lift . lift
run :: (Sized fun, Monad m) => Config -> Pruner fun m a -> m a
run Config{..} (Pruner x) =
evalStateT (runReaderT x config) initialState
where
config =
defaultConfig {
Twee.cfg_accept_term = Just (\t -> size t <= cfg_max_term_size),
Twee.cfg_max_cp_depth = cfg_max_cp_depth }
instance Sized fun => Sized (Twee.Term fun) where
size (Twee.Var _) = 1
size (Twee.App f ts) =
size (Twee.fun_value f) + sum (map size (Twee.unpack ts))
instance Sized fun => Sized (Twee.Extended fun) where
size Twee.Minimal = 1
size (Twee.Skolem _) = 1
size (Twee.Function f) = size f
instance (Ord fun, Typeable fun, Arity fun, Twee.Sized fun, PrettyTerm fun, EqualsBonus fun, Monad m) =>
MonadPruner (Term fun) (Term fun) (Pruner fun m) where
normaliser = Pruner $ do
state <- lift get
return $ \t ->
let u = normaliseTwee state t in
u
add ([] :=>: t :=: u) = Pruner $ do
state <- lift get
config <- ask
let
t' = normalFormsTwee state t
u' = normalFormsTwee state u
lift (put $! addTwee config t u state)
return (Set.null (Set.intersection t' u'))
add _ =
error "twee pruner doesn't support non-unit equalities"
normaliseTwee :: (Ord fun, Typeable fun, Arity fun, Twee.Sized fun, PrettyTerm fun, EqualsBonus fun) =>
State (Extended fun) -> Term fun -> Term fun
normaliseTwee state t =
fromTwee $
result (normaliseTerm state (simplifyTerm state (skolemise t)))
normalFormsTwee :: (Ord fun, Typeable fun, Arity fun, Twee.Sized fun, PrettyTerm fun, EqualsBonus fun) =>
State (Extended fun) -> Term fun -> Set (Term fun)
normalFormsTwee state t =
Set.map fromTwee $
Set.map result (normalForms state (skolemise t))
addTwee :: (Ord fun, Typeable fun, Arity fun, Twee.Sized fun, PrettyTerm fun, EqualsBonus fun) =>
Twee.Config (Extended fun) -> Term fun -> Term fun -> State (Extended fun) -> State (Extended fun)
addTwee config t u state =
completePure config $
addAxiom config state axiom
where
axiom = Axiom 0 (prettyShow (t :=: u)) (toTwee t Twee.:=: toTwee u)
toTwee :: (Ord f, Typeable f) =>
Term f -> Twee.Term (Extended f)
toTwee = Twee.build . tt
where
tt (Var (V _ x)) =
Twee.var (Twee.V x)
tt (App f ts) =
Twee.app (Twee.fun (Function f)) (map tt ts)
skolemise :: (Ord f, Typeable f) =>
Term f -> Twee.Term (Extended f)
skolemise = Twee.build . sk
where
sk (Var (V _ x)) =
Twee.con (Twee.fun (Skolem (Twee.V x)))
sk (App f ts) =
Twee.app (Twee.fun (Function f)) (map sk ts)
fromTwee :: Twee.Term (Extended f) -> Term f
fromTwee = unsk
where
unsk (Twee.App (F Minimal) Empty) =
Var (V typeVar 0)
unsk (Twee.App (F (Skolem (Twee.V x))) Empty) =
Var (V typeVar x)
unsk (Twee.App (F (Function f)) ts) =
App f (map unsk (unpack ts))
unsk _ = error "variable introduced by rewriting"