module Tip.Pass.Booleans where
import Tip.Core
import Data.Generics.Geniplate
theoryBoolOpToIf :: Ord a => Theory a -> Theory a
theoryBoolOpToIf Theory{..} =
Theory{
thy_funcs = map boolOpToIf thy_funcs,
thy_asserts =
let k fm@Formula{..} = fm { fm_body = formulaBoolOpToIf fm_body }
in map k thy_asserts,
..
}
formulaBoolOpToIf :: Ord a => Expr a -> Expr a
formulaBoolOpToIf e0 =
case e0 of
Builtin op :@: args@(a:_)
| op `elem` [And,Or,Not,Implies] ||
op `elem` [Equal,Distinct] && hasBoolType a ->
Builtin op :@: map formulaBoolOpToIf args
Quant qi q as e -> Quant qi q as (formulaBoolOpToIf e)
_ -> boolOpToIf e0
hasBoolType :: Ord a => Expr a -> Bool
hasBoolType e = exprType e == boolType
boolOpToIf :: (Ord a,TransformBi (Expr a) (f a)) => f a -> f a
boolOpToIf = transformExprIn $
\ e0 -> case e0 of
Builtin And :@: [a,b] -> makeIf a b falseExpr
Builtin Or :@: [a,b] -> makeIf a trueExpr b
Builtin Not :@: [a] -> makeIf a falseExpr trueExpr
Builtin Implies :@: [a,b] -> makeIf a b trueExpr
Builtin Equal :@: [a,b] | hasBoolType a -> makeIf a b (neg_if b)
Builtin Distinct :@: [a,b] | hasBoolType a -> makeIf a (neg_if b) b
_ -> e0
where
neg_if a = makeIf a falseExpr trueExpr
ifToBoolOp :: TransformBi (Expr a) (f a) => f a -> f a
ifToBoolOp = transformExprIn $
\ e0 -> case ifView e0 of
Just (b,t,f)
| Just True <- boolView t -> b \/ f
| Just False <- boolView t -> neg b /\ f
| Just True <- boolView f -> b ==> t
| Just False <- boolView f -> b /\ t
_ -> e0