summaryrefslogtreecommitdiff
path: root/source/Tptp/SmtLib.hs
blob: 418501991083c4441ae3c911ec1fd1b356c95b0b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
{-# LANGUAGE NoImplicitPrelude #-}


module Tptp.SmtLib where
-- ^ Export TPTP problems to SMT-LIB S-expressions

import Tptp.UnsortedFirstOrder qualified as Fof
import Text.Builder
import Prelude hiding (head, tail)
import Data.Text qualified as Text
import Data.List.NonEmpty qualified as NonEmpty

buildList :: [Builder] -> Builder
buildList bs = char '(' <> intercalate (char ' ') bs <> char ')'
{-# INLINE buildList #-}

quotedAtom :: Builder -> Builder
quotedAtom b = char '|' <> b <> char '|'
{-# INLINE quotedAtom #-}

buildAtomicWord :: Fof.AtomicWord -> Builder
buildAtomicWord (Fof.AtomicWord w) = if Fof.isProperAtomicWord w then text w else quotedAtom (text w)

buildVariable :: Fof.Variable -> Builder
buildVariable (Fof.Variable v) = text (Text.replace "'" "_" v)

buildApply :: Fof.AtomicWord -> [Fof.Expr] -> Builder
buildApply f args = buildList (buildAtomicWord f : map buildExpr args)

buildExpr :: Fof.Expr -> Builder
buildExpr = \case
    Fof.Apply f [] -> buildAtomicWord f
    Fof.Apply f args -> buildApply f args
    Fof.Var var -> buildVariable var
    Fof.Top -> text "$true"
    Fof.Bottom -> text "$false"
    Fof.Eq t1 t2 -> buildExpr t1 <> char '=' <> buildExpr t2
    Fof.NotEq t1 t2 -> buildExpr t1 <> text "!=" <> buildExpr t2
    Fof.Not f ->
        text "(not " <> buildExpr f <> char ')'
    Fof.Conn Fof.And f1 f2 ->
        text "(and  " <> buildExpr f1 <> char ' ' <> buildExpr f2 <> char ' '
    Fof.Conn Fof.Or f1 f2 ->
        text "(or  " <> buildExpr f1 <> char ' ' <> buildExpr f2 <> char ' '
    Fof.Conn Fof.Imply f1 f2 ->
        text "(=>  " <> buildExpr f1 <> char ' ' <> buildExpr f2 <> char ' '
    Fof.Conn Fof.Iff f1 f2 ->
        text "(=  " <> buildExpr f1 <> char ' ' <> buildExpr f2 <> char ' '
    Fof.Quantified quant vars f ->
        buildQuantifier quant <> char ' ' <>
        buildList (map buildVariable (NonEmpty.toList vars))
        <> char ' ' <> buildExpr f
    where
        buildQuantifier :: Fof.Quantifier -> Builder
        buildQuantifier Fof.Forall = "(forall "
        buildQuantifier Fof.Exists = "(exists "



buildName :: Fof.Name -> Builder
buildName = \case
        Fof.NameAtomicWord w -> buildAtomicWord w
        Fof.NameInt n -> decimal n

buildAnnotatedFormula :: Fof.AnnotatedFormula -> Builder
buildAnnotatedFormula (Fof.AnnotatedFormula _name _role phi) =
        "(assert " <> buildExpr phi <> char ')'

buildTask :: Fof.Task -> Builder
buildTask (Fof.Task fofs) = intercalate (char '\n') decls <> "\n(check-sat)\n"
    where
        decls = "(set-logic UF)" : map buildAnnotatedFormula fofs