Eq-1.0: EqManips/Algorithm/Eval/Meta.hs
module EqManips.Algorithm.Eval.Meta ( metaEval
, metaFilter
) where
import Control.Applicative
import Data.List( sort )
import EqManips.Algorithm.Utils
import EqManips.Algorithm.Expand
import EqManips.Algorithm.Cleanup
import EqManips.Algorithm.Eval.Types
import EqManips.Types
import EqManips.EvaluationContext
import EqManips.FormulaIterator
import qualified EqManips.ErrorMessages as Err
-- | The only meta evaluation avaible
metaEval :: (Formula ListForm -> EqContext (Formula ListForm))
-> MetaOperation
-> Formula ListForm
-> EqContext (Formula ListForm)
metaEval evaluator Force f = evaluator f
metaEval evaluator Cleanup f = return . cleanup =<< evaluator f
metaEval _ Hold f = return f
metaEval _ Expand f = return . listifyFormula . expand . treeIfyFormula $ f
metaEval evaluator Sort (Formula (List _ lst)) =
Formula . list . sort <$> mapM unclap lst
where unclap formu = unTagFormula <$> evaluator (Formula formu)
metaEval evaluator Sort f = return . sortFormula =<< evaluator f
metaEval evaluator LambdaBuild (Formula (Lambda _ [([arg], body)])) = do
arg' <- metaFilter (\a -> unTagFormula <$> (evaluator $ Formula a)) arg
body' <- metaFilter (\a -> unTagFormula <$> (evaluator $ Formula a)) body
return . Formula $ lambda [([arg'], body')]
metaEval _ LambdaBuild _ = eqFail (Formula $ Block 1 1 1) Err.wrong_lambda_format
-- | Run across the formula to find meta evaluation and then
-- evaluate it. Used to level the use of Force/Hold & everyting.
metaFilter :: EvalFun -> FormulaPrim -> EqContext FormulaPrim
metaFilter evaluator formu = topDownScanning metaCatch formu
where metaCatch (Meta _ op f) = Just . unTagFormula
<$> (metaEval eval' op $ Formula f)
metaCatch _ = pure Nothing
eval' a = Formula <$> (evaluator $ unTagFormula a)