@@ -12,6 +12,12 @@ import parser.Parser
1212import lexer .Lexer
1313import printer .RecursivePrinter
1414import interpreters ._
15+ import smtlib .trees .Commands .*
16+ import smtlib .trees .Terms .Term
17+ import smtlib .trees .Tree
18+ import smtlib .trees .TreesOps
19+ import smtlib .theories .FixedSizeBitVectors .BitVectorSort
20+ import smtlib .theories .FloatingPoint .FloatingPointSort
1521
1622/** Provide helper functions to test solver interfaces and files.
1723 *
@@ -43,6 +49,7 @@ trait TestHelpers {
4349 def getZ3Interpreter : Interpreter = Z3Interpreter .buildDefault
4450 def getCVC4Interpreter : Interpreter = CVC4Interpreter .buildDefault
4551 def getCVC5Interpreter : Interpreter = CVC5Interpreter .buildDefault
52+ def getBitwuzlaInterpreter : Interpreter = BitwuzlaInterpreter .buildDefault
4653
4754 def isZ3Available : Boolean = try {
4855 val _: String = " z3 -help" .!!
@@ -67,6 +74,13 @@ trait TestHelpers {
6774 case _ : Exception => false
6875 }
6976
77+ def isBitwuzlaAvailable : Boolean = try {
78+ val _: String = " bitwuzla --version" .!!
79+ true
80+ } catch {
81+ case _ : Exception => false
82+ }
83+
7084 def executeZ3 (file : File )(f : (String ) => Unit ): Unit = {
7185 Seq (" z3" , " -smt2" , file.getPath) ! ProcessLogger (f, s => ())
7286 }
@@ -79,5 +93,47 @@ trait TestHelpers {
7993 Seq (" cvc5" , " --lang" , " smt" , file.getPath) ! ProcessLogger (f, s => ())
8094 }
8195
96+ def executeBitwuzla (file : File )(f : (String ) => Unit ): Unit = {
97+ Seq (" bitwuzla" , " -v" , " 0" , " --lang" , " --smt2" , file.getPath) ! ProcessLogger (f, s => ())
98+ }
99+
100+ // //////////////////////////////////////////////////////////////
101+ // Solver specific helpers
102+
103+ /**
104+ * Is test in the fragment supported by bitwuzla?
105+ *
106+ * May not contain ints, reals, arrays, ADTs
107+ *
108+ */
109+ def testIsBitwuzlaCompatible (cmds : Seq [Command ], formula : Term ): Boolean =
110+ def isCompat (term : Term ): Boolean =
111+ def violatingTerm (term : Tree , children : Seq [Boolean ]): Boolean = {
112+ import smtlib .theories .*
113+ term match
114+ case FixedSizeBitVectors .BitVectorConstant (_, _) => false // internally contains IntNumeral, but in a valid place
115+ case Ints .NumeralLit (_) => true
116+ case Reals .DecimalLit (_) => true
117+ case FixedSizeBitVectors .Int2BV (_, _) => true
118+ case FixedSizeBitVectors .BV2Nat (_) => true
119+ // this is enough to rule out the current problematic tests,
120+ // but may need refinement
121+ case _ => children.contains(true )
122+ }
123+ ! TreesOps .fold(violatingTerm)(term)
124+
125+ def compatibleCommand (cmd : Command ): Boolean =
126+ cmd match
127+ case DeclareFun (_, paramSorts, sort) => (sort +: paramSorts).forall {
128+ case BitVectorSort (_) => true
129+ case FloatingPointSort (_, _) => true
130+ case _ => false
131+ }
132+ case DeclareSort (_, _) => false
133+ case DeclareDatatypes (_) => false
134+ case Assert (term) => isCompat(term)
135+ case _ => true // may need refinement
136+ cmds.forall(compatibleCommand) && (isCompat(formula))
137+
82138}
83139
0 commit comments