module Tip.Property where
import Tip.Core
import Tip.Id
import Tip.Pretty
import Tip.Pretty.SMT
import Tip.ParseDSL
import Tip.GHCUtils
import Control.Monad.Error
import Control.Applicative
import Data.Foldable (Foldable)
import Data.List (intercalate,union)
import Data.Map (Map)
import Data.Maybe (mapMaybe)
import Data.Traversable (Traversable)
import qualified Data.Map as M
import Var (Var)
import TysWiredIn (trueDataCon,falseDataCon,boolTyCon)
trProperty :: Function Id -> Either String (Formula Id)
trProperty (Function _name tvs [] res_ty b) = case unLam b of
(args,e) -> do
pr <- parseProperty e
return (Formula Prove UserAsserted tvs (mkQuant Forall args pr))
where
unLam (Lam xs e) = let (ys,e') = unLam e in (xs ++ ys,e')
unLam e = ([],e)
parseProperty :: Expr Id -> Either String (Expr Id)
parseProperty = goo 0
where
go = goo 1
goo i e0@(projAt -> Just (projGlobal -> Just x,Lam bs e))
| isId "forAll" x || isId "Forall" x = mkQuant Forall bs <$> go e
| isId "exists" x || isId "Exists" x = mkQuant Exists bs <$> go e
goo i e0@(projAt -> Just (projGlobal -> Just x,e))
| isId "bool" x = return e
| isId "Neg" x || isId "neg" x || isId "question" x = neg <$> go e
goo i e0@(projAt -> Just (projAt -> Just (projGlobal -> Just x,e1),e2))
| isId "===" x || isId ":=:" x = return (e1 === e2)
| isId "=/=" x = return (e1 =/= e2)
| isId "==>" x || isId "Given" x = (==>) <$> go e1 <*> go e2
| isId ".&&." x || isId "And" x = (/\) <$> go e1 <*> go e2
| isId ".||." x || isId "Or" x = (\/) <$> go e1 <*> go e2
goo i e0 | i > 0 && exprType e0 == boolType = return e0
goo i e0 = throwError $ "Cannot parse property: " ++ ppRender e0