Eq-1.0: EqManips/Algorithm/Eval/Utils.hs
module EqManips.Algorithm.Eval.Utils( left
, right
, binOpReducer
, binEval
) where
import Control.Applicative
import Data.List( sort, foldl' )
import EqManips.Types
import EqManips.EvaluationContext
import EqManips.Algorithm.Eval.Types
import EqManips.Algorithm.Utils
import EqManips.Propreties
left :: (Monad m) => a -> m (Either a b)
left = return . Left
right :: (Monad m) => b -> m (Either a b)
right = return . Right
-- | Used to transform a binop to a scalar if size
-- is small
binOpReducer :: BinOperator -> [FormulaPrim] -> FormulaPrim
binOpReducer _ [x] = x
binOpReducer op lst = binOp op lst
-- | Assuming children in list form, parse the list to
-- keep the general listform.
binListRepacker :: BinOperator -> [FormulaPrim] -> FormulaPrim
binListRepacker op lst = binOpReducer op
$ foldl' emergeSubOp id lst []
where emergeSubOp acc (BinOp _ op2 subLst)
| op == op2 = acc . (subLst ++)
emergeSubOp acc sub = acc . (sub:)
-- | Evaluate a binary operator
-- Right associative operators are called with arguments reversed!
binEval :: BinOperator -> EvalOp -> EvalOp -> [FormulaPrim] -> EqContext FormulaPrim
binEval op f inv formulaList
| op `hasProp` Associativ && op `hasProp` Commutativ =
#ifdef _DEBUG
addTrace ("Sorting => ", treeIfyFormula . Formula $ binOp op formulaList) >>
#endif
binListRepacker op <$> biAssocM f inv (sort formulaList)
| op `obtainProp` AssocSide == OpAssocRight =
#ifdef _DEBUG
addTrace ("Basic Right Eval=>", treeIfyFormula . Formula $ binOp op formulaList) >>
#endif
binListRepacker op . reverse <$> (biAssocM f inv $ reverse formulaList)
| otherwise =
#ifdef _DEBUG
addTrace ("Basic Eval=>", treeIfyFormula . Formula $ binOp op formulaList) >>
#endif
binListRepacker op <$> biAssocM f inv formulaList