module PropPlogic where
import Prelude hiding (pred)
import PropPosSyntax(HsName,HsIdent,HsIdentI(..),HsExp,HsPat,HsQualType,hsPVar,
Assertion,Predicate,PredArg,PropOp,Quantifier)
import HasPropStruct
import MUtils
import Monad(mplus)
data Plogic
= Quant Quantifier HsName (Maybe HsQualType) Plogic
| App HsName [PredArg HsExp Plogic]
| InfixApp Plogic HsName Plogic
| Neg Plogic
| Op PropOp Plogic Plogic
| Equal HsExp HsExp
| Has HsExp Plogic
| Arrow Plogic Plogic
| Lfp HsName Plogic
| Gfp HsName Plogic
| Nil
| Lifted HsExp
| Strong Plogic
| Comp [(HsPat,Maybe HsQualType)] Plogic
| Abs [HsIdent] Plogic
| Paren Plogic -- preserve parens to rewrite infix apps after parsing
-- A hack to give '->' higher precedence than ':::' in Plogic assertions:
Has e p1 `arrow` p2 = Has e (p1 `Arrow` p2)
p1 `arrow` p2 = p1 `Arrow` p2
plogicAssertion p = prop p
prop :: (Functor m,Monad m) => Plogic -> m Assertion
prop p =
case p of
Quant q n optt p -> quant q n optt # prop p
App n args -> propApp n # plogicArgs args
Neg p -> propNeg # prop p
Op op p1 p2 -> propOp op # prop p1 <# prop p2
Equal e1 e2 -> return (propEqual e1 e2)
Has e p -> propHas e # pred p
Paren p -> propParen # prop p
_ -> fail "Bad Plogic assertion" -- !!!
plogicArgs args = mapM plogicArg args
plogicArg args = either (return . Left) (Right #. pred) args
propDecl loc c xs p = uncurry (hsPropDecl loc c) # pred' xs p
pred' [] p = (,) [] # pred p
pred' args p = ((,) args # pred p) `mplus` pred'' args p
where
pred'' args p =
do HsVar x <- return (last args)
(,) (init args) . predComp [(hsPVar x,Nothing)] # prop p
pred :: (Functor m,Monad m) => Plogic -> m Predicate
pred p =
case p of
App n args -> predApp n # plogicArgs args
Arrow p1 p2 -> predArrow # pred p1 <# pred p2
InfixApp p1 i p2 -> predInfixApp # pred p1 <# return i <# pred p2
Neg p -> predNeg Nothing # pred p
Op op p1 p2 -> predOp op Nothing # pred p1 <# pred p2
Lfp i p -> predLfp i # pred p
Gfp i p -> predGfp i # pred p
Nil -> return predNil
Lifted e -> return (predLifted e)
Strong p -> predStrong # pred p
Comp tps p -> predComp tps # prop p
Abs is p -> predAbs is # pred p
Paren p -> predParen # pred p
_ -> fail "Bad Plogic predicate"