eflint-3.0.0.1: src/Language/EFLINT/Saturation.hs
{-# LANGUAGE LambdaCase #-}
module Language.EFLINT.Saturation (rebase_and_sat) where
import Language.EFLINT.Spec
import Language.EFLINT.State
import Language.EFLINT.Eval
import Control.Monad (forM)
import Control.Applicative (empty)
import qualified Data.Map as M
import qualified Data.Set as S
rebase_and_sat spec = saturate spec . rebase spec
rebase :: Spec -> State -> State
rebase spec s = s { contents = M.filterWithKey op (contents s) }
where op (_,d) i = not (from_sat i)
saturate :: Spec -> State -> State
saturate spec state = case saturate' spec state of
state' | state == state' -> state
| otherwise -> saturate spec state'
where
saturate' spec s = foldl op s (S.toList (derived spec))
where op s d = case find_decl spec d of
Nothing -> s
Just tdecl -> foldl clause s (derivation tdecl)
where clause s (HoldsWhen t)
| Products xs <- domain tdecl = derive xs (When (App d $ Right []) t) s
| otherwise = derive [no_decoration d] (When (Ref $ no_decoration d) t) s
clause s (Dv xs t) = derive xs t s
where derive xs t s = let dyn = do tes <- foreach xs (whenTagged (eval t) return)
forM tes $ \te -> sat_conditions te >>= \case
True -> return te
False -> empty
ress = case runSubs dyn spec s M.empty M.empty of
Left err -> [] --error ("saturation error:\n" ++ show err)
Right x -> x
in derive_all (concat ress) s