├── .gitignore ├── .larabot.conf ├── LICENSE ├── NOTICE ├── README.md ├── build.sbt ├── lib-bin └── README ├── project ├── Build.scala ├── build.properties └── build.sbt ├── src ├── main │ ├── java │ │ └── z3 │ │ │ ├── AbstractErrorHandler.java │ │ │ ├── DefaultErrorHandler.java │ │ │ ├── Z3ErrorException.java │ │ │ ├── Z3Wrapper.java │ │ │ └── java │ │ │ ├── README │ │ │ ├── Z3AST.java │ │ │ ├── Z3Context.java │ │ │ ├── Z3Model.java │ │ │ ├── Z3Pointer.java │ │ │ ├── Z3Sort.java │ │ │ └── Z3Symbol.java │ └── scala │ │ └── z3 │ │ └── scala │ │ ├── Default.scala │ │ ├── Z3AST.scala │ │ ├── Z3ASTKind.scala │ │ ├── Z3ASTVector.scala │ │ ├── Z3Context.scala │ │ ├── Z3DeclKind.scala │ │ ├── Z3FuncDecl.scala │ │ ├── Z3FuncInterp.scala │ │ ├── Z3FuncInterpEntry.scala │ │ ├── Z3Model.scala │ │ ├── Z3Object.scala │ │ ├── Z3Optimizer.scala │ │ ├── Z3Params.scala │ │ ├── Z3Pattern.scala │ │ ├── Z3Pointer.scala │ │ ├── Z3RefCountQueue.scala │ │ ├── Z3SearchFailure.scala │ │ ├── Z3Solver.scala │ │ ├── Z3Sort.scala │ │ ├── Z3Symbol.scala │ │ ├── Z3SymbolKind.scala │ │ ├── Z3Tactic.scala │ │ ├── dsl │ │ ├── Operands.scala │ │ ├── Trees.scala │ │ ├── ValHandler.scala │ │ └── package.scala │ │ └── package.scala └── test │ └── scala │ └── z3 │ └── scala │ ├── ADTs.scala │ ├── Abs.scala │ ├── Arrays.scala │ ├── Calendar.scala │ ├── Core.scala │ ├── ForComprehension.scala │ ├── IntArith.scala │ ├── NQueens.scala │ ├── Optimizer.scala │ ├── Quantifiers.scala │ ├── SatSolver.scala │ ├── Sequences.scala │ └── Sets.scala └── z3_mk_abs.patch /.gitignore: -------------------------------------------------------------------------------- 1 | .bsp/ 2 | 3 | # Generated shared lib for various platforms 4 | lib-bin/*.so 5 | lib-bin/*.dylib 6 | lib-bin/*.jnilib 7 | lib-bin/*dSYM 8 | lib-bin/*.dll 9 | jars/ 10 | 11 | # sbt specific 12 | lib_managed 13 | project/boot 14 | project/build/target 15 | target 16 | 17 | # Generated by javah 18 | src/c/z3_Z3Wrapper.h 19 | src/c/z3_Z3Wrapper_IntPtr.h 20 | 21 | # Generated at compilation 22 | src/main/java/z3/LibraryChecksum.java 23 | 24 | # Z3 distributions 25 | z3/* 26 | 27 | # Vim and more 28 | *.swp 29 | 30 | # IDEA project files 31 | .idea/* 32 | *.iml 33 | -------------------------------------------------------------------------------- /.larabot.conf: -------------------------------------------------------------------------------- 1 | commands = [ 2 | "sbt -batch test" 3 | ] 4 | 5 | trusted = [ 6 | "colder" 7 | "larsrh" 8 | "mantognini" 9 | "manoskouk" 10 | "MikaelMayer" 11 | "ravimad" 12 | "regb" 13 | "romac" 14 | "samarion" 15 | "vkuncak" 16 | "redelmann" 17 | "jad-hamza" 18 | "gsps" 19 | "mario-bucev" 20 | ] 21 | 22 | notify { 23 | master = [ 24 | "leon-dev@googlegroups.com" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | ScalaZ3 2 | Copyright (c) 2009-2019 EPFL 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"). 5 | Unless required by applicable law or agreed to in writing, software 6 | distributed under the License is distributed on an "AS IS" BASIS, 7 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 8 | See the License for the specific language governing permissions and 9 | limitations under the License. 10 | 11 | The software may link to projects with other licenses. 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ScalaZ3 ![Build status](http://laraquad4.epfl.ch:9000/epfl-lara/ScalaZ3/status/master) 2 | ======= 3 | 4 | This is ScalaZ3 for Z3 4.8.14 and Scala 3.2.0. 5 | 6 | [API documentation](https://epfl-lara.github.io/ScalaZ3/z3/index.html) 7 | ------------------- 8 | 9 | Compiling ScalaZ3 10 | ----------------- 11 | 12 | You should have Java and SBT 1.7.x installed. 13 | 14 | ### Mac & Unix 15 | 16 | Run 17 | 18 | sbt +package 19 | 20 | to compile Z3 4.8.14 for Scala 3.2.0. 21 | 22 | The JAR files will be in `target/scala-3.2.0/scalaz3_3-4.8.14.jar` 23 | and will contain the shared library dependencies. 24 | 25 | For testing, run 26 | 27 | sbt +test 28 | 29 | ### Windows 30 | 31 | #### Prerequisites 32 | 33 | Install Visual Studio Community edition 2015 34 | Make sure to have the following: 35 | - Programming Languages 36 | - Visual C++ 37 | - Common tools for Visual C++ 2015 (CHECK) 38 | 39 | Install JDK 1.8 (or higher) 40 | * There is a folder `include` in `C:\Program Files\Java\jdk1.8.0_121`. Create a copy of this `include` folder directly in `C:\Program Files\Java\` 41 | 42 | Install a 64-bit version of GCC. To chec that, run `gcc -v`, it should display 64. If it shows `mingw32` you need to install a new version. 43 | 44 | We were able to successfully package and test ScalaZ3 with the MinGW 64bit compiler suite with the following options. 45 | 46 | Version: 6.3.0 47 | Architecture: x86_64 48 | Threads: wind32 49 | Esception: seh 50 | Build revision: 2 51 | 52 | #### Packaging instructions 53 | 54 | Open the native x64 command prompt (available in the start menu under the Visual Studio folder) 55 | 56 | Now navigate to the scalaz3 folder and type: 57 | 58 | sbt +package 59 | 60 | The JAR files will be in `target/scala-3.2.0/scalaz3_3-4.8.14.jar` and will contain the shared library 61 | dependencies. 62 | 63 | #### Test your package. 64 | 65 | Run 66 | 67 | sbt test 68 | 69 | If this does not work, check that `lib-bin/scalaz3.dll` is a correctly set up 64 bit dll: 70 | 71 | dumpbin /headers lib-bin/scalaz3.dll | findstr machine 72 | 73 | The output should be (x64). If you encounter any other issue, please let us know. 74 | 75 | Using ScalaZ3 76 | ------------- 77 | 78 | ### On a single operating system / architecture 79 | 80 | Create a folder named `unmanaged` at the same level as your `build.sbt` file, and copy the JAR file in `target/scala-3.2.0/scalaz3_3-4.8.14.jar` into it. 81 | 82 | Then add, the following lines to your `build.sbt` file: 83 | 84 | ```scala 85 | Compile / unmanagedJars += { 86 | baseDirectory.value / "unmanaged" / s"scalaz3_3-4.8.14.jar" 87 | } 88 | ``` 89 | 90 | ### On multiple operating systems / architectures 91 | 92 | If you want to use ScalaZ3 in a project which must support various operating systems and architectures, you will have to compile ScalaZ3 on each of those systems/architectures, following the instructions above. 93 | 94 | Make sure to name the resulting JAR files as `scalaz3-[osName]-[osArch]-3.jar`, where: 95 | 96 | - `[osName]` is one of: `mac`, `win`, `unix`. 97 | - `[osArch]` corresponds to `System.getProperty("sun.arch.data.model")`, ie. `x64`, `fds`, etc. 98 | 99 | Create a folder named `unmanaged` at the same level as your `build.sbt` file, and copy the aforementioned JAR files into it. 100 | 101 | Add the following lines to your `build.sbt` file: 102 | 103 | ```scala 104 | val osInf = Option(System.getProperty("os.name")).getOrElse("") 105 | val osArch = System.getProperty("sun.arch.data.model") 106 | 107 | val isUnix = osInf.indexOf("nix") >= 0 || osInf.indexOf("nux") >= 0 108 | val isWindows = osInf.indexOf("Win") >= 0 109 | val isMac = osInf.indexOf("Mac") >= 0 110 | 111 | val osName = if (isWindows) "win" else if (isMac) "mac" else "unix" 112 | 113 | Compile / unmanagedJars += { 114 | baseDirectory.value / "unmanaged" / s"scalaz3-$osName-$osArch-3.jar" 115 | } 116 | ``` 117 | -------------------------------------------------------------------------------- /build.sbt: -------------------------------------------------------------------------------- 1 | import ScalaZ3Build._ 2 | 3 | lazy val root = (project in file(".")) 4 | .settings( 5 | name := "ScalaZ3", 6 | version := "4.8.14", 7 | organization := "ch.epfl.lara", 8 | scalacOptions ++= Seq( 9 | "-deprecation", 10 | "-unchecked", 11 | "-feature", 12 | ), 13 | scalaVersion := "3.2.0", 14 | libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.14" % "test", 15 | Test / fork := true, 16 | checksumKey := checksumTask.value, 17 | gccKey := gccTask.value, 18 | z3Key := z3Task.value, 19 | Compile / Keys.`package` := packageTask.value, 20 | Compile / unmanagedJars += Attributed.blank(z3JarFile), 21 | Compile / compile := ((Compile / compile) dependsOn checksumTask).value, 22 | Test / test := ((Test / test) dependsOn (Compile / Keys.`package`)).value, 23 | Test / compile := ((Test / compile) dependsOn (Compile / Keys.`package`)).value, 24 | Test / testOnly := ((Test / testOnly) dependsOn (Compile / Keys.`package`)).evaluated, 25 | Test / internalDependencyClasspath := testClasspath.value, 26 | Compile / packageBin / mappings := newMappingsTask.value, 27 | ) 28 | 29 | -------------------------------------------------------------------------------- /lib-bin/README: -------------------------------------------------------------------------------- 1 | The shared library for the bindings will be generated in this directory. 2 | -------------------------------------------------------------------------------- /project/Build.scala: -------------------------------------------------------------------------------- 1 | import sbt._ 2 | import sbt.Keys._ 3 | import org.eclipse.jgit.api._ 4 | import org.eclipse.jgit.treewalk.filter.PathFilter 5 | 6 | import java.io.{FileInputStream, InputStream} 7 | import scala.sys.process._ 8 | 9 | object ScalaZ3Build { 10 | 11 | lazy val z3SourceRepo = "https://github.com/Z3Prover/z3.git" 12 | lazy val z3SourceTag = "z3-4.8.14" 13 | 14 | lazy val PS = java.io.File.pathSeparator 15 | lazy val DS = java.io.File.separator 16 | 17 | lazy val soName = System.mapLibraryName("scalaz3") 18 | 19 | lazy val z3Name = { 20 | if (isMac) "libz3.dylib" 21 | else if (isWindows) "libz3.dll" 22 | else System.mapLibraryName("z3") 23 | } 24 | 25 | lazy val javaZ3Name = { 26 | if (isMac) "libz3java.dylib" 27 | else if (isWindows) "libz3java.dll" 28 | else System.mapLibraryName("z3java") 29 | } 30 | 31 | lazy val libBinPath = file("lib-bin") 32 | lazy val z3BinFilePath = z3BuildPath / z3Name 33 | lazy val javaZ3BinFilePath = z3BuildPath / javaZ3Name 34 | lazy val libBinFilePath = libBinPath / soName 35 | 36 | lazy val jdkIncludePath = file(System.getProperty("java.home")) / ".." / "include" 37 | lazy val jdkUnixIncludePath = jdkIncludePath / "linux" 38 | lazy val jdkMacIncludePath = jdkIncludePath / "darwin" 39 | lazy val jdkWinIncludePath = jdkIncludePath / "win32" 40 | 41 | lazy val osInf: String = Option(System.getProperty("os.name")).getOrElse("") 42 | 43 | lazy val osArch: String = { 44 | Option(System.getProperty("sun.arch.data.model")) 45 | .orElse(Option(System.getProperty("os.arch"))) 46 | .getOrElse("N/A") 47 | } 48 | 49 | lazy val is64b = osArch.indexOf("64") >= 0 50 | 51 | lazy val isUnix = osInf.indexOf("nix") >= 0 || osInf.indexOf("nux") >= 0 52 | lazy val isWindows = osInf.indexOf("Win") >= 0 53 | lazy val isMac = osInf.indexOf("Mac") >= 0 54 | 55 | lazy val z3Path = file(".") / "z3" / z3SourceTag 56 | lazy val z3BuildPath = z3Path / "build" 57 | lazy val z3BinaryFiles = Seq(z3BuildPath / z3Name, z3BuildPath / javaZ3Name) 58 | 59 | lazy val z3JavaDepsPrefixes = Seq( 60 | "com.microsoft.z3.Native", 61 | "com.microsoft.z3.Z3Exception", 62 | "com.microsoft.z3.enumerations", 63 | ) 64 | 65 | def exec(cmd: String, s: TaskStreams): Int = { 66 | s.log.info("$ " + cmd) 67 | cmd ! s.log 68 | } 69 | 70 | def exec(cmd: String, dir: File, s: TaskStreams): Int = { 71 | s.log.info("$ cd " + dir + " && " + cmd) 72 | Process(cmd, dir) ! s.log 73 | } 74 | 75 | val z3Key = TaskKey[String]("z3", "Compiles z3 sources") 76 | val gccKey = TaskKey[Unit]("gcc", "Compiles the C sources") 77 | val checksumKey = TaskKey[String]("checksum", "Generates checksum file.") 78 | 79 | def listAllFiles(f: File): List[File] = 80 | f :: (if (f.isDirectory) f.listFiles().toList.flatMap(listAllFiles) else Nil) 81 | 82 | def hashFiles(files: List[File], base: String = ""): String = { 83 | import java.io.{File,InputStream,FileInputStream} 84 | import java.security.MessageDigest 85 | 86 | val algo = MessageDigest.getInstance("MD5") 87 | algo.reset 88 | algo.update(base.getBytes) 89 | 90 | for (f <- files.sortBy(_.absolutePath) if !f.isDirectory) { 91 | val is : InputStream = new FileInputStream(f) 92 | val bytes = new Array[Byte](f.length.asInstanceOf[Int]) 93 | 94 | var offset : Int = 0 95 | var read : Int = 0 96 | while(read >= 0 && offset < bytes.length) { 97 | read = is.read(bytes, offset, bytes.length - offset) 98 | if(read >= 0) offset += read 99 | } 100 | is.close 101 | 102 | algo.update(f.absolutePath.getBytes) 103 | algo.update(bytes) 104 | } 105 | 106 | val digest : Array[Byte] = algo.digest 107 | val strBuf = new StringBuffer() 108 | digest.foreach(b => strBuf.append(Integer.toHexString(0xFF & b))) 109 | strBuf.toString 110 | } 111 | 112 | lazy val z3JarFile = z3BuildPath / "com.microsoft.z3.jar" 113 | 114 | val z3Task = Def.task { 115 | val s = streams.value 116 | 117 | if (!z3Path.asFile.exists) { 118 | s.log.info(s"Cloning Z3 source repository to $z3Path...") 119 | Git.cloneRepository() 120 | .setDirectory(z3Path.asFile) 121 | .setURI(z3SourceRepo) 122 | .call() 123 | } 124 | 125 | Git.open(z3Path.asFile) 126 | .checkout() 127 | .setName(z3SourceTag) 128 | .call() 129 | 130 | val diffs = Git.open(z3Path.asFile) 131 | .diff() 132 | .setPathFilter(PathFilter.create("src/api/")) 133 | .call() 134 | if (diffs.isEmpty) { 135 | s.log.info(s"Applying mk_abs API patch...") 136 | var is: InputStream = null 137 | try { 138 | is = new FileInputStream(new File("z3_mk_abs.patch")) 139 | Git.open(z3Path.asFile) 140 | .apply() 141 | .setPatch(is) 142 | .call() 143 | } finally { 144 | if (is != null) is.close() 145 | } 146 | } 147 | 148 | val hashFile = z3Path / ".build-hash" 149 | 150 | def computeHash(): String = { 151 | hashFiles(listAllFiles((z3Path / "src").asFile).filter { f => 152 | !f.getName.endsWith(".pyc") && 153 | !f.isHidden && 154 | !f.getName.startsWith(".") && 155 | !f.getName.endsWith(".a") 156 | }) 157 | } 158 | 159 | val initialHash = computeHash() 160 | s.log.info("Checksum of Z3 source file: " + initialHash) 161 | 162 | if (hashFile.exists && IO.read(hashFile).trim == initialHash.trim) { 163 | s.log.info("Checksum of Z3 source files matched previous, skipping build...") 164 | initialHash 165 | } else { 166 | s.log.info("Compiling Z3...") 167 | 168 | val code = if (isUnix) { 169 | val python = if (("which python2.7" #> file("/dev/null")).! == 0) "python2.7" else "python" 170 | 171 | val i1 = exec(python + " scripts/mk_make.py --java", z3Path, s) 172 | if (i1 != 0) i1 else exec("make -j4", z3Path / "build", s) 173 | } else if (isWindows) { 174 | val i1 = if (is64b) exec("python scripts/mk_make.py -x --java", z3Path, s) 175 | else exec("python scripts/mk_make.py --java", z3Path, s) 176 | if (i1 != 0) i1 else exec("nmake -j4", z3Path / "build", s) 177 | } else if (isMac) { 178 | val i1 = exec("python scripts/mk_make.py --java", z3Path, s) 179 | if (i1 != 0) i1 else exec("make -j4", z3Path / "build", s) 180 | } else { 181 | sys.error("Don't know how to compile Z3 on arch: " + osInf + " - " + osArch) 182 | } 183 | 184 | if (code == 0) { 185 | val finalHash = computeHash() 186 | IO.write(hashFile, finalHash) 187 | 188 | s.log.info("Wrote checksum " + finalHash + " for z3 build.") 189 | finalHash 190 | } else { 191 | sys.error("Compilation of Z3 failed... aborting") 192 | } 193 | } 194 | } 195 | 196 | val checksumTask = Def.task { 197 | val s = streams.value 198 | val z3checksum = z3Key.value 199 | val sd = (Compile / sourceDirectory).value 200 | 201 | val checksumFilePath = sd / "java" / "z3" / "LibraryChecksum.java" 202 | 203 | val extensions = Set("java", "c", "h", "sbt", "properties") 204 | 205 | val checksumSourcePaths = listAllFiles(sd.asFile).filter { file => 206 | val pathParts = file.getPath.split(".") 207 | pathParts.size > 1 && extensions(pathParts.last) 208 | } 209 | 210 | val md5String = hashFiles(checksumSourcePaths.map(_.asFile), z3checksum) 211 | s.log.info(s"Library checksum: $md5String") 212 | 213 | val regenerate = if (checksumFilePath.exists()) { 214 | val source = scala.io.Source.fromFile(checksumFilePath.asFile, "UTF-8") 215 | !source.getLines.exists(_.contains(md5String)) 216 | } else { 217 | true 218 | } 219 | 220 | if (regenerate) { 221 | val fw = new java.io.FileWriter(checksumFilePath.asFile) 222 | val nl = System.getProperty("line.separator") 223 | fw.write("// THIS FILE IS AUTOMATICALLY GENERATED, DO NOT EDIT" + nl) 224 | fw.write("package z3;" + nl) 225 | fw.write(nl) 226 | fw.write("public final class LibraryChecksum {" + nl) 227 | fw.write(" public static final String value = \"" + md5String + "\";" + nl) 228 | fw.write("}" + nl) 229 | fw.close 230 | 231 | s.log.info("Wrote checksum " + md5String + " as part of " + checksumFilePath.asFile + ".") 232 | } else { 233 | s.log.info("Found library file with matching checksum.") 234 | } 235 | 236 | md5String 237 | } 238 | 239 | val gccTask = Def.task { 240 | val s = streams.value 241 | val cs = checksumKey.value 242 | 243 | s.log.info("Compiling dummy C sources ...") 244 | 245 | def extractDir(checksum: String): String = { 246 | System.getProperty("java.io.tmpdir") + DS + "SCALAZ3_" + checksum + DS + "lib-bin" + DS 247 | } 248 | 249 | // First, we look for z3 250 | for (file <- (z3BinaryFiles :+ z3JarFile) if !file.exists) { 251 | sys.error("Could not find Z3 : " + file.absolutePath) 252 | } 253 | 254 | libBinFilePath.getParentFile.mkdirs() 255 | 256 | if (isUnix) { 257 | exec("gcc -std=gnu89 -o " + libBinFilePath.absolutePath + " " + 258 | "-shared -Wl,-soname," + soName + " " + 259 | "-I" + jdkIncludePath.absolutePath + " " + 260 | "-I" + jdkUnixIncludePath.absolutePath + " " + 261 | "-L" + z3BuildPath.absolutePath + " " + 262 | "-Wall " + 263 | "-g -lc " + 264 | "-Wl,-rpath,"+extractDir(cs)+" -Wl,--no-as-needed -Wl,--copy-dt-needed " + 265 | "-lz3 -fPIC -O2 -fopenmp", s) 266 | 267 | } else if (isWindows) { 268 | exec("gcc -std=gnu89 -m64 -shared -o " + libBinFilePath.absolutePath + " " + 269 | "-D_JNI_IMPLEMENTATION_ -Wl,--kill-at " + 270 | "-D__int64=\"long long\" " + 271 | "-I " + "\"" + jdkIncludePath.absolutePath + "\" " + 272 | "-I " + "\"" + jdkWinIncludePath.absolutePath + "\" " + 273 | "-I " + "\"" + z3BinFilePath.getParentFile.absolutePath + "\" " + 274 | "-Wreturn-type ", s) 275 | 276 | } else if (isMac) { 277 | val frameworkPath = "/System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers" 278 | 279 | exec("install_name_tool -id @loader_path/" + z3Name + " " + z3BinFilePath.absolutePath, s) 280 | exec("install_name_tool -id @loader_path/" + javaZ3Name + " " + javaZ3BinFilePath.absolutePath, s) 281 | // make the dependency to z3 be relative to the caller's location 282 | exec("install_name_tool -change " + z3Name + " @loader_path/" + z3Name + " " + javaZ3BinFilePath.absolutePath, s) 283 | 284 | exec("gcc -std=gnu89 -o " + libBinFilePath.absolutePath + " " + 285 | "-dynamiclib" + " " + 286 | "-install_name @loader_path/"+soName + " " + 287 | "-I" + jdkIncludePath.absolutePath + " " + 288 | "-I" + jdkMacIncludePath.absolutePath + " " + 289 | "-I" + frameworkPath + " " + 290 | "-L" + z3BuildPath.absolutePath + " " + 291 | "-g -lc " + 292 | "-Wl,-rpath," + extractDir(cs) + " " + 293 | "-lz3 -fPIC -O2", s) 294 | 295 | } else { 296 | sys.error("Unknown arch: " + osInf + " - " + osArch) 297 | } 298 | 299 | () // unit task! 300 | } 301 | 302 | val packageTask = (Compile / Keys.`package`).dependsOn(gccKey) 303 | 304 | val newMappingsTask = Def.task { 305 | val s = streams.value 306 | val normalFiles = (Compile / packageBin / mappings).value 307 | 308 | val newBinaryFiles = (libBinFilePath +: z3BinaryFiles).map { f => 309 | f.getAbsoluteFile -> ("lib-bin" + DS + f.getName) 310 | } 311 | 312 | s.log.info("Bundling binary files:") 313 | for ((from, to) <- newBinaryFiles) { 314 | s.log.info(" - " + from+" -> " + to) 315 | } 316 | 317 | s.log.info("Bundling relevant java-Z3 files:") 318 | val outputDir = new File(System.getProperty("java.io.tmpdir") + DS + "Z3JAR_jars" + DS) 319 | outputDir.delete 320 | outputDir.mkdirs 321 | IO.unzip(z3JarFile, outputDir) 322 | 323 | val z3JavaDepsMappings: Seq[(File, String)] = listAllFiles(outputDir).flatMap { f => 324 | if (f.isDirectory) None else { 325 | import java.nio.file.Paths 326 | val path = Paths.get(outputDir.getAbsolutePath).relativize(Paths.get(f.getAbsolutePath)).toString 327 | val extensionSplit = path.split("\\.") 328 | if (extensionSplit.length < 2 || extensionSplit(1) != "class") None else { 329 | val classPath = extensionSplit(0).replace(DS, ".") 330 | if (z3JavaDepsPrefixes.exists(prefix => classPath.startsWith(prefix))) { 331 | s.log.info(" - " + classPath) 332 | Some(f.getAbsoluteFile -> path) 333 | } else { 334 | None 335 | } 336 | } 337 | } 338 | } 339 | 340 | newBinaryFiles ++ z3JavaDepsMappings ++ normalFiles 341 | } 342 | 343 | val testClasspath = Def.task { 344 | val jar = (Compile / packageBin / artifactPath).value 345 | Seq(Attributed.blank(jar)) 346 | } 347 | } 348 | -------------------------------------------------------------------------------- /project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version=1.7.3 2 | -------------------------------------------------------------------------------- /project/build.sbt: -------------------------------------------------------------------------------- 1 | 2 | libraryDependencies ++= Seq( 3 | "org.eclipse.jgit" % "org.eclipse.jgit.pgm" % "5.2.1.201812262042-r", 4 | "org.slf4j" % "slf4j-log4j12" % "1.7.25" 5 | ) 6 | 7 | scalacOptions ++= Seq("-deprecation", "-feature") 8 | -------------------------------------------------------------------------------- /src/main/java/z3/AbstractErrorHandler.java: -------------------------------------------------------------------------------- 1 | package z3; 2 | 3 | public abstract class AbstractErrorHandler { 4 | public abstract void handleError(int errorCode); 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/z3/DefaultErrorHandler.java: -------------------------------------------------------------------------------- 1 | package z3; 2 | 3 | public final class DefaultErrorHandler { 4 | 5 | // errorCode description: 6 | // 0 -- OK 7 | // 1 -- sort error 8 | // 2 -- index out of bounds 9 | // 3 -- invalid arg 10 | // 4 -- parser error 11 | // 5 -- no parser 12 | // 6 -- invalid pattern 13 | // 7 -- memout fail 14 | // 8 -- file access error 15 | // 9 -- internal fatal 16 | // 10 -- invalid usage 17 | // 11 -- dec ref error 18 | public void handleError(int errorCode) { 19 | String msg; 20 | switch(errorCode) { 21 | case 0 : msg = "OK"; break; 22 | case 1 : msg = "Sort error"; break; 23 | case 2 : msg = "Index out of bounds"; break; 24 | case 3 : msg = "Invalid argument"; break; 25 | case 4 : msg = "Parser error"; break; 26 | case 5 : msg = "No parser"; break; 27 | case 6 : msg = "Invalid pattern"; break; 28 | case 7 : msg = "Memout fail error"; break; 29 | case 8 : msg = "File access error"; break; 30 | case 9 : msg = "Internal fatal error"; break; 31 | case 10 : msg = "Invalid usage"; break; 32 | case 11 : msg = "Dec. ref. error"; break; 33 | default : msg = "Unknown error"; break; 34 | } 35 | 36 | int errCode; 37 | if(errorCode >= 0 && errorCode <= 11) { 38 | errCode = errorCode; 39 | } else { 40 | errCode = -1; 41 | } 42 | 43 | throw new Z3ErrorException(errCode, msg); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/z3/Z3ErrorException.java: -------------------------------------------------------------------------------- 1 | package z3; 2 | 3 | public final class Z3ErrorException extends RuntimeException { 4 | 5 | private static final long serialVersionUID = 3382203884603330972L; 6 | 7 | private final int errCode; 8 | 9 | public Z3ErrorException(int errorCode, String message) { 10 | super(message); 11 | errCode = errorCode; 12 | } 13 | 14 | public int getErrorCode() { 15 | return errCode; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/z3/Z3Wrapper.java: -------------------------------------------------------------------------------- 1 | package z3; 2 | 3 | import com.microsoft.z3.Native; 4 | import z3.scala.Z3Context; 5 | 6 | import java.io.File; 7 | import java.io.FileOutputStream; 8 | import java.io.InputStream; 9 | import java.io.OutputStream; 10 | import java.lang.ref.WeakReference; 11 | import java.net.URL; 12 | import java.security.CodeSource; 13 | import java.util.HashMap; 14 | import java.util.zip.ZipEntry; 15 | import java.util.zip.ZipInputStream; 16 | 17 | /** 18 | * This class contains all the native functions. It should be accessed 19 | * mostly through the other classes, though. 20 | */ 21 | public final class Z3Wrapper { 22 | // related to the path in the jar file 23 | private static final String DS = java.io.File.separator; 24 | 25 | private static final String LIB_BIN = DS + "lib-bin" + DS; 26 | 27 | public static Object creation_lock = new Object(); 28 | 29 | private static final String versionString = LibraryChecksum.value; 30 | 31 | private static final String isDebug = System.getProperty("scalaz3.debug.load"); 32 | 33 | // this is just to force class loading, and therefore library loading. 34 | static { 35 | if (!withinJar()) { 36 | System.err.println("It seems you are not running ScalaZ3 from its JAR"); 37 | System.exit(1); 38 | } 39 | 40 | // We load the library by ourselves, so we kindly ask the Java Z3 bindings to not do so. 41 | System.setProperty("z3.skipLibraryLoad", "true"); 42 | loadFromJar(); 43 | // We run this to ensure class loading of Native. 44 | debug("Z3 version: " + z3VersionString()); 45 | } 46 | 47 | private static void debug(String msg) { 48 | if (isDebug != null) { 49 | System.out.println(msg); 50 | } 51 | } 52 | 53 | public static boolean withinJar() { 54 | java.net.URL classJar = Z3Wrapper.class.getResource("/lib-bin/"); 55 | return classJar != null; 56 | } 57 | 58 | public static String wrapperVersionString() { 59 | // Version number should match smallest Z3 with which we know it to work, plus a letter for "internal" versions. 60 | return "ScalaZ3 4.8.14a"; 61 | } 62 | 63 | public static String z3VersionString() { 64 | Native.IntPtr major = new Native.IntPtr(); 65 | Native.IntPtr minor = new Native.IntPtr(); 66 | Native.IntPtr buildNumber = new Native.IntPtr(); 67 | Native.IntPtr revisionNumber = new Native.IntPtr(); 68 | Native.getVersion(major, minor, buildNumber, revisionNumber); 69 | return "Z3 " + major.value + "." + minor.value + " (build " + buildNumber.value + ", rev. " + revisionNumber.value + ")"; 70 | } 71 | 72 | private static void loadFromJar() { 73 | String path = "SCALAZ3_" + versionString; 74 | File libDir = new File(System.getProperty("java.io.tmpdir") + DS + path + LIB_BIN); 75 | 76 | try { 77 | if (!libDir.isDirectory() || !libDir.canRead()) { 78 | libDir.mkdirs(); 79 | extractFromJar(libDir); 80 | } 81 | 82 | System.load(libDir.getAbsolutePath() + DS + System.mapLibraryName("z3")); 83 | System.load(libDir.getAbsolutePath() + DS + System.mapLibraryName("z3java")); 84 | System.load(libDir.getAbsolutePath() + DS + System.mapLibraryName("scalaz3")); 85 | } catch (Exception e) { 86 | System.err.println(e.getMessage()); 87 | e.printStackTrace(); 88 | } 89 | } 90 | 91 | private static void extractFromJar(File toDir) throws Exception { 92 | CodeSource src = Z3Wrapper.class.getProtectionDomain().getCodeSource(); 93 | if (src != null) { 94 | URL jar = src.getLocation(); 95 | ZipInputStream zip = new ZipInputStream(jar.openStream()); 96 | while (true) { 97 | ZipEntry e = zip.getNextEntry(); 98 | if (e == null) break; 99 | 100 | String path = e.getName(); 101 | 102 | if (path.startsWith("lib-bin/") && !e.isDirectory()) { 103 | 104 | String name = new File(path).getName(); 105 | 106 | debug("Extracting " + path + " from jar to " + name + "..."); 107 | 108 | File to = new File(toDir.getAbsolutePath() + DS + name); 109 | 110 | InputStream in = Z3Wrapper.class.getResourceAsStream("/" + path); 111 | OutputStream out = new FileOutputStream(to); 112 | byte[] buf = new byte[4096]; 113 | int len; 114 | while ((len = in.read(buf)) > 0) { 115 | out.write(buf, 0, len); 116 | } 117 | out.close(); 118 | in.close(); 119 | } 120 | } 121 | } 122 | 123 | } 124 | 125 | public static long[] toPtrArray(Native.LongPtr[] ptrs) { 126 | long[] result = new long[ptrs.length]; 127 | for (int i = 0; i < ptrs.length; i++) { 128 | result[i] = ptrs[i].value; 129 | } 130 | return result; 131 | } 132 | 133 | private static final HashMap> ptrToCtx = new HashMap<>(); 134 | 135 | public static void onZ3Error(long contextPtr, long code) { 136 | Z3Context ctx = ptrToCtx.get(contextPtr).get(); 137 | ctx.onError(code); 138 | } 139 | 140 | public static void registerContext(long contextPtr, Z3Context ctx) { 141 | ptrToCtx.put(contextPtr, new WeakReference<>(ctx)); 142 | } 143 | 144 | public static void unregisterContext(long contextPtr) { 145 | ptrToCtx.remove(contextPtr); 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /src/main/java/z3/java/README: -------------------------------------------------------------------------------- 1 | This folder contains some code that demonstrates how to use the JNI wrapper 2 | from Java. This is not maintained and is kept here only as an encouragement for 3 | volunteers to pick it up and develop a full-fledged version of a Z3 wrapper for 4 | Java. 5 | -------------------------------------------------------------------------------- /src/main/java/z3/java/Z3AST.java: -------------------------------------------------------------------------------- 1 | package z3.java; 2 | 3 | public class Z3AST extends Z3Pointer { 4 | protected Z3AST(long ptr) { 5 | super(ptr); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/z3/java/Z3Context.java: -------------------------------------------------------------------------------- 1 | package z3.java; 2 | 3 | import z3.Z3Wrapper; 4 | import java.util.Map; 5 | import com.microsoft.z3.Native; 6 | 7 | public class Z3Context extends Z3Pointer { 8 | public static Boolean lbool2Boolean(int v) { 9 | if(v == -1) 10 | return false; 11 | else if (v == 0) 12 | return null; 13 | else 14 | return true; 15 | } 16 | 17 | public Z3Context(Map config) { 18 | synchronized(Z3Wrapper.creation_lock) { 19 | long cfgPtr = Native.mkConfig(); 20 | for (Map.Entry entry : config.entrySet()) { 21 | Native.setParamValue(cfgPtr, entry.getKey(), entry.getValue()); 22 | } 23 | value = Native.mkContext(cfgPtr); 24 | Native.delConfig(cfgPtr); 25 | } 26 | } 27 | 28 | public void delete() { 29 | Native.delContext(this.value); 30 | this.value = 0; 31 | } 32 | 33 | public void updateParamValue(String paramID, String paramValue) { 34 | Native.updateParamValue(this.value, paramID, paramValue); 35 | } 36 | 37 | public Z3Symbol mkIntSymbol(int i) { 38 | return new Z3Symbol(Native.mkIntSymbol(this.value, i)); 39 | } 40 | 41 | public Z3Symbol mkStringSymbol(String s) { 42 | return new Z3Symbol(Native.mkStringSymbol(this.value, s)); 43 | } 44 | 45 | public boolean isEqSort(Z3Sort s1, Z3Sort s2) { 46 | return Native.isEqSort(this.value, s1.value, s2.value); 47 | } 48 | 49 | public Z3Sort mkUninterpretedSort(Z3Symbol s) { 50 | return new Z3Sort(Native.mkUninterpretedSort(this.value, s.value)); 51 | } 52 | 53 | public Z3Sort mkBoolSort() { 54 | return new Z3Sort(Native.mkBoolSort(this.value)); 55 | } 56 | 57 | public Z3Sort mkIntSort() { 58 | return new Z3Sort(Native.mkIntSort(this.value)); 59 | } 60 | 61 | public Z3Sort mkRealSort() { 62 | return new Z3Sort(Native.mkRealSort(this.value)); 63 | } 64 | 65 | public boolean isEqAST(Z3AST t1, Z3AST t2) { 66 | return Native.isEqAst(this.value, t1.value, t2.value); 67 | } 68 | 69 | public Z3AST mkConst(Z3Symbol symbol, Z3Sort sort) { 70 | return new Z3AST(Native.mkConst(this.value, symbol.value, sort.value)); 71 | } 72 | 73 | public Z3AST mkTrue() { 74 | return new Z3AST(Native.mkTrue(this.value)); 75 | } 76 | 77 | public Z3AST mkFalse() { 78 | return new Z3AST(Native.mkFalse(this.value)); 79 | } 80 | 81 | public Z3AST mkEq(Z3AST ast1, Z3AST ast2) { 82 | return new Z3AST(Native.mkEq(this.value, ast1.value, ast2.value)); 83 | } 84 | 85 | public Z3AST mkDistinct(Z3AST ... args) { 86 | if(args.length == 0) 87 | throw new IllegalArgumentException("mkDistinct needs at least one argument"); 88 | return new Z3AST(Native.mkDistinct(this.value, args.length, Z3Wrapper.toPtrArray(args))); 89 | } 90 | 91 | public Z3AST mkNot(Z3AST ast) { 92 | return new Z3AST(Native.mkNot(this.value, ast.value)); 93 | } 94 | 95 | public Z3AST mkITE(Z3AST t1, Z3AST t2, Z3AST t3) { 96 | return new Z3AST(Native.mkIte(this.value, t1.value, t2.value, t3.value)); 97 | } 98 | 99 | public Z3AST mkIff(Z3AST t1, Z3AST t2) { 100 | return new Z3AST(Native.mkIff(this.value, t1.value, t2.value)); 101 | } 102 | 103 | public Z3AST mkImplies(Z3AST t1, Z3AST t2) { 104 | return new Z3AST(Native.mkImplies(this.value, t1.value, t2.value)); 105 | } 106 | 107 | public Z3AST mkXor(Z3AST t1, Z3AST t2) { 108 | return new Z3AST(Native.mkXor(this.value, t1.value, t2.value)); 109 | } 110 | 111 | public Z3AST mkAnd(Z3AST ... args) { 112 | if(args.length == 0) 113 | throw new IllegalArgumentException("mkAnd needs at least one argument"); 114 | return new Z3AST(Native.mkAnd(this.value, args.length, Z3Wrapper.toPtrArray(args))); 115 | } 116 | 117 | public Z3AST mkOr(Z3AST ... args) { 118 | if(args.length == 0) 119 | throw new IllegalArgumentException("mkOr needs at least one argument"); 120 | return new Z3AST(Native.mkOr(this.value, args.length, Z3Wrapper.toPtrArray(args))); 121 | } 122 | 123 | public Z3AST mkAdd(Z3AST ... args) { 124 | if(args.length == 0) 125 | throw new IllegalArgumentException("mkAdd needs at least one argument"); 126 | return new Z3AST(Native.mkAdd(this.value, args.length, Z3Wrapper.toPtrArray(args))); 127 | } 128 | 129 | public Z3AST mkMul(Z3AST ... args) { 130 | if(args.length == 0) 131 | throw new IllegalArgumentException("mkMul needs at least one argument"); 132 | return new Z3AST(Native.mkMul(this.value, args.length, Z3Wrapper.toPtrArray(args))); 133 | } 134 | 135 | public Z3AST mkSub(Z3AST ... args) { 136 | if(args.length == 0) 137 | throw new IllegalArgumentException("mkSub needs at least one argument"); 138 | return new Z3AST(Native.mkSub(this.value, args.length, Z3Wrapper.toPtrArray(args))); 139 | } 140 | 141 | public Z3AST mkUnaryMinus(Z3AST ast) { 142 | return new Z3AST(Native.mkUnaryMinus(this.value, ast.value)); 143 | } 144 | 145 | public Z3AST mkDiv(Z3AST ast1, Z3AST ast2) { 146 | return new Z3AST(Native.mkDiv(this.value, ast1.value, ast2.value)); 147 | } 148 | 149 | public Z3AST mkMod(Z3AST ast1, Z3AST ast2) { 150 | return new Z3AST(Native.mkMod(this.value, ast1.value, ast2.value)); 151 | } 152 | 153 | public Z3AST mkRem(Z3AST ast1, Z3AST ast2) { 154 | return new Z3AST(Native.mkRem(this.value, ast1.value, ast2.value)); 155 | } 156 | 157 | public Z3AST mkLT(Z3AST ast1, Z3AST ast2) { 158 | return new Z3AST(Native.mkLt(this.value, ast1.value, ast2.value)); 159 | } 160 | 161 | public Z3AST mkLE(Z3AST ast1, Z3AST ast2) { 162 | return new Z3AST(Native.mkLe(this.value, ast1.value, ast2.value)); 163 | } 164 | 165 | public Z3AST mkGT(Z3AST ast1, Z3AST ast2) { 166 | return new Z3AST(Native.mkGt(this.value, ast1.value, ast2.value)); 167 | } 168 | 169 | public Z3AST mkGE(Z3AST ast1, Z3AST ast2) { 170 | return new Z3AST(Native.mkGe(this.value, ast1.value, ast2.value)); 171 | } 172 | 173 | public Z3AST mkInt2Real(Z3AST ast) { 174 | return new Z3AST(Native.mkInt2real(this.value, ast.value)); 175 | } 176 | 177 | public Z3AST mkReal2Int(Z3AST ast) { 178 | return new Z3AST(Native.mkReal2int(this.value, ast.value)); 179 | } 180 | 181 | public Z3AST mkIsInt(Z3AST ast) { 182 | return new Z3AST(Native.mkIsInt(this.value, ast.value)); 183 | } 184 | 185 | public Z3AST mkInt(int value, Z3Sort sort) { 186 | return new Z3AST(Native.mkInt(this.value, value, sort.value)); 187 | } 188 | 189 | public Z3AST mkReal(double value, int numerator, int denominator) { 190 | return new Z3AST(Native.mkReal(this.value, numerator, denominator)); 191 | } 192 | 193 | public Integer getNumeralInt(Z3AST ast) { 194 | Native.IntPtr ip = new Native.IntPtr(); 195 | boolean res = Native.getNumeralInt(this.value, ast.value, ip); 196 | if(res) 197 | return ip.value; 198 | else 199 | return null; 200 | } 201 | 202 | public Boolean getBoolValue(Z3AST ast) { 203 | return lbool2Boolean(Native.getBoolValue(this.value, ast.value)); 204 | } 205 | 206 | } 207 | -------------------------------------------------------------------------------- /src/main/java/z3/java/Z3Model.java: -------------------------------------------------------------------------------- 1 | package z3.java; 2 | 3 | import com.microsoft.z3.Native; 4 | 5 | public class Z3Model extends Z3Pointer { 6 | private final Z3Context context; 7 | 8 | protected Z3Model(Z3Context context) { 9 | super(0L); 10 | this.context = context; 11 | } 12 | 13 | public Z3AST eval(Z3AST ast, boolean completion) { 14 | if(this.value == 0L) { 15 | throw new IllegalStateException("The model is not initialized."); 16 | } 17 | Z3AST out = new Z3AST(0L); 18 | boolean result = Native.modelEval(context.value, this.value, ast.value, completion, out); 19 | if (result) { 20 | return out; 21 | } else { 22 | return null; 23 | } 24 | } 25 | 26 | public Z3AST eval(Z3AST ast) { 27 | return eval(ast, false); 28 | } 29 | 30 | public Integer evalAsInt(Z3AST ast) { 31 | Z3AST res = this.eval(ast); 32 | if(res == null) return null; 33 | return context.getNumeralInt(res); 34 | } 35 | 36 | public Boolean evalAsBool(Z3AST ast) { 37 | Z3AST res = this.eval(ast); 38 | if(res == null) return null; 39 | return context.getBoolValue(res); 40 | } 41 | 42 | public void incRef() { 43 | Native.modelIncRef(context.value, this.value); 44 | } 45 | 46 | public void decRef() { 47 | Native.modelDecRef(context.value, this.value); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/z3/java/Z3Pointer.java: -------------------------------------------------------------------------------- 1 | package z3.java; 2 | 3 | import com.microsoft.z3.Native; 4 | 5 | class Z3Pointer extends Native.LongPtr { 6 | protected Z3Pointer() { 7 | this(0L); 8 | } 9 | 10 | protected Z3Pointer(long ptr) { 11 | this.value = ptr; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/z3/java/Z3Sort.java: -------------------------------------------------------------------------------- 1 | package z3.java; 2 | 3 | public class Z3Sort extends Z3Pointer { 4 | protected Z3Sort(long ptr) { 5 | super(ptr); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/z3/java/Z3Symbol.java: -------------------------------------------------------------------------------- 1 | package z3.java; 2 | 3 | public class Z3Symbol extends Z3Pointer { 4 | protected Z3Symbol(long ptr) { 5 | super(ptr); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/scala/z3/scala/Default.scala: -------------------------------------------------------------------------------- 1 | package z3.scala 2 | 3 | import scala.annotation.implicitNotFound 4 | 5 | /** A type class for Scala types that are representable in Z3 and that admit 6 | * a default value. The default value is used for model reconstruction when 7 | * no other value is available. */ 8 | @implicitNotFound(msg = "Cannot find a default value for ${A}.") 9 | trait Default[A] { 10 | val value : A 11 | } 12 | -------------------------------------------------------------------------------- /src/main/scala/z3/scala/Z3AST.scala: -------------------------------------------------------------------------------- 1 | package z3.scala 2 | 3 | sealed class Z3AST private[z3](val ptr : Long, val context : Z3Context) extends Z3ASTLike { 4 | override def equals(that : Any) : Boolean = { 5 | that != null && 6 | that.isInstanceOf[Z3AST] && { 7 | val that2 = that.asInstanceOf[Z3AST] 8 | that2.ptr == this.ptr // && context.isEqAST(this, that2) 9 | } 10 | } 11 | 12 | private val hc : Int = ptr.hashCode() 13 | override def hashCode : Int = hc 14 | override def toString : String = context.astToString(this) 15 | 16 | lazy val getSort : Z3Sort = context.getSort(this) 17 | 18 | def ===(that: Z3AST): Z3AST = context.mkEq(this, that) 19 | def !==(that: Z3AST): Z3AST = context.mkDistinct(this, that) 20 | 21 | import dsl.{Tree,TopSort,BoolSort,BottomSort,Z3ASTWrapper,Eq,Distinct} 22 | def ===(that: Tree[_ >: BottomSort <: TopSort]): Tree[BoolSort] = Eq(Z3ASTWrapper[BottomSort](this), that) 23 | def !==(that: Tree[_ >: BottomSort <: TopSort]): Tree[BoolSort] = Distinct(Z3ASTWrapper[BottomSort](this), that) 24 | 25 | locally { 26 | context.astQueue.track(this) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/scala/z3/scala/Z3ASTKind.scala: -------------------------------------------------------------------------------- 1 | package z3.scala 2 | 3 | // models the Z3_ast_kind enum 4 | sealed abstract class Z3ASTKind 5 | 6 | sealed abstract class Z3NumeralAST extends Z3ASTKind 7 | case class Z3NumeralIntAST private[z3](value: Option[Int]) extends Z3NumeralAST 8 | case class Z3NumeralRealAST private[z3](numerator: BigInt, denominator: BigInt) extends Z3NumeralAST 9 | case class Z3AppAST private[z3](decl: Z3FuncDecl, args: Seq[Z3AST]) extends Z3ASTKind 10 | case class Z3VarAST private[z3](index:Int) extends Z3ASTKind 11 | case class Z3QuantifierAST private[z3](forall: Boolean, vars: Seq[String], body: Z3AST) extends Z3ASTKind 12 | case class Z3SortAST private[z3](sort: Z3Sort) extends Z3ASTKind 13 | case class Z3FuncDeclAST private[z3](funcDecl: Z3FuncDecl) extends Z3ASTKind 14 | case object Z3UnknownAST extends Z3ASTKind 15 | -------------------------------------------------------------------------------- /src/main/scala/z3/scala/Z3ASTVector.scala: -------------------------------------------------------------------------------- 1 | package z3.scala 2 | 3 | import com.microsoft.z3.Native 4 | 5 | final class Z3ASTVector private[z3](val ptr: Long, val context: Z3Context) extends Z3Object { 6 | 7 | def incRef(): Unit = { 8 | Native.astVectorIncRef(context.ptr, this.ptr) 9 | } 10 | 11 | def decRef(): Unit = { 12 | Native.astVectorDecRef(context.ptr, this.ptr) 13 | } 14 | 15 | def get(i: Int): Z3AST = { 16 | new Z3AST(Native.astVectorGet(context.ptr, this.ptr, i), context) 17 | } 18 | 19 | def set(i: Int, v: Z3AST): Unit = { 20 | Native.astVectorSet(context.ptr, this.ptr, i, v.ptr) 21 | } 22 | 23 | def size: Int = { 24 | Native.astVectorSize(context.ptr, this.ptr) 25 | } 26 | 27 | // Utility functions 28 | def apply(i: Int): Z3AST = { 29 | get(i) 30 | } 31 | 32 | def update(i: Int, v: Z3AST) = { 33 | set(i, v) 34 | } 35 | 36 | def toSeq: Seq[Z3AST] = { 37 | for (i <- 0 until size) yield { 38 | get(i) 39 | } 40 | } 41 | 42 | locally { 43 | context.astVectorQueue.track(this) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/scala/z3/scala/Z3DeclKind.scala: -------------------------------------------------------------------------------- 1 | package z3.scala 2 | 3 | import com.microsoft.z3.enumerations._ 4 | 5 | sealed abstract class Z3DeclKind(val value: Int) 6 | 7 | // Basic 8 | object OpTrue extends Z3DeclKind (Z3_decl_kind.Z3_OP_TRUE.toInt) 9 | object OpFalse extends Z3DeclKind (Z3_decl_kind.Z3_OP_FALSE.toInt) 10 | object OpEq extends Z3DeclKind (Z3_decl_kind.Z3_OP_EQ.toInt) 11 | object OpDistinct extends Z3DeclKind (Z3_decl_kind.Z3_OP_DISTINCT.toInt) 12 | object OpITE extends Z3DeclKind (Z3_decl_kind.Z3_OP_ITE.toInt) 13 | object OpAnd extends Z3DeclKind (Z3_decl_kind.Z3_OP_AND.toInt) 14 | object OpOr extends Z3DeclKind (Z3_decl_kind.Z3_OP_OR.toInt) 15 | object OpIff extends Z3DeclKind (Z3_decl_kind.Z3_OP_IFF.toInt) 16 | object OpXor extends Z3DeclKind (Z3_decl_kind.Z3_OP_XOR.toInt) 17 | object OpNot extends Z3DeclKind (Z3_decl_kind.Z3_OP_NOT.toInt) 18 | object OpImplies extends Z3DeclKind (Z3_decl_kind.Z3_OP_IMPLIES.toInt) 19 | object OpOEq extends Z3DeclKind (Z3_decl_kind.Z3_OP_OEQ.toInt) // NEW in ScalaZ3 3.0 20 | 21 | // Arithmetic 22 | object OpANum extends Z3DeclKind (Z3_decl_kind.Z3_OP_ANUM.toInt) 23 | object OpAGNum extends Z3DeclKind (Z3_decl_kind.Z3_OP_AGNUM.toInt) // NEW in ScalaZ3 3.0 24 | object OpLE extends Z3DeclKind (Z3_decl_kind.Z3_OP_LE.toInt) 25 | object OpGE extends Z3DeclKind (Z3_decl_kind.Z3_OP_GE.toInt) 26 | object OpLT extends Z3DeclKind (Z3_decl_kind.Z3_OP_LT.toInt) 27 | object OpGT extends Z3DeclKind (Z3_decl_kind.Z3_OP_GT.toInt) 28 | object OpAdd extends Z3DeclKind (Z3_decl_kind.Z3_OP_ADD.toInt) 29 | object OpSub extends Z3DeclKind (Z3_decl_kind.Z3_OP_SUB.toInt) 30 | object OpUMinus extends Z3DeclKind (Z3_decl_kind.Z3_OP_UMINUS.toInt) 31 | object OpMul extends Z3DeclKind (Z3_decl_kind.Z3_OP_MUL.toInt) 32 | object OpDiv extends Z3DeclKind (Z3_decl_kind.Z3_OP_DIV.toInt) 33 | object OpIDiv extends Z3DeclKind (Z3_decl_kind.Z3_OP_IDIV.toInt) 34 | object OpRem extends Z3DeclKind (Z3_decl_kind.Z3_OP_REM.toInt) 35 | object OpMod extends Z3DeclKind (Z3_decl_kind.Z3_OP_MOD.toInt) 36 | object OpToReal extends Z3DeclKind (Z3_decl_kind.Z3_OP_TO_REAL.toInt) 37 | object OpToInt extends Z3DeclKind (Z3_decl_kind.Z3_OP_TO_INT.toInt) 38 | object OpIsInt extends Z3DeclKind (Z3_decl_kind.Z3_OP_IS_INT.toInt) 39 | object OpPower extends Z3DeclKind (Z3_decl_kind.Z3_OP_POWER.toInt) // NEW in ScalaZ3 3.0 40 | object OpAbs extends Z3DeclKind (Z3_decl_kind.Z3_OP_ABS.toInt) // NEW in ScalaZ3 4.8.12 41 | 42 | // Arrays & Sets 43 | object OpStore extends Z3DeclKind (Z3_decl_kind.Z3_OP_STORE.toInt) 44 | object OpSelect extends Z3DeclKind (Z3_decl_kind.Z3_OP_SELECT.toInt) 45 | object OpConstArray extends Z3DeclKind (Z3_decl_kind.Z3_OP_CONST_ARRAY.toInt) 46 | object OpArrayMap extends Z3DeclKind (Z3_decl_kind.Z3_OP_ARRAY_MAP.toInt) 47 | object OpArrayDefault extends Z3DeclKind (Z3_decl_kind.Z3_OP_ARRAY_DEFAULT.toInt) 48 | object OpSetUnion extends Z3DeclKind (Z3_decl_kind.Z3_OP_SET_UNION.toInt) 49 | object OpSetIntersect extends Z3DeclKind (Z3_decl_kind.Z3_OP_SET_INTERSECT.toInt) 50 | object OpSetDifference extends Z3DeclKind (Z3_decl_kind.Z3_OP_SET_DIFFERENCE.toInt) 51 | object OpSetComplement extends Z3DeclKind (Z3_decl_kind.Z3_OP_SET_COMPLEMENT.toInt) 52 | object OpSetSubset extends Z3DeclKind (Z3_decl_kind.Z3_OP_SET_SUBSET.toInt) 53 | object OpAsArray extends Z3DeclKind (Z3_decl_kind.Z3_OP_AS_ARRAY.toInt) 54 | object OpArrayExt extends Z3DeclKind (Z3_decl_kind.Z3_OP_ARRAY_EXT.toInt) // NEW in ScalaZ3 3.0 55 | 56 | // Bit-vectors 57 | object OpBNum extends Z3DeclKind (Z3_decl_kind.Z3_OP_BNUM.toInt) // NEW in ScalaZ3 3.0 58 | object OpBit1 extends Z3DeclKind (Z3_decl_kind.Z3_OP_BIT1.toInt) // NEW in ScalaZ3 3.0 59 | object OpBit0 extends Z3DeclKind (Z3_decl_kind.Z3_OP_BIT0.toInt) // NEW in ScalaZ3 3.0 60 | object OpBNeg extends Z3DeclKind (Z3_decl_kind.Z3_OP_BNEG.toInt) // NEW in ScalaZ3 3.0 61 | object OpBAdd extends Z3DeclKind (Z3_decl_kind.Z3_OP_BADD.toInt) // NEW in ScalaZ3 3.0 62 | object OpBSub extends Z3DeclKind (Z3_decl_kind.Z3_OP_BSUB.toInt) // NEW in ScalaZ3 3.0 63 | object OpBMul extends Z3DeclKind (Z3_decl_kind.Z3_OP_BMUL.toInt) // NEW in ScalaZ3 3.0 64 | 65 | object OpBSDiv extends Z3DeclKind (Z3_decl_kind.Z3_OP_BSDIV.toInt) // NEW in ScalaZ3 3.0 66 | object OpBUDiv extends Z3DeclKind (Z3_decl_kind.Z3_OP_BUDIV.toInt) // NEW in ScalaZ3 3.0 67 | object OpBSRem extends Z3DeclKind (Z3_decl_kind.Z3_OP_BSREM.toInt) // NEW in ScalaZ3 3.0 68 | object OpBURem extends Z3DeclKind (Z3_decl_kind.Z3_OP_BUREM.toInt) // NEW in ScalaZ3 3.0 69 | object OpBSMod extends Z3DeclKind (Z3_decl_kind.Z3_OP_BSMOD.toInt) // NEW in ScalaZ3 3.0 70 | 71 | object OpULE extends Z3DeclKind (Z3_decl_kind.Z3_OP_ULEQ.toInt) // NEW in ScalaZ3 3.0 72 | object OpSLE extends Z3DeclKind (Z3_decl_kind.Z3_OP_SLEQ.toInt) // NEW in ScalaZ3 3.0 73 | object OpUGE extends Z3DeclKind (Z3_decl_kind.Z3_OP_UGEQ.toInt) // NEW in ScalaZ3 3.0 74 | object OpSGE extends Z3DeclKind (Z3_decl_kind.Z3_OP_SGEQ.toInt) // NEW in ScalaZ3 3.0 75 | object OpULT extends Z3DeclKind (Z3_decl_kind.Z3_OP_ULT.toInt) // NEW in ScalaZ3 3.0 76 | object OpSLT extends Z3DeclKind (Z3_decl_kind.Z3_OP_SLT.toInt) // NEW in ScalaZ3 3.0 77 | object OpUGT extends Z3DeclKind (Z3_decl_kind.Z3_OP_UGT.toInt) // NEW in ScalaZ3 3.0 78 | object OpSGT extends Z3DeclKind (Z3_decl_kind.Z3_OP_SGT.toInt) // NEW in ScalaZ3 3.0 79 | 80 | object OpBAnd extends Z3DeclKind (Z3_decl_kind.Z3_OP_BAND.toInt) // NEW in ScalaZ3 3.0 81 | object OpBOr extends Z3DeclKind (Z3_decl_kind.Z3_OP_BOR.toInt) // NEW in ScalaZ3 3.0 82 | object OpBNot extends Z3DeclKind (Z3_decl_kind.Z3_OP_BNOT.toInt) // NEW in ScalaZ3 3.0 83 | object OpBXor extends Z3DeclKind (Z3_decl_kind.Z3_OP_BXOR.toInt) // NEW in ScalaZ3 3.0 84 | object OpBNand extends Z3DeclKind (Z3_decl_kind.Z3_OP_BNAND.toInt) // NEW in ScalaZ3 3.0 85 | object OpBNor extends Z3DeclKind (Z3_decl_kind.Z3_OP_BNOR.toInt) // NEW in ScalaZ3 3.0 86 | object OpBXnor extends Z3DeclKind (Z3_decl_kind.Z3_OP_BXNOR.toInt) // NEW in ScalaZ3 3.0 87 | 88 | object OpConcat extends Z3DeclKind (Z3_decl_kind.Z3_OP_CONCAT.toInt) // NEW in ScalaZ3 3.0 89 | object OpSignExt extends Z3DeclKind (Z3_decl_kind.Z3_OP_SIGN_EXT.toInt) // NEW in ScalaZ3 3.0 90 | object OpZeroExt extends Z3DeclKind (Z3_decl_kind.Z3_OP_ZERO_EXT.toInt) // NEW in ScalaZ3 3.0 91 | object OpExtract extends Z3DeclKind (Z3_decl_kind.Z3_OP_EXTRACT.toInt) // NEW in ScalaZ3 3.0 92 | object OpRepeat extends Z3DeclKind (Z3_decl_kind.Z3_OP_REPEAT.toInt) // NEW in ScalaZ3 3.0 93 | 94 | object OpBRedAnd extends Z3DeclKind (Z3_decl_kind.Z3_OP_BREDAND.toInt) // NEW in ScalaZ3 3.0 95 | object OpBRedOr extends Z3DeclKind (Z3_decl_kind.Z3_OP_BREDOR.toInt) // NEW in ScalaZ3 3.0 96 | object OpBComp extends Z3DeclKind (Z3_decl_kind.Z3_OP_BCOMP.toInt) // NEW in ScalaZ3 3.0 97 | 98 | object OpBShl extends Z3DeclKind (Z3_decl_kind.Z3_OP_BSHL.toInt) // NEW in ScalaZ3 3.0 99 | object OpBLshr extends Z3DeclKind (Z3_decl_kind.Z3_OP_BLSHR.toInt) // NEW in ScalaZ3 3.0 100 | object OpBAshr extends Z3DeclKind (Z3_decl_kind.Z3_OP_BASHR.toInt) // NEW in ScalaZ3 3.0 101 | object OpRotateLeft extends Z3DeclKind (Z3_decl_kind.Z3_OP_ROTATE_LEFT.toInt) // NEW in ScalaZ3 3.0 102 | object OpRotateRight extends Z3DeclKind (Z3_decl_kind.Z3_OP_ROTATE_RIGHT.toInt) // NEW in ScalaZ3 3.0 103 | object OpExtRotateLeft extends Z3DeclKind (Z3_decl_kind.Z3_OP_EXT_ROTATE_LEFT.toInt) // NEW in ScalaZ3 3.0 104 | object OpExtRotateRight extends Z3DeclKind (Z3_decl_kind.Z3_OP_EXT_ROTATE_RIGHT.toInt) // NEW in ScalaZ3 3.0 105 | 106 | object OpIntToBV extends Z3DeclKind (Z3_decl_kind.Z3_OP_INT2BV.toInt) // NEW in ScalaZ3 3.0 107 | object OpBVToInt extends Z3DeclKind (Z3_decl_kind.Z3_OP_BV2INT.toInt) // NEW in ScalaZ3 3.0 108 | object OpCarry extends Z3DeclKind (Z3_decl_kind.Z3_OP_CARRY.toInt) // NEW in ScalaZ3 3.0 109 | object OpXor3 extends Z3DeclKind (Z3_decl_kind.Z3_OP_XOR3.toInt) // NEW in ScalaZ3 3.0 110 | 111 | // Proofs 112 | object OpPrUndef extends Z3DeclKind (Z3_decl_kind.Z3_OP_PR_UNDEF.toInt) // NEW in ScalaZ3 3.0 113 | object OpPrTrue extends Z3DeclKind (Z3_decl_kind.Z3_OP_PR_TRUE.toInt) // NEW in ScalaZ3 3.0 114 | object OpPrAsserted extends Z3DeclKind (Z3_decl_kind.Z3_OP_PR_ASSERTED.toInt) // NEW in ScalaZ3 3.0 115 | object OpPrGoal extends Z3DeclKind (Z3_decl_kind.Z3_OP_PR_GOAL.toInt) // NEW in ScalaZ3 3.0 116 | object OpPrModusPonens extends Z3DeclKind (Z3_decl_kind.Z3_OP_PR_MODUS_PONENS.toInt) // NEW in ScalaZ3 3.0 117 | object OpPrReflexivity extends Z3DeclKind (Z3_decl_kind.Z3_OP_PR_REFLEXIVITY.toInt) // NEW in ScalaZ3 3.0 118 | object OpPrSymmetry extends Z3DeclKind (Z3_decl_kind.Z3_OP_PR_SYMMETRY.toInt) // NEW in ScalaZ3 3.0 119 | object OpPrTransitivity extends Z3DeclKind (Z3_decl_kind.Z3_OP_PR_TRANSITIVITY.toInt) // NEW in ScalaZ3 3.0 120 | object OpPrTransitivityStar extends Z3DeclKind (Z3_decl_kind.Z3_OP_PR_TRANSITIVITY_STAR.toInt) // NEW in ScalaZ3 3.0 121 | object OpPrMonotonicity extends Z3DeclKind (Z3_decl_kind.Z3_OP_PR_MONOTONICITY.toInt) // NEW in ScalaZ3 3.0 122 | object OpPrQuantIntro extends Z3DeclKind (Z3_decl_kind.Z3_OP_PR_QUANT_INTRO.toInt) // NEW in ScalaZ3 3.0 123 | object OpPrDistributivity extends Z3DeclKind (Z3_decl_kind.Z3_OP_PR_DISTRIBUTIVITY.toInt) // NEW in ScalaZ3 3.0 124 | object OpPrAndElim extends Z3DeclKind (Z3_decl_kind.Z3_OP_PR_AND_ELIM.toInt) // NEW in ScalaZ3 3.0 125 | object OpPrNotOrElim extends Z3DeclKind (Z3_decl_kind.Z3_OP_PR_NOT_OR_ELIM.toInt) // NEW in ScalaZ3 3.0 126 | object OpPrRewrite extends Z3DeclKind (Z3_decl_kind.Z3_OP_PR_REWRITE.toInt) // NEW in ScalaZ3 3.0 127 | object OpPrRewriteStar extends Z3DeclKind (Z3_decl_kind.Z3_OP_PR_REWRITE_STAR.toInt) // NEW in ScalaZ3 3.0 128 | object OpPrPullQuant extends Z3DeclKind (Z3_decl_kind.Z3_OP_PR_PULL_QUANT.toInt) // NEW in ScalaZ3 3.0 129 | object OpPrPushQuant extends Z3DeclKind (Z3_decl_kind.Z3_OP_PR_PUSH_QUANT.toInt) // NEW in ScalaZ3 3.0 130 | object OpPrElimUnusedVars extends Z3DeclKind (Z3_decl_kind.Z3_OP_PR_ELIM_UNUSED_VARS.toInt) // NEW in ScalaZ3 3.0 131 | object OpPrDER extends Z3DeclKind (Z3_decl_kind.Z3_OP_PR_DER.toInt) // NEW in ScalaZ3 3.0 132 | object OpPrQuantInst extends Z3DeclKind (Z3_decl_kind.Z3_OP_PR_QUANT_INST.toInt) // NEW in ScalaZ3 3.0 133 | object OpPrHypothesis extends Z3DeclKind (Z3_decl_kind.Z3_OP_PR_HYPOTHESIS.toInt) // NEW in ScalaZ3 3.0 134 | object OpPrLemma extends Z3DeclKind (Z3_decl_kind.Z3_OP_PR_LEMMA.toInt) // NEW in ScalaZ3 3.0 135 | object OpPrUnitResolution extends Z3DeclKind (Z3_decl_kind.Z3_OP_PR_UNIT_RESOLUTION.toInt) // NEW in ScalaZ3 3.0 136 | object OpPrIffTrue extends Z3DeclKind (Z3_decl_kind.Z3_OP_PR_IFF_TRUE.toInt) // NEW in ScalaZ3 3.0 137 | object OpPrIffFalse extends Z3DeclKind (Z3_decl_kind.Z3_OP_PR_IFF_FALSE.toInt) // NEW in ScalaZ3 3.0 138 | object OpPrCommutativity extends Z3DeclKind (Z3_decl_kind.Z3_OP_PR_COMMUTATIVITY.toInt) // NEW in ScalaZ3 3.0 139 | object OpPrDefAxiom extends Z3DeclKind (Z3_decl_kind.Z3_OP_PR_DEF_AXIOM.toInt) // NEW in ScalaZ3 3.0 140 | object OpPrDefIntro extends Z3DeclKind (Z3_decl_kind.Z3_OP_PR_DEF_INTRO.toInt) // NEW in ScalaZ3 3.0 141 | object OpPrApplyDef extends Z3DeclKind (Z3_decl_kind.Z3_OP_PR_APPLY_DEF.toInt) // NEW in ScalaZ3 3.0 142 | object OpPrIffOEq extends Z3DeclKind (Z3_decl_kind.Z3_OP_PR_IFF_OEQ.toInt) // NEW in ScalaZ3 3.0 143 | object OpPrNNFPos extends Z3DeclKind (Z3_decl_kind.Z3_OP_PR_NNF_POS.toInt) // NEW in ScalaZ3 3.0 144 | object OpPrNNFNeg extends Z3DeclKind (Z3_decl_kind.Z3_OP_PR_NNF_NEG.toInt) // NEW in ScalaZ3 3.0 145 | object OpPrSkolemize extends Z3DeclKind (Z3_decl_kind.Z3_OP_PR_SKOLEMIZE.toInt) // NEW in ScalaZ3 3.0 146 | object OpPrModusPonensOEq extends Z3DeclKind (Z3_decl_kind.Z3_OP_PR_MODUS_PONENS_OEQ.toInt) // NEW in ScalaZ3 3.0 147 | object OpPrThLemma extends Z3DeclKind (Z3_decl_kind.Z3_OP_PR_TH_LEMMA.toInt) // NEW in ScalaZ3 3.0 148 | object OpPrHyperResolve extends Z3DeclKind (Z3_decl_kind.Z3_OP_PR_HYPER_RESOLVE.toInt) // NEW in ScalaZ3 3.0 149 | 150 | // Relational algebra 151 | object OpRAStore extends Z3DeclKind (Z3_decl_kind.Z3_OP_RA_STORE.toInt) // NEW in ScalaZ3 3.0 152 | object OpRAEmpty extends Z3DeclKind (Z3_decl_kind.Z3_OP_RA_EMPTY.toInt) // NEW in ScalaZ3 3.0 153 | object OpRAIsEmpty extends Z3DeclKind (Z3_decl_kind.Z3_OP_RA_IS_EMPTY.toInt) // NEW in ScalaZ3 3.0 154 | object OpRAJoin extends Z3DeclKind (Z3_decl_kind.Z3_OP_RA_JOIN.toInt) // NEW in ScalaZ3 3.0 155 | object OpRAUnion extends Z3DeclKind (Z3_decl_kind.Z3_OP_RA_UNION.toInt) // NEW in ScalaZ3 3.0 156 | object OpRAWiden extends Z3DeclKind (Z3_decl_kind.Z3_OP_RA_WIDEN.toInt) // NEW in ScalaZ3 3.0 157 | object OpRAProject extends Z3DeclKind (Z3_decl_kind.Z3_OP_RA_PROJECT.toInt) // NEW in ScalaZ3 3.0 158 | object OpRAFilter extends Z3DeclKind (Z3_decl_kind.Z3_OP_RA_FILTER.toInt) // NEW in ScalaZ3 3.0 159 | object OpRANegationFilter extends Z3DeclKind (Z3_decl_kind.Z3_OP_RA_NEGATION_FILTER.toInt) // NEW in ScalaZ3 3.0 160 | object OpRARename extends Z3DeclKind (Z3_decl_kind.Z3_OP_RA_RENAME.toInt) // NEW in ScalaZ3 3.0 161 | object OpRAComplement extends Z3DeclKind (Z3_decl_kind.Z3_OP_RA_COMPLEMENT.toInt) // NEW in ScalaZ3 3.0 162 | object OpRASelect extends Z3DeclKind (Z3_decl_kind.Z3_OP_RA_SELECT.toInt) // NEW in ScalaZ3 3.0 163 | object OpRAClone extends Z3DeclKind (Z3_decl_kind.Z3_OP_RA_CLONE.toInt) // NEW in ScalaZ3 3.0 164 | object OpFdConstant extends Z3DeclKind (Z3_decl_kind.Z3_OP_FD_CONSTANT.toInt) // NEW in ScalaZ3 3.0 165 | object OpFdLT extends Z3DeclKind (Z3_decl_kind.Z3_OP_FD_LT.toInt) // NEW in ScalaZ3 3.0 166 | 167 | // Sequences 168 | object OpSeqUnit extends Z3DeclKind (Z3_decl_kind.Z3_OP_SEQ_UNIT.toInt) // NEW in ScalaZ3 3.0 169 | object OpSeqEmpty extends Z3DeclKind (Z3_decl_kind.Z3_OP_SEQ_EMPTY.toInt) // NEW in ScalaZ3 3.0 170 | object OpSeqConcat extends Z3DeclKind (Z3_decl_kind.Z3_OP_SEQ_CONCAT.toInt) // NEW in ScalaZ3 3.0 171 | object OpSeqPrefix extends Z3DeclKind (Z3_decl_kind.Z3_OP_SEQ_PREFIX.toInt) // NEW in ScalaZ3 3.0 172 | object OpSeqSuffix extends Z3DeclKind (Z3_decl_kind.Z3_OP_SEQ_SUFFIX.toInt) // NEW in ScalaZ3 3.0 173 | object OpSeqContains extends Z3DeclKind (Z3_decl_kind.Z3_OP_SEQ_CONTAINS.toInt) // NEW in ScalaZ3 3.0 174 | object OpSeqExtract extends Z3DeclKind (Z3_decl_kind.Z3_OP_SEQ_EXTRACT.toInt) // NEW in ScalaZ3 3.0 175 | object OpSeqReplace extends Z3DeclKind (Z3_decl_kind.Z3_OP_SEQ_REPLACE.toInt) // NEW in ScalaZ3 3.0 176 | object OpSeqAt extends Z3DeclKind (Z3_decl_kind.Z3_OP_SEQ_AT.toInt) // NEW in ScalaZ3 3.0 177 | object OpSeqLength extends Z3DeclKind (Z3_decl_kind.Z3_OP_SEQ_LENGTH.toInt) // NEW in ScalaZ3 3.0 178 | object OpSeqIndex extends Z3DeclKind (Z3_decl_kind.Z3_OP_SEQ_INDEX.toInt) // NEW in ScalaZ3 3.0 179 | object OpSeqToRE extends Z3DeclKind (Z3_decl_kind.Z3_OP_SEQ_TO_RE.toInt) // NEW in ScalaZ3 3.0 180 | object OpSeqInRE extends Z3DeclKind (Z3_decl_kind.Z3_OP_SEQ_IN_RE.toInt) // NEW in ScalaZ3 3.0 181 | 182 | // Regular expressions 183 | object OpREPlus extends Z3DeclKind (Z3_decl_kind.Z3_OP_RE_PLUS.toInt) // NEW in ScalaZ3 3.0 184 | object OpREStar extends Z3DeclKind (Z3_decl_kind.Z3_OP_RE_STAR.toInt) // NEW in ScalaZ3 3.0 185 | object OpREOption extends Z3DeclKind (Z3_decl_kind.Z3_OP_RE_OPTION.toInt) // NEW in ScalaZ3 3.0 186 | object OpREConcat extends Z3DeclKind (Z3_decl_kind.Z3_OP_RE_CONCAT.toInt) // NEW in ScalaZ3 3.0 187 | object OpREUnion extends Z3DeclKind (Z3_decl_kind.Z3_OP_RE_UNION.toInt) // NEW in ScalaZ3 3.0 188 | 189 | // Auxiliary 190 | object OpLabel extends Z3DeclKind (Z3_decl_kind.Z3_OP_LABEL.toInt) // NEW in ScalaZ3 3.0 191 | object OpLabelLit extends Z3DeclKind (Z3_decl_kind.Z3_OP_LABEL_LIT.toInt) // NEW in ScalaZ3 3.0 192 | 193 | // Datatypes 194 | object OpDTConstructor extends Z3DeclKind (Z3_decl_kind.Z3_OP_DT_CONSTRUCTOR.toInt) // NEW in ScalaZ3 3.0 195 | object OpDTRecogniser extends Z3DeclKind (Z3_decl_kind.Z3_OP_DT_RECOGNISER.toInt) // NEW in ScalaZ3 3.0 196 | object OpDTAccessor extends Z3DeclKind (Z3_decl_kind.Z3_OP_DT_ACCESSOR.toInt) // NEW in ScalaZ3 3.0 197 | object OpDTUpdateField extends Z3DeclKind (Z3_decl_kind.Z3_OP_DT_UPDATE_FIELD.toInt) // NEW in ScalaZ3 3.0 198 | 199 | // Pseudo booleans 200 | object OpPBAtMost extends Z3DeclKind (Z3_decl_kind.Z3_OP_PB_AT_MOST.toInt) // NEW in ScalaZ3 3.0 201 | object OpPBLE extends Z3DeclKind (Z3_decl_kind.Z3_OP_PB_LE.toInt) // NEW in ScalaZ3 3.0 202 | object OpPBGE extends Z3DeclKind (Z3_decl_kind.Z3_OP_PB_GE.toInt) // NEW in ScalaZ3 3.0 203 | 204 | // Floating-point arithmetic 205 | object OpFPARmNearestTiesToEven extends Z3DeclKind (Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN.toInt) // NEW in ScalaZ3 3.0 206 | object OpFPARmNearestTiesToAway extends Z3DeclKind (Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY.toInt) // NEW in ScalaZ3 3.0 207 | object OpFPARmTowardPositive extends Z3DeclKind (Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_POSITIVE.toInt) // NEW in ScalaZ3 3.0 208 | object OpFPARmTowardNegative extends Z3DeclKind (Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_NEGATIVE.toInt) // NEW in ScalaZ3 3.0 209 | object OpFPARmTowardZero extends Z3DeclKind (Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_ZERO.toInt) // NEW in ScalaZ3 3.0 210 | 211 | object OpFPANum extends Z3DeclKind (Z3_decl_kind.Z3_OP_FPA_NUM.toInt) // NEW in ScalaZ3 3.0 212 | object OpFPAPlusInf extends Z3DeclKind (Z3_decl_kind.Z3_OP_FPA_PLUS_INF.toInt) // NEW in ScalaZ3 3.0 213 | object OpFPAMinusInf extends Z3DeclKind (Z3_decl_kind.Z3_OP_FPA_MINUS_INF.toInt) // NEW in ScalaZ3 3.0 214 | object OpFPANaN extends Z3DeclKind (Z3_decl_kind.Z3_OP_FPA_NAN.toInt) // NEW in ScalaZ3 3.0 215 | object OpFPAPlusZero extends Z3DeclKind (Z3_decl_kind.Z3_OP_FPA_PLUS_ZERO.toInt) // NEW in ScalaZ3 3.0 216 | object OpFPAMinusZero extends Z3DeclKind (Z3_decl_kind.Z3_OP_FPA_MINUS_ZERO.toInt) // NEW in ScalaZ3 3.0 217 | 218 | object OpFPAAdd extends Z3DeclKind (Z3_decl_kind.Z3_OP_FPA_ADD.toInt) // NEW in ScalaZ3 3.0 219 | object OpFPASub extends Z3DeclKind (Z3_decl_kind.Z3_OP_FPA_SUB.toInt) // NEW in ScalaZ3 3.0 220 | object OpFPANeg extends Z3DeclKind (Z3_decl_kind.Z3_OP_FPA_NEG.toInt) // NEW in ScalaZ3 3.0 221 | object OpFPAMul extends Z3DeclKind (Z3_decl_kind.Z3_OP_FPA_MUL.toInt) // NEW in ScalaZ3 3.0 222 | object OpFPADiv extends Z3DeclKind (Z3_decl_kind.Z3_OP_FPA_DIV.toInt) // NEW in ScalaZ3 3.0 223 | object OpFPARem extends Z3DeclKind (Z3_decl_kind.Z3_OP_FPA_REM.toInt) // NEW in ScalaZ3 3.0 224 | object OpFPAAbs extends Z3DeclKind (Z3_decl_kind.Z3_OP_FPA_ABS.toInt) // NEW in ScalaZ3 3.0 225 | object OpFPAMin extends Z3DeclKind (Z3_decl_kind.Z3_OP_FPA_MIN.toInt) // NEW in ScalaZ3 3.0 226 | object OpFPAMax extends Z3DeclKind (Z3_decl_kind.Z3_OP_FPA_MAX.toInt) // NEW in ScalaZ3 3.0 227 | object OpFPAFMA extends Z3DeclKind (Z3_decl_kind.Z3_OP_FPA_FMA.toInt) // NEW in ScalaZ3 3.0 228 | object OpFPASqrt extends Z3DeclKind (Z3_decl_kind.Z3_OP_FPA_SQRT.toInt) // NEW in ScalaZ3 3.0 229 | object OpFPARoundToIntegral extends Z3DeclKind (Z3_decl_kind.Z3_OP_FPA_ROUND_TO_INTEGRAL.toInt) // NEW in ScalaZ3 3.0 230 | 231 | object OpFPAEq extends Z3DeclKind (Z3_decl_kind.Z3_OP_FPA_EQ.toInt) // NEW in ScalaZ3 3.0 232 | object OpFPALT extends Z3DeclKind (Z3_decl_kind.Z3_OP_FPA_LT.toInt) // NEW in ScalaZ3 3.0 233 | object OpFPAGT extends Z3DeclKind (Z3_decl_kind.Z3_OP_FPA_GT.toInt) // NEW in ScalaZ3 3.0 234 | object OpFPALE extends Z3DeclKind (Z3_decl_kind.Z3_OP_FPA_LE.toInt) // NEW in ScalaZ3 3.0 235 | object OpFPAGE extends Z3DeclKind (Z3_decl_kind.Z3_OP_FPA_GE.toInt) // NEW in ScalaZ3 3.0 236 | object OpFPAIsNaN extends Z3DeclKind (Z3_decl_kind.Z3_OP_FPA_IS_NAN.toInt) // NEW in ScalaZ3 3.0 237 | object OpFPAIsInf extends Z3DeclKind (Z3_decl_kind.Z3_OP_FPA_IS_INF.toInt) // NEW in ScalaZ3 3.0 238 | object OpFPAIsZero extends Z3DeclKind (Z3_decl_kind.Z3_OP_FPA_IS_ZERO.toInt) // NEW in ScalaZ3 3.0 239 | object OpFPAIsNormal extends Z3DeclKind (Z3_decl_kind.Z3_OP_FPA_IS_NORMAL.toInt) // NEW in ScalaZ3 3.0 240 | object OpFPAIsSubnormal extends Z3DeclKind (Z3_decl_kind.Z3_OP_FPA_IS_SUBNORMAL.toInt) // NEW in ScalaZ3 3.0 241 | object OpFPAIsNegative extends Z3DeclKind (Z3_decl_kind.Z3_OP_FPA_IS_NEGATIVE.toInt) // NEW in ScalaZ3 3.0 242 | object OpFPAIsPositive extends Z3DeclKind (Z3_decl_kind.Z3_OP_FPA_IS_POSITIVE.toInt) // NEW in ScalaZ3 3.0 243 | 244 | object OpFPAFP extends Z3DeclKind (Z3_decl_kind.Z3_OP_FPA_FP.toInt) // NEW in ScalaZ3 3.0 245 | object OpFPAToFP extends Z3DeclKind (Z3_decl_kind.Z3_OP_FPA_TO_FP.toInt) // NEW in ScalaZ3 3.0 246 | object OpFPAToFPUnsigned extends Z3DeclKind (Z3_decl_kind.Z3_OP_FPA_TO_FP_UNSIGNED.toInt) // NEW in ScalaZ3 3.0 247 | object OpFPAToUBV extends Z3DeclKind (Z3_decl_kind.Z3_OP_FPA_TO_UBV.toInt) // NEW in ScalaZ3 3.0 248 | object OpFPAToSBV extends Z3DeclKind (Z3_decl_kind.Z3_OP_FPA_TO_SBV.toInt) // NEW in ScalaZ3 3.0 249 | object OpFPAToReal extends Z3DeclKind (Z3_decl_kind.Z3_OP_FPA_TO_REAL.toInt) // NEW in ScalaZ3 3.0 250 | 251 | object OpFPAToIEEEBV extends Z3DeclKind (Z3_decl_kind.Z3_OP_FPA_TO_IEEE_BV.toInt) // NEW in ScalaZ3 3.0 252 | 253 | object OpInternal extends Z3DeclKind (Z3_decl_kind.Z3_OP_INTERNAL.toInt) 254 | object OpUninterpreted extends Z3DeclKind (Z3_decl_kind.Z3_OP_UNINTERPRETED.toInt) 255 | 256 | object Other extends Z3DeclKind (9999) 257 | 258 | object Z3DeclKind { 259 | 260 | def fromInt(i: Int): Z3DeclKind = { 261 | if (i == 9999) Other 262 | else fromZ3(Z3_decl_kind.fromInt(i)) 263 | } 264 | 265 | def fromZ3(kind: Z3_decl_kind): Z3DeclKind = kind match { 266 | case Z3_decl_kind.Z3_OP_TRUE => OpTrue 267 | case Z3_decl_kind.Z3_OP_FALSE => OpFalse 268 | case Z3_decl_kind.Z3_OP_EQ => OpEq 269 | case Z3_decl_kind.Z3_OP_DISTINCT => OpDistinct 270 | case Z3_decl_kind.Z3_OP_ITE => OpITE 271 | case Z3_decl_kind.Z3_OP_AND => OpAnd 272 | case Z3_decl_kind.Z3_OP_OR => OpOr 273 | case Z3_decl_kind.Z3_OP_IFF => OpIff 274 | case Z3_decl_kind.Z3_OP_XOR => OpXor 275 | case Z3_decl_kind.Z3_OP_NOT => OpNot 276 | case Z3_decl_kind.Z3_OP_IMPLIES => OpImplies 277 | case Z3_decl_kind.Z3_OP_OEQ => OpOEq 278 | 279 | case Z3_decl_kind.Z3_OP_ANUM => OpANum 280 | case Z3_decl_kind.Z3_OP_AGNUM => OpAGNum 281 | case Z3_decl_kind.Z3_OP_LE => OpLE 282 | case Z3_decl_kind.Z3_OP_GE => OpGE 283 | case Z3_decl_kind.Z3_OP_LT => OpLT 284 | case Z3_decl_kind.Z3_OP_GT => OpGT 285 | case Z3_decl_kind.Z3_OP_ADD => OpAdd 286 | case Z3_decl_kind.Z3_OP_SUB => OpSub 287 | case Z3_decl_kind.Z3_OP_UMINUS => OpUMinus 288 | case Z3_decl_kind.Z3_OP_MUL => OpMul 289 | case Z3_decl_kind.Z3_OP_DIV => OpDiv 290 | case Z3_decl_kind.Z3_OP_IDIV => OpIDiv 291 | case Z3_decl_kind.Z3_OP_REM => OpRem 292 | case Z3_decl_kind.Z3_OP_MOD => OpMod 293 | case Z3_decl_kind.Z3_OP_TO_REAL => OpToReal 294 | case Z3_decl_kind.Z3_OP_TO_INT => OpToInt 295 | case Z3_decl_kind.Z3_OP_IS_INT => OpIsInt 296 | case Z3_decl_kind.Z3_OP_POWER => OpPower 297 | case Z3_decl_kind.Z3_OP_ABS => OpAbs 298 | 299 | case Z3_decl_kind.Z3_OP_STORE => OpStore 300 | case Z3_decl_kind.Z3_OP_SELECT => OpSelect 301 | case Z3_decl_kind.Z3_OP_CONST_ARRAY => OpConstArray 302 | case Z3_decl_kind.Z3_OP_ARRAY_MAP => OpArrayMap 303 | case Z3_decl_kind.Z3_OP_ARRAY_DEFAULT => OpArrayDefault 304 | case Z3_decl_kind.Z3_OP_SET_UNION => OpSetUnion 305 | case Z3_decl_kind.Z3_OP_SET_INTERSECT => OpSetIntersect 306 | case Z3_decl_kind.Z3_OP_SET_DIFFERENCE => OpSetDifference 307 | case Z3_decl_kind.Z3_OP_SET_COMPLEMENT => OpSetComplement 308 | case Z3_decl_kind.Z3_OP_SET_SUBSET => OpSetSubset 309 | case Z3_decl_kind.Z3_OP_AS_ARRAY => OpAsArray 310 | case Z3_decl_kind.Z3_OP_ARRAY_EXT => OpArrayExt 311 | 312 | case Z3_decl_kind.Z3_OP_BNUM => OpBNum 313 | case Z3_decl_kind.Z3_OP_BIT1 => OpBit1 314 | case Z3_decl_kind.Z3_OP_BIT0 => OpBit0 315 | case Z3_decl_kind.Z3_OP_BNEG => OpBNeg 316 | case Z3_decl_kind.Z3_OP_BADD => OpBAdd 317 | case Z3_decl_kind.Z3_OP_BSUB => OpBSub 318 | case Z3_decl_kind.Z3_OP_BMUL => OpBMul 319 | 320 | case Z3_decl_kind.Z3_OP_BSDIV => OpBSDiv 321 | case Z3_decl_kind.Z3_OP_BUDIV => OpBUDiv 322 | case Z3_decl_kind.Z3_OP_BSREM => OpBSRem 323 | case Z3_decl_kind.Z3_OP_BUREM => OpBURem 324 | case Z3_decl_kind.Z3_OP_BSMOD => OpBSMod 325 | 326 | case Z3_decl_kind.Z3_OP_ULEQ => OpULE 327 | case Z3_decl_kind.Z3_OP_SLEQ => OpSLE 328 | case Z3_decl_kind.Z3_OP_UGEQ => OpUGE 329 | case Z3_decl_kind.Z3_OP_SGEQ => OpSGE 330 | case Z3_decl_kind.Z3_OP_ULT => OpULT 331 | case Z3_decl_kind.Z3_OP_SLT => OpSLT 332 | case Z3_decl_kind.Z3_OP_UGT => OpUGT 333 | case Z3_decl_kind.Z3_OP_SGT => OpSGT 334 | 335 | case Z3_decl_kind.Z3_OP_BAND => OpBAnd 336 | case Z3_decl_kind.Z3_OP_BOR => OpBOr 337 | case Z3_decl_kind.Z3_OP_BNOT => OpBNot 338 | case Z3_decl_kind.Z3_OP_BXOR => OpBXor 339 | case Z3_decl_kind.Z3_OP_BNAND => OpBNand 340 | case Z3_decl_kind.Z3_OP_BNOR => OpBNor 341 | case Z3_decl_kind.Z3_OP_BXNOR => OpBXnor 342 | 343 | case Z3_decl_kind.Z3_OP_CONCAT => OpConcat 344 | case Z3_decl_kind.Z3_OP_SIGN_EXT => OpSignExt 345 | case Z3_decl_kind.Z3_OP_ZERO_EXT => OpZeroExt 346 | case Z3_decl_kind.Z3_OP_EXTRACT => OpExtract 347 | case Z3_decl_kind.Z3_OP_REPEAT => OpRepeat 348 | 349 | case Z3_decl_kind.Z3_OP_BREDOR => OpBRedOr 350 | case Z3_decl_kind.Z3_OP_BREDAND => OpBRedAnd 351 | case Z3_decl_kind.Z3_OP_BCOMP => OpBComp 352 | 353 | case Z3_decl_kind.Z3_OP_BSHL => OpBShl 354 | case Z3_decl_kind.Z3_OP_BLSHR => OpBLshr 355 | case Z3_decl_kind.Z3_OP_BASHR => OpBAshr 356 | case Z3_decl_kind.Z3_OP_ROTATE_LEFT => OpRotateLeft 357 | case Z3_decl_kind.Z3_OP_ROTATE_RIGHT => OpRotateRight 358 | case Z3_decl_kind.Z3_OP_EXT_ROTATE_LEFT => OpExtRotateLeft 359 | case Z3_decl_kind.Z3_OP_EXT_ROTATE_RIGHT => OpExtRotateRight 360 | 361 | case Z3_decl_kind.Z3_OP_INT2BV => OpIntToBV 362 | case Z3_decl_kind.Z3_OP_BV2INT => OpBVToInt 363 | case Z3_decl_kind.Z3_OP_CARRY => OpCarry 364 | case Z3_decl_kind.Z3_OP_XOR3 => OpXor3 365 | 366 | case Z3_decl_kind.Z3_OP_PR_UNDEF => OpPrUndef 367 | case Z3_decl_kind.Z3_OP_PR_TRUE => OpPrTrue 368 | case Z3_decl_kind.Z3_OP_PR_ASSERTED => OpPrAsserted 369 | case Z3_decl_kind.Z3_OP_PR_GOAL => OpPrGoal 370 | case Z3_decl_kind.Z3_OP_PR_MODUS_PONENS => OpPrModusPonens 371 | case Z3_decl_kind.Z3_OP_PR_REFLEXIVITY => OpPrReflexivity 372 | case Z3_decl_kind.Z3_OP_PR_SYMMETRY => OpPrSymmetry 373 | case Z3_decl_kind.Z3_OP_PR_TRANSITIVITY => OpPrTransitivity 374 | case Z3_decl_kind.Z3_OP_PR_TRANSITIVITY_STAR => OpPrTransitivityStar 375 | case Z3_decl_kind.Z3_OP_PR_MONOTONICITY => OpPrMonotonicity 376 | case Z3_decl_kind.Z3_OP_PR_QUANT_INTRO => OpPrQuantIntro 377 | case Z3_decl_kind.Z3_OP_PR_DISTRIBUTIVITY => OpPrDistributivity 378 | case Z3_decl_kind.Z3_OP_PR_AND_ELIM => OpPrAndElim 379 | case Z3_decl_kind.Z3_OP_PR_NOT_OR_ELIM => OpPrNotOrElim 380 | case Z3_decl_kind.Z3_OP_PR_REWRITE => OpPrRewrite 381 | case Z3_decl_kind.Z3_OP_PR_REWRITE_STAR => OpPrRewriteStar 382 | case Z3_decl_kind.Z3_OP_PR_PULL_QUANT => OpPrPullQuant 383 | case Z3_decl_kind.Z3_OP_PR_PUSH_QUANT => OpPrPushQuant 384 | case Z3_decl_kind.Z3_OP_PR_ELIM_UNUSED_VARS => OpPrElimUnusedVars 385 | case Z3_decl_kind.Z3_OP_PR_DER => OpPrDER 386 | case Z3_decl_kind.Z3_OP_PR_QUANT_INST => OpPrQuantInst 387 | case Z3_decl_kind.Z3_OP_PR_HYPOTHESIS => OpPrHypothesis 388 | case Z3_decl_kind.Z3_OP_PR_LEMMA => OpPrLemma 389 | case Z3_decl_kind.Z3_OP_PR_UNIT_RESOLUTION => OpPrUnitResolution 390 | case Z3_decl_kind.Z3_OP_PR_IFF_TRUE => OpPrIffTrue 391 | case Z3_decl_kind.Z3_OP_PR_IFF_FALSE => OpPrIffFalse 392 | case Z3_decl_kind.Z3_OP_PR_COMMUTATIVITY => OpPrCommutativity 393 | case Z3_decl_kind.Z3_OP_PR_DEF_AXIOM => OpPrDefAxiom 394 | case Z3_decl_kind.Z3_OP_PR_DEF_INTRO => OpPrDefIntro 395 | case Z3_decl_kind.Z3_OP_PR_APPLY_DEF => OpPrApplyDef 396 | case Z3_decl_kind.Z3_OP_PR_IFF_OEQ => OpPrIffOEq 397 | case Z3_decl_kind.Z3_OP_PR_NNF_POS => OpPrNNFPos 398 | case Z3_decl_kind.Z3_OP_PR_NNF_NEG => OpPrNNFNeg 399 | case Z3_decl_kind.Z3_OP_PR_SKOLEMIZE => OpPrSkolemize 400 | case Z3_decl_kind.Z3_OP_PR_MODUS_PONENS_OEQ => OpPrModusPonensOEq 401 | case Z3_decl_kind.Z3_OP_PR_TH_LEMMA => OpPrThLemma 402 | case Z3_decl_kind.Z3_OP_PR_HYPER_RESOLVE => OpPrHyperResolve 403 | 404 | case Z3_decl_kind.Z3_OP_RA_STORE => OpRAStore 405 | case Z3_decl_kind.Z3_OP_RA_EMPTY => OpRAEmpty 406 | case Z3_decl_kind.Z3_OP_RA_IS_EMPTY => OpRAIsEmpty 407 | case Z3_decl_kind.Z3_OP_RA_JOIN => OpRAJoin 408 | case Z3_decl_kind.Z3_OP_RA_UNION => OpRAUnion 409 | case Z3_decl_kind.Z3_OP_RA_WIDEN => OpRAWiden 410 | case Z3_decl_kind.Z3_OP_RA_PROJECT => OpRAProject 411 | case Z3_decl_kind.Z3_OP_RA_FILTER => OpRAFilter 412 | case Z3_decl_kind.Z3_OP_RA_NEGATION_FILTER => OpRANegationFilter 413 | case Z3_decl_kind.Z3_OP_RA_RENAME => OpRARename 414 | case Z3_decl_kind.Z3_OP_RA_COMPLEMENT => OpRAComplement 415 | case Z3_decl_kind.Z3_OP_RA_SELECT => OpRASelect 416 | case Z3_decl_kind.Z3_OP_RA_CLONE => OpRAClone 417 | case Z3_decl_kind.Z3_OP_FD_CONSTANT => OpFdConstant 418 | case Z3_decl_kind.Z3_OP_FD_LT => OpFdLT 419 | 420 | case Z3_decl_kind.Z3_OP_SEQ_UNIT => OpSeqUnit 421 | case Z3_decl_kind.Z3_OP_SEQ_EMPTY => OpSeqEmpty 422 | case Z3_decl_kind.Z3_OP_SEQ_CONCAT => OpSeqConcat 423 | case Z3_decl_kind.Z3_OP_SEQ_PREFIX => OpSeqPrefix 424 | case Z3_decl_kind.Z3_OP_SEQ_SUFFIX => OpSeqSuffix 425 | case Z3_decl_kind.Z3_OP_SEQ_CONTAINS => OpSeqContains 426 | case Z3_decl_kind.Z3_OP_SEQ_EXTRACT => OpSeqExtract 427 | case Z3_decl_kind.Z3_OP_SEQ_REPLACE => OpSeqReplace 428 | case Z3_decl_kind.Z3_OP_SEQ_AT => OpSeqAt 429 | case Z3_decl_kind.Z3_OP_SEQ_LENGTH => OpSeqLength 430 | case Z3_decl_kind.Z3_OP_SEQ_INDEX => OpSeqIndex 431 | case Z3_decl_kind.Z3_OP_SEQ_TO_RE => OpSeqToRE 432 | case Z3_decl_kind.Z3_OP_SEQ_IN_RE => OpSeqInRE 433 | 434 | case Z3_decl_kind.Z3_OP_RE_PLUS => OpREPlus 435 | case Z3_decl_kind.Z3_OP_RE_STAR => OpREStar 436 | case Z3_decl_kind.Z3_OP_RE_OPTION => OpREOption 437 | case Z3_decl_kind.Z3_OP_RE_CONCAT => OpREConcat 438 | case Z3_decl_kind.Z3_OP_RE_UNION => OpREUnion 439 | 440 | case Z3_decl_kind.Z3_OP_LABEL => OpLabel 441 | case Z3_decl_kind.Z3_OP_LABEL_LIT => OpLabelLit 442 | 443 | case Z3_decl_kind.Z3_OP_DT_CONSTRUCTOR => OpDTConstructor 444 | case Z3_decl_kind.Z3_OP_DT_RECOGNISER => OpDTRecogniser 445 | case Z3_decl_kind.Z3_OP_DT_ACCESSOR => OpDTAccessor 446 | case Z3_decl_kind.Z3_OP_DT_UPDATE_FIELD => OpDTUpdateField 447 | 448 | case Z3_decl_kind.Z3_OP_PB_AT_MOST => OpPBAtMost 449 | case Z3_decl_kind.Z3_OP_PB_LE => OpPBLE 450 | case Z3_decl_kind.Z3_OP_PB_GE => OpPBGE 451 | 452 | case Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN => OpFPARmNearestTiesToEven 453 | case Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY => OpFPARmNearestTiesToAway 454 | case Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_POSITIVE => OpFPARmTowardPositive 455 | case Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_NEGATIVE => OpFPARmTowardNegative 456 | case Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_ZERO => OpFPARmTowardZero 457 | 458 | case Z3_decl_kind.Z3_OP_FPA_NUM => OpFPANum 459 | case Z3_decl_kind.Z3_OP_FPA_PLUS_INF => OpFPAPlusInf 460 | case Z3_decl_kind.Z3_OP_FPA_MINUS_INF => OpFPAMinusInf 461 | case Z3_decl_kind.Z3_OP_FPA_NAN => OpFPANaN 462 | case Z3_decl_kind.Z3_OP_FPA_PLUS_ZERO => OpFPAPlusZero 463 | case Z3_decl_kind.Z3_OP_FPA_MINUS_ZERO => OpFPAMinusZero 464 | 465 | case Z3_decl_kind.Z3_OP_FPA_ADD => OpFPAAdd 466 | case Z3_decl_kind.Z3_OP_FPA_SUB => OpFPASub 467 | case Z3_decl_kind.Z3_OP_FPA_NEG => OpFPANeg 468 | case Z3_decl_kind.Z3_OP_FPA_MUL => OpFPAMul 469 | case Z3_decl_kind.Z3_OP_FPA_DIV => OpFPADiv 470 | case Z3_decl_kind.Z3_OP_FPA_REM => OpFPARem 471 | case Z3_decl_kind.Z3_OP_FPA_ABS => OpFPAAbs 472 | case Z3_decl_kind.Z3_OP_FPA_MIN => OpFPAMin 473 | case Z3_decl_kind.Z3_OP_FPA_MAX => OpFPAMax 474 | case Z3_decl_kind.Z3_OP_FPA_FMA => OpFPAFMA 475 | case Z3_decl_kind.Z3_OP_FPA_SQRT => OpFPASqrt 476 | case Z3_decl_kind.Z3_OP_FPA_ROUND_TO_INTEGRAL => OpFPARoundToIntegral 477 | 478 | case Z3_decl_kind.Z3_OP_FPA_EQ => OpFPAEq 479 | case Z3_decl_kind.Z3_OP_FPA_LT => OpFPALT 480 | case Z3_decl_kind.Z3_OP_FPA_GT => OpFPAGT 481 | case Z3_decl_kind.Z3_OP_FPA_LE => OpFPALE 482 | case Z3_decl_kind.Z3_OP_FPA_GE => OpFPAGE 483 | case Z3_decl_kind.Z3_OP_FPA_IS_NAN => OpFPAIsNaN 484 | case Z3_decl_kind.Z3_OP_FPA_IS_INF => OpFPAIsInf 485 | case Z3_decl_kind.Z3_OP_FPA_IS_ZERO => OpFPAIsZero 486 | case Z3_decl_kind.Z3_OP_FPA_IS_NORMAL => OpFPAIsNormal 487 | case Z3_decl_kind.Z3_OP_FPA_IS_SUBNORMAL => OpFPAIsSubnormal 488 | case Z3_decl_kind.Z3_OP_FPA_IS_NEGATIVE => OpFPAIsNegative 489 | case Z3_decl_kind.Z3_OP_FPA_IS_POSITIVE => OpFPAIsPositive 490 | 491 | case Z3_decl_kind.Z3_OP_FPA_FP => OpFPAFP 492 | case Z3_decl_kind.Z3_OP_FPA_TO_FP => OpFPAToFP 493 | case Z3_decl_kind.Z3_OP_FPA_TO_FP_UNSIGNED => OpFPAToFPUnsigned 494 | case Z3_decl_kind.Z3_OP_FPA_TO_UBV => OpFPAToUBV 495 | case Z3_decl_kind.Z3_OP_FPA_TO_SBV => OpFPAToSBV 496 | case Z3_decl_kind.Z3_OP_FPA_TO_REAL => OpFPAToReal 497 | 498 | case Z3_decl_kind.Z3_OP_FPA_TO_IEEE_BV => OpFPAToIEEEBV 499 | 500 | case Z3_decl_kind.Z3_OP_INTERNAL => OpInternal 501 | case Z3_decl_kind.Z3_OP_UNINTERPRETED => OpUninterpreted 502 | case other => error("Unhandled int code for Z3KindDecl: " + other) 503 | } 504 | } 505 | -------------------------------------------------------------------------------- /src/main/scala/z3/scala/Z3FuncDecl.scala: -------------------------------------------------------------------------------- 1 | package z3.scala 2 | 3 | // We store the arity when it's known to help preventing segfaults... 4 | sealed class Z3FuncDecl private[z3](val ptr: Long, val arity: Int, val context: Z3Context) extends Z3ASTLike { 5 | def apply(args: Z3AST*) : Z3AST = context.mkApp(this, args:_*) 6 | 7 | lazy val getName: Z3Symbol = context.getDeclName(this) 8 | 9 | def getDomainSize : Int = arity 10 | 11 | def getDomain(i: Int) : Z3Sort = context.getDomain(this, i) 12 | 13 | lazy val getRange : Z3Sort = context.getRange(this) 14 | 15 | // override def equals(that: Any) : Boolean = { 16 | // if(that == null) false else (that.isInstanceOf[Z3FuncDecl] && this.ptr == that.asInstanceOf[Z3FuncDecl].ptr) 17 | // } 18 | 19 | override def equals(that: Any) : Boolean = { 20 | that != null && that.isInstanceOf[Z3FuncDecl] && context.isEqFuncDecl(this, that.asInstanceOf[Z3FuncDecl]) 21 | } 22 | 23 | private val hc : Int = ptr.hashCode() 24 | override def hashCode : Int = hc 25 | 26 | override def toString : String = context.funcDeclToString(this) 27 | 28 | locally { 29 | context.astQueue.track(this) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/scala/z3/scala/Z3FuncInterp.scala: -------------------------------------------------------------------------------- 1 | package z3.scala 2 | 3 | import com.microsoft.z3.Native 4 | 5 | private[scala] class Z3FuncInterp (val ptr: Long, val context: Z3Context) extends Z3Object { 6 | 7 | lazy val default: Z3AST = new Z3AST(Native.funcInterpGetElse(context.ptr, ptr), context) 8 | 9 | lazy val entries: Seq[(Seq[Z3AST], Z3AST)] = { 10 | val numEntries = Native.funcInterpGetNumEntries(context.ptr, ptr) 11 | for (entryIndex <- (0 until numEntries).toList) yield { 12 | val entry = new Z3FuncInterpEntry(Native.funcInterpGetEntry(context.ptr, ptr, entryIndex), context) 13 | entry.args -> entry.value 14 | } 15 | } 16 | 17 | override def toString = "[" + entries.map { case (args, value) => 18 | args.mkString("(", ", ", ")") + " -> " + value 19 | }.mkString(", ") + ", else -> " + default + "]" 20 | 21 | final protected[z3] def incRef(): Unit = { 22 | Native.funcInterpIncRef(context.ptr, ptr) 23 | } 24 | 25 | final protected[z3] def decRef(): Unit = { 26 | Native.funcInterpDecRef(context.ptr, ptr) 27 | } 28 | 29 | locally { context.interpQueue.track(this) } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/scala/z3/scala/Z3FuncInterpEntry.scala: -------------------------------------------------------------------------------- 1 | package z3.scala 2 | 3 | import com.microsoft.z3.Native 4 | 5 | private[scala] class Z3FuncInterpEntry(val ptr: Long, val context: Z3Context) extends Z3Object { 6 | 7 | lazy val value = new Z3AST(Native.funcEntryGetValue(context.ptr, ptr), context) 8 | 9 | lazy val args: Seq[Z3AST] = { 10 | val numArgs = Native.funcEntryGetNumArgs(context.ptr, ptr) 11 | for (argIndex <- (0 until numArgs).toList) yield { 12 | new Z3AST(Native.funcEntryGetArg(context.ptr, ptr, argIndex), context) 13 | } 14 | } 15 | 16 | final protected[z3] def incRef(): Unit = { 17 | Native.funcEntryIncRef(context.ptr, ptr) 18 | } 19 | 20 | final protected[z3] def decRef(): Unit = { 21 | Native.funcEntryDecRef(context.ptr, ptr) 22 | } 23 | 24 | locally { context.entryQueue.track(this) } 25 | } 26 | 27 | -------------------------------------------------------------------------------- /src/main/scala/z3/scala/Z3Model.scala: -------------------------------------------------------------------------------- 1 | package z3.scala 2 | 3 | import com.microsoft.z3.Native 4 | 5 | object Z3Model { 6 | given ast2int: Conversion[(Z3Model, Z3AST), Option[Int]] = { (model, ast) => 7 | val res = model.eval(ast) 8 | if (res.isEmpty) 9 | None 10 | else 11 | model.context.getNumeralInt(res.get).value 12 | } 13 | 14 | given ast2bool: Conversion[(Z3Model, Z3AST), Option[Boolean]] = { (model, ast) => 15 | val res = model.eval(ast) 16 | if (res.isEmpty) 17 | None 18 | else 19 | model.context.getBoolValue(res.get) 20 | } 21 | 22 | given ast2char: Conversion[(Z3Model, Z3AST), Option[Char]] = { (model, ast) => 23 | val res = model.eval(ast) 24 | if (res.isEmpty) 25 | None 26 | else 27 | model.context.getNumeralInt(res.get).value.map(_.toChar) 28 | } 29 | } 30 | 31 | sealed class Z3Model private[z3](val ptr: Long, val context: Z3Context) extends Z3Object { 32 | override def toString : String = context.modelToString(this) 33 | 34 | def incRef(): Unit = { 35 | Native.modelIncRef(context.ptr, this.ptr) 36 | } 37 | 38 | def decRef(): Unit = { 39 | Native.modelDecRef(context.ptr, this.ptr) 40 | } 41 | 42 | def eval(ast: Z3AST, completion: Boolean = false) : Option[Z3AST] = { 43 | if(this.ptr == 0L) { 44 | throw new IllegalStateException("The model is not initialized.") 45 | } 46 | val out = new Native.LongPtr() 47 | val result = Native.modelEval(context.ptr, this.ptr, ast.ptr, completion, out) 48 | if (result && out.value != 0L) { 49 | Some(new Z3AST(out.value, context)) 50 | } else { 51 | None 52 | } 53 | } 54 | 55 | def evalAs[T](input: Z3AST)(using converter: Conversion[(Z3Model, Z3AST), Option[T]]): Option[T] = converter(this, input) 56 | 57 | def getConsts: Iterator[Z3FuncDecl] = { 58 | val model = this 59 | new Iterator[Z3FuncDecl] { 60 | val total: Int = Native.modelGetNumConsts(context.ptr, model.ptr) 61 | var returned: Int = 0 62 | 63 | override def hasNext: Boolean = (returned < total) 64 | override def next(): Z3FuncDecl = { 65 | val toReturn = new Z3FuncDecl(Native.modelGetConstDecl(context.ptr, model.ptr, returned), 0, context) 66 | returned += 1 67 | toReturn 68 | } 69 | } 70 | } 71 | 72 | def getConstInterpretations : Iterator[(Z3FuncDecl, Z3AST)] = { 73 | val model = this 74 | val constantIterator = getConsts 75 | new Iterator[(Z3FuncDecl, Z3AST)] { 76 | override def hasNext: Boolean = constantIterator.hasNext 77 | override def next(): (Z3FuncDecl, Z3AST) = { 78 | val nextConstant = constantIterator.next() 79 | (nextConstant, model.eval(nextConstant()).get) 80 | } 81 | } 82 | } 83 | 84 | private lazy val constantInterpretationMap: Map[String, Z3AST] = 85 | getConstInterpretations.map(p => (p._1.getName.toString, p._2)).toMap 86 | 87 | def getConstInterpretation(name: String): Option[Z3AST] = constantInterpretationMap.get(name) 88 | 89 | def getFuncInterpretations : Iterator[(Z3FuncDecl, Seq[(Seq[Z3AST], Z3AST)], Z3AST)] = { 90 | val model = this 91 | new Iterator[(Z3FuncDecl, Seq[(Seq[Z3AST], Z3AST)], Z3AST)] { 92 | val total: Int = Native.modelGetNumFuncs(context.ptr, model.ptr) 93 | var returned: Int = 0 94 | 95 | override def hasNext: Boolean = (returned < total) 96 | override def next(): (Z3FuncDecl, Seq[(Seq[Z3AST], Z3AST)], Z3AST) = { 97 | val declPtr = Native.modelGetFuncDecl(context.ptr, model.ptr, returned) 98 | val arity = Native.getDomainSize(context.ptr, declPtr) 99 | val funcDecl = new Z3FuncDecl(declPtr, arity, context) 100 | val funcInterp = new Z3FuncInterp(Native.modelGetFuncInterp(context.ptr, model.ptr, declPtr), context) 101 | returned += 1 102 | (funcDecl, funcInterp.entries, funcInterp.default) 103 | } 104 | } 105 | } 106 | 107 | private lazy val funcInterpretationMap: Map[Z3FuncDecl, (Seq[(Seq[Z3AST], Z3AST)], Z3AST)] = 108 | getFuncInterpretations.map(i => (i._1, (i._2, i._3))).toMap 109 | 110 | def isArrayValue(ast: Z3AST) : Boolean = { 111 | Native.isAsArray(context.ptr, ast.ptr) 112 | } 113 | 114 | def getArrayValue(ast: Z3AST) : Option[(Map[Z3AST, Z3AST], Z3AST)] = if (isArrayValue(ast)) { 115 | val funcPtr = Native.getAsArrayFuncDecl(context.ptr, ast.ptr) 116 | val arity = Native.getDomainSize(context.ptr, funcPtr) 117 | assert(arity == 1, "Arrays with arity > 1 aren't handled by ScalaZ3") 118 | val funcInterp = new Z3FuncInterp(Native.modelGetFuncInterp(context.ptr, this.ptr, funcPtr), context) 119 | Some(funcInterp.entries.map { case (args, value) => args.head -> value }.toMap, funcInterp.default) 120 | } else { 121 | import Z3DeclKind._ 122 | def rec(ast: Z3AST): Option[(Map[Z3AST, Z3AST], Z3AST)] = context.getASTKind(ast) match { 123 | case Z3AppAST(funcDecl, args) => context.getDeclKind(funcDecl) match { 124 | case OpStore => rec(args(0)).map { case (mapping, default) => 125 | (mapping + (args(1) -> args(2)), default) 126 | } 127 | case OpConstArray => 128 | Some(Map.empty, args(0)) 129 | case _ => None 130 | } 131 | case _ => None 132 | } 133 | 134 | rec(ast) 135 | } 136 | 137 | def getSetValue(ast: Z3AST) : Option[(Set[Z3AST], Boolean)] = { 138 | val value = getArrayValue(ast) 139 | 140 | value.flatMap { case (mapping, dflt) => 141 | evalAs[Boolean](dflt) match { 142 | case Some(false) => // finite set 143 | Some((mapping.collect { case (k, v) if evalAs[Boolean](v) == Some(true) => k }.toSet, true)) 144 | case Some(true) => // co-finite set 145 | Some((mapping.collect { case (k, v) if evalAs[Boolean](v) == Some(false) => k }.toSet, false)) 146 | case _ => 147 | None 148 | } 149 | } 150 | } 151 | 152 | def getFuncInterpretation(fd: Z3FuncDecl): Option[(Seq[(Seq[Z3AST], Z3AST)], Z3AST)] = 153 | funcInterpretationMap.get(fd) 154 | 155 | locally { 156 | context.modelQueue.track(this) 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /src/main/scala/z3/scala/Z3Object.scala: -------------------------------------------------------------------------------- 1 | package z3.scala 2 | 3 | import com.microsoft.z3.Native 4 | 5 | trait Z3Object extends Z3Pointer { 6 | val ptr: Long 7 | val context: Z3Context 8 | 9 | protected[z3] def incRef(): Unit 10 | protected[z3] def decRef(): Unit 11 | } 12 | 13 | trait Z3ASTLike extends Z3Object { 14 | final protected[z3] def incRef(): Unit = { 15 | Native.incRef(context.ptr, ptr) 16 | } 17 | 18 | final protected[z3] def decRef(): Unit = { 19 | Native.decRef(context.ptr, ptr) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/scala/z3/scala/Z3Optimizer.scala: -------------------------------------------------------------------------------- 1 | package z3.scala 2 | 3 | import com.microsoft.z3.Native 4 | import scala.collection.mutable.{Map => MutableMap} 5 | 6 | class Z3Optimizer private[z3](val ptr: Long, val context: Z3Context) extends Z3Object { 7 | 8 | override def equals(that: Any): Boolean = { 9 | that != null && 10 | that.isInstanceOf[Z3Optimizer] && 11 | that.asInstanceOf[Z3Optimizer].ptr == this.ptr 12 | } 13 | 14 | def pop() = { 15 | Native.optimizePop(context.ptr, this.ptr) 16 | } 17 | 18 | def push() = { 19 | Native.optimizePush(context.ptr, this.ptr) 20 | } 21 | 22 | def set(params: Map[String, Any]): Unit = { 23 | val z3params = new Z3Params(Native.mkParams(context.ptr), context) 24 | for ((k, v) <- params) z3params.set(k, v) 25 | Native.optimizeSetParams(context.ptr, ptr, z3params.ptr) 26 | } 27 | 28 | def assertCnstr(ast: Z3AST) = { 29 | Native.optimizeAssert(context.ptr, this.ptr, ast.ptr) 30 | } 31 | 32 | class Handle private[z3](handle: Int) { 33 | def getUpper: Z3AST = new Z3AST(Native.optimizeGetUpper(context.ptr, Z3Optimizer.this.ptr, handle), context) 34 | def getLower: Z3AST = new Z3AST(Native.optimizeGetLower(context.ptr, Z3Optimizer.this.ptr, handle), context) 35 | } 36 | 37 | def maximize(ast: Z3AST) = { 38 | Native.optimizeMaximize(context.ptr, this.ptr, ast.ptr) 39 | } 40 | 41 | def minimize(ast: Z3AST) = { 42 | Native.optimizeMinimize(context.ptr, this.ptr, ast.ptr) 43 | } 44 | 45 | def assertCnstr(ast: Z3AST, weight: Int) = { 46 | val s = context.mkFreshStringSymbol("opt$group") 47 | new Handle(Native.optimizeAssertSoft(context.ptr, this.ptr, ast.ptr, weight.toString, s.ptr)) 48 | } 49 | 50 | private val groupSymbols: MutableMap[String, Z3Symbol] = MutableMap.empty 51 | 52 | def assertCnstr(ast: Z3AST, weight: Int, group: String) = { 53 | val s = groupSymbols.get(group) match { 54 | case Some(s) => s 55 | case None => 56 | val s = context.mkFreshStringSymbol(group) 57 | groupSymbols += group -> s 58 | s 59 | } 60 | new Handle(Native.optimizeAssertSoft(context.ptr, this.ptr, ast.ptr, weight.toString, s.ptr)) 61 | } 62 | 63 | def getAssertions(): Z3ASTVector = { 64 | new Z3ASTVector(Native.optimizeGetAssertions(context.ptr, this.ptr), context) 65 | } 66 | 67 | private[this] var lastResult: Option[Boolean] = None 68 | 69 | def check(): Option[Boolean] = { 70 | val res = i2ob(Native.optimizeCheck(context.ptr, this.ptr, 0, null)) 71 | lastResult = res 72 | res 73 | } 74 | 75 | def getModel(): Z3Model = { 76 | if (lastResult == Some(true)) { 77 | new Z3Model(Native.optimizeGetModel(context.ptr, this.ptr), context) 78 | } else { 79 | throw new Exception("Cannot get model if check failed") 80 | } 81 | } 82 | 83 | def incRef(): Unit = { 84 | Native.optimizeIncRef(context.ptr, this.ptr) 85 | } 86 | 87 | def decRef(): Unit = { 88 | Native.optimizeDecRef(context.ptr, this.ptr) 89 | } 90 | 91 | def getReasonUnknown(): String = { 92 | Native.optimizeGetReasonUnknown(context.ptr, this.ptr) 93 | } 94 | 95 | override def toString: String = { 96 | Native.optimizeToString(context.ptr, this.ptr) 97 | } 98 | 99 | locally { 100 | context.optimizerQueue.track(this) 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/main/scala/z3/scala/Z3Params.scala: -------------------------------------------------------------------------------- 1 | package z3.scala 2 | 3 | import com.microsoft.z3.Native 4 | import com.microsoft.z3.Z3Exception 5 | 6 | private[scala] class Z3Params(val ptr: Long, val context: Z3Context) extends Z3Object { 7 | 8 | def set(key: String, value: Any): Unit = value match { 9 | case b: Boolean => Native.paramsSetBool(context.ptr, ptr, context.mkSymbol(key).ptr, b) 10 | case d: Double => Native.paramsSetDouble(context.ptr, ptr, context.mkSymbol(key).ptr, d) 11 | case i: Int => Native.paramsSetUint(context.ptr, ptr, context.mkSymbol(key).ptr, i) 12 | case s: String => Native.paramsSetSymbol(context.ptr, ptr, context.mkSymbol(key).ptr, context.mkSymbol(s).ptr) 13 | case _ => throw new Z3Exception("Can't set value " + value + " of type " + value.getClass) 14 | } 15 | 16 | final protected[z3] def incRef(): Unit = { 17 | Native.paramsIncRef(context.ptr, ptr) 18 | } 19 | 20 | final protected[z3] def decRef(): Unit = { 21 | Native.paramsDecRef(context.ptr, ptr) 22 | } 23 | 24 | locally { 25 | context.paramsQueue.track(this) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/scala/z3/scala/Z3Pattern.scala: -------------------------------------------------------------------------------- 1 | package z3.scala 2 | 3 | sealed class Z3Pattern private[z3](val ptr: Long, val context: Z3Context) extends Z3ASTLike { 4 | override def toString : String = context.patternToString(this) 5 | 6 | locally { 7 | context.astQueue.track(this) 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/main/scala/z3/scala/Z3Pointer.scala: -------------------------------------------------------------------------------- 1 | package z3.scala 2 | 3 | trait Z3Pointer { 4 | val ptr: Long 5 | } 6 | -------------------------------------------------------------------------------- /src/main/scala/z3/scala/Z3RefCountQueue.scala: -------------------------------------------------------------------------------- 1 | package z3.scala 2 | 3 | class Z3RefCountQueue[T <: Z3Object] { 4 | private val drQueue = collection.mutable.Queue[T]() 5 | 6 | protected[z3] def track(t: T): Unit = { 7 | t.incRef() 8 | synchronized { 9 | drQueue += t 10 | } 11 | } 12 | 13 | protected[z3] def clearQueue(): Unit = { 14 | synchronized { 15 | for (t <- drQueue) { 16 | t.decRef() 17 | } 18 | drQueue.clear() 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/scala/z3/scala/Z3SearchFailure.scala: -------------------------------------------------------------------------------- 1 | package z3.scala 2 | 3 | sealed abstract class Z3SearchFailure(val id: Int, val message: String) 4 | case object Z3NoFailure extends Z3SearchFailure(0, "The last search was successful") 5 | case object Z3Unknown extends Z3SearchFailure(1, "Undocumented failure reason") 6 | case object Z3Timeout extends Z3SearchFailure(2, "Timeout") 7 | case object Z3MemoutWatermark extends Z3SearchFailure(3, "Search hit a memory high-watermak limit") 8 | case object Z3Canceled extends Z3SearchFailure(4, "External cancel flag was set") 9 | case object Z3NumConflicts extends Z3SearchFailure(5, "Maximum number of conflicts was reached") 10 | case object Z3IncompleteTheory extends Z3SearchFailure(6, "Theory is incomplete") 11 | case object Z3Quantifiers extends Z3SearchFailure(7, "Logical context contains universal quantifiers") 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/main/scala/z3/scala/Z3Solver.scala: -------------------------------------------------------------------------------- 1 | package z3.scala 2 | 3 | import com.microsoft.z3.Native 4 | 5 | class Z3Solver private[z3](val ptr: Long, val context: Z3Context) extends Z3Object { 6 | override def equals(that: Any) : Boolean = { 7 | that != null && 8 | that.isInstanceOf[Z3Solver] && { 9 | val that2 = that.asInstanceOf[Z3Solver] 10 | that2.ptr == this.ptr // && context.isEqAST(this, that2) 11 | } 12 | } 13 | 14 | def pop(numScopes : Int = 1) = { 15 | Native.solverPop(context.ptr, this.ptr, numScopes) 16 | } 17 | 18 | def push() = { 19 | Native.solverPush(context.ptr, this.ptr) 20 | } 21 | 22 | def set(params: Map[String, Any]): Unit = { 23 | val z3params = new Z3Params(Native.mkParams(context.ptr), context) 24 | for ((k, v) <- params) z3params.set(k, v) 25 | Native.solverSetParams(context.ptr, ptr, z3params.ptr) 26 | } 27 | 28 | def assertCnstr(ast: Z3AST) = { 29 | Native.solverAssert(context.ptr, this.ptr, ast.ptr) 30 | } 31 | 32 | def getAssertions(): Z3ASTVector = { 33 | new Z3ASTVector(Native.solverGetAssertions(context.ptr, this.ptr), context) 34 | } 35 | 36 | private[this] var isModelAvailable = false 37 | 38 | def check() : Option[Boolean] = { 39 | val res = i2ob(Native.solverCheck(context.ptr, this.ptr)) 40 | isModelAvailable = res != Some(false) 41 | res 42 | } 43 | 44 | def getModel() : Z3Model = { 45 | if (isModelAvailable) { 46 | new Z3Model(Native.solverGetModel(context.ptr, this.ptr), context) 47 | } else { 48 | throw new Exception("Cannot get model if check failed") 49 | } 50 | } 51 | 52 | def getProof() : Z3AST = { 53 | if (!isModelAvailable) { 54 | new Z3AST(Native.solverGetProof(context.ptr, this.ptr), context) 55 | } else { 56 | throw new Exception("Cannot get proof if formula is SAT") 57 | } 58 | } 59 | 60 | def getUnsatCore() : Z3ASTVector = { 61 | new Z3ASTVector(Native.solverGetUnsatCore(context.ptr, this.ptr), context) 62 | } 63 | 64 | def reset() = { 65 | Native.solverReset(context.ptr, this.ptr) 66 | } 67 | 68 | def getNumScopes() = { 69 | Native.solverGetNumScopes(context.ptr, this.ptr) 70 | } 71 | 72 | def incRef(): Unit = { 73 | Native.solverIncRef(context.ptr, this.ptr) 74 | } 75 | 76 | def decRef(): Unit = { 77 | Native.solverDecRef(context.ptr, this.ptr) 78 | } 79 | 80 | def checkAssumptions(assumptions: Z3AST*) : Option[Boolean] = { 81 | val res = i2ob( 82 | Native.solverCheckAssumptions( 83 | context.ptr, 84 | this.ptr, 85 | assumptions.size, 86 | toPtrArray(assumptions) 87 | ) 88 | ) 89 | 90 | isModelAvailable = res != Some(false) 91 | res 92 | } 93 | 94 | // Utility functions that should no longer be exposed 95 | private[z3] def checkAndGetModel() = { 96 | (check(), if (isModelAvailable) getModel() else null) 97 | } 98 | 99 | private[z3] def checkAssumptionsGetModelOrCore(assumptions: Z3AST*) = { 100 | (checkAssumptions(assumptions : _*), if (isModelAvailable) getModel() else null, getUnsatCore()) 101 | } 102 | 103 | def assertCnstr(tree : dsl.Tree[dsl.BoolSort]) : Unit = { 104 | assertCnstr(tree.ast(context)) 105 | } 106 | 107 | def checkAndGetAllModels(): Iterator[Z3Model] = { 108 | new Iterator[Z3Model] { 109 | var constraints: Z3AST = context.mkTrue() 110 | var nextModel: Option[Option[Z3Model]] = None 111 | 112 | override def hasNext: Boolean = nextModel match { 113 | case None => 114 | // Check whether there are any more models 115 | push() 116 | assertCnstr(constraints) 117 | val result = checkAndGetModel() 118 | pop(1) 119 | val toReturn = (result match { 120 | case (Some(true), m) => 121 | nextModel = Some(Some(m)) 122 | val newConstraints = m.getConstInterpretations.foldLeft(context.mkTrue()){ 123 | (acc, s) => context.mkAnd(acc, context.mkEq(s._1(), s._2)) 124 | } 125 | constraints = context.mkAnd(constraints, context.mkNot(newConstraints)) 126 | true 127 | case (Some(false), _) => 128 | nextModel = Some(None) 129 | false 130 | case (None, _) => 131 | nextModel = Some(None) 132 | false 133 | }) 134 | toReturn 135 | case Some(None) => false 136 | case Some(Some(m)) => true 137 | } 138 | 139 | override def next(): Z3Model = nextModel match { 140 | case None => 141 | // Compute next model 142 | push() 143 | assertCnstr(constraints) 144 | val result = checkAndGetModel() 145 | pop(1) 146 | val toReturn = (result match { 147 | case (Some(true), m) => 148 | val newConstraints = m.getConstInterpretations.foldLeft(context.mkTrue()){ 149 | (acc, s) => context.mkAnd(acc, context.mkEq(s._1(), s._2)) 150 | } 151 | constraints = context.mkAnd(constraints, context.mkNot(newConstraints)) 152 | m 153 | case _ => 154 | throw new Exception("Requesting a new model while there are no more models.") 155 | }) 156 | toReturn 157 | case Some(Some(m)) => 158 | nextModel = None 159 | m 160 | case Some(None) => throw new Exception("Requesting a new model while there are no more models.") 161 | } 162 | } 163 | } 164 | 165 | private[z3] def checkAndGetAllEventualModels(): Iterator[(Option[Boolean], Z3Model)] = { 166 | new Iterator[(Option[Boolean], Z3Model)] { 167 | var constraints: Z3AST = context.mkTrue() 168 | var nextModel: Option[Option[(Option[Boolean],Z3Model)]] = None 169 | 170 | override def hasNext: Boolean = nextModel match { 171 | case None => 172 | // Check whether there are any more models 173 | push() 174 | assertCnstr(constraints) 175 | val result = checkAndGetModel() 176 | pop(1) 177 | val toReturn = (result match { 178 | case (Some(false), _) => 179 | nextModel = Some(None) 180 | false 181 | case (outcome, m) => 182 | nextModel = Some(Some((outcome, m))) 183 | val newConstraints = m.getConstInterpretations.foldLeft(context.mkTrue()){ 184 | (acc, s) => context.mkAnd(acc, context.mkEq(s._1(), s._2)) 185 | } 186 | constraints = context.mkAnd(constraints, context.mkNot(newConstraints)) 187 | true 188 | }) 189 | toReturn 190 | case Some(None) => false 191 | case Some(Some(_)) => true 192 | } 193 | 194 | override def next(): (Option[Boolean], Z3Model) = nextModel match { 195 | case None => 196 | // Compute next model 197 | push() 198 | assertCnstr(constraints) 199 | val result = checkAndGetModel() 200 | pop(1) 201 | val toReturn = (result match { 202 | case (Some(false), _) => 203 | throw new Exception("Requesting a new model while there are no more models.") 204 | case (outcome, m) => 205 | val newConstraints = m.getConstInterpretations.foldLeft(context.mkTrue()){ 206 | (acc, s) => context.mkAnd(acc, context.mkEq(s._1(), s._2)) 207 | } 208 | constraints = context.mkAnd(constraints, context.mkNot(newConstraints)) 209 | (outcome, m) 210 | }) 211 | toReturn 212 | case Some(Some((outcome, m))) => 213 | nextModel = None 214 | (outcome, m) 215 | case Some(None) => throw new Exception("Requesting a new model while there are no more models.") 216 | } 217 | } 218 | } 219 | 220 | def getReasonUnknown() : String = { 221 | Native.solverGetReasonUnknown(context.ptr, this.ptr) 222 | } 223 | 224 | override def toString() : String = { 225 | Native.solverToString(context.ptr, this.ptr) 226 | } 227 | 228 | locally { 229 | context.solverQueue.track(this) 230 | } 231 | } 232 | -------------------------------------------------------------------------------- /src/main/scala/z3/scala/Z3Sort.scala: -------------------------------------------------------------------------------- 1 | package z3.scala 2 | 3 | sealed class Z3Sort private[z3](val ptr: Long, val context: Z3Context) extends Z3ASTLike { 4 | override def equals(that: Any) : Boolean = { 5 | that != null && that.isInstanceOf[Z3Sort] && context.isEqSort(this, that.asInstanceOf[Z3Sort]) 6 | } 7 | 8 | private val hc : Int = ptr.hashCode() 9 | override def hashCode : Int = hc 10 | 11 | override def toString : String = context.sortToString(this) 12 | 13 | lazy val isBoolSort : Boolean = context.isEqSort(this, context.mkBoolSort()) 14 | lazy val isIntSort : Boolean = context.isEqSort(this, context.mkIntSort()) 15 | lazy val isIntSetSort : Boolean = context.isEqSort(this, context.mkSetSort(context.mkIntSort())) 16 | lazy val isRealSort : Boolean = context.isEqSort(this, context.mkRealSort()) 17 | 18 | locally { 19 | context.astQueue.track(this) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/scala/z3/scala/Z3Symbol.scala: -------------------------------------------------------------------------------- 1 | package z3.scala 2 | 3 | sealed class Z3Symbol private[z3](val ptr: Long, context: Z3Context) extends Z3Pointer { 4 | override def equals(that: Any) : Boolean = { 5 | that != null && that.isInstanceOf[Z3Symbol] && that.asInstanceOf[Z3Symbol].ptr == this.ptr 6 | } 7 | 8 | def getKind : Z3SymbolKind[_] = context.getSymbolKind(this) 9 | 10 | private lazy val strRepr: String = getKind match { 11 | case Z3IntSymbol(v) => "sym#" + v 12 | case Z3StringSymbol(s) => s 13 | } 14 | 15 | override def toString : String = strRepr 16 | } 17 | -------------------------------------------------------------------------------- /src/main/scala/z3/scala/Z3SymbolKind.scala: -------------------------------------------------------------------------------- 1 | package z3.scala 2 | 3 | sealed abstract class Z3SymbolKind[T] { 4 | val value: T 5 | } 6 | 7 | case class Z3IntSymbol private[z3](value: Int) extends Z3SymbolKind[Int] 8 | case class Z3StringSymbol private[z3](value: String) extends Z3SymbolKind[String] 9 | -------------------------------------------------------------------------------- /src/main/scala/z3/scala/Z3Tactic.scala: -------------------------------------------------------------------------------- 1 | package z3.scala 2 | 3 | import com.microsoft.z3.Native 4 | 5 | class Z3Tactic private[z3](val ptr : Long, val context : Z3Context) extends Z3Object { 6 | override def equals(that: Any) : Boolean = { 7 | that != null && 8 | that.isInstanceOf[Z3Tactic] && { 9 | val that2 = that.asInstanceOf[Z3Tactic] 10 | that2.ptr == this.ptr // && context.isEqAST(this, that2) 11 | } 12 | } 13 | 14 | def incRef(): Unit = { 15 | Native.tacticIncRef(context.ptr, this.ptr) 16 | } 17 | 18 | def decRef(): Unit = { 19 | Native.tacticDecRef(context.ptr, this.ptr) 20 | } 21 | 22 | locally { 23 | context.tacticQueue.track(this) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/scala/z3/scala/dsl/Operands.scala: -------------------------------------------------------------------------------- 1 | package z3.scala.dsl 2 | 3 | /** We call Operands what is otherwise known as "Rich" classes (from the "Pimp 4 | * My Library" paradigm). For simplicity and to avoid ambiguous resolutions, 5 | * operations on operands always return operands, never trees. Conversion from 6 | * and to trees are done by implicit functions in the dsl package object. */ 7 | object Operands { 8 | class BoolOperand private[dsl](val tree : Tree[_ >: BottomSort <: BoolSort]) { 9 | def &&[T >: BottomSort <: BoolSort](other : BoolOperand) : BoolOperand = { 10 | new BoolOperand(And(tree, other.tree)) 11 | } 12 | 13 | def ||(other : BoolOperand) : BoolOperand = { 14 | new BoolOperand(Or(tree, other.tree)) 15 | } 16 | 17 | def unary_! : BoolOperand= { 18 | new BoolOperand(Not(tree)) 19 | } 20 | 21 | def <-->(other : BoolOperand) : BoolOperand = { 22 | new BoolOperand(Iff(tree, other.tree)) 23 | } 24 | 25 | def ===(other : BoolOperand) = <-->(other) 26 | 27 | def -->(other : BoolOperand) : BoolOperand = { 28 | new BoolOperand(Implies(tree, other.tree)) 29 | } 30 | 31 | def ^^(other : BoolOperand) : BoolOperand = { 32 | new BoolOperand(Xor(tree, other.tree)) 33 | } 34 | 35 | def !==(other : BoolOperand) = ^^(other) 36 | } 37 | 38 | class IntOperand private[dsl](val tree : Tree[_ >: BottomSort <: IntSort]) { 39 | def +(other : IntOperand) : IntOperand= { 40 | new IntOperand(Add(tree, other.tree)) 41 | } 42 | 43 | def *(other : IntOperand) : IntOperand = { 44 | new IntOperand(Mul(tree, other.tree)) 45 | } 46 | 47 | def -(other : IntOperand) : IntOperand = { 48 | new IntOperand(Sub(tree, other.tree)) 49 | } 50 | 51 | def /(other : IntOperand) : IntOperand = { 52 | new IntOperand(Div(tree, other.tree)) 53 | } 54 | 55 | def %(other : IntOperand) : IntOperand = { 56 | new IntOperand(Mod(tree, other.tree)) 57 | } 58 | 59 | def rem(other : IntOperand) : IntOperand = { 60 | new IntOperand(Rem(tree, other.tree)) 61 | } 62 | 63 | def ===(other : IntOperand) : BoolOperand = { 64 | new BoolOperand(Eq(tree, other.tree)) 65 | } 66 | 67 | def !==(other : IntOperand) : BoolOperand = { 68 | new BoolOperand(Distinct(tree, other.tree)) 69 | } 70 | 71 | def <(other : IntOperand) : BoolOperand = { 72 | new BoolOperand(LT(tree, other.tree)) 73 | } 74 | 75 | def <=(other : IntOperand) : BoolOperand = { 76 | new BoolOperand(LE(tree, other.tree)) 77 | } 78 | 79 | def >(other : IntOperand) : BoolOperand = { 80 | new BoolOperand(GT(tree, other.tree)) 81 | } 82 | 83 | def >=(other : IntOperand) : BoolOperand = { 84 | new BoolOperand(GE(tree, other.tree)) 85 | } 86 | } 87 | 88 | class BitVectorOperand private[dsl](val tree : Tree[_ >: BottomSort <: BVSort]) { 89 | def unary_~ : BitVectorOperand = { 90 | new BitVectorOperand(BVNot(tree)) 91 | } 92 | 93 | def reducedAnd : BitVectorOperand = { 94 | new BitVectorOperand(BVRedAnd(tree)) 95 | } 96 | 97 | def reducedOr : BitVectorOperand = { 98 | new BitVectorOperand(BVRedOr(tree)) 99 | } 100 | 101 | def |(other : BitVectorOperand) : BitVectorOperand = { 102 | new BitVectorOperand(BVOr(tree, other.tree)) 103 | } 104 | 105 | def &(other : BitVectorOperand) : BitVectorOperand = { 106 | new BitVectorOperand(BVAnd(tree, other.tree)) 107 | } 108 | 109 | def ^(other : BitVectorOperand) : BitVectorOperand = { 110 | new BitVectorOperand(BVXor(tree, other.tree)) 111 | } 112 | 113 | def nand(other : BitVectorOperand) : BitVectorOperand = { 114 | new BitVectorOperand(BVNand(tree, other.tree)) 115 | } 116 | 117 | def nor(other : BitVectorOperand) : BitVectorOperand = { 118 | new BitVectorOperand(BVNor(tree, other.tree)) 119 | } 120 | 121 | def xnor(other : BitVectorOperand) : BitVectorOperand = { 122 | new BitVectorOperand(BVXnor(tree, other.tree)) 123 | } 124 | 125 | def unary_- : BitVectorOperand = { 126 | new BitVectorOperand(BVNeg(tree)) 127 | } 128 | 129 | def *(other : BitVectorOperand) : BitVectorOperand = { 130 | new BitVectorOperand(BVMul(tree, other.tree)) 131 | } 132 | 133 | def -(other : BitVectorOperand) : BitVectorOperand = { 134 | new BitVectorOperand(BVSub(tree, other.tree)) 135 | } 136 | 137 | def ~/(other : BitVectorOperand) : BitVectorOperand = { 138 | new BitVectorOperand(BVUdiv(tree, other.tree)) 139 | } 140 | 141 | def /(other : BitVectorOperand) : BitVectorOperand = { 142 | new BitVectorOperand(BVSdiv(tree, other.tree)) 143 | } 144 | 145 | def %(other : BitVectorOperand) : BitVectorOperand = { 146 | new BitVectorOperand(BVSmod(tree, other.tree)) 147 | } 148 | 149 | def urem(other : BitVectorOperand) : BitVectorOperand = { 150 | new BitVectorOperand(BVUrem(tree, other.tree)) 151 | } 152 | 153 | def srem(other : BitVectorOperand) : BitVectorOperand = { 154 | new BitVectorOperand(BVSrem(tree, other.tree)) 155 | } 156 | 157 | def ===(other : BitVectorOperand) : BoolOperand = { 158 | new BoolOperand(Eq(tree, other.tree)) 159 | } 160 | 161 | def !==(other : BitVectorOperand) : BoolOperand = { 162 | new BoolOperand(Distinct(tree, other.tree)) 163 | } 164 | 165 | def ~<(other : BitVectorOperand) : BoolOperand = { 166 | new BoolOperand(BVUlt(tree, other.tree)) 167 | } 168 | 169 | def ~<=(other : BitVectorOperand) : BoolOperand = { 170 | new BoolOperand(BVUle(tree, other.tree)) 171 | } 172 | 173 | def ~>(other : BitVectorOperand) : BoolOperand = { 174 | new BoolOperand(BVUgt(tree, other.tree)) 175 | } 176 | 177 | def ~>=(other : BitVectorOperand) : BoolOperand = { 178 | new BoolOperand(BVUge(tree, other.tree)) 179 | } 180 | 181 | def <(other : BitVectorOperand) : BoolOperand = { 182 | new BoolOperand(BVSlt(tree, other.tree)) 183 | } 184 | 185 | def <=(other : BitVectorOperand) : BoolOperand = { 186 | new BoolOperand(BVSle(tree, other.tree)) 187 | } 188 | 189 | def >(other : BitVectorOperand) : BoolOperand = { 190 | new BoolOperand(BVSgt(tree, other.tree)) 191 | } 192 | 193 | def >=(other : BitVectorOperand) : BoolOperand = { 194 | new BoolOperand(BVSge(tree, other.tree)) 195 | } 196 | 197 | def concat(other : BitVectorOperand) : BitVectorOperand = { 198 | new BitVectorOperand(Concat(tree, other.tree)) 199 | } 200 | 201 | def extract(high: Int, low: Int) : BitVectorOperand = { 202 | new BitVectorOperand(Extract(high, low, tree)) 203 | } 204 | 205 | def signExt(extraSize: Int) : BitVectorOperand = { 206 | new BitVectorOperand(SignExt(extraSize, tree)) 207 | } 208 | 209 | def zeroExt(extraSize: Int) : BitVectorOperand = { 210 | new BitVectorOperand(ZeroExt(extraSize, tree)) 211 | } 212 | 213 | def repeat(count: Int) : BitVectorOperand = { 214 | new BitVectorOperand(Repeat(count, tree)) 215 | } 216 | 217 | def <<(other : BitVectorOperand) : BitVectorOperand = { 218 | new BitVectorOperand(BVShl(tree, other.tree)) 219 | } 220 | 221 | def >>(other : BitVectorOperand) : BitVectorOperand = { 222 | new BitVectorOperand(BVAshr(tree, other.tree)) 223 | } 224 | 225 | def >>>(other : BitVectorOperand) : BitVectorOperand = { 226 | new BitVectorOperand(BVLshr(tree, other.tree)) 227 | } 228 | 229 | def rotateLeft(other : BitVectorOperand) : BitVectorOperand = { 230 | new BitVectorOperand(ExtRotateLeft(tree, other.tree)) 231 | } 232 | 233 | def rotateRight(other : BitVectorOperand) : BitVectorOperand = { 234 | new BitVectorOperand(ExtRotateRight(tree, other.tree)) 235 | } 236 | 237 | def addNoOverflow(other : BitVectorOperand, isSigned: Boolean) : BitVectorOperand = { 238 | new BitVectorOperand(BVAddNoOverflow(tree, other.tree, isSigned)) 239 | } 240 | 241 | def addNoUnderflow(other : BitVectorOperand) : BitVectorOperand = { 242 | new BitVectorOperand(BVAddNoUnderflow(tree, other.tree)) 243 | } 244 | 245 | def subNoOverflow(other : BitVectorOperand) : BitVectorOperand = { 246 | new BitVectorOperand(BVSubNoOverflow(tree, other.tree)) 247 | } 248 | 249 | def subNoUnderflow(other : BitVectorOperand, isSigned: Boolean) : BitVectorOperand = { 250 | new BitVectorOperand(BVSubNoUnderflow(tree, other.tree, isSigned)) 251 | } 252 | 253 | def sdivNoOverflow(other : BitVectorOperand) : BitVectorOperand = { 254 | new BitVectorOperand(BVSDivNoOverflow(tree, other.tree)) 255 | } 256 | 257 | def negNoOverflow : BitVectorOperand= { 258 | new BitVectorOperand(BVNegNoOverflow(tree)) 259 | } 260 | 261 | def mulNoOverflow(other : BitVectorOperand, isSigned: Boolean) : BitVectorOperand = { 262 | new BitVectorOperand(BVMulNoOverflow(tree, other.tree, isSigned)) 263 | } 264 | 265 | def mulNoUnderflow(other : BitVectorOperand) : BitVectorOperand = { 266 | new BitVectorOperand(BVMulNoUnderflow(tree, other.tree)) 267 | } 268 | } 269 | 270 | class SetOperand private[dsl](val tree : Tree[_ >: BottomSort <: SetSort]) { 271 | def ++(other : SetOperand) : SetOperand = { 272 | new SetOperand(SetUnion(tree, other.tree)) 273 | } 274 | 275 | def **(other : SetOperand) : SetOperand = { 276 | new SetOperand(SetIntersect(tree, other.tree)) 277 | } 278 | 279 | def --(other : SetOperand) : SetOperand = { 280 | new SetOperand(SetDifference(tree, other.tree)) 281 | } 282 | 283 | def ===(other : SetOperand) : BoolOperand = { 284 | new BoolOperand(Eq(tree, other.tree)) 285 | } 286 | 287 | def !==(other : SetOperand) : BoolOperand = { 288 | new BoolOperand(Distinct(tree, other.tree)) 289 | } 290 | 291 | def subsetOf(other : SetOperand) : BoolOperand = { 292 | new BoolOperand(SetSubset(tree, other.tree)) 293 | } 294 | } 295 | } 296 | -------------------------------------------------------------------------------- /src/main/scala/z3/scala/dsl/Trees.scala: -------------------------------------------------------------------------------- 1 | package z3.scala.dsl 2 | 3 | import z3.scala.{Z3AST, Z3Context} 4 | 5 | sealed trait TopSort 6 | sealed trait BoolSort extends TopSort 7 | sealed trait IntSort extends TopSort 8 | sealed trait RealSort extends TopSort 9 | sealed trait BVSort extends TopSort 10 | sealed trait SetSort extends TopSort 11 | sealed trait ArraySort extends TopSort 12 | sealed trait BottomSort extends BoolSort with IntSort with RealSort with BVSort with SetSort with ArraySort 13 | 14 | sealed trait Tree[+T >: BottomSort <: TopSort] { 15 | private[dsl] def build(z3 : Z3Context) : Z3AST 16 | 17 | private var built : Boolean = false 18 | private var t : Z3AST = null 19 | def ast(z3 : Z3Context) : Z3AST = { 20 | if(!built) { 21 | built = true 22 | t = build(z3) 23 | } 24 | t 25 | } 26 | } 27 | 28 | /** The type parameter refers to a Scala type for a value that the user 29 | * wishes to obtain through a call to choose, find or findAll. */ 30 | class Val[A : ValHandler] { 31 | val tree: Tree[_ >: BottomSort <: TopSort] = summon[ValHandler[A]].construct 32 | } 33 | 34 | abstract class ValTree[S >: BottomSort <: TopSort] extends Tree[S] { 35 | import Operands._ 36 | 37 | // def ===(other : Val[A]) : BoolOperand = { 38 | // new BoolOperand(Eq(this, other)) 39 | // } 40 | 41 | //def !==(other : Val[A]) : BoolOperand = { 42 | // new BoolOperand(Distinct(this, other)) 43 | //} 44 | 45 | // This is more general. 46 | def ===(other : Tree[BottomSort]) : BoolOperand = { 47 | new BoolOperand(Eq(this, other)) 48 | } 49 | 50 | def !==(other : Tree[BottomSort]) : BoolOperand = { 51 | new BoolOperand(Distinct(this, other)) 52 | } 53 | 54 | // Unsafe as such. Better would be to have this in Tree itself, and restrict 55 | // it to trees of array sorts. 56 | def apply(t : Tree[_ >: BottomSort <: TopSort]) : Tree[BottomSort] = { 57 | new MapSelect(this, t) 58 | } 59 | } 60 | 61 | /** This class is used to bridge the gap between non-DSL Z3ASTs and DSL ASTs. 62 | * There are two important things to check: that the Z3Context is the correct 63 | * one (when the DSL tree actually gets converted), and that the sort is the 64 | * advertised one. This second check is currently not performed. It will need 65 | * to be a runtime check that can happen through an implicit "checker" 66 | * parameter. */ 67 | case class Z3ASTWrapper[+A >: BottomSort <: TopSort] private[z3](ast : Z3AST) extends Tree[A] { 68 | def build(z3 : Z3Context) : Z3AST = returnIfCompatible(z3) 69 | override def ast(z3 : Z3Context) : Z3AST = returnIfCompatible(z3) 70 | 71 | private def returnIfCompatible(z3 : Z3Context) : Z3AST = { 72 | if(z3.ptr != ast.context.ptr) { 73 | throw new Exception("Error: using incompatible context to convert DSL Tree.") 74 | } else { 75 | this.ast 76 | } 77 | } 78 | } 79 | 80 | sealed trait BinaryOp[+A >: BottomSort <: TopSort,B >: BottomSort <: TopSort] extends Tree[B] { 81 | val left : Tree[A] 82 | val right : Tree[A] 83 | } 84 | sealed trait BinaryPred[+A >: BottomSort <: TopSort] extends BinaryOp[A,BoolSort] 85 | 86 | sealed trait NAryPred[+A >: BottomSort <: TopSort] extends Tree[BoolSort] { 87 | val args : Seq[Tree[A]] 88 | } 89 | 90 | case class BoolConstant(value : Boolean) extends Tree[BoolSort] { 91 | private[dsl] def build(z3 : Z3Context) = if(value) z3.mkTrue() else z3.mkFalse() 92 | } 93 | 94 | case class IntConstant(value : Int) extends Tree[IntSort] { 95 | private[dsl] def build(z3 : Z3Context) = z3.mkInt(value, z3.mkIntSort()) 96 | } 97 | 98 | case class CharConstant(value : Char) extends Tree[BVSort] { 99 | private[dsl] def build(z3 : Z3Context) = z3.mkInt(value, z3.mkBVSort(16)) 100 | } 101 | 102 | case class BoolVar() extends Tree[BoolSort] { 103 | private[dsl] def build(z3 : Z3Context) = z3.mkFreshConst("C", z3.mkBoolSort()) 104 | } 105 | 106 | case class IntVar() extends Tree[IntSort] { 107 | private[dsl] def build(z3 : Z3Context) = z3.mkFreshConst("I", z3.mkIntSort()) 108 | } 109 | 110 | case class CharVar() extends Tree[BVSort] { 111 | private[dsl] def build(z3 : Z3Context) = z3.mkFreshConst("BV", z3.mkBVSort(16)) 112 | } 113 | 114 | case class IntSetVar() extends Tree[SetSort] { 115 | private[dsl] def build(z3 : Z3Context) = z3.mkFreshConst("IS", z3.mkSetSort(z3.mkIntSort())) 116 | } 117 | 118 | case class Eq[+A >: BottomSort <: TopSort](left : Tree[A], right : Tree[A]) extends BinaryPred[A] { 119 | private[dsl] def build(z3 : Z3Context) = z3.mkEq(left.ast(z3), right.ast(z3)) 120 | } 121 | 122 | case class Distinct[+A >: BottomSort <: TopSort](args : Tree[A]*) extends NAryPred[A] { 123 | private[dsl] def build(z3 : Z3Context) = z3.mkDistinct(args.map(_.ast(z3)) : _*) 124 | } 125 | 126 | case class And[+A >: BottomSort <: BoolSort](args : Tree[A]*) extends NAryPred[A] { 127 | private[dsl] def build(z3 : Z3Context) = z3.mkAnd(args.map(_.ast(z3)) : _*) 128 | } 129 | 130 | case class Or[+A >: BottomSort <: BoolSort](args : Tree[A]*) extends NAryPred[A] { 131 | private[dsl] def build(z3 : Z3Context) = z3.mkOr(args.map(_.ast(z3)) : _*) 132 | } 133 | 134 | case class Not[+A >: BottomSort <: BoolSort](tree : Tree[A]) extends Tree[BoolSort] { 135 | private[dsl] def build(z3 : Z3Context) = z3.mkNot(tree.ast(z3)) 136 | } 137 | 138 | case class Iff[+A >: BottomSort <: BoolSort](left : Tree[A], right : Tree[A]) extends BinaryPred[BoolSort] { 139 | private[dsl] def build(z3 : Z3Context) = z3.mkIff(left.ast(z3), right.ast(z3)) 140 | } 141 | 142 | case class Implies[+A >: BottomSort <: BoolSort](left : Tree[A], right : Tree[A]) extends BinaryPred[BoolSort] { 143 | private[dsl] def build(z3 : Z3Context) = z3.mkImplies(left.ast(z3), right.ast(z3)) 144 | } 145 | 146 | case class Xor[+A >: BottomSort <: BoolSort](left : Tree[A], right : Tree[A]) extends BinaryPred[BoolSort] { 147 | private[dsl] def build(z3 : Z3Context) = z3.mkXor(left.ast(z3), right.ast(z3)) 148 | } 149 | 150 | case class Add[+A >: BottomSort <: IntSort](args : Tree[A]*) extends Tree[IntSort] { 151 | private[dsl] def build(z3 : Z3Context) = z3.mkAdd(args.map(_.ast(z3)) : _*) 152 | } 153 | 154 | case class Mul[+A >: BottomSort <: IntSort](args : Tree[A]*) extends Tree[IntSort] { 155 | private[dsl] def build(z3 : Z3Context) = z3.mkMul(args.map(_.ast(z3)) : _*) 156 | } 157 | 158 | case class Sub[+A >: BottomSort <: IntSort](left : Tree[A], right : Tree[A]) extends BinaryOp[A,IntSort] { 159 | private[dsl] def build(z3 : Z3Context) = z3.mkSub(left.ast(z3), right.ast(z3)) 160 | } 161 | 162 | case class Div[+A >: BottomSort <: IntSort](left : Tree[A], right : Tree[A]) extends BinaryOp[A,IntSort] { 163 | private[dsl] def build(z3 : Z3Context) = z3.mkDiv(left.ast(z3), right.ast(z3)) 164 | } 165 | 166 | case class Mod[+A >: BottomSort <: IntSort](left : Tree[A], right : Tree[A]) extends BinaryOp[A,IntSort] { 167 | private[dsl] def build(z3 : Z3Context) = z3.mkMod(left.ast(z3), right.ast(z3)) 168 | } 169 | 170 | case class Rem[+A >: BottomSort <: IntSort](left : Tree[A], right : Tree[A]) extends BinaryOp[A,IntSort] { 171 | private[dsl] def build(z3 : Z3Context) = z3.mkRem(left.ast(z3), right.ast(z3)) 172 | } 173 | 174 | case class LT[+A >: BottomSort <: IntSort](left : Tree[A], right : Tree[A]) extends BinaryPred[IntSort] { 175 | private[dsl] def build(z3 : Z3Context) = z3.mkLT(left.ast(z3), right.ast(z3)) 176 | } 177 | 178 | case class LE[+A >: BottomSort <: IntSort](left : Tree[A], right : Tree[A]) extends BinaryPred[IntSort] { 179 | private[dsl] def build(z3 : Z3Context) = z3.mkLE(left.ast(z3), right.ast(z3)) 180 | } 181 | 182 | case class GT[+A >: BottomSort <: IntSort](left : Tree[A], right : Tree[A]) extends BinaryPred[IntSort] { 183 | private[dsl] def build(z3 : Z3Context) = z3.mkGT(left.ast(z3), right.ast(z3)) 184 | } 185 | 186 | case class GE[+A >: BottomSort <: IntSort](left : Tree[A], right : Tree[A]) extends BinaryPred[IntSort] { 187 | private[dsl] def build(z3 : Z3Context) = z3.mkGE(left.ast(z3), right.ast(z3)) 188 | } 189 | 190 | case class BVNot[+A >: BottomSort <: BVSort](tree : Tree[A]) extends Tree[BVSort] { 191 | private[dsl] def build(z3 : Z3Context) = z3.mkBVNot(tree.ast(z3)) 192 | } 193 | 194 | case class BVRedAnd[+A >: BottomSort <: BVSort](tree : Tree[A]) extends Tree[BVSort] { 195 | private[dsl] def build(z3 : Z3Context) = z3.mkBVRedAnd(tree.ast(z3)) 196 | } 197 | 198 | case class BVRedOr[+A >: BottomSort <: BVSort](tree : Tree[A]) extends Tree[BVSort] { 199 | private[dsl] def build(z3 : Z3Context) = z3.mkBVRedOr(tree.ast(z3)) 200 | } 201 | 202 | case class BVAnd[+A >: BottomSort <: BVSort](left : Tree[A], right : Tree[A]) extends BinaryOp[A,BVSort] { 203 | private[dsl] def build(z3 : Z3Context) = z3.mkBVAnd(left.ast(z3), right.ast(z3)) 204 | } 205 | 206 | case class BVOr[+A >: BottomSort <: BVSort](left : Tree[A], right : Tree[A]) extends BinaryOp[A,BVSort] { 207 | private[dsl] def build(z3 : Z3Context) = z3.mkBVOr(left.ast(z3), right.ast(z3)) 208 | } 209 | 210 | case class BVXor[+A >: BottomSort <: BVSort](left : Tree[A], right : Tree[A]) extends BinaryOp[A,BVSort] { 211 | private[dsl] def build(z3 : Z3Context) = z3.mkBVXor(left.ast(z3), right.ast(z3)) 212 | } 213 | 214 | case class BVNand[+A >: BottomSort <: BVSort](left : Tree[A], right : Tree[A]) extends BinaryOp[A,BVSort] { 215 | private[dsl] def build(z3 : Z3Context) = z3.mkBVNand(left.ast(z3), right.ast(z3)) 216 | } 217 | 218 | case class BVNor[+A >: BottomSort <: BVSort](left : Tree[A], right : Tree[A]) extends BinaryOp[A,BVSort] { 219 | private[dsl] def build(z3 : Z3Context) = z3.mkBVNor(left.ast(z3), right.ast(z3)) 220 | } 221 | 222 | case class BVXnor[+A >: BottomSort <: BVSort](left : Tree[A], right : Tree[A]) extends BinaryOp[A,BVSort] { 223 | private[dsl] def build(z3 : Z3Context) = z3.mkBVXnor(left.ast(z3), right.ast(z3)) 224 | } 225 | 226 | case class BVNeg[+A >: BottomSort <: BVSort](tree : Tree[A]) extends Tree[BVSort] { 227 | private[dsl] def build(z3 : Z3Context) = z3.mkBVNeg(tree.ast(z3)) 228 | } 229 | 230 | case class BVAdd[+A >: BottomSort <: BVSort](left : Tree[A], right : Tree[A]) extends BinaryOp[A,BVSort] { 231 | private[dsl] def build(z3 : Z3Context) = z3.mkBVAdd(left.ast(z3), right.ast(z3)) 232 | } 233 | 234 | case class BVSub[+A >: BottomSort <: BVSort](left : Tree[A], right : Tree[A]) extends BinaryOp[A,BVSort] { 235 | private[dsl] def build(z3 : Z3Context) = z3.mkBVSub(left.ast(z3), right.ast(z3)) 236 | } 237 | 238 | case class BVMul[+A >: BottomSort <: BVSort](left : Tree[A], right : Tree[A]) extends BinaryOp[A,BVSort] { 239 | private[dsl] def build(z3 : Z3Context) = z3.mkBVMul(left.ast(z3), right.ast(z3)) 240 | } 241 | 242 | case class BVUdiv[+A >: BottomSort <: BVSort](left : Tree[A], right : Tree[A]) extends BinaryOp[A,BVSort] { 243 | private[dsl] def build(z3 : Z3Context) = z3.mkBVUdiv(left.ast(z3), right.ast(z3)) 244 | } 245 | 246 | case class BVSdiv[+A >: BottomSort <: BVSort](left : Tree[A], right : Tree[A]) extends BinaryOp[A,BVSort] { 247 | private[dsl] def build(z3 : Z3Context) = z3.mkBVSdiv(left.ast(z3), right.ast(z3)) 248 | } 249 | 250 | case class BVUrem[+A >: BottomSort <: BVSort](left : Tree[A], right : Tree[A]) extends BinaryOp[A,BVSort] { 251 | private[dsl] def build(z3 : Z3Context) = z3.mkBVUrem(left.ast(z3), right.ast(z3)) 252 | } 253 | 254 | case class BVSrem[+A >: BottomSort <: BVSort](left : Tree[A], right : Tree[A]) extends BinaryOp[A,BVSort] { 255 | private[dsl] def build(z3 : Z3Context) = z3.mkBVSrem(left.ast(z3), right.ast(z3)) 256 | } 257 | 258 | case class BVSmod[+A >: BottomSort <: BVSort](left : Tree[A], right : Tree[A]) extends BinaryOp[A,BVSort] { 259 | private[dsl] def build(z3 : Z3Context) = z3.mkBVSmod(left.ast(z3), right.ast(z3)) 260 | } 261 | 262 | case class BVUlt[+A >: BottomSort <: BVSort](left : Tree[A], right : Tree[A]) extends BinaryPred[BVSort] { 263 | private[dsl] def build(z3 : Z3Context) = z3.mkBVUlt(left.ast(z3), right.ast(z3)) 264 | } 265 | 266 | case class BVSlt[+A >: BottomSort <: BVSort](left : Tree[A], right : Tree[A]) extends BinaryPred[BVSort] { 267 | private[dsl] def build(z3 : Z3Context) = z3.mkBVSlt(left.ast(z3), right.ast(z3)) 268 | } 269 | 270 | case class BVUle[+A >: BottomSort <: BVSort](left : Tree[A], right : Tree[A]) extends BinaryPred[BVSort] { 271 | private[dsl] def build(z3 : Z3Context) = z3.mkBVUle(left.ast(z3), right.ast(z3)) 272 | } 273 | 274 | case class BVSle[+A >: BottomSort <: BVSort](left : Tree[A], right : Tree[A]) extends BinaryPred[BVSort] { 275 | private[dsl] def build(z3 : Z3Context) = z3.mkBVSle(left.ast(z3), right.ast(z3)) 276 | } 277 | 278 | case class BVUgt[+A >: BottomSort <: BVSort](left : Tree[A], right : Tree[A]) extends BinaryPred[BVSort] { 279 | private[dsl] def build(z3 : Z3Context) = z3.mkBVUgt(left.ast(z3), right.ast(z3)) 280 | } 281 | 282 | case class BVSgt[+A >: BottomSort <: BVSort](left : Tree[A], right : Tree[A]) extends BinaryPred[BVSort] { 283 | private[dsl] def build(z3 : Z3Context) = z3.mkBVSgt(left.ast(z3), right.ast(z3)) 284 | } 285 | 286 | case class BVUge[+A >: BottomSort <: BVSort](left : Tree[A], right : Tree[A]) extends BinaryPred[BVSort] { 287 | private[dsl] def build(z3 : Z3Context) = z3.mkBVUge(left.ast(z3), right.ast(z3)) 288 | } 289 | 290 | case class BVSge[+A >: BottomSort <: BVSort](left : Tree[A], right : Tree[A]) extends BinaryPred[BVSort] { 291 | private[dsl] def build(z3 : Z3Context) = z3.mkBVSge(left.ast(z3), right.ast(z3)) 292 | } 293 | 294 | case class Concat[+A >: BottomSort <: BVSort](left : Tree[A], right : Tree[A]) extends BinaryOp[A,BVSort] { 295 | private[dsl] def build(z3 : Z3Context) = z3.mkConcat(left.ast(z3), right.ast(z3)) 296 | } 297 | 298 | case class Extract[+A >: BottomSort <: BVSort](high: Int, low: Int, tree : Tree[A]) extends Tree[BVSort] { 299 | private[dsl] def build(z3 : Z3Context) = z3.mkExtract(high, low, tree.ast(z3)) 300 | } 301 | 302 | case class SignExt[+A >: BottomSort <: BVSort](extraSize: Int, tree : Tree[A]) extends Tree[BVSort] { 303 | private[dsl] def build(z3 : Z3Context) = z3.mkSignExt(extraSize, tree.ast(z3)) 304 | } 305 | 306 | case class ZeroExt[+A >: BottomSort <: BVSort](extraSize: Int, tree : Tree[A]) extends Tree[BVSort] { 307 | private[dsl] def build(z3 : Z3Context) = z3.mkZeroExt(extraSize, tree.ast(z3)) 308 | } 309 | 310 | case class Repeat[+A >: BottomSort <: BVSort](count: Int, tree : Tree[A]) extends Tree[BVSort] { 311 | private[dsl] def build(z3 : Z3Context) = z3.mkRepeat(count, tree.ast(z3)) 312 | } 313 | 314 | case class BVShl[+A >: BottomSort <: BVSort](left : Tree[A], right : Tree[A]) extends BinaryOp[A,BVSort] { 315 | private[dsl] def build(z3 : Z3Context) = z3.mkBVShl(left.ast(z3), right.ast(z3)) 316 | } 317 | 318 | case class BVLshr[+A >: BottomSort <: BVSort](left : Tree[A], right : Tree[A]) extends BinaryOp[A,BVSort] { 319 | private[dsl] def build(z3 : Z3Context) = z3.mkBVLshr(left.ast(z3), right.ast(z3)) 320 | } 321 | 322 | case class BVAshr[+A >: BottomSort <: BVSort](left : Tree[A], right : Tree[A]) extends BinaryOp[A,BVSort] { 323 | private[dsl] def build(z3 : Z3Context) = z3.mkBVAshr(left.ast(z3), right.ast(z3)) 324 | } 325 | 326 | case class ExtRotateLeft[+A >: BottomSort <: BVSort](left : Tree[A], right : Tree[A]) extends BinaryOp[A,BVSort] { 327 | private[dsl] def build(z3 : Z3Context) = z3.mkExtRotateLeft(left.ast(z3), right.ast(z3)) 328 | } 329 | 330 | case class ExtRotateRight[+A >: BottomSort <: BVSort](left : Tree[A], right : Tree[A]) extends BinaryOp[A,BVSort] { 331 | private[dsl] def build(z3 : Z3Context) = z3.mkExtRotateRight(left.ast(z3), right.ast(z3)) 332 | } 333 | 334 | case class BVAddNoOverflow[+A >: BottomSort <: BVSort](left : Tree[A], right : Tree[A], isSigned: Boolean) extends BinaryOp[A,BVSort] { 335 | private[dsl] def build(z3 : Z3Context) = z3.mkBVAddNoOverflow(left.ast(z3), right.ast(z3), isSigned) 336 | } 337 | 338 | case class BVAddNoUnderflow[+A >: BottomSort <: BVSort](left : Tree[A], right : Tree[A]) extends BinaryOp[A,BVSort] { 339 | private[dsl] def build(z3 : Z3Context) = z3.mkBVAddNoUnderflow(left.ast(z3), right.ast(z3)) 340 | } 341 | 342 | case class BVSubNoOverflow[+A >: BottomSort <: BVSort](left : Tree[A], right : Tree[A]) extends BinaryOp[A,BVSort] { 343 | private[dsl] def build(z3 : Z3Context) = z3.mkBVSubNoOverflow(left.ast(z3), right.ast(z3)) 344 | } 345 | 346 | case class BVSubNoUnderflow[+A >: BottomSort <: BVSort](left : Tree[A], right : Tree[A], isSigned: Boolean) extends BinaryOp[A,BVSort] { 347 | private[dsl] def build(z3 : Z3Context) = z3.mkBVSubNoUnderflow(left.ast(z3), right.ast(z3), isSigned) 348 | } 349 | 350 | case class BVSDivNoOverflow[+A >: BottomSort <: BVSort](left : Tree[A], right : Tree[A]) extends BinaryOp[A,BVSort] { 351 | private[dsl] def build(z3 : Z3Context) = z3.mkBVSDivNoOverflow(left.ast(z3), right.ast(z3)) 352 | } 353 | 354 | case class BVNegNoOverflow[+A >: BottomSort <: BVSort](tree : Tree[A]) extends Tree[BVSort] { 355 | private[dsl] def build(z3 : Z3Context) = z3.mkBVNegNoOverflow(tree.ast(z3)) 356 | } 357 | 358 | case class BVMulNoOverflow[+A >: BottomSort <: BVSort](left : Tree[A], right : Tree[A], isSigned: Boolean) extends BinaryOp[A,BVSort] { 359 | private[dsl] def build(z3 : Z3Context) = z3.mkBVMulNoOverflow(left.ast(z3), right.ast(z3), isSigned) 360 | } 361 | 362 | case class BVMulNoUnderflow[+A >: BottomSort <: BVSort](left : Tree[A], right : Tree[A]) extends BinaryOp[A,BVSort] { 363 | private[dsl] def build(z3 : Z3Context) = z3.mkBVMulNoUnderflow(left.ast(z3), right.ast(z3)) 364 | } 365 | 366 | case class SetUnion[+A >: BottomSort <: SetSort](args: Tree[A]*) extends Tree[SetSort] { 367 | private[dsl] def build(z3 : Z3Context) = z3.mkSetUnion(args.map(_.ast(z3)) : _*) 368 | } 369 | 370 | case class SetIntersect[+A >: BottomSort <: SetSort](args: Tree[A]*) extends Tree[SetSort] { 371 | private[dsl] def build(z3 : Z3Context) = z3.mkSetIntersect(args.map(_.ast(z3)) : _*) 372 | } 373 | 374 | case class SetDifference[+A >: BottomSort <: SetSort](left : Tree[A], right : Tree[A]) extends Tree[SetSort] { 375 | private[dsl] def build(z3 : Z3Context) = z3.mkSetDifference(left.ast(z3), right.ast(z3)) 376 | } 377 | 378 | case class SetSubset[+A >: BottomSort <: SetSort](left : Tree[A], right : Tree[A]) extends BinaryPred[SetSort] { 379 | private[dsl] def build(z3 : Z3Context) = z3.mkSetSubset(left.ast(z3), right.ast(z3)) 380 | } 381 | 382 | case class EmptyIntSet() extends Tree[SetSort] { 383 | private [dsl] def build(z3 : Z3Context) = z3.mkEmptySet(z3.mkIntSort()) 384 | } 385 | 386 | case class SetAdd[+A >: BottomSort <: TopSort](set : Tree[SetSort], elem : Tree[A]) extends Tree[SetSort] { 387 | private [dsl] def build(z3 : Z3Context) = z3.mkSetAdd(set.ast(z3), elem.ast(z3)) 388 | } 389 | 390 | // Unsafe. 391 | case class MapSelect(map : Tree[_ >: BottomSort <: TopSort], index : Tree[_ >: BottomSort <: TopSort]) extends Tree[BottomSort] { 392 | private [dsl] def build(z3 : Z3Context) = z3.mkSelect(map.ast(z3), index.ast(z3)) 393 | } 394 | -------------------------------------------------------------------------------- /src/main/scala/z3/scala/dsl/ValHandler.scala: -------------------------------------------------------------------------------- 1 | package z3.scala 2 | package dsl 3 | 4 | import scala.annotation.implicitNotFound 5 | 6 | /** A ValHandler encapsulates everything that is needed to build a Z3Sort 7 | * representing A, a fresh identifier of that sort and to reconstruct a Scala 8 | * value from a model. */ 9 | @implicitNotFound(msg = "The following type cannot be converted to Z3 : ${A}.") 10 | abstract class ValHandler[A : Default] { 11 | // Note: it seems to be better at this point NOT to make ValHandler inherit 12 | // from Default. The reason is clarity while we're developing/refactoring. 13 | // From a logical/rational point of view, I believe it should in fact 14 | // inherit from Default and the implicit ValHandlers would serve as the 15 | // providers of default values. One argument against that is that Defaults 16 | // exist outside of the DSL while ValHandlers do not. PS. 17 | val default : Default[A] = summon[Default[A]] 18 | private val defaultValue : A = default.value 19 | 20 | /** Z3 code to construct a sort representing the Scala A type. */ 21 | def mkSort(z3 : Z3Context) : Z3Sort 22 | 23 | type ValSort >: BottomSort <: TopSort 24 | 25 | /** Constructs a ValTree[A], i.e. the representation of a variable of type A. */ 26 | def construct: Tree[ValSort] = new ValTree[ValSort] { 27 | override def build(z3: Z3Context): Z3AST = z3.mkFreshConst("valCst", mkSort(z3)) 28 | } 29 | 30 | def convert(model : Z3Model, ast : Z3AST) : A 31 | } 32 | -------------------------------------------------------------------------------- /src/main/scala/z3/scala/dsl/package.scala: -------------------------------------------------------------------------------- 1 | package z3.scala 2 | 3 | import scala.language.implicitConversions 4 | 5 | package object dsl { 6 | 7 | import Operands._ 8 | 9 | class UnsatisfiableConstraintException extends Exception 10 | 11 | class SortMismatchException(msg: String) extends Exception("Sort mismatch: " + msg) 12 | 13 | given z3ASTToBoolOperand: Conversion[Z3AST, BoolOperand] = { ast => 14 | if (!ast.getSort.isBoolSort) { 15 | throw new SortMismatchException("expected boolean operand, got: " + ast) 16 | } 17 | new BoolOperand(Z3ASTWrapper[BoolSort](ast)) 18 | } 19 | 20 | given booleanValueToBoolTree: Conversion[Boolean, Tree[BoolSort]] = BoolConstant.apply 21 | 22 | given booleanValueToBoolOperand: Conversion[Boolean, BoolOperand] = x => new BoolOperand(BoolConstant(x)) 23 | 24 | given booleanValToBoolTree: Conversion[Val[Boolean], Tree[BoolSort]] = _.tree.asInstanceOf[Tree[BoolSort]] 25 | 26 | given booleanValToBoolOperand: Conversion[Val[Boolean], BoolOperand] = x => new BoolOperand(x.tree.asInstanceOf[Tree[BoolSort]]) 27 | 28 | given boolTreeToBoolOperand[T >: BottomSort <: BoolSort]: Conversion[Tree[T], BoolOperand] = new BoolOperand(_) 29 | 30 | given boolOperandToBoolTree: Conversion[BoolOperand, Tree[BoolSort]] = _.tree 31 | 32 | given z3ASTToIntOperand: Conversion[Z3AST, IntOperand] = { ast => 33 | if (!ast.getSort.isIntSort) { 34 | throw new SortMismatchException("expected integer operand, got: " + ast) 35 | } 36 | new IntOperand(Z3ASTWrapper[IntSort](ast)) 37 | } 38 | 39 | given intValueToIntTree: Conversion[Int, Tree[IntSort]] = IntConstant.apply 40 | 41 | given intValueToIntOperand: Conversion[Int, IntOperand] = x => new IntOperand(IntConstant(x)) 42 | 43 | given intValToIntTree: Conversion[Val[Int], Tree[IntSort]] = _.tree.asInstanceOf[Tree[IntSort]] 44 | 45 | given intValToIntOperand: Conversion[Val[Int], IntOperand] = x => new IntOperand(x.tree.asInstanceOf[Tree[IntSort]]) 46 | 47 | given intTreeToIntOperand[T >: BottomSort <: IntSort]: Conversion[Tree[T], IntOperand] = new IntOperand(_) 48 | 49 | given intOperandToIntTree: Conversion[IntOperand, Tree[IntSort]] = _.tree 50 | 51 | given charValueToBVTree: Conversion[Char, Tree[BVSort]] = CharConstant.apply 52 | 53 | given charValueToBVOperand: Conversion[Char, BitVectorOperand] = x => new BitVectorOperand(CharConstant(x)) 54 | 55 | given charValToCharTree: Conversion[Val[Char], Tree[BVSort]] = _.tree.asInstanceOf[Tree[BVSort]] 56 | 57 | given charValToBVOperand: Conversion[Val[Char], BitVectorOperand] = x => new BitVectorOperand(x.tree.asInstanceOf[Tree[BVSort]]) 58 | 59 | given bvTreeToBVOperand[T >: BottomSort <: BVSort]: Conversion[Tree[T], BitVectorOperand] = new BitVectorOperand(_) 60 | 61 | given bvOperandToBVTree: Conversion[BitVectorOperand, Tree[BVSort]] = _.tree 62 | 63 | given z3ASTToSetOperand: Conversion[Z3AST, SetOperand] = x => 64 | // TODO how do we check the type (set of any type?) here? 65 | new SetOperand(Z3ASTWrapper[SetSort](x)) 66 | 67 | given intSetValueToSetTree: Conversion[Set[Int], Tree[SetSort]] = _.foldLeft[Tree[SetSort]](EmptyIntSet())((set, elem) => SetAdd(set, IntConstant(elem))) 68 | 69 | given intSetValueToSetOperand: Conversion[Set[Int], SetOperand] = x => new SetOperand(intSetValueToSetTree(x)) 70 | 71 | given setTreeToSetOperand[T >: BottomSort <: SetSort]: Conversion[Tree[T], SetOperand] = new SetOperand(_) 72 | 73 | given setOperandToSetTree: Conversion[SetOperand, Tree[SetSort]] = _.tree 74 | 75 | // All default values 76 | 77 | given DefaultInt: Default[Int] with 78 | val value = 0 79 | 80 | given DefaultBoolean: Default[Boolean] with 81 | val value = true 82 | 83 | given DefaultChar: Default[Char] with 84 | val value = '\u0000' 85 | 86 | given liftDefaultToSet[A: Default]: Default[Set[A]] = { 87 | new Default[Set[A]] { 88 | val value = Set.empty[A] 89 | } 90 | } 91 | 92 | given liftDefaultToFun[A, B: Default]: Default[A => B] = { 93 | new Default[A => B] { 94 | val value = ((a: A) => summon[Default[B]].value) 95 | } 96 | } 97 | 98 | // Predefined ValHandler's 99 | 100 | given BooleanValHandler: ValHandler[Boolean] with 101 | def mkSort(z3: Z3Context): Z3Sort = z3.mkBoolSort() 102 | 103 | def convert(model: Z3Model, ast: Z3AST): Boolean = 104 | model.evalAs[Boolean](ast).getOrElse(false) 105 | 106 | override type ValSort = BoolSort 107 | 108 | given IntValHandler: ValHandler[Int] with 109 | def mkSort(z3: Z3Context): Z3Sort = z3.mkIntSort() 110 | 111 | def convert(model: Z3Model, ast: Z3AST): Int = 112 | model.evalAs[Int](ast).getOrElse(0) 113 | 114 | override type ValSort = IntSort 115 | 116 | given CharValHandler: ValHandler[Char] with 117 | def mkSort(z3: Z3Context): Z3Sort = z3.mkBVSort(16) 118 | 119 | def convert(model: Z3Model, ast: Z3AST): Char = 120 | model.evalAs[Char](ast).getOrElse('\u0000') 121 | 122 | override type ValSort = BVSort 123 | 124 | /** Instances of this class are used to represent models of Z3 maps, which 125 | * are typically defined by a finite collection of pairs and a default 126 | * value. More sophisticated representations à la functional programs that 127 | * can sometimes be obtained from quantified formulas are not yet 128 | * supported. PS. */ 129 | class PointWiseFunction[-A, +B](points: Map[A, B], default: B) extends (A => B) { 130 | def apply(a: A): B = points.getOrElse(a, default) 131 | } 132 | 133 | given liftToFuncHandler[A: Default : ValHandler, B: Default : ValHandler]: ValHandler[A => B] = new ValHandler[A => B] { 134 | private val underlyingA = summon[ValHandler[A]] 135 | private val underlyingB = summon[ValHandler[B]] 136 | 137 | def mkSort(z3: Z3Context): Z3Sort = 138 | z3.mkArraySort(underlyingA.mkSort(z3), underlyingB.mkSort(z3)) 139 | 140 | def convert(model: Z3Model, ast: Z3AST): (A => B) = { 141 | model.eval(ast) match { 142 | case None => default.value 143 | case Some(evaluated) => model.getArrayValue(evaluated) match { 144 | case Some((mp, dflt)) => 145 | new PointWiseFunction[A, B]( 146 | mp.map(kv => (underlyingA.convert(model, kv._1), underlyingB.convert(model, kv._2))), 147 | underlyingB.convert(model, dflt) 148 | ) 149 | case None => default.value 150 | } 151 | } 152 | } 153 | 154 | override type ValSort = ArraySort 155 | } 156 | 157 | def choose[T: ValHandler](predicate: Val[T] => Tree[BoolSort]): T = find(predicate) match { 158 | case Some(result) => result 159 | case None => throw new UnsatisfiableConstraintException 160 | } 161 | 162 | def find[T: ValHandler](predicate: Val[T] => Tree[BoolSort]): Option[T] = { 163 | val z3 = new Z3Context("MODEL" -> true) 164 | val solver = z3.mkSolver() 165 | val vh = summon[ValHandler[T]] 166 | val value = new Val[T] 167 | val valAST = value.tree.ast(z3) 168 | val constraintTree = predicate(value) 169 | solver.assertCnstr(constraintTree.ast(z3)) 170 | solver.checkAndGetModel() match { 171 | case (Some(true), m) => 172 | val result = vh.convert(m, valAST) 173 | z3.delete() 174 | Some(result) 175 | case _ => 176 | z3.delete() 177 | None 178 | } 179 | } 180 | 181 | def findAll[T: ValHandler](predicate: Val[T] => Tree[BoolSort]): Iterator[T] = { 182 | val z3 = new Z3Context("MODEL" -> true) 183 | val solver = z3.mkSolver() 184 | val vh = summon[ValHandler[T]] 185 | val value = new Val[T] 186 | val valAST = value.tree.ast(z3) 187 | val constraintTree = predicate(value) 188 | 189 | solver.assertCnstr(constraintTree.ast(z3)) 190 | solver.checkAndGetAllModels().map(m => { 191 | val result = vh.convert(m, valAST) 192 | result 193 | }) 194 | } 195 | 196 | def choose[T1: ValHandler, T2: ValHandler](predicate: (Val[T1], Val[T2]) => Tree[BoolSort]): (T1, T2) = find(predicate) match { 197 | case Some(p) => p 198 | case None => throw new UnsatisfiableConstraintException 199 | } 200 | 201 | def find[T1: ValHandler, T2: ValHandler](predicate: (Val[T1], Val[T2]) => Tree[BoolSort]): Option[(T1, T2)] = { 202 | val z3 = new Z3Context("MODEL" -> true) 203 | val solver = z3.mkSolver() 204 | val vh1 = summon[ValHandler[T1]] 205 | val vh2 = summon[ValHandler[T2]] 206 | val value1 = new Val[T1] 207 | val value2 = new Val[T2] 208 | val valAST1 = value1.tree.ast(z3) 209 | val valAST2 = value2.tree.ast(z3) 210 | val constraintTree = predicate(value1, value2) 211 | solver.assertCnstr(constraintTree.ast(z3)) 212 | solver.checkAndGetModel() match { 213 | case (Some(true), m) => 214 | val result1 = vh1.convert(m, valAST1) 215 | val result2 = vh2.convert(m, valAST2) 216 | z3.delete() 217 | Some((result1, result2)) 218 | case _ => 219 | z3.delete() 220 | None 221 | } 222 | } 223 | 224 | def findAll[T1: ValHandler, T2: ValHandler](predicate: (Val[T1], Val[T2]) => Tree[BoolSort]): Iterator[(T1, T2)] = { 225 | val z3 = new Z3Context("MODEL" -> true) 226 | val solver = z3.mkSolver() 227 | val vh1 = summon[ValHandler[T1]] 228 | val vh2 = summon[ValHandler[T2]] 229 | val value1 = new Val[T1] 230 | val value2 = new Val[T2] 231 | val valAST1 = value1.tree.ast(z3) 232 | val valAST2 = value2.tree.ast(z3) 233 | val constraintTree = predicate(value1, value2) 234 | 235 | solver.assertCnstr(constraintTree.ast(z3)) 236 | solver.checkAndGetAllModels().map(m => { 237 | val result1 = vh1.convert(m, valAST1) 238 | val result2 = vh2.convert(m, valAST2) 239 | (result1, result2) 240 | }) 241 | } 242 | 243 | def choose[T1: ValHandler, T2: ValHandler, T3: ValHandler](predicate: (Val[T1], Val[T2], Val[T3]) => Tree[BoolSort]): (T1, T2, T3) = find(predicate) match { 244 | case Some(p) => p 245 | case None => throw new UnsatisfiableConstraintException 246 | } 247 | 248 | def find[T1: ValHandler, T2: ValHandler, T3: ValHandler](predicate: (Val[T1], Val[T2], Val[T3]) => Tree[BoolSort]): Option[(T1, T2, T3)] = { 249 | val z3 = new Z3Context("MODEL" -> true) 250 | val solver = z3.mkSolver() 251 | val vh1 = summon[ValHandler[T1]] 252 | val vh2 = summon[ValHandler[T2]] 253 | val vh3 = summon[ValHandler[T3]] 254 | val value1 = new Val[T1] 255 | val value2 = new Val[T2] 256 | val value3 = new Val[T3] 257 | val valAST1 = value1.tree.ast(z3) 258 | val valAST2 = value2.tree.ast(z3) 259 | val valAST3 = value3.tree.ast(z3) 260 | val constraintTree = predicate(value1, value2, value3) 261 | solver.assertCnstr(constraintTree.ast(z3)) 262 | solver.checkAndGetModel() match { 263 | case (Some(true), m) => 264 | val result1 = vh1.convert(m, valAST1) 265 | val result2 = vh2.convert(m, valAST2) 266 | val result3 = vh3.convert(m, valAST3) 267 | z3.delete() 268 | Some((result1, result2, result3)) 269 | case _ => 270 | z3.delete() 271 | None 272 | } 273 | } 274 | 275 | def findAll[T1: ValHandler, T2: ValHandler, T3: ValHandler](predicate: (Val[T1], Val[T2], Val[T3]) => Tree[BoolSort]): Iterator[(T1, T2, T3)] = { 276 | val z3 = new Z3Context("MODEL" -> true) 277 | val solver = z3.mkSolver() 278 | 279 | val vh1 = summon[ValHandler[T1]] 280 | val vh2 = summon[ValHandler[T2]] 281 | val vh3 = summon[ValHandler[T3]] 282 | val value1 = new Val[T1] 283 | val value2 = new Val[T2] 284 | val value3 = new Val[T3] 285 | val valAST1 = value1.tree.ast(z3) 286 | val valAST2 = value2.tree.ast(z3) 287 | val valAST3 = value3.tree.ast(z3) 288 | val constraintTree = predicate(value1, value2, value3) 289 | 290 | solver.assertCnstr(constraintTree.ast(z3)) 291 | solver.checkAndGetAllModels().map(m => { 292 | val result1 = vh1.convert(m, valAST1) 293 | val result2 = vh2.convert(m, valAST2) 294 | val result3 = vh3.convert(m, valAST3) 295 | (result1, result2, result3) 296 | }) 297 | } 298 | 299 | given astVectorToSeq: Conversion[Z3ASTVector, Seq[Z3AST]] = _.toSeq 300 | } 301 | -------------------------------------------------------------------------------- /src/main/scala/z3/scala/package.scala: -------------------------------------------------------------------------------- 1 | package z3 2 | 3 | import com.microsoft.z3.Native 4 | import _root_.scala.language.implicitConversions 5 | 6 | package object scala { 7 | // make sure Z3Wrapper has been loaded! 8 | Z3Wrapper.withinJar() 9 | 10 | def toggleWarningMessages(enabled: Boolean) : Unit = { 11 | Native.toggleWarningMessages(enabled) 12 | } 13 | 14 | def resetMemory : Unit = { 15 | Native.resetMemory() 16 | } 17 | 18 | /** A string representation of the version numbers for Z3, and the API (including bindings) */ 19 | lazy val version : String = { 20 | Z3Wrapper.z3VersionString() + ", " + Z3Wrapper.wrapperVersionString() 21 | } 22 | 23 | protected[z3] def toPtrArray(ptrs : Iterable[Z3Pointer]) : Array[Long] = { 24 | ptrs.map(_.ptr).toArray 25 | } 26 | 27 | protected[z3] def i2ob(value: Int) : Option[Boolean] = value match { 28 | case -1 => Some(false) 29 | case 0 => None 30 | case _ => Some(true) 31 | } 32 | 33 | 34 | def error(any : Any) : Nothing = { 35 | //Predef.error(any.toString) 36 | sys.error(any.toString) // 2.9 37 | } 38 | 39 | given astVectorToSeq: Conversion[Z3ASTVector, Seq[Z3AST]] = _.toSeq 40 | } 41 | -------------------------------------------------------------------------------- /src/test/scala/z3/scala/ADTs.scala: -------------------------------------------------------------------------------- 1 | package z3.scala 2 | 3 | import org.scalatest.funsuite.AnyFunSuite 4 | import org.scalatest.matchers.should.Matchers 5 | 6 | class ADTs extends AnyFunSuite with Matchers { 7 | 8 | test("ADTs") { 9 | val ctx = new Z3Context("MODEL" -> true) 10 | 11 | toggleWarningMessages(true) 12 | val intSort = ctx.mkIntSort() 13 | 14 | import Z3Context.{RecursiveType,RegularSort} 15 | 16 | // this builds two (recursive) datatypes: 17 | // Tree ::= Tree * Int * Tree | Leaf 18 | // and 19 | // TreeList ::= Tree TreeList | Nil 20 | // ...and constructor/tester functions, as well as selectors. 21 | val creationResult = ctx.mkADTSorts( 22 | List( 23 | ("Tree", 24 | List("Node", "Leaf"), 25 | List( 26 | List( // Fields for Node 27 | ("left", RecursiveType(0)), // '0' means "Tree", because that's the first in the mkADTSorts call. 28 | ("value", RegularSort(intSort)), 29 | ("right", RecursiveType(0))), 30 | Nil // Fields for Leaf 31 | ) 32 | ), 33 | ("TreeList", 34 | List("Cons", "Nil"), 35 | List( 36 | List( // Fields for Cons 37 | ("head", RecursiveType(0)), // head has type Tree 38 | ("tail", RecursiveType(1))), 39 | Nil // Nields for Nil 40 | ) 41 | ) 42 | ) 43 | ).toList 44 | 45 | // we then recover all the relevant Function Declarations... 46 | assert(creationResult.size == 2) 47 | val firstType = creationResult(0) 48 | val (treeSort: Z3Sort, consSeq, testSeq, selesSeq) = firstType 49 | assert(consSeq.size == 2) 50 | assert(testSeq.size == 2) 51 | assert(selesSeq.size == 2) 52 | val nodeCons: Z3FuncDecl = consSeq(0) 53 | val leafCons: Z3FuncDecl = consSeq(1) 54 | val isNode: Z3FuncDecl = testSeq(0) 55 | val isLeaf: Z3FuncDecl = testSeq(1) 56 | val nodeSels: Seq[Z3FuncDecl] = selesSeq(0) 57 | assert(selesSeq(1).size == 0) // no fields for Leaf 58 | assert(nodeSels.size == 3) 59 | val nodeLeftSelector: Z3FuncDecl = nodeSels(0) 60 | val nodeValueSelector: Z3FuncDecl = nodeSels(1) 61 | val nodeRightSelector: Z3FuncDecl = nodeSels(2) 62 | 63 | val secondType = creationResult(1) 64 | val (treeListSort: Z3Sort, consSeq2, testSeq2, selesSeq2) = secondType 65 | assert(consSeq2.size == 2) 66 | assert(testSeq2.size == 2) 67 | assert(selesSeq2.size == 2) 68 | val consCons: Z3FuncDecl = consSeq2(0) 69 | val nilCons: Z3FuncDecl = consSeq2(1) 70 | val isCons: Z3FuncDecl = testSeq2(0) 71 | val isNil: Z3FuncDecl = testSeq2(1) 72 | val consHeadSelector: Z3FuncDecl = selesSeq2(0)(0) 73 | val consTailSelector: Z3FuncDecl = selesSeq2(0)(1) 74 | 75 | // ...and finally we can use them to build a problem. 76 | val x: Z3AST = ctx.mkIntConst(ctx.mkStringSymbol("x")) 77 | val t1: Z3AST = ctx.mkConst(ctx.mkStringSymbol("t1"), treeSort) 78 | val t2: Z3AST = ctx.mkConst(ctx.mkStringSymbol("t2"), treeSort) 79 | val t3: Z3AST = ctx.mkConst(ctx.mkStringSymbol("t3"), treeSort) 80 | 81 | // t1 == t2 82 | //ctx.assertCnstr(ctx.mkEq(t1,t2)) 83 | //// t1 != t3 84 | //ctx.assertCnstr(ctx.mkDistinct(t1,t3)) 85 | //// x > 4 86 | //ctx.assertCnstr(ctx.mkGT(x, ctx.mkInt(4, intSort))) 87 | 88 | val solver = ctx.mkSolver() 89 | solver.assertCnstr(t1 === leafCons()) 90 | solver.assertCnstr(nodeValueSelector(t1) === ctx.mkInt(4, intSort)) 91 | 92 | // t1 != Leaf 93 | //ctx.assertCnstr(ctx.mkNot(isLeaf(t1))) 94 | 95 | // isNode(t2) => (t2 = Node(Leaf, x, t3)) 96 | // ctx.assertCnstr(ctx.mkImplies(isNode(t2), ctx.mkEq(t2, nodeCons(leafCons(), x, t3)))) 97 | // replace by this and it becomes unsat.. 98 | // ctx.assertCnstr(ctx.mkEq(t1,t3)) 99 | 100 | //println(ctx.mkImplies(isNode(t2), nodeValueSelector(t2) === ctx.mkInt(12, intSort))) 101 | 102 | val (sol, model) = solver.checkAndGetModel() 103 | 104 | sol should equal(Some(true)) 105 | model.eval(t1) should equal(Some(leafCons())) 106 | 107 | ctx.delete() 108 | } 109 | } 110 | 111 | -------------------------------------------------------------------------------- /src/test/scala/z3/scala/Abs.scala: -------------------------------------------------------------------------------- 1 | package z3.scala 2 | 3 | import org.scalatest.funsuite.AnyFunSuite 4 | import org.scalatest.matchers.should.Matchers 5 | 6 | class Abs extends AnyFunSuite with Matchers { 7 | 8 | test("array-map absolute value") { 9 | val z3 = new Z3Context("MODEL" -> true) 10 | 11 | val is = z3.mkIntSort() 12 | val intArraySort = z3.mkArraySort(is, is) 13 | val array1 = z3.mkFreshConst("arr", intArraySort) 14 | val array2 = z3.mkFreshConst("arr", intArraySort) 15 | 16 | val abs = z3.getAbsFuncDecl() 17 | 18 | val solver = z3.mkSolver() 19 | 20 | solver.assertCnstr(z3.mkEq(z3.mkSelect(array1, z3.mkInt(0, is)), z3.mkInt(1, is))) 21 | solver.assertCnstr(z3.mkEq(z3.mkSelect(array1, z3.mkInt(1, is)), z3.mkInt(0, is))) 22 | solver.assertCnstr(z3.mkEq(z3.mkSelect(array1, z3.mkInt(2, is)), z3.mkInt(-1, is))) 23 | 24 | solver.assertCnstr(z3.mkEq(array2, z3.mkArrayMap(abs, array1))) 25 | 26 | val (result, model) = solver.checkAndGetModel() 27 | 28 | result should equal(Some(true)) 29 | 30 | val array2Ev = model.eval(array2) 31 | array2Ev should be (Symbol("defined")) 32 | val array2Val = model.getArrayValue(array2Ev.get) 33 | array2Val should be (Symbol("defined")) 34 | val (valueMap0, default) = array2Val.get 35 | val valueMap = valueMap0.withDefaultValue(default) 36 | valueMap(z3.mkInt(0, is)) should equal (z3.mkInt(1, is)) 37 | valueMap(z3.mkInt(1, is)) should equal (z3.mkInt(0, is)) 38 | valueMap(z3.mkInt(2, is)) should equal (z3.mkInt(1, is)) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/test/scala/z3/scala/Arrays.scala: -------------------------------------------------------------------------------- 1 | package z3.scala 2 | 3 | import org.scalatest.funsuite.AnyFunSuite 4 | import org.scalatest.matchers.should.Matchers 5 | 6 | class Arrays extends AnyFunSuite with Matchers { 7 | 8 | test("Arrays") { 9 | val z3 = new Z3Context("MODEL" -> true) 10 | 11 | val is = z3.mkIntSort() 12 | val intArraySort = z3.mkArraySort(is, is) 13 | val array1 = z3.mkFreshConst("arr", intArraySort) 14 | val array2 = z3.mkFreshConst("arr", intArraySort) 15 | val x = z3.mkFreshConst("x", is) 16 | 17 | val solver = z3.mkSolver() 18 | // array1 = [ 42, 42, 42, ... ] 19 | solver.assertCnstr(z3.mkEq(array1,z3.mkConstArray(is, z3.mkInt(42, is)))) 20 | // x = array1[6] 21 | solver.assertCnstr(z3.mkEq(x, z3.mkSelect(array1, z3.mkInt(6, is)))) 22 | // array2 = array1[x - 40 -> 0] 23 | solver.assertCnstr(z3.mkEq(array2, z3.mkStore(array1, z3.mkSub(x, z3.mkInt(40, is)), z3.mkInt(0, is)))) 24 | 25 | // "reading" the default value of array2 (should be 42) 26 | val fourtyTwo = z3.mkFreshConst("ft", is) 27 | solver.assertCnstr(z3.mkEq(fourtyTwo, z3.mkArrayDefault(array2))) 28 | 29 | val (result, model) = solver.checkAndGetModel() 30 | 31 | //println("model is") 32 | //println(model) 33 | result should equal(Some(true)) 34 | 35 | val array1Evaluated = model.eval(array1) 36 | array1Evaluated should be (Symbol("defined")) 37 | array1Evaluated match { 38 | case Some(ae) => 39 | val array1Val = model.getArrayValue(ae) 40 | array1Val should be (Symbol("defined")) 41 | //println("When evaluated, array1 is: " + array1Val) 42 | array1Val match { 43 | case Some((valueMap,default)) => 44 | model.evalAs[Int](default) should equal (Some(42)) 45 | case None => 46 | } 47 | case None => 48 | } 49 | 50 | val array2Evaluated = model.eval(array2) 51 | array2Evaluated should be (Symbol("defined")) 52 | array2Evaluated match { 53 | case Some(ae) => { 54 | val array2Val = model.getArrayValue(ae) 55 | array2Val should be (Symbol("defined")) 56 | //println("When evaluated, array2 is: " + array2Val) 57 | array2Val match { 58 | case Some((valueMap,default)) => { 59 | valueMap(z3.mkInt(2, z3.mkIntSort())) should equal (z3.mkInt(0, z3.mkIntSort())) 60 | model.evalAs[Int](default) should equal (Some(42)) 61 | } 62 | case None => 63 | } 64 | } 65 | case None => 66 | } 67 | 68 | // These all seem to fail. Perhaps mkArrayDefault is not 69 | // supported anymore ? 70 | 71 | //model.evalAs[Int](z3.mkArrayDefault(array1)) should equal (Some(42)) 72 | //model.evalAs[Int](z3.mkArrayDefault(array2)) should equal (Some(42)) 73 | //model.evalAs[Int](fourtyTwo) should equal (Some(42)) 74 | } 75 | } 76 | 77 | -------------------------------------------------------------------------------- /src/test/scala/z3/scala/Calendar.scala: -------------------------------------------------------------------------------- 1 | package z3.scala 2 | 3 | import org.scalatest.funsuite.AnyFunSuite 4 | import org.scalatest.matchers.should.Matchers 5 | import z3.scala.dsl.Operands.* 6 | import z3.scala.dsl.{*, given} 7 | 8 | import scala.language.implicitConversions 9 | 10 | class Calendar extends AnyFunSuite with Matchers { 11 | 12 | test("Calendar") { 13 | val totalDays: IntOperand = 10593 14 | val originYear: IntOperand = 1980 15 | 16 | val (year, day) = choose[Int, Int] { (year, day) => 17 | def leapDaysUntil(y: Tree[IntSort]): IntOperand = (y - 1) / 4 - (y - 1) / 100 + (y - 1) / 400 18 | 19 | totalDays === (year - originYear) * 365 + leapDaysUntil(year) - leapDaysUntil(originYear) + day && day > 0 && day <= 366 20 | } 21 | 22 | year should equal(2008) 23 | day should equal(366) 24 | } 25 | } 26 | 27 | -------------------------------------------------------------------------------- /src/test/scala/z3/scala/Core.scala: -------------------------------------------------------------------------------- 1 | package z3.scala 2 | 3 | import org.scalatest.funsuite.AnyFunSuite 4 | import org.scalatest.matchers.should.Matchers 5 | 6 | import z3.scala.dsl.{*, given} 7 | 8 | import scala.language.implicitConversions 9 | 10 | class Core extends AnyFunSuite with Matchers { 11 | import dsl._ 12 | 13 | test("Core") { 14 | val z3 = new Z3Context("MODEL" -> "true") 15 | 16 | val x = z3.mkFreshConst("x", z3.mkIntSort()) 17 | val y = z3.mkFreshConst("y", z3.mkIntSort()) 18 | val p1 = z3.mkFreshConst("p1", z3.mkBoolSort()) 19 | val p2 = z3.mkFreshConst("p2", z3.mkBoolSort()) 20 | val p3 = z3.mkFreshConst("p3", z3.mkBoolSort()) 21 | 22 | val zero = z3.mkInt(0, z3.mkIntSort()) 23 | 24 | val solver = z3.mkSolver() 25 | solver.assertCnstr(p1 --> !(!(x === zero))) 26 | solver.assertCnstr(p2 --> !(y === zero)) 27 | solver.assertCnstr(p3 --> !(x === zero)) 28 | 29 | val (result, model, core) = solver.checkAssumptionsGetModelOrCore(p1, p2, p3) 30 | 31 | result should equal (Some(false)) 32 | core.toSet should equal (Set(p1, p3)) 33 | } 34 | } 35 | 36 | -------------------------------------------------------------------------------- /src/test/scala/z3/scala/ForComprehension.scala: -------------------------------------------------------------------------------- 1 | package z3.scala 2 | 3 | import org.scalatest.funsuite.AnyFunSuite 4 | import org.scalatest.matchers.should.Matchers 5 | 6 | import z3.scala.dsl.{*, given} 7 | 8 | import scala.language.implicitConversions 9 | 10 | class ForComprehension extends AnyFunSuite with Matchers { 11 | 12 | import dsl._ 13 | 14 | def isPrime(i: Int): Boolean = { 15 | !(2 until i).exists(i % _ == 0) 16 | } 17 | 18 | test("ForComprehension") { 19 | val results = for { 20 | (x, y) <- findAll[Int, Int]((x, y) => x > 0 && y > x && x * 2 + y * 3 <= 40) 21 | if isPrime(y) 22 | z <- findAll[Int](z => z * x === 3 * y * y) 23 | } yield (x, y, z) 24 | 25 | results.size should equal(8) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/test/scala/z3/scala/IntArith.scala: -------------------------------------------------------------------------------- 1 | package z3.scala 2 | 3 | import org.scalatest.funsuite.AnyFunSuite 4 | import org.scalatest.matchers.should.Matchers 5 | 6 | class IntArith extends AnyFunSuite with Matchers { 7 | 8 | test("Comfusy-like") { 9 | val z3 = new Z3Context("MODEL" -> true) 10 | val i = z3.mkIntSort() 11 | val h = z3.mkConst(z3.mkStringSymbol("h"), i) 12 | val m = z3.mkConst(z3.mkStringSymbol("m"), i) 13 | val s = z3.mkConst(z3.mkStringSymbol("s"), i) 14 | // builds a constant integer value from the CL arg. 15 | val t = z3.mkInt(1234, i) 16 | // more integer constants 17 | val z = z3.mkInt(0, i) 18 | val sx = z3.mkInt(60, i) 19 | // builds the constraint h*3600 + m * 60 + s == totSecs 20 | val cs1 = z3.mkEq( 21 | z3.mkAdd( 22 | z3.mkMul(z3.mkInt(3600, i), h), 23 | z3.mkMul(sx, m), 24 | s), 25 | t) 26 | // more constraints 27 | val cs2 = z3.mkAnd(z3.mkGE(h, z), z3.mkLT(h, z3.mkInt(24, i))) 28 | val cs3 = z3.mkAnd(z3.mkGE(m, z), z3.mkLT(m, sx)) 29 | val cs4 = z3.mkAnd(z3.mkGE(s, z), z3.mkLT(s, sx)) 30 | 31 | val solver = z3.mkSolver() 32 | solver.assertCnstr(z3.mkAnd(cs1, cs2, cs3, cs4)) 33 | 34 | // attempting to solve the constraints 35 | val (sol, model) = solver.checkAndGetModel() 36 | 37 | sol should equal(Some(true)) 38 | model.evalAs[Int](h) should equal(Some(0)) 39 | model.evalAs[Int](m) should equal(Some(20)) 40 | model.evalAs[Int](s) should equal(Some(34)) 41 | 42 | z3.delete() 43 | } 44 | } 45 | 46 | -------------------------------------------------------------------------------- /src/test/scala/z3/scala/NQueens.scala: -------------------------------------------------------------------------------- 1 | package z3.scala 2 | 3 | import org.scalatest.funsuite.AnyFunSuite 4 | import org.scalatest.matchers.should.Matchers 5 | 6 | import z3.scala.dsl.{*, given} 7 | 8 | import scala.language.implicitConversions 9 | 10 | class NQueens extends AnyFunSuite with Matchers { 11 | import dsl._ 12 | 13 | test("NQueens") { 14 | 15 | val numCols = 8 16 | val ctx = new Z3Context("MODEL" -> true) 17 | 18 | /* Declaring column variables */ 19 | val columns = (0 until numCols).map{ _ => IntVar() } 20 | 21 | /* All queens are on different columns */ 22 | val diffCnstr = Distinct(columns: _*) 23 | 24 | /* Columns are within the bounds */ 25 | val boundsCnstr = for (c <- columns) yield (c >= 0 && c < numCols) 26 | 27 | /* No two queens are on same diagonal */ 28 | val diagonalsCnstr = 29 | for (i <- 0 until numCols; j <- 0 until i) yield 30 | ((columns(i) - columns(j) !== i - j) && 31 | (columns(i) - columns(j) !== j - i)) 32 | 33 | /* We assert all of the above */ 34 | val solver = ctx.mkSolver() 35 | solver.assertCnstr(diffCnstr) 36 | boundsCnstr map (solver.assertCnstr(_)) 37 | diagonalsCnstr map (solver.assertCnstr(_)) 38 | 39 | val nbModels = solver.checkAndGetAllModels().size 40 | 41 | //println("Total number of models: " + nbModels) 42 | nbModels should equal (92) 43 | 44 | ctx.delete() 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/test/scala/z3/scala/Optimizer.scala: -------------------------------------------------------------------------------- 1 | package z3.scala 2 | 3 | import org.scalatest.funsuite.AnyFunSuite 4 | import org.scalatest.matchers.should.Matchers 5 | 6 | class Optimizer extends AnyFunSuite with Matchers { 7 | 8 | test("Optimizer") { 9 | val z3 = new Z3Context("MODEL" -> true) 10 | 11 | val is = z3.mkIntSort() 12 | val x = z3.mkIntConst("x") 13 | val y = z3.mkIntConst("y") 14 | 15 | val a1 = z3.mkGT(x, z3.mkInt(0, is)) 16 | val a2 = z3.mkLT(x, y) 17 | val a3 = z3.mkLE(z3.mkAdd(y, x), z3.mkInt(0, is)) 18 | 19 | val opt = z3.mkOptimizer() 20 | opt.assertCnstr(z3.mkIff(a3, a1)) 21 | opt.assertCnstr(z3.mkOr(a3, a2)) 22 | opt.assertCnstr(a3, 3) 23 | opt.assertCnstr(z3.mkNot(a3), 5) 24 | opt.assertCnstr(z3.mkNot(a1), 10) 25 | opt.assertCnstr(z3.mkNot(a2), 3) 26 | 27 | val result = opt.check() 28 | result should equal (Some(true)) 29 | 30 | val model = opt.getModel() 31 | val a1eval = model.evalAs[Boolean](a1) 32 | val a2eval = model.evalAs[Boolean](a2) 33 | val a3eval = model.evalAs[Boolean](a3) 34 | 35 | a1eval should equal (Some(true)) 36 | a2eval should equal (Some(false)) 37 | a3eval should equal (Some(true)) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/test/scala/z3/scala/Quantifiers.scala: -------------------------------------------------------------------------------- 1 | package z3.scala 2 | 3 | import org.scalatest.funsuite.AnyFunSuite 4 | import org.scalatest.matchers.should.Matchers 5 | 6 | class Quantifiers extends AnyFunSuite with Matchers { 7 | 8 | /* 9 | * (declare-sort Type) 10 | * (declare-fun subtype (Type Type) Bool) 11 | * (declare-fun array-of (Type) Type) 12 | * (assert (forall ((x Type)) (subtype x x))) 13 | * (assert (forall ((x Type) (y Type) (z Type)) 14 | * (=> (and (subtype x y) (subtype y z)) 15 | * (subtype x z)))) 16 | * (assert (forall ((x Type) (y Type)) 17 | * (=> (and (subtype x y) (subtype y x)) 18 | * (= x y)))) 19 | * (assert (forall ((x Type) (y Type) (z Type)) 20 | * (=> (and (subtype x y) (subtype x z)) 21 | * (or (subtype y z) (subtype z y))))) 22 | * (assert (forall ((x Type) (y Type)) 23 | * (=> (subtype x y) 24 | * (subtype (array-of x) (array-of y))))) 25 | * (declare-const root-type Type) 26 | * (assert (forall ((x Type)) (subtype x root-type))) 27 | * (check-sat) 28 | */ 29 | 30 | test("Quantifiers") { 31 | val z3 = new Z3Context("MODEL" -> true) 32 | val solver = z3.mkSolver() 33 | 34 | /* 35 | * (declare-sort Type) 36 | * (declare-fun subtype (Type Type) Bool) 37 | * (declare-fun array-of (Type) Type) 38 | */ 39 | val typeSort = z3.mkUninterpretedSort("Type") 40 | val subtype = z3.mkFuncDecl("subtype", List[Z3Sort](typeSort, typeSort).toIndexedSeq, z3.mkBoolSort()) 41 | val arrayOf = z3.mkFuncDecl("array-of", List[Z3Sort](typeSort).toIndexedSeq, typeSort) 42 | 43 | val syms @ List(xSym, ySym, zSym) = List("x", "y", "z").map(z3.mkSymbol(_)) 44 | val consts @ List(x, y, z) = syms.map(sym => z3.mkConst(sym, typeSort)) 45 | 46 | /* (assert (forall ((x Type)) (subtype x x))) */ 47 | solver.assertCnstr(z3.mkForall(0, Seq.empty, 48 | Seq(xSym -> typeSort), 49 | subtype(x, x))) 50 | 51 | /* (assert (forall ((x Type) (y Type) (z Type)) 52 | (=> (and (subtype x y) (subtype y z)) 53 | (subtype x z)))) */ 54 | solver.assertCnstr(z3.mkForall(0, Seq.empty, 55 | Seq(xSym -> typeSort, ySym -> typeSort, zSym -> typeSort), 56 | z3.mkImplies(z3.mkAnd(subtype(x, y), subtype(y, z)), subtype(x, z)))) 57 | 58 | /* (assert (forall ((x Type) (y Type)) 59 | (=> (and (subtype x y) (subtype y x)) 60 | (= x y)))) */ 61 | solver.assertCnstr(z3.mkForall(0, Seq.empty, 62 | Seq(xSym -> typeSort, ySym -> typeSort), 63 | z3.mkImplies(z3.mkAnd(subtype(x, y), subtype(y, x)), z3.mkEq(x, y)))) 64 | 65 | /* (assert (forall ((x Type) (y Type) (z Type)) 66 | (=> (and (subtype x y) (subtype x z)) 67 | (or (subtype y z) (subtype z y))))) */ 68 | solver.assertCnstr(z3.mkForall(0, Seq.empty, 69 | Seq(xSym -> typeSort, ySym -> typeSort, zSym -> typeSort), 70 | z3.mkImplies(z3.mkAnd(subtype(x, y), subtype(x, z)), z3.mkOr(subtype(y, z), subtype(z, y))))) 71 | 72 | /* (assert (forall ((x Type) (y Type)) 73 | (=> (subtype x y) 74 | (subtype (array-of x) (array-of y))))) */ 75 | solver.assertCnstr(z3.mkForall(0, Seq.empty, 76 | Seq(xSym -> typeSort, ySym -> typeSort), 77 | z3.mkImplies(subtype(x, y), subtype(arrayOf(x), arrayOf(y))))) 78 | 79 | /* (declare-const root-type Type) */ 80 | val rootType = z3.mkConst("root-type", typeSort) 81 | 82 | /* (assert (forall ((x Type)) (subtype x root-type))) */ 83 | solver.assertCnstr(z3.mkForall(0, Seq.empty, 84 | Seq(xSym -> typeSort), 85 | subtype(x, rootType))) 86 | 87 | solver.check() should equal(Some(true)) 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/test/scala/z3/scala/SatSolver.scala: -------------------------------------------------------------------------------- 1 | package z3.scala 2 | 3 | import org.scalatest.funsuite.AnyFunSuite 4 | import org.scalatest.matchers.should.Matchers 5 | 6 | class SatSolver extends AnyFunSuite with Matchers { 7 | import dsl._ 8 | 9 | test("Sat solver") { 10 | case class Literal(name: String, polarity: Boolean) 11 | type Clause = Set[Literal] 12 | 13 | def DPLL(f : Set[Clause]) : (Boolean, Map[String,Option[Boolean]]) = 14 | if(f.isEmpty) (true, Map.empty) 15 | else if(f.exists(clause => clause.isEmpty)) (false, Map.empty) 16 | else { 17 | val z3 = new Z3Context("MODEL" -> true) 18 | val b = z3.mkBoolSort() 19 | 20 | val literals = f.reduceLeft((a,b) => a ++ b) 21 | val litMap: _root_.scala.collection.mutable.Map[String,Z3AST] = 22 | _root_.scala.collection.mutable.Map.empty[String,Z3AST] 23 | 24 | literals.foreach(lit => { 25 | if(!litMap.keySet.contains(lit.name)) { 26 | val ast = z3.mkBoolConst(z3.mkStringSymbol(lit.name)) 27 | litMap(lit.name) = ast 28 | } 29 | }) 30 | 31 | val solver = z3.mkSolver() 32 | 33 | f.foreach(clause => { 34 | if (clause.size > 1) { 35 | val nc: Array[Z3AST] = new Array[Z3AST](clause.size) 36 | var c: Int = 0 37 | clause.foreach(lit => { 38 | nc(c) = if(lit.polarity) litMap(lit.name) else z3.mkNot(litMap(lit.name)) 39 | c = c + 1 40 | }) 41 | solver.assertCnstr(nc.reduceLeft(z3.mkOr(_, _))) 42 | } else { 43 | val singleLit = clause.head 44 | if(singleLit.polarity) 45 | solver.assertCnstr(litMap(singleLit.name)) 46 | else 47 | solver.assertCnstr(z3.mkNot(litMap(singleLit.name))) 48 | } 49 | }) 50 | 51 | val (result, model) = solver.checkAndGetModel() 52 | 53 | result match { 54 | case None => println("There was an error with Z3."); (false, Map.empty) 55 | case Some(false) => (false, Map.empty) // formula was unsat 56 | case Some(true) => (true, Map.empty[String,Option[Boolean]] ++ litMap.map(p => (p._1, model.evalAs[Boolean](p._2)))) 57 | } 58 | } 59 | 60 | // DIMACS parser by Hossein Hojjat 61 | var form = Set.empty[Clause] 62 | var clause = Set.empty[Literal] 63 | var tok:String = "" 64 | io.Source.fromString(Benchmark.str).getLines().foreach { 65 | line => if( !line.startsWith("c") && !line.startsWith("p")) { 66 | val scanner = new _root_.java.util.Scanner(line) 67 | while(scanner.hasNext) { 68 | tok = scanner.next 69 | if (tok != "0") 70 | {if( tok.startsWith("-")) clause += Literal(tok.drop(1), false) else clause += Literal(tok, true)} 71 | else { 72 | form += clause 73 | clause = Set.empty[Literal] 74 | }}}} 75 | if (clause.size != 0) form += clause 76 | val (rs,rm) = DPLL(form) 77 | 78 | rs should equal(true) 79 | 80 | // val pos = rm.filter(p => p._2.isDefined && p._2.get).map(p => p._1.toInt).toSet 81 | // val neg = rm.filter(p => p._2.isDefined && !p._2.get).map(p => p._1.toInt).toSet 82 | // val dnt = rm.filter(p => p._2.isEmpty).map(p => p._1.toInt).toSet 83 | 84 | // println("pos: " + pos) 85 | // println("neg: " + neg) 86 | // println("dnt: " + dnt) 87 | 88 | def eval(form : Set[Clause], model : Map[String,Option[Boolean]], default : Boolean) : Boolean = { 89 | form.forall(clause => 90 | clause.exists(literal => literal match { 91 | case Literal(lit, true) => model(lit).getOrElse(default) 92 | case Literal(lit, false) => !model(lit).getOrElse(!default) 93 | }) 94 | ) 95 | } 96 | 97 | // Too restrictive: 98 | // pos should equal(Set(15, 9, 6, 1, 17, 14, 20)) 99 | // neg should equal(Set(12, 8, 19, 4, 11, 13, 16, 5, 10, 2, 18, 7, 3)) 100 | 101 | // We evaluate the formula with the model, with don't care set to 102 | // true and false. 103 | eval(form, rm, true) should equal(true) 104 | eval(form, rm, false) should equal(true) 105 | } 106 | 107 | 108 | object Benchmark { 109 | val str = """c This Formular is generated by mcnf 110 | c 111 | c horn? no 112 | c forced? no 113 | c mixed sat? no 114 | c clause length = 3 115 | c 116 | p cnf 20 91 117 | 4 -18 19 0 118 | 3 18 -5 0 119 | -5 -8 -15 0 120 | -20 7 -16 0 121 | 10 -13 -7 0 122 | -12 -9 17 0 123 | 17 19 5 0 124 | -16 9 15 0 125 | 11 -5 -14 0 126 | 18 -10 13 0 127 | -3 11 12 0 128 | -6 -17 -8 0 129 | -18 14 1 0 130 | -19 -15 10 0 131 | 12 18 -19 0 132 | -8 4 7 0 133 | -8 -9 4 0 134 | 7 17 -15 0 135 | 12 -7 -14 0 136 | -10 -11 8 0 137 | 2 -15 -11 0 138 | 9 6 1 0 139 | -11 20 -17 0 140 | 9 -15 13 0 141 | 12 -7 -17 0 142 | -18 -2 20 0 143 | 20 12 4 0 144 | 19 11 14 0 145 | -16 18 -4 0 146 | -1 -17 -19 0 147 | -13 15 10 0 148 | -12 -14 -13 0 149 | 12 -14 -7 0 150 | -7 16 10 0 151 | 6 10 7 0 152 | 20 14 -16 0 153 | -19 17 11 0 154 | -7 1 -20 0 155 | -5 12 15 0 156 | -4 -9 -13 0 157 | 12 -11 -7 0 158 | -5 19 -8 0 159 | 1 16 17 0 160 | 20 -14 -15 0 161 | 13 -4 10 0 162 | 14 7 10 0 163 | -5 9 20 0 164 | 10 1 -19 0 165 | -16 -15 -1 0 166 | 16 3 -11 0 167 | -15 -10 4 0 168 | 4 -15 -3 0 169 | -10 -16 11 0 170 | -8 12 -5 0 171 | 14 -6 12 0 172 | 1 6 11 0 173 | -13 -5 -1 0 174 | -7 -2 12 0 175 | 1 -20 19 0 176 | -2 -13 -8 0 177 | 15 18 4 0 178 | -11 14 9 0 179 | -6 -15 -2 0 180 | 5 -12 -15 0 181 | -6 17 5 0 182 | -13 5 -19 0 183 | 20 -1 14 0 184 | 9 -17 15 0 185 | -5 19 -18 0 186 | -12 8 -10 0 187 | -18 14 -4 0 188 | 15 -9 13 0 189 | 9 -5 -1 0 190 | 10 -19 -14 0 191 | 20 9 4 0 192 | -9 -2 19 0 193 | -5 13 -17 0 194 | 2 -10 -18 0 195 | -18 3 11 0 196 | 7 -9 17 0 197 | -15 -6 -3 0 198 | -2 3 -13 0 199 | 12 3 -2 0 200 | -2 -3 17 0 201 | 20 -15 -16 0 202 | -5 -17 -19 0 203 | -20 -18 11 0 204 | -9 1 -5 0 205 | -19 9 17 0 206 | 12 -2 17 0 207 | 4 -16 -5 0 208 | """ 209 | } 210 | } 211 | 212 | -------------------------------------------------------------------------------- /src/test/scala/z3/scala/Sequences.scala: -------------------------------------------------------------------------------- 1 | package z3.scala 2 | 3 | import org.scalatest.funsuite.AnyFunSuite 4 | import org.scalatest.matchers.should.Matchers 5 | 6 | class Sequences extends AnyFunSuite with Matchers { 7 | 8 | test("Simple SAT") { 9 | val z3 = new Z3Context("MODEL" -> true) 10 | 11 | val is = z3.mkIntSort() 12 | val iss = z3.mkSeqSort(is) 13 | val s1 = z3.mkFreshConst("s1", iss) 14 | val s2 = z3.mkFreshConst("s2", iss) 15 | 16 | val solver = z3.mkSolver() 17 | solver.assertCnstr(z3.mkDistinct(s1, s2)) 18 | 19 | val (result, model) = solver.checkAndGetModel() 20 | result should equal (Some(true)) 21 | 22 | val s1eval = model.eval(s1) 23 | val s2eval = model.eval(s2) 24 | 25 | s1eval should be (Symbol("defined")) 26 | s2eval should be (Symbol("defined")) 27 | } 28 | 29 | test("Different head") { 30 | val z3 = new Z3Context("MODEL" -> true) 31 | 32 | val is = z3.mkIntSort() 33 | val iss = z3.mkSeqSort(is) 34 | val s1 = z3.mkFreshConst("s1", iss) 35 | val s2 = z3.mkFreshConst("s2", iss) 36 | 37 | val solver = z3.mkSolver() 38 | solver.assertCnstr(z3.mkEq(s1, s2)) 39 | solver.assertCnstr(z3.mkEq(z3.mkUnitSeq(z3.mkInt(1, is)), z3.mkSeqExtract(s1, z3.mkInt(0, is), z3.mkInt(1, is)))) 40 | solver.assertCnstr(z3.mkEq(z3.mkUnitSeq(z3.mkInt(0, is)), z3.mkSeqExtract(s2, z3.mkInt(0, is), z3.mkInt(1, is)))) 41 | 42 | val result = solver.check() 43 | result should equal (Some(false)) 44 | } 45 | 46 | test("Compatible sub-sequences") { 47 | val z3 = new Z3Context("MODEL" -> true) 48 | 49 | val is = z3.mkIntSort() 50 | val iss = z3.mkSeqSort(is) 51 | val s1 = z3.mkFreshConst("s1", iss) 52 | val s2 = z3.mkFreshConst("s2", iss) 53 | 54 | val solver = z3.mkSolver() 55 | solver.assertCnstr(z3.mkEq(s1, s2)) 56 | solver.assertCnstr(z3.mkEq(z3.mkUnitSeq(z3.mkInt(1, is)), z3.mkSeqExtract(s1, z3.mkInt(0, is), z3.mkInt(1, is)))) 57 | solver.assertCnstr(z3.mkEq(z3.mkUnitSeq(z3.mkInt(0, is)), z3.mkSeqExtract(s2, z3.mkInt(1, is), z3.mkInt(1, is)))) 58 | 59 | val (result, model) = solver.checkAndGetModel() 60 | result should equal (Some(true)) 61 | 62 | val s1eval = model.eval(s1) 63 | val s2eval = model.eval(s2) 64 | 65 | s1eval should be (Symbol("defined")) 66 | s2eval should be (Symbol("defined")) 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/test/scala/z3/scala/Sets.scala: -------------------------------------------------------------------------------- 1 | package z3.scala 2 | 3 | import org.scalatest.funsuite.AnyFunSuite 4 | import org.scalatest.matchers.should.Matchers 5 | 6 | class Sets extends AnyFunSuite with Matchers { 7 | 8 | test("Sets") { 9 | val z3 = new Z3Context("MODEL" -> true) 10 | 11 | val is = z3.mkIntSort() 12 | val iss = z3.mkSetSort(is) 13 | val s1 = z3.mkFreshConst("s1", iss) 14 | val s2 = z3.mkFreshConst("s2", iss) 15 | 16 | val solver = z3.mkSolver() 17 | solver.assertCnstr(z3.mkDistinct(s1, s2)) 18 | 19 | val (result, model) = solver.checkAndGetModel() 20 | result should equal(Some(true)) 21 | 22 | val s1eval = model.eval(s1) 23 | val s2eval = model.eval(s2) 24 | s1eval should be (Symbol("defined")) 25 | s2eval should be (Symbol("defined")) 26 | (s1eval,s2eval) match { 27 | case (Some(se1), Some(se2)) => 28 | val s1val = model.getSetValue(se1) 29 | val s2val = model.getSetValue(se2) 30 | s1val should be (Symbol("defined")) 31 | s2val should be (Symbol("defined")) 32 | s1val should not equal (s2val) 33 | //println("Set values :" + s1val + ", " + s2val) 34 | case _ => 35 | } 36 | } 37 | } 38 | 39 | -------------------------------------------------------------------------------- /z3_mk_abs.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/api/api_arith.cpp b/src/api/api_arith.cpp 2 | index 57f96dd6d..5fe7b8497 100644 3 | --- a/src/api/api_arith.cpp 4 | +++ b/src/api/api_arith.cpp 5 | @@ -65,6 +65,7 @@ extern "C" { 6 | MK_BINARY_ARITH_OP(Z3_mk_power, OP_POWER); 7 | MK_BINARY_ARITH_OP(Z3_mk_mod, OP_MOD); 8 | MK_BINARY_ARITH_OP(Z3_mk_rem, OP_REM); 9 | + MK_UNARY(Z3_mk_abs, mk_c(c)->get_arith_fid(), OP_ABS, SKIP); 10 | 11 | Z3_ast Z3_API Z3_mk_div(Z3_context c, Z3_ast n1, Z3_ast n2) { 12 | Z3_TRY; 13 | diff --git a/src/api/api_ast.cpp b/src/api/api_ast.cpp 14 | index d11ce313e..208269021 100644 15 | --- a/src/api/api_ast.cpp 16 | +++ b/src/api/api_ast.cpp 17 | @@ -1041,6 +1041,7 @@ extern "C" { 18 | case OP_TO_REAL: return Z3_OP_TO_REAL; 19 | case OP_TO_INT: return Z3_OP_TO_INT; 20 | case OP_IS_INT: return Z3_OP_IS_INT; 21 | + case OP_ABS: return Z3_OP_ABS; 22 | default: 23 | return Z3_OP_INTERNAL; 24 | } 25 | diff --git a/src/api/z3_api.h b/src/api/z3_api.h 26 | index d5bd1e11c..703301492 100644 27 | --- a/src/api/z3_api.h 28 | +++ b/src/api/z3_api.h 29 | @@ -1032,6 +1032,7 @@ typedef enum { 30 | Z3_OP_TO_INT, 31 | Z3_OP_IS_INT, 32 | Z3_OP_POWER, 33 | + Z3_OP_ABS, 34 | 35 | // Arrays & Sets 36 | Z3_OP_STORE = 0x300, 37 | @@ -2420,6 +2421,11 @@ extern "C" { 38 | */ 39 | Z3_ast Z3_API Z3_mk_add(Z3_context c, unsigned num_args, Z3_ast const args[]); 40 | 41 | + /** 42 | + def_API('Z3_mk_abs', AST, (_in(CONTEXT), _in(AST))) 43 | + */ 44 | + Z3_ast Z3_API Z3_mk_abs(Z3_context c, Z3_ast t1); 45 | + 46 | /** 47 | \brief Create an AST node representing \ccode{args[0] * ... * args[num_args-1]}. 48 | 49 | --------------------------------------------------------------------------------