Skip to content

Commit 0dc7f3e

Browse files
committed
Add BigInt extraction and test for Int->BigInt conversion
1 parent e6bfc84 commit 0dc7f3e

File tree

3 files changed

+72
-15
lines changed

3 files changed

+72
-15
lines changed

src/main/scala/z3/scala/Z3Model.scala

+17-15
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,30 @@ package z3.scala
33
import com.microsoft.z3.Native
44

55
object Z3Model {
6+
implicit def ast2bigint(model: Z3Model, ast: Z3AST): Option[BigInt] = {
7+
model.eval(ast) flatMap { res =>
8+
model.context.getNumeralInt(res).value.map(BigInt(_)).orElse {
9+
Some(BigInt(res.toString, 10))
10+
}
11+
}
12+
}
13+
614
implicit def ast2int(model: Z3Model, ast: Z3AST): Option[Int] = {
7-
val res = model.eval(ast)
8-
if (res.isEmpty)
9-
None
10-
else
11-
model.context.getNumeralInt(res.get).value
15+
model.eval(ast) flatMap { res =>
16+
model.context.getNumeralInt(res).value
17+
}
1218
}
1319

1420
implicit def ast2bool(model: Z3Model, ast: Z3AST): Option[Boolean] = {
15-
val res = model.eval(ast)
16-
if (res.isEmpty)
17-
None
18-
else
19-
model.context.getBoolValue(res.get)
21+
model.eval(ast) flatMap { res =>
22+
model.context.getBoolValue(res)
23+
}
2024
}
2125

2226
implicit def ast2char(model: Z3Model, ast: Z3AST): Option[Char] = {
23-
val res = model.eval(ast)
24-
if (res.isEmpty)
25-
None
26-
else
27-
model.context.getNumeralInt(res.get).value.map(_.toChar)
27+
model.eval(ast) flatMap { res =>
28+
model.context.getNumeralInt(res).value.map(_.toChar)
29+
}
2830
}
2931
}
3032

src/test/scala/z3/scala/IntArith.scala

+29
Original file line numberDiff line numberDiff line change
@@ -40,5 +40,34 @@ class IntArith extends FunSuite with Matchers {
4040

4141
z3.delete
4242
}
43+
44+
testIntToBigIntConversion(0)
45+
testIntToBigIntConversion(42)
46+
testIntToBigIntConversion(-42)
47+
testIntToBigIntConversion(Int.MinValue)
48+
testIntToBigIntConversion(Int.MaxValue)
49+
50+
private def testIntToBigIntConversion(value: Int): Unit = test(s"Integer conversion: $value") {
51+
val z3 = new Z3Context("MODEL" -> true)
52+
53+
val Int = z3.mkIntSort
54+
val BV32 = z3.mkBVSort(32)
55+
56+
val in = z3.mkConst(z3.mkStringSymbol("in"), BV32)
57+
val out = z3.mkConst(z3.mkStringSymbol("out"), Int)
58+
59+
val solver = z3.mkSolver
60+
61+
solver.assertCnstr(z3.mkEq(in, z3.mkInt(value, BV32)))
62+
solver.assertCnstr(z3.mkEq(out, z3.mkBV2Int(in, true)))
63+
solver.assertCnstr(z3.mkEq(out, z3.mkInt(value, Int)))
64+
65+
val (sol, model) = solver.checkAndGetModel
66+
67+
sol should equal(Some(true))
68+
model.evalAs[BigInt](out) should equal(Some(BigInt(value)))
69+
70+
z3.delete
71+
}
4372
}
4473

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package z3.scala
2+
3+
import org.scalatest.{FunSuite, Matchers}
4+
5+
class IntExtraction extends FunSuite with Matchers {
6+
7+
test(s"BigInt extraction") {
8+
val z3 = new Z3Context("MODEL" -> true)
9+
10+
val i = z3.mkIntSort
11+
val x = z3.mkConst(z3.mkStringSymbol("x"), i)
12+
val m = z3.mkInt(Int.MaxValue, i)
13+
14+
val solver = z3.mkSolver
15+
16+
solver.assertCnstr(z3.mkEq(x, z3.mkAdd(m, m)))
17+
18+
val (sol, model) = solver.checkAndGetModel
19+
20+
sol should equal(Some(true))
21+
model.evalAs[BigInt](x) should equal(Some(BigInt(Int.MaxValue) * 2))
22+
23+
z3.delete
24+
}
25+
}
26+

0 commit comments

Comments
 (0)