{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE Safe #-}
module Copilot.Theorem.Kind2.Output (parseOutput) where
import Data.List.Extra (isInfixOf, splitOn, stripInfix, trim)
import Data.Maybe (mapMaybe)
import Copilot.Theorem.Prove as P
import qualified Copilot.Core as C
import qualified Copilot.Theorem.Misc.Error as Err
parseOutput :: String
-> C.Prop
-> String
-> P.Output
parseOutput :: String -> Prop -> String -> Output
parseOutput String
propId Prop
propQuantifier String
xml
| String
"valid" String -> [String] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [String]
answers = Output -> Output -> Output
forall {p}. p -> p -> p
quantified (Status -> [String] -> Output
Output Status
Valid [])
(Status -> [String] -> Output
Output Status
Invalid [])
| String
"falsifiable" String -> [String] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [String]
answers = Output -> Output -> Output
forall {p}. p -> p -> p
quantified (Status -> [String] -> Output
Output Status
Invalid [])
(Status -> [String] -> Output
Output Status
Valid [])
| String
"unknown" String -> [String] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [String]
answers = Status -> [String] -> Output
Output Status
Unknown []
| [String] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [String]
answers = String -> Output
forall a. String -> a
err (String -> Output) -> String -> Output
forall a b. (a -> b) -> a -> b
$ String
"Answer for property " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
propId String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" not found"
| Bool
otherwise = String -> Output
forall a. String -> a
err (String -> Output) -> String -> Output
forall a b. (a -> b) -> a -> b
$ String
"Unrecognized status : " String -> String -> String
forall a. [a] -> [a] -> [a]
++ [String] -> String
unwords [String]
answers
where
quantified :: p -> p -> p
quantified p
ifValid p
ifInvalid = case Prop
propQuantifier of
C.Forall {} -> p
ifValid
C.Exists {} -> p
ifInvalid
answers :: [String]
answers = (String -> Maybe String) -> [String] -> [String]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe String -> Maybe String
answerText
([String] -> [String]) -> [String] -> [String]
forall a b. (a -> b) -> a -> b
$ (String -> Bool) -> [String] -> [String]
forall a. (a -> Bool) -> [a] -> [a]
filter String -> Bool
isRightProperty
([String] -> [String]) -> [String] -> [String]
forall a b. (a -> b) -> a -> b
$ String -> [String]
propertyElems String
xml
propertyElems :: String -> [String]
propertyElems = Int -> [String] -> [String]
forall a. Int -> [a] -> [a]
drop Int
1 ([String] -> [String])
-> (String -> [String]) -> String -> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String -> [String]
forall a. (Partial, Eq a) => [a] -> [a] -> [[a]]
splitOn String
"<Property "
isRightProperty :: String -> Bool
isRightProperty String
elem' =
(String
"name=\"" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> String
escapeAttr String
propId String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\"") String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isInfixOf` String
openingTag
where
openingTag :: String
openingTag = (Char -> Bool) -> String -> String
forall a. (a -> Bool) -> [a] -> [a]
takeWhile (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'>') String
elem'
answerText :: String -> Maybe String
answerText String
elem' = do
(_, rest) <- String -> String -> Maybe (String, String)
forall a. Eq a => [a] -> [a] -> Maybe ([a], [a])
stripInfix String
"<Answer" String
elem'
(_, rest') <- stripInfix ">" rest
let answer = String -> String
trim (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ (Char -> Bool) -> String -> String
forall a. (a -> Bool) -> [a] -> [a]
takeWhile (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'<') String
rest'
if null answer then Nothing else Just answer
err :: forall a . String -> a
err :: forall a. String -> a
err String
msg = String -> a
forall a. String -> a
Err.fatal (String -> a) -> String -> a
forall a b. (a -> b) -> a -> b
$
String
"Parse error while reading the Kind2 XML output : \n"
String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
msg String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\n\n" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
xml
escapeAttr :: String -> String
escapeAttr :: String -> String
escapeAttr = (Char -> String) -> String -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Char -> String
escapeChar
where
escapeChar :: Char -> String
escapeChar Char
'&' = String
"&"
escapeChar Char
'<' = String
"<"
escapeChar Char
'>' = String
">"
escapeChar Char
'"' = String
"""
escapeChar Char
c = [Char
c]