mirror of
				https://github.com/Z3Prover/z3
				synced 2025-11-04 05:19:11 +00:00 
			
		
		
		
	Merge remote-tracking branch 'upstream/master' into fix-length-testing
This commit is contained in:
		
						commit
						5e19e905fa
					
				
					 178 changed files with 3204 additions and 1694 deletions
				
			
		
							
								
								
									
										22
									
								
								.travis.yml
									
										
									
									
									
								
							
							
						
						
									
										22
									
								
								.travis.yml
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -17,15 +17,31 @@ env:
 | 
			
		|||
###############################################################################
 | 
			
		||||
# Ubuntu 16.04 LTS
 | 
			
		||||
###############################################################################
 | 
			
		||||
    # 64-bit UBSan Debug build
 | 
			
		||||
    - LINUX_BASE=ubuntu_16.04 C_COMPILER=/usr/bin/clang-3.9 CXX_COMPILER=/usr/bin/clang++-3.9 TARGET_ARCH=x86_64 Z3_BUILD_TYPE=Debug UBSAN_BUILD=1 RUN_UNIT_TESTS=SKIP
 | 
			
		||||
    # 64-bit ASan Debug build
 | 
			
		||||
    - LINUX_BASE=ubuntu_16.04 C_COMPILER=/usr/bin/clang-3.9 CXX_COMPILER=/usr/bin/clang++-3.9 TARGET_ARCH=x86_64 Z3_BUILD_TYPE=Debug ASAN_BUILD=1 RUN_UNIT_TESTS=SKIP ASAN_DSO=/usr/lib/clang/3.9/lib/linux/libclang_rt.asan-x86_64.so
 | 
			
		||||
    # Build for running unit tests under ASan/UBSan
 | 
			
		||||
    # FIXME: We should really be doing a debug build but the unit tests run too
 | 
			
		||||
    # slowly when we do that.
 | 
			
		||||
    - LINUX_BASE=ubuntu_16.04 C_COMPILER=/usr/bin/clang-3.9 CXX_COMPILER=/usr/bin/clang++-3.9 TARGET_ARCH=x86_64 Z3_BUILD_TYPE=RelWithDebInfo ASAN_BUILD=1 RUN_UNIT_TESTS=BUILD_AND_RUN ASAN_DSO=/usr/lib/clang/3.9/lib/linux/libclang_rt.asan-x86_64.so UBSAN_BUILD=1 RUN_API_EXAMPLES=0 RUN_SYSTEM_TESTS=0 DOTNET_BINDINGS=0 JAVA_BINDINGS=0 PYTHON_BINDINGS=0
 | 
			
		||||
 | 
			
		||||
    # 64-bit GCC 5.4 RelWithDebInfo
 | 
			
		||||
    - LINUX_BASE=ubuntu_16.04 C_COMPILER=/usr/bin/gcc-5 CXX_COMPILER=/usr/bin/g++-5 TARGET_ARCH=x86_64 Z3_BUILD_TYPE=RelWithDebInfo
 | 
			
		||||
    # 64-bit Clang 3.9 RelWithDebInfo
 | 
			
		||||
    - LINUX_BASE=ubuntu_16.04 C_COMPILER=/usr/bin/clang-3.9 CXX_COMPILER=/usr/bin/clang++-3.9 TARGET_ARCH=x86_64 Z3_BUILD_TYPE=RelWithDebInfo
 | 
			
		||||
 | 
			
		||||
    # Debug builds
 | 
			
		||||
    #
 | 
			
		||||
    # Note the unit tests for the debug builds are compiled but **not**
 | 
			
		||||
    # executed. This is because the debug build of unit tests takes a large
 | 
			
		||||
    # amount of time to execute compared to the optimized builds. The hope is
 | 
			
		||||
    # that just running the optimized unit tests is sufficient.
 | 
			
		||||
    #
 | 
			
		||||
    # 64-bit GCC 5.4 Debug
 | 
			
		||||
    - LINUX_BASE=ubuntu_16.04 C_COMPILER=/usr/bin/gcc-5 CXX_COMPILER=/usr/bin/g++-5 TARGET_ARCH=x86_64 Z3_BUILD_TYPE=Debug
 | 
			
		||||
    - LINUX_BASE=ubuntu_16.04 C_COMPILER=/usr/bin/gcc-5 CXX_COMPILER=/usr/bin/g++-5 TARGET_ARCH=x86_64 Z3_BUILD_TYPE=Debug RUN_UNIT_TESTS=BUILD_ONLY
 | 
			
		||||
    # 64-bit Clang Debug
 | 
			
		||||
    - LINUX_BASE=ubuntu_16.04 C_COMPILER=/usr/bin/clang-3.9 CXX_COMPILER=/usr/bin/clang++-3.9 TARGET_ARCH=x86_64 Z3_BUILD_TYPE=Debug
 | 
			
		||||
    - LINUX_BASE=ubuntu_16.04 C_COMPILER=/usr/bin/clang-3.9 CXX_COMPILER=/usr/bin/clang++-3.9 TARGET_ARCH=x86_64 Z3_BUILD_TYPE=Debug RUN_UNIT_TESTS=BUILD_ONLY
 | 
			
		||||
 | 
			
		||||
    # 32-bit GCC 5.4 RelWithDebInfo
 | 
			
		||||
    - LINUX_BASE=ubuntu32_16.04 C_COMPILER=/usr/bin/gcc-5 CXX_COMPILER=/usr/bin/g++-5 TARGET_ARCH=i686 Z3_BUILD_TYPE=RelWithDebInfo
 | 
			
		||||
| 
						 | 
				
			
			@ -57,7 +73,7 @@ env:
 | 
			
		|||
    # 64-bit GCC 4.8 RelWithDebInfo
 | 
			
		||||
    - LINUX_BASE=ubuntu_14.04 C_COMPILER=/usr/bin/gcc-4.8 CXX_COMPILER=/usr/bin/g++-4.8 TARGET_ARCH=x86_64 Z3_BUILD_TYPE=RelWithDebInfo
 | 
			
		||||
    # 64-bit GCC 4.8 Debug
 | 
			
		||||
    - LINUX_BASE=ubuntu_14.04 C_COMPILER=/usr/bin/gcc-4.8 CXX_COMPILER=/usr/bin/g++-4.8 TARGET_ARCH=x86_64 Z3_BUILD_TYPE=Debug
 | 
			
		||||
    - LINUX_BASE=ubuntu_14.04 C_COMPILER=/usr/bin/gcc-4.8 CXX_COMPILER=/usr/bin/g++-4.8 TARGET_ARCH=x86_64 Z3_BUILD_TYPE=Debug RUN_UNIT_TESTS=BUILD_ONLY
 | 
			
		||||
 | 
			
		||||
# macOS (a.k.a OSX) support
 | 
			
		||||
matrix:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -270,6 +270,7 @@ The following useful options can be passed to CMake whilst configuring.
 | 
			
		|||
* ``API_LOG_SYNC`` - BOOL. If set to ``TRUE`` will enable experimental API log sync feature.
 | 
			
		||||
* ``WARNINGS_AS_ERRORS`` - STRING. If set to ``TRUE`` compiler warnings will be treated as errors. If set to ``False`` compiler warnings will not be treated as errors.
 | 
			
		||||
    If set to ``SERIOUS_ONLY`` a subset of compiler warnings will be treated as errors.
 | 
			
		||||
* ``Z3_C_EXAMPLES_FORCE_CXX_LINKER`` - BOOL. If set to ``TRUE`` the C API examples will request that the C++ linker is used rather than the C linker.
 | 
			
		||||
 | 
			
		||||
On the command line these can be passed to ``cmake`` using the ``-D`` option. In ``ccmake`` and ``cmake-gui`` these can be set in the user interface.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										12
									
								
								README.md
									
										
									
									
									
								
							
							
						
						
									
										12
									
								
								README.md
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -12,9 +12,9 @@ See the [release notes](RELEASE_NOTES) for notes on various stable releases of Z
 | 
			
		|||
 | 
			
		||||
## Build status
 | 
			
		||||
 | 
			
		||||
| Windows x86 | Windows x64 | Ubuntu x64 | Ubuntu x86 | Debian x64 | OSX | TravisCI |
 | 
			
		||||
| ----------- | ----------- | ---------- | ---------- | ---------- | --- | -------- |
 | 
			
		||||
[](https://cz3.visualstudio.com/Z3/_build/index?definitionId=4) | [](https://cz3.visualstudio.com/Z3/_build/index?definitionId=7) | [](https://cz3.visualstudio.com/Z3/_build/index?definitionId=3) | [](https://cz3.visualstudio.com/Z3/_build/index?definitionId=6) | [](https://cz3.visualstudio.com/Z3/_build/index?definitionId=5) | [](https://cz3.visualstudio.com/Z3/_build/index?definitionId=2) | [](https://travis-ci.org/Z3Prover/z3)
 | 
			
		||||
| Windows x86 | Windows x64 | Ubuntu x64 | Debian x64 | OSX | TravisCI |
 | 
			
		||||
| ----------- | ----------- | ---------- | ---------- | --- | -------- |
 | 
			
		||||
[](https://cz3.visualstudio.com/Z3/_build/index?definitionId=4) | [](https://cz3.visualstudio.com/Z3/_build/index?definitionId=7) | [](https://cz3.visualstudio.com/Z3/_build/index?definitionId=3) | [](https://cz3.visualstudio.com/Z3/_build/index?definitionId=5) | [](https://cz3.visualstudio.com/Z3/_build/index?definitionId=2) | [](https://travis-ci.org/Z3Prover/z3)
 | 
			
		||||
 | 
			
		||||
[1]: #building-z3-on-windows-using-visual-studio-command-prompt
 | 
			
		||||
[2]: #building-z3-using-make-and-gccclang
 | 
			
		||||
| 
						 | 
				
			
			@ -124,7 +124,7 @@ utility is used to install ``Microsoft.Z3.dll`` into the
 | 
			
		|||
[pkg-config](http://www.freedesktop.org/wiki/Software/pkg-config/) file
 | 
			
		||||
(``Microsoft.Z3.Sharp.pc``) is also installed which allows the
 | 
			
		||||
[MonoDevelop](http://www.monodevelop.com/) IDE to find the bindings. Running
 | 
			
		||||
``make uninstall`` will remove the dll from the GAC and the pkg-config file.
 | 
			
		||||
``make uninstall`` will remove the dll from the GAC and the ``pkg-config`` file.
 | 
			
		||||
 | 
			
		||||
See [``examples/dotnet``](examples/dotnet) for examples.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -170,8 +170,8 @@ If you do need to install to a non standard prefix a better approach is to use
 | 
			
		|||
a [Python virtual environment](https://virtualenv.readthedocs.org/en/latest/)
 | 
			
		||||
and install Z3 there. Python packages also work for Python3.
 | 
			
		||||
Under Windows, recall to build inside the Visual C++ native command build environment.
 | 
			
		||||
Note that the buit/python/z3 directory should be accessible from where python is used with Z3 
 | 
			
		||||
and it depends on libz3.dll to be in the path.
 | 
			
		||||
Note that the ``build/python/z3`` directory should be accessible from where python is used with Z3 
 | 
			
		||||
and it depends on ``libz3.dll`` to be in the path.
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
virtualenv venv
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,6 +30,7 @@ RUN apt-get update && \
 | 
			
		|||
        libgomp1 \
 | 
			
		||||
        libomp5 \
 | 
			
		||||
        libomp-dev \
 | 
			
		||||
        llvm-3.9 \
 | 
			
		||||
        make \
 | 
			
		||||
        mono-devel \
 | 
			
		||||
        ninja-build \
 | 
			
		||||
| 
						 | 
				
			
			@ -47,4 +48,4 @@ RUN useradd -m user && \
 | 
			
		|||
    echo 'user  ALL=(root) NOPASSWD: ALL' >> /etc/sudoers
 | 
			
		||||
USER user
 | 
			
		||||
WORKDIR /home/user
 | 
			
		||||
 | 
			
		||||
ENV ASAN_SYMBOLIZER_PATH=/usr/lib/llvm-3.9/bin/llvm-symbolizer
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,6 +16,7 @@ RUN apt-get update && \
 | 
			
		|||
        libgmp-dev \
 | 
			
		||||
        libgomp1 \
 | 
			
		||||
        lib32gomp1 \
 | 
			
		||||
        llvm-3.9 \
 | 
			
		||||
        make \
 | 
			
		||||
        mono-devel \
 | 
			
		||||
        ninja-build \
 | 
			
		||||
| 
						 | 
				
			
			@ -32,4 +33,4 @@ RUN useradd -m user && \
 | 
			
		|||
    echo 'user  ALL=(root) NOPASSWD: ALL' >> /etc/sudoers
 | 
			
		||||
USER user
 | 
			
		||||
WORKDIR /home/user
 | 
			
		||||
 | 
			
		||||
ENV ASAN_SYMBOLIZER_PATH=/usr/lib/llvm-3.9/bin/llvm-symbolizer
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,6 +18,7 @@ RUN apt-get update && \
 | 
			
		|||
        libgomp1 \
 | 
			
		||||
        libomp5 \
 | 
			
		||||
        libomp-dev \
 | 
			
		||||
        llvm-3.9 \
 | 
			
		||||
        make \
 | 
			
		||||
        mono-devel \
 | 
			
		||||
        ninja-build \
 | 
			
		||||
| 
						 | 
				
			
			@ -35,4 +36,4 @@ RUN useradd -m user && \
 | 
			
		|||
    echo 'user  ALL=(root) NOPASSWD: ALL' >> /etc/sudoers
 | 
			
		||||
USER user
 | 
			
		||||
WORKDIR /home/user
 | 
			
		||||
 | 
			
		||||
ENV ASAN_SYMBOLIZER_PATH=/usr/lib/llvm-3.9/bin/llvm-symbolizer
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,37 +2,40 @@ ARG DOCKER_IMAGE_BASE
 | 
			
		|||
FROM ${DOCKER_IMAGE_BASE}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Specify defaults. This can be changed when invoking
 | 
			
		||||
# Build arguments. This can be changed when invoking
 | 
			
		||||
# `docker build`.
 | 
			
		||||
ARG ASAN_BUILD=0
 | 
			
		||||
ARG BUILD_DOCS=0
 | 
			
		||||
ARG CC=gcc
 | 
			
		||||
ARG CXX=g++
 | 
			
		||||
ARG DOTNET_BINDINGS=1
 | 
			
		||||
ARG JAVA_BINDINGS=1
 | 
			
		||||
ARG NO_SUPPRESS_OUTPUT=0
 | 
			
		||||
ARG PYTHON_BINDINGS=1
 | 
			
		||||
ARG ASAN_BUILD
 | 
			
		||||
ARG ASAN_DSO
 | 
			
		||||
ARG BUILD_DOCS
 | 
			
		||||
ARG CC
 | 
			
		||||
ARG CXX
 | 
			
		||||
ARG DOTNET_BINDINGS
 | 
			
		||||
ARG JAVA_BINDINGS
 | 
			
		||||
ARG NO_SUPPRESS_OUTPUT
 | 
			
		||||
ARG PYTHON_BINDINGS
 | 
			
		||||
ARG PYTHON_EXECUTABLE=/usr/bin/python2.7
 | 
			
		||||
ARG RUN_SYSTEM_TESTS=1
 | 
			
		||||
ARG RUN_UNIT_TESTS=1
 | 
			
		||||
ARG TARGET_ARCH=x86_64
 | 
			
		||||
ARG TEST_INSTALL=1
 | 
			
		||||
ARG UBSAN_BUILD=0
 | 
			
		||||
ARG USE_LIBGMP=0
 | 
			
		||||
ARG USE_LTO=0
 | 
			
		||||
ARG USE_OPENMP=1
 | 
			
		||||
ARG RUN_API_EXAMPLES
 | 
			
		||||
ARG RUN_SYSTEM_TESTS
 | 
			
		||||
ARG RUN_UNIT_TESTS
 | 
			
		||||
ARG SANITIZER_PRINT_SUPPRESSIONS
 | 
			
		||||
ARG TARGET_ARCH
 | 
			
		||||
ARG TEST_INSTALL
 | 
			
		||||
ARG UBSAN_BUILD
 | 
			
		||||
ARG USE_LIBGMP
 | 
			
		||||
ARG USE_LTO
 | 
			
		||||
ARG USE_OPENMP
 | 
			
		||||
ARG Z3_SRC_DIR=/home/user/z3_src
 | 
			
		||||
ARG Z3_BUILD_TYPE=RelWithDebInfo
 | 
			
		||||
ARG Z3_CMAKE_GENERATOR=Ninja
 | 
			
		||||
ARG Z3_INSTALL_PREFIX=/usr
 | 
			
		||||
ARG Z3_STATIC_BUILD=0
 | 
			
		||||
# Blank default indicates use latest.
 | 
			
		||||
ARG Z3_BUILD_TYPE
 | 
			
		||||
ARG Z3_CMAKE_GENERATOR
 | 
			
		||||
ARG Z3_INSTALL_PREFIX
 | 
			
		||||
ARG Z3_STATIC_BUILD
 | 
			
		||||
ARG Z3_SYSTEM_TEST_GIT_REVISION
 | 
			
		||||
ARG Z3_WARNINGS_AS_ERRORS=SERIOUS_ONLY
 | 
			
		||||
ARG Z3_VERBOSE_BUILD_OUTPUT=0
 | 
			
		||||
ARG Z3_WARNINGS_AS_ERRORS
 | 
			
		||||
ARG Z3_VERBOSE_BUILD_OUTPUT
 | 
			
		||||
 | 
			
		||||
ENV \
 | 
			
		||||
  ASAN_BUILD=${ASAN_BUILD} \
 | 
			
		||||
  ASAN_DSO=${ASAN_DSO} \
 | 
			
		||||
  BUILD_DOCS=${BUILD_DOCS} \
 | 
			
		||||
  CC=${CC} \
 | 
			
		||||
  CXX=${CXX} \
 | 
			
		||||
| 
						 | 
				
			
			@ -41,6 +44,8 @@ ENV \
 | 
			
		|||
  NO_SUPPRESS_OUTPUT=${NO_SUPPRESS_OUTPUT} \
 | 
			
		||||
  PYTHON_BINDINGS=${PYTHON_BINDINGS} \
 | 
			
		||||
  PYTHON_EXECUTABLE=${PYTHON_EXECUTABLE} \
 | 
			
		||||
  SANITIZER_PRINT_SUPPRESSIONS=${SANITIZER_PRINT_SUPPRESSIONS} \
 | 
			
		||||
  RUN_API_EXAMPLES=${RUN_API_EXAMPLES} \
 | 
			
		||||
  RUN_SYSTEM_TESTS=${RUN_SYSTEM_TESTS} \
 | 
			
		||||
  RUN_UNIT_TESTS=${RUN_UNIT_TESTS} \
 | 
			
		||||
  TARGET_ARCH=${TARGET_ARCH} \
 | 
			
		||||
| 
						 | 
				
			
			@ -51,6 +56,7 @@ ENV \
 | 
			
		|||
  USE_OPENMP=${USE_OPENMP} \
 | 
			
		||||
  Z3_SRC_DIR=${Z3_SRC_DIR} \
 | 
			
		||||
  Z3_BUILD_DIR=/home/user/z3_build \
 | 
			
		||||
  Z3_BUILD_TYPE=${Z3_BUILD_TYPE} \
 | 
			
		||||
  Z3_CMAKE_GENERATOR=${Z3_CMAKE_GENERATOR} \
 | 
			
		||||
  Z3_VERBOSE_BUILD_OUTPUT=${Z3_VERBOSE_BUILD_OUTPUT} \
 | 
			
		||||
  Z3_STATIC_BUILD=${Z3_STATIC_BUILD} \
 | 
			
		||||
| 
						 | 
				
			
			@ -63,7 +69,8 @@ ENV \
 | 
			
		|||
 | 
			
		||||
# Build Z3
 | 
			
		||||
RUN mkdir -p "${Z3_SRC_DIR}" && \
 | 
			
		||||
  mkdir -p "${Z3_SRC_DIR}/contrib/ci/scripts"
 | 
			
		||||
  mkdir -p "${Z3_SRC_DIR}/contrib/ci/scripts" && \
 | 
			
		||||
  mkdir -p "${Z3_SRC_DIR}/contrib/suppressions/sanitizers"
 | 
			
		||||
# Deliberately leave out `contrib`
 | 
			
		||||
ADD /cmake ${Z3_SRC_DIR}/cmake/
 | 
			
		||||
ADD /doc ${Z3_SRC_DIR}/doc/
 | 
			
		||||
| 
						 | 
				
			
			@ -74,6 +81,7 @@ ADD *.txt *.md RELEASE_NOTES ${Z3_SRC_DIR}/
 | 
			
		|||
 | 
			
		||||
ADD \
 | 
			
		||||
  /contrib/ci/scripts/build_z3_cmake.sh \
 | 
			
		||||
  /contrib/ci/scripts/ci_defaults.sh \
 | 
			
		||||
  /contrib/ci/scripts/set_compiler_flags.sh \
 | 
			
		||||
  /contrib/ci/scripts/set_generator_args.sh \
 | 
			
		||||
  ${Z3_SRC_DIR}/contrib/ci/scripts/
 | 
			
		||||
| 
						 | 
				
			
			@ -89,7 +97,13 @@ RUN ${Z3_SRC_DIR}/contrib/ci/scripts/test_z3_docs.sh
 | 
			
		|||
# Test examples
 | 
			
		||||
ADD \
 | 
			
		||||
  /contrib/ci/scripts/test_z3_examples_cmake.sh \
 | 
			
		||||
  /contrib/ci/scripts/sanitizer_env.sh \
 | 
			
		||||
  ${Z3_SRC_DIR}/contrib/ci/scripts/
 | 
			
		||||
ADD \
 | 
			
		||||
  /contrib/suppressions/sanitizers/asan.txt \
 | 
			
		||||
  /contrib/suppressions/sanitizers/lsan.txt \
 | 
			
		||||
  /contrib/suppressions/sanitizers/ubsan.txt \
 | 
			
		||||
  ${Z3_SRC_DIR}/contrib/suppressions/sanitizers/
 | 
			
		||||
RUN ${Z3_SRC_DIR}/contrib/ci/scripts/test_z3_examples_cmake.sh
 | 
			
		||||
 | 
			
		||||
# Run unit tests
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,8 +30,10 @@ the future.
 | 
			
		|||
* `JAVA_BINDINGS` - Build and test Java API bindings (`0` or `1`)
 | 
			
		||||
* `NO_SUPPRESS_OUTPUT` - Don't suppress output of some commands (`0` or `1`)
 | 
			
		||||
* `PYTHON_BINDINGS` - Build and test Python API bindings (`0` or `1`)
 | 
			
		||||
* `RUN_API_EXAMPLES` - Build and run API examples (`0` or `1`)
 | 
			
		||||
* `RUN_SYSTEM_TESTS` - Run system tests (`0` or `1`)
 | 
			
		||||
* `RUN_UNIT_TESTS` - Run unit tests (`0` or `1`)
 | 
			
		||||
* `RUN_UNIT_TESTS` - Run unit tests (`BUILD_ONLY` or `BUILD_AND_RUN` or `SKIP`)
 | 
			
		||||
* `SANITIZER_PRINT_SUPPRESSIONS` - Show ASan/UBSan suppressions (`0` or `1`)
 | 
			
		||||
* `TARGET_ARCH` - Target architecture (`x86_64` or `i686`)
 | 
			
		||||
* `TEST_INSTALL` - Test running `install` target (`0` or `1`)
 | 
			
		||||
* `UBSAN_BUILD` - Do [UndefinedBehaviourSanitizer](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html) build (`0` or `1`)
 | 
			
		||||
| 
						 | 
				
			
			@ -58,8 +60,9 @@ The `scripts/travis_ci_linux_entry_point.sh` script
 | 
			
		|||
   variables (if set) into the build using the `--build-arg` argument of the `docker run`
 | 
			
		||||
   command.
 | 
			
		||||
 | 
			
		||||
If an environemnt variable is not set a defaults value is used which can be
 | 
			
		||||
found in `Dockerfiles/z3_build.Dockerfile`.
 | 
			
		||||
The default values of the configuration environment variables
 | 
			
		||||
can be found in
 | 
			
		||||
[`scripts/ci_defaults.sh`](scripts/ci_defaults.sh).
 | 
			
		||||
 | 
			
		||||
#### Linux specific configuration variables
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -67,8 +70,9 @@ found in `Dockerfiles/z3_build.Dockerfile`.
 | 
			
		|||
 | 
			
		||||
#### Reproducing a build locally
 | 
			
		||||
 | 
			
		||||
A build can be reproduced locally by using the `scripts/travis_ci_linux_entry_point.sh`
 | 
			
		||||
script and setting the appropriate environment variable.
 | 
			
		||||
A build can be reproduced locally by using the
 | 
			
		||||
`scripts/travis_ci_linux_entry_point.sh` script and setting the appropriate
 | 
			
		||||
environment variable.
 | 
			
		||||
 | 
			
		||||
For example lets say we wanted to reproduce the build below.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -104,11 +108,43 @@ feature might be removed in the future.
 | 
			
		|||
 | 
			
		||||
It may be better to just build the base image once (outside of TravisCI), upload
 | 
			
		||||
it to [DockerHub](https://hub.docker.com/) and have the build pull down the pre-built
 | 
			
		||||
image everytime.
 | 
			
		||||
image every time.
 | 
			
		||||
 | 
			
		||||
An [organization](https://hub.docker.com/u/z3prover/) has been created on
 | 
			
		||||
DockerHub for this.
 | 
			
		||||
 | 
			
		||||
### macOS
 | 
			
		||||
 | 
			
		||||
Not yet implemented.
 | 
			
		||||
For macOS we execute directly on TravisCI's macOS environment.  The entry point
 | 
			
		||||
for the TravisCI builds is the
 | 
			
		||||
[`scripts/travis_ci_osx_entry_point.sh`](scripts/travis_ci_osx_entry_point.sh)
 | 
			
		||||
scripts.
 | 
			
		||||
 | 
			
		||||
#### macOS specific configuration variables
 | 
			
		||||
 | 
			
		||||
* `MACOS_SKIP_DEPS_UPDATE` - If set to `1` installing the necessary build dependencies
 | 
			
		||||
  is skipped. This is useful for local testing if the dependencies are already installed.
 | 
			
		||||
* `MACOS_UPDATE_CMAKE` - If set to `1` the installed version of CMake will be upgraded.
 | 
			
		||||
 | 
			
		||||
#### Reproducing a build locally
 | 
			
		||||
 | 
			
		||||
To reproduce a build (e.g. like the one shown below)
 | 
			
		||||
 | 
			
		||||
```yaml
 | 
			
		||||
- os: osx
 | 
			
		||||
  osx_image: xcode8.3
 | 
			
		||||
  # Note: Apple Clang does not support OpenMP
 | 
			
		||||
  env: Z3_BUILD_TYPE=RelWithDebInfo USE_OPENMP=0
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Run the following:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
TRAVIS_BUILD_DIR=$(pwd) \
 | 
			
		||||
Z3_BUILD_TYPE=RelWithDebInfo \
 | 
			
		||||
USE_OPEN_MP=0 \
 | 
			
		||||
contrib/ci/scripts/travis_ci_osx_entry_point.sh
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Note this assumes that the current working directory is the root of the Z3
 | 
			
		||||
git repository.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,6 +22,7 @@ set -o pipefail
 | 
			
		|||
: ${USE_LTO?"USE_LTO must be specified"}
 | 
			
		||||
: ${Z3_INSTALL_PREFIX?"Z3_INSTALL_PREFIX must be specified"}
 | 
			
		||||
: ${Z3_WARNINGS_AS_ERRORS?"Z3_WARNINGS_AS_ERRORS must be specified"}
 | 
			
		||||
: ${UBSAN_BUILD?"UBSAN_BUILD must be specified"}
 | 
			
		||||
 | 
			
		||||
ADDITIONAL_Z3_OPTS=()
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -105,6 +106,16 @@ fi
 | 
			
		|||
# Set compiler flags
 | 
			
		||||
source ${SCRIPT_DIR}/set_compiler_flags.sh
 | 
			
		||||
 | 
			
		||||
if [ "X${UBSAN_BUILD}" = "X1" ]; then
 | 
			
		||||
  # HACK: When building with UBSan the C++ linker
 | 
			
		||||
  # must be used to avoid the following linker errors.
 | 
			
		||||
  # undefined reference to `__ubsan_vptr_type_cache'
 | 
			
		||||
  # undefined reference to `__ubsan_handle_dynamic_type_cache_miss'
 | 
			
		||||
  ADDITIONAL_Z3_OPTS+=( \
 | 
			
		||||
    '-DZ3_C_EXAMPLES_FORCE_CXX_LINKER=ON' \
 | 
			
		||||
  )
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# Sanity check
 | 
			
		||||
if [ ! -e "${Z3_SRC_DIR}/CMakeLists.txt" ]; then
 | 
			
		||||
  echo "Z3_SRC_DIR is invalid"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										60
									
								
								contrib/ci/scripts/ci_defaults.sh
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								contrib/ci/scripts/ci_defaults.sh
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,60 @@
 | 
			
		|||
# This file should be sourced by other scripts
 | 
			
		||||
# and not executed directly
 | 
			
		||||
 | 
			
		||||
# Set CI build defaults
 | 
			
		||||
 | 
			
		||||
export ASAN_BUILD="${ASAN_BUILD:-0}"
 | 
			
		||||
export BUILD_DOCS="${BUILD_DOCS:-0}"
 | 
			
		||||
export DOTNET_BINDINGS="${DOTNET_BINDINGS:-1}"
 | 
			
		||||
export JAVA_BINDINGS="${JAVA_BINDINGS:-1}"
 | 
			
		||||
export NO_SUPPRESS_OUTPUT="${NO_SUPPRESS_OUTPUT:-0}"
 | 
			
		||||
export PYTHON_BINDINGS="${PYTHON_BINDINGS:-1}"
 | 
			
		||||
export RUN_API_EXAMPLES="${RUN_API_EXAMPLES:-1}"
 | 
			
		||||
export RUN_SYSTEM_TESTS="${RUN_SYSTEM_TESTS:-1}"
 | 
			
		||||
export RUN_UNIT_TESTS="${RUN_UNIT_TESTS:-BUILD_AND_RUN}"
 | 
			
		||||
# Don't print suppressions by default because that breaks the Z3
 | 
			
		||||
# regression tests because they don't expect them to appear in Z3's
 | 
			
		||||
# output.
 | 
			
		||||
export SANITIZER_PRINT_SUPPRESSIONS="${SANITIZER_PRINT_SUPPRESSIONS:-0}"
 | 
			
		||||
export TARGET_ARCH="${TARGET_ARCH:-x86_64}"
 | 
			
		||||
export TEST_INSTALL="${TEST_INSTALL:-1}"
 | 
			
		||||
export UBSAN_BUILD="${UBSAN_BUILD:-0}"
 | 
			
		||||
export USE_LIBGMP="${USE_LIBGMP:-0}"
 | 
			
		||||
export USE_LTO="${USE_LTO:-0}"
 | 
			
		||||
export USE_OPENMP="${USE_OPENMP:-1}"
 | 
			
		||||
 | 
			
		||||
export Z3_BUILD_TYPE="${Z3_BUILD_TYPE:-RelWithDebInfo}"
 | 
			
		||||
export Z3_CMAKE_GENERATOR="${Z3_CMAKE_GENERATOR:-Ninja}"
 | 
			
		||||
export Z3_STATIC_BUILD="${Z3_STATIC_BUILD:-0}"
 | 
			
		||||
# Default is blank which means get latest revision
 | 
			
		||||
export Z3_SYSTEM_TEST_GIT_REVISION="${Z3_SYSTEM_TEST_GIT_REVISION:-}"
 | 
			
		||||
export Z3_WARNINGS_AS_ERRORS="${Z3_WARNINGS_AS_ERRORS:-SERIOUS_ONLY}"
 | 
			
		||||
export Z3_VERBOSE_BUILD_OUTPUT="${Z3_VERBOSE_BUILD_OUTPUT:-0}"
 | 
			
		||||
 | 
			
		||||
# Platform specific defaults
 | 
			
		||||
PLATFORM="$(uname -s)"
 | 
			
		||||
case "${PLATFORM}" in
 | 
			
		||||
  Linux*)
 | 
			
		||||
    export C_COMPILER="${C_COMPILER:-gcc}"
 | 
			
		||||
    export CXX_COMPILER="${CXX_COMPILER:-g++}"
 | 
			
		||||
    export Z3_INSTALL_PREFIX="${Z3_INSTALL_PREFIX:-/usr}"
 | 
			
		||||
  ;;
 | 
			
		||||
  Darwin*)
 | 
			
		||||
    export C_COMPILER="${C_COMPILER:-clang}"
 | 
			
		||||
    export CXX_COMPILER="${CXX_COMPILER:-clang++}"
 | 
			
		||||
    export Z3_INSTALL_PREFIX="${Z3_INSTALL_PREFIX:-/usr/local}"
 | 
			
		||||
  ;;
 | 
			
		||||
  *)
 | 
			
		||||
    echo "Unknown platform \"${PLATFORM}\""
 | 
			
		||||
    exit 1
 | 
			
		||||
  ;;
 | 
			
		||||
esac
 | 
			
		||||
unset PLATFORM
 | 
			
		||||
 | 
			
		||||
# NOTE: The following variables are not set here because
 | 
			
		||||
# they are specific to the CI implementation
 | 
			
		||||
# PYTHON_EXECUTABLE
 | 
			
		||||
# ASAN_DSO
 | 
			
		||||
# Z3_SRC_DIR
 | 
			
		||||
# Z3_BUILD_DIR
 | 
			
		||||
# Z3_SYSTEM_TEST_DIR
 | 
			
		||||
| 
						 | 
				
			
			@ -34,8 +34,8 @@ function run_quiet() {
 | 
			
		|||
    fi
 | 
			
		||||
    # Clean up
 | 
			
		||||
    rm "${STDOUT}" "${STDERR}"
 | 
			
		||||
    [ $( echo "${OLD_SETTINGS}" | grep -c 'e') -ne 0 ] && set -e
 | 
			
		||||
    [ $( echo "${OLD_SETTINGS}" | grep -c 'x') -ne 0 ] && set -x
 | 
			
		||||
    [ "$( echo "${OLD_SETTINGS}" | grep -c 'e')" != "0" ] && set -e
 | 
			
		||||
    [ "$( echo "${OLD_SETTINGS}" | grep -c 'x')" != "0" ] && set -x
 | 
			
		||||
    return ${EXIT_STATUS}
 | 
			
		||||
  fi
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										82
									
								
								contrib/ci/scripts/sanitizer_env.sh
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								contrib/ci/scripts/sanitizer_env.sh
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,82 @@
 | 
			
		|||
# This script is intended to be included by other
 | 
			
		||||
# scripts and should not be executed directly
 | 
			
		||||
 | 
			
		||||
: ${Z3_SRC_DIR?"Z3_SRC_DIR must be specified"}
 | 
			
		||||
: ${ASAN_BUILD?"ASAN_BUILD must be specified"}
 | 
			
		||||
: ${UBSAN_BUILD?"UBSAN_BUILD must be specified"}
 | 
			
		||||
 | 
			
		||||
if [ "X${ASAN_BUILD}" = "X1" ]; then
 | 
			
		||||
  # Use suppression files
 | 
			
		||||
  export LSAN_OPTIONS="suppressions=${Z3_SRC_DIR}/contrib/suppressions/sanitizers/lsan.txt"
 | 
			
		||||
  # NOTE: If you get bad stacktraces try using `fast_unwind_on_malloc=0`
 | 
			
		||||
  # NOTE: `malloc_context_size` controls size of recorded stacktrace for allocations.
 | 
			
		||||
  #       If the reported stacktraces appear incomplete try increasing the value.
 | 
			
		||||
  export ASAN_OPTIONS="malloc_context_size=100,suppressions=${Z3_SRC_DIR}/contrib/suppressions/sanitizers/asan.txt"
 | 
			
		||||
 | 
			
		||||
  : ${SANITIZER_PRINT_SUPPRESSIONS?"SANITIZER_PRINT_SUPPRESSIONS must be specified"}
 | 
			
		||||
  if [ "X${SANITIZER_PRINT_SUPPRESSIONS}" = "X1" ]; then
 | 
			
		||||
    export LSAN_OPTIONS="${LSAN_OPTIONS},print_suppressions=1"
 | 
			
		||||
    export ASAN_OPTIONS="${ASAN_OPTIONS},print_suppressions=1"
 | 
			
		||||
  else
 | 
			
		||||
    export LSAN_OPTIONS="${LSAN_OPTIONS},print_suppressions=0"
 | 
			
		||||
    export ASAN_OPTIONS="${ASAN_OPTIONS},print_suppressions=0"
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  : ${ASAN_SYMBOLIZER_PATH?"ASAN_SYMBOLIZER_PATH must be specified"}
 | 
			
		||||
 | 
			
		||||
  # Run command without checking for leaks
 | 
			
		||||
  function run_no_lsan() {
 | 
			
		||||
    ASAN_OPTIONS="${ASAN_OPTIONS},detect_leaks=0" "${@}"
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  # Check path to ASan DSO
 | 
			
		||||
  : ${ASAN_DSO?"ASAN_DSO must be specified"}
 | 
			
		||||
  if [ ! -e "${ASAN_DSO}" ]; then
 | 
			
		||||
    echo "ASAN_DSO (${ASAN_DSO}) does not exist"
 | 
			
		||||
    exit 1
 | 
			
		||||
  fi
 | 
			
		||||
  # FIXME: We'll need to refactor this when we can do UBSan builds
 | 
			
		||||
  # against a UBSan DSO.
 | 
			
		||||
  function run_non_native_binding() {
 | 
			
		||||
    # We need to preload the ASan DSO that libz3
 | 
			
		||||
    # will have undefined references to.
 | 
			
		||||
    # Don't run leak checking because we get lots reported leaks
 | 
			
		||||
    # in the language runtime (e.g. python).
 | 
			
		||||
    PLATFORM="$(uname -s)"
 | 
			
		||||
    case "${PLATFORM}" in
 | 
			
		||||
      Linux*)
 | 
			
		||||
        LD_PRELOAD="${ASAN_DSO}" run_no_lsan "${@}"
 | 
			
		||||
      ;;
 | 
			
		||||
      Darwin*)
 | 
			
		||||
        DYLD_INSERT_LIBRARIES="${ASAN_DSO}" run_no_lsan "${@}"
 | 
			
		||||
      ;;
 | 
			
		||||
      *)
 | 
			
		||||
        echo "Unknown platform \"${PLATFORM}\""
 | 
			
		||||
        exit 1
 | 
			
		||||
      ;;
 | 
			
		||||
    esac
 | 
			
		||||
    unset PLATFORM
 | 
			
		||||
  }
 | 
			
		||||
else
 | 
			
		||||
  # In non-ASan build just run directly
 | 
			
		||||
  function run_no_lsan() {
 | 
			
		||||
    "${@}"
 | 
			
		||||
  }
 | 
			
		||||
  function run_non_native_binding() {
 | 
			
		||||
    "${@}"
 | 
			
		||||
  }
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if [ "X${UBSAN_BUILD}" = "X1" ]; then
 | 
			
		||||
  # `halt_on_error=1,abort_on_error=1` means that on the first UBSan error
 | 
			
		||||
  # the program will terminate by calling `abort(). Without this UBSan will
 | 
			
		||||
  # allow execution to continue. We also use a suppression file.
 | 
			
		||||
  export UBSAN_OPTIONS="halt_on_error=1,abort_on_error=1,suppressions=${Z3_SRC_DIR}/contrib/suppressions/sanitizers/ubsan.txt"
 | 
			
		||||
 | 
			
		||||
  : ${SANITIZER_PRINT_SUPPRESSIONS?"SANITIZER_PRINT_SUPPRESSIONS must be specified"}
 | 
			
		||||
  if [ "X${SANITIZER_PRINT_SUPPRESSIONS}" = "X1" ]; then
 | 
			
		||||
    export UBSAN_OPTIONS="${UBSAN_OPTIONS},print_suppressions=1"
 | 
			
		||||
  else
 | 
			
		||||
    export UBSAN_OPTIONS="${UBSAN_OPTIONS},print_suppressions=0"
 | 
			
		||||
  fi
 | 
			
		||||
fi
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
# This script should is intended to be included by other
 | 
			
		||||
# This script is intended to be included by other
 | 
			
		||||
# scripts and should not be executed directly
 | 
			
		||||
 | 
			
		||||
: ${Z3_CMAKE_GENERATOR?"Z3_CMAKE_GENERATOR must be specified"}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,6 +14,13 @@ set -o pipefail
 | 
			
		|||
: ${PYTHON_EXECUTABLE?"PYTHON_EXECUTABLE must be specified"}
 | 
			
		||||
: ${DOTNET_BINDINGS?"DOTNET_BINDINGS must be specified"}
 | 
			
		||||
: ${JAVA_BINDINGS?"JAVA_BINDINGS must be specified"}
 | 
			
		||||
: ${UBSAN_BUILD?"UBSAN_BUILD must be specified"}
 | 
			
		||||
: ${RUN_API_EXAMPLES?"RUN_API_EXAMPLES must be specified"}
 | 
			
		||||
 | 
			
		||||
if [ "X${RUN_API_EXAMPLES}" = "X0" ]; then
 | 
			
		||||
  echo "Skipping run of API examples"
 | 
			
		||||
  exit 0
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# Set compiler flags
 | 
			
		||||
source ${SCRIPT_DIR}/set_compiler_flags.sh
 | 
			
		||||
| 
						 | 
				
			
			@ -21,6 +28,9 @@ source ${SCRIPT_DIR}/set_compiler_flags.sh
 | 
			
		|||
# Set CMake generator args
 | 
			
		||||
source ${SCRIPT_DIR}/set_generator_args.sh
 | 
			
		||||
 | 
			
		||||
# Sanitizer environment variables
 | 
			
		||||
source ${SCRIPT_DIR}/sanitizer_env.sh
 | 
			
		||||
 | 
			
		||||
cd "${Z3_BUILD_DIR}"
 | 
			
		||||
 | 
			
		||||
# Build and run C example
 | 
			
		||||
| 
						 | 
				
			
			@ -38,9 +48,21 @@ run_quiet examples/tptp_build_dir/z3_tptp5 -help
 | 
			
		|||
 | 
			
		||||
# Build an run c_maxsat_example
 | 
			
		||||
cmake --build $(pwd) --target c_maxsat_example "${GENERATOR_ARGS[@]}"
 | 
			
		||||
run_quiet \
 | 
			
		||||
  examples/c_maxsat_example_build_dir/c_maxsat_example \
 | 
			
		||||
  ${Z3_SRC_DIR}/examples/maxsat/ex.smt
 | 
			
		||||
# FIXME: It is known that the maxsat example leaks memory and the
 | 
			
		||||
# the Z3 developers have stated this is "wontfix".
 | 
			
		||||
# See https://github.com/Z3Prover/z3/issues/1299
 | 
			
		||||
run_no_lsan \
 | 
			
		||||
  run_quiet \
 | 
			
		||||
    examples/c_maxsat_example_build_dir/c_maxsat_example \
 | 
			
		||||
    ${Z3_SRC_DIR}/examples/maxsat/ex.smt
 | 
			
		||||
 | 
			
		||||
if [ "X${UBSAN_BUILD}" = "X1" ]; then
 | 
			
		||||
  # FIXME: We really need libz3 to link against a shared UBSan runtime.
 | 
			
		||||
  # Right now we link against the static runtime which breaks all the
 | 
			
		||||
  # non-native language bindings.
 | 
			
		||||
  echo "FIXME: Can't run other examples when building with UBSan"
 | 
			
		||||
  exit 0
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if [ "X${PYTHON_BINDINGS}" = "X1" ]; then
 | 
			
		||||
| 
						 | 
				
			
			@ -48,16 +70,21 @@ if [ "X${PYTHON_BINDINGS}" = "X1" ]; then
 | 
			
		|||
  # `all_interval_series.py` produces a lot of output so just throw
 | 
			
		||||
  # away output.
 | 
			
		||||
  # TODO: This example is slow should we remove it from testing?
 | 
			
		||||
  run_quiet ${PYTHON_EXECUTABLE} python/all_interval_series.py
 | 
			
		||||
  run_quiet ${PYTHON_EXECUTABLE} python/complex.py
 | 
			
		||||
  run_quiet ${PYTHON_EXECUTABLE} python/example.py
 | 
			
		||||
  if [ "X${ASAN_BUILD}" = "X1" -a "X${Z3_BUILD_TYPE}" = "XDebug" ]; then
 | 
			
		||||
    # Too slow when doing ASan Debug build
 | 
			
		||||
    echo "Skipping all_interval_series.py under ASan Debug build"
 | 
			
		||||
  else
 | 
			
		||||
    run_quiet run_non_native_binding ${PYTHON_EXECUTABLE} python/all_interval_series.py
 | 
			
		||||
  fi
 | 
			
		||||
  run_quiet run_non_native_binding ${PYTHON_EXECUTABLE} python/complex.py
 | 
			
		||||
  run_quiet run_non_native_binding ${PYTHON_EXECUTABLE} python/example.py
 | 
			
		||||
  # FIXME: `hamiltonian.py` example is disabled because its too slow.
 | 
			
		||||
  #${PYTHON_EXECUTABLE} python/hamiltonian.py
 | 
			
		||||
  run_quiet ${PYTHON_EXECUTABLE} python/marco.py
 | 
			
		||||
  run_quiet ${PYTHON_EXECUTABLE} python/mss.py
 | 
			
		||||
  run_quiet ${PYTHON_EXECUTABLE} python/socrates.py
 | 
			
		||||
  run_quiet ${PYTHON_EXECUTABLE} python/visitor.py
 | 
			
		||||
  run_quiet ${PYTHON_EXECUTABLE} python/z3test.py
 | 
			
		||||
  run_quiet run_non_native_binding ${PYTHON_EXECUTABLE} python/marco.py
 | 
			
		||||
  run_quiet run_non_native_binding ${PYTHON_EXECUTABLE} python/mss.py
 | 
			
		||||
  run_quiet run_non_native_binding ${PYTHON_EXECUTABLE} python/socrates.py
 | 
			
		||||
  run_quiet run_non_native_binding ${PYTHON_EXECUTABLE} python/visitor.py
 | 
			
		||||
  run_quiet run_non_native_binding ${PYTHON_EXECUTABLE} python/z3test.py
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if [ "X${DOTNET_BINDINGS}" = "X1" ]; then
 | 
			
		||||
| 
						 | 
				
			
			@ -65,7 +92,7 @@ if [ "X${DOTNET_BINDINGS}" = "X1" ]; then
 | 
			
		|||
  # FIXME: Move compliation step into CMake target
 | 
			
		||||
  mcs ${Z3_SRC_DIR}/examples/dotnet/Program.cs /target:exe /out:dotnet_test.exe /reference:Microsoft.Z3.dll /r:System.Numerics.dll
 | 
			
		||||
  # Run .NET example
 | 
			
		||||
  run_quiet mono ./dotnet_test.exe
 | 
			
		||||
  run_quiet run_non_native_binding mono ./dotnet_test.exe
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if [ "X${JAVA_BINDINGS}" = "X1" ]; then
 | 
			
		||||
| 
						 | 
				
			
			@ -82,6 +109,14 @@ if [ "X${JAVA_BINDINGS}" = "X1" ]; then
 | 
			
		|||
    # Assume Linux for now
 | 
			
		||||
    export LD_LIBRARY_PATH=$(pwd):${LD_LIBRARY_PATH}
 | 
			
		||||
  fi
 | 
			
		||||
  run_quiet java -cp .:examples/java:com.microsoft.z3.jar JavaExample
 | 
			
		||||
  if [ "X${ASAN_BUILD}" = "X1" ]; then
 | 
			
		||||
    # The JVM seems to crash (SEGV) if we pre-load ASan
 | 
			
		||||
    # so don't run it for now.
 | 
			
		||||
    echo "Skipping JavaExample under ASan build"
 | 
			
		||||
  else
 | 
			
		||||
    run_quiet \
 | 
			
		||||
      run_non_native_binding \
 | 
			
		||||
        java -cp .:examples/java:com.microsoft.z3.jar JavaExample
 | 
			
		||||
  fi
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,12 +10,17 @@ set -o pipefail
 | 
			
		|||
: ${PYTHON_BINDINGS?"PYTHON_BINDINGS must be specified"}
 | 
			
		||||
: ${PYTHON_EXECUTABLE?"PYTHON_EXECUTABLE must be specified"}
 | 
			
		||||
: ${Z3_SYSTEM_TEST_DIR?"Z3_SYSTEM_TEST_DIR must be specified"}
 | 
			
		||||
: ${UBSAN_BUILD?"UBSAN_BUILD must be specified"}
 | 
			
		||||
 | 
			
		||||
if [ "X${RUN_SYSTEM_TESTS}" != "X1" ]; then
 | 
			
		||||
  echo "Skipping system tests"
 | 
			
		||||
  exit 0
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# Sanitizer environment variables
 | 
			
		||||
SCRIPT_DIR="$( cd ${BASH_SOURCE[0]%/*} ; echo $PWD )"
 | 
			
		||||
source ${SCRIPT_DIR}/sanitizer_env.sh
 | 
			
		||||
 | 
			
		||||
Z3_EXE="${Z3_BUILD_DIR}/z3"
 | 
			
		||||
Z3_LIB_DIR="${Z3_BUILD_DIR}"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -23,7 +28,7 @@ Z3_LIB_DIR="${Z3_BUILD_DIR}"
 | 
			
		|||
Z3_SYSTEM_TEST_GIT_URL="${Z3_GIT_URL:-https://github.com/Z3Prover/z3test.git}"
 | 
			
		||||
 | 
			
		||||
# Clone repo to destination
 | 
			
		||||
mkdir -p "${Z3_SYSTEM_TEST_GIT_URL}"
 | 
			
		||||
mkdir -p "${Z3_SYSTEM_TEST_DIR}"
 | 
			
		||||
git clone "${Z3_SYSTEM_TEST_GIT_URL}" "${Z3_SYSTEM_TEST_DIR}"
 | 
			
		||||
cd "${Z3_SYSTEM_TEST_DIR}"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -48,7 +53,18 @@ fi
 | 
			
		|||
 | 
			
		||||
if [ "X${PYTHON_BINDINGS}" = "X1" ]; then
 | 
			
		||||
  # Run python binding tests
 | 
			
		||||
  ${PYTHON_EXECUTABLE} scripts/test_pyscripts.py "${Z3_LIB_DIR}" regressions/python/
 | 
			
		||||
  if [ "X${UBSAN_BUILD}" = "X1" ]; then
 | 
			
		||||
    # FIXME: We need to build libz3 with a shared UBSan runtime for the bindings
 | 
			
		||||
    # to work.
 | 
			
		||||
    echo "FIXME: Skipping python binding tests when building with UBSan"
 | 
			
		||||
  elif [ "X${ASAN_BUILD}" = "X1" ]; then
 | 
			
		||||
    # FIXME: The `test_pyscripts.py` doesn't propagate LD_PRELOAD
 | 
			
		||||
    # so under ASan the tests fail to run
 | 
			
		||||
    # to work.
 | 
			
		||||
    echo "FIXME: Skipping python binding tests when building with ASan"
 | 
			
		||||
  else
 | 
			
		||||
    run_non_native_binding ${PYTHON_EXECUTABLE} scripts/test_pyscripts.py "${Z3_LIB_DIR}" regressions/python/
 | 
			
		||||
  fi
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# FIXME: Run `scripts/test_cs.py` once it has been modified to support mono
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,17 +10,38 @@ set -o pipefail
 | 
			
		|||
: ${Z3_BUILD_DIR?"Z3_BUILD_DIR must be specified"}
 | 
			
		||||
: ${RUN_UNIT_TESTS?"RUN_UNIT_TESTS must be specified"}
 | 
			
		||||
 | 
			
		||||
if [ "X${RUN_UNIT_TESTS}" != "X1" ]; then
 | 
			
		||||
  echo "Skipping unit tests"
 | 
			
		||||
  exit 0
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# Set CMake generator args
 | 
			
		||||
source ${SCRIPT_DIR}/set_generator_args.sh
 | 
			
		||||
 | 
			
		||||
# Sanitizer environment variables
 | 
			
		||||
source ${SCRIPT_DIR}/sanitizer_env.sh
 | 
			
		||||
 | 
			
		||||
cd "${Z3_BUILD_DIR}"
 | 
			
		||||
 | 
			
		||||
# Build and run internal tests
 | 
			
		||||
cmake --build $(pwd) --target test-z3 "${GENERATOR_ARGS[@]}"
 | 
			
		||||
# Run all tests that don't require arguments
 | 
			
		||||
run_quiet ./test-z3 /a
 | 
			
		||||
function build_unit_tests() {
 | 
			
		||||
  # Build internal tests
 | 
			
		||||
  cmake --build $(pwd) --target test-z3 "${GENERATOR_ARGS[@]}"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function run_unit_tests() {
 | 
			
		||||
  # Run all tests that don't require arguments
 | 
			
		||||
  run_quiet ./test-z3 /a
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
case "${RUN_UNIT_TESTS}" in
 | 
			
		||||
  BUILD_AND_RUN)
 | 
			
		||||
    build_unit_tests
 | 
			
		||||
    run_unit_tests
 | 
			
		||||
  ;;
 | 
			
		||||
  BUILD_ONLY)
 | 
			
		||||
    build_unit_tests
 | 
			
		||||
  ;;
 | 
			
		||||
  SKIP)
 | 
			
		||||
    echo "RUN_UNIT_TESTS set to \"${RUN_UNIT_TESTS}\" so skipping build and run"
 | 
			
		||||
    exit 0
 | 
			
		||||
  ;;
 | 
			
		||||
  *)
 | 
			
		||||
    echo "Error: RUN_UNIT_TESTS set to unhandled value \"${RUN_UNIT_TESTS}\""
 | 
			
		||||
    exit 1
 | 
			
		||||
  ;;
 | 
			
		||||
esac
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,16 +11,21 @@ DOCKER_FILE_DIR="$(cd ${SCRIPT_DIR}/../Dockerfiles; echo $PWD)"
 | 
			
		|||
: ${LINUX_BASE?"LINUX_BASE must be specified"}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Sanity check. Current working directory should be repo root
 | 
			
		||||
if [ ! -f "./README.md" ]; then
 | 
			
		||||
  echo "Current working directory should be repo root"
 | 
			
		||||
  exit 1
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# Get defaults
 | 
			
		||||
source "${SCRIPT_DIR}/ci_defaults.sh"
 | 
			
		||||
 | 
			
		||||
BUILD_OPTS=()
 | 
			
		||||
# Override options if they have been provided.
 | 
			
		||||
# Otherwise the defaults in the Docker file will be used
 | 
			
		||||
# Pass Docker build arguments
 | 
			
		||||
if [ -n "${Z3_BUILD_TYPE}" ]; then
 | 
			
		||||
  BUILD_OPTS+=("--build-arg" "Z3_BUILD_TYPE=${Z3_BUILD_TYPE}")
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if [ -n "${Z3_CMAKE_GENERATOR}" ]; then
 | 
			
		||||
  BUILD_OPTS+=("--build-arg" "Z3_CMAKE_GENERATOR=${Z3_CMAKE_GENERATOR}")
 | 
			
		||||
fi
 | 
			
		||||
| 
						 | 
				
			
			@ -79,6 +84,14 @@ if [ -n "${ASAN_BUILD}" ]; then
 | 
			
		|||
  BUILD_OPTS+=("--build-arg" "ASAN_BUILD=${ASAN_BUILD}")
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if [ -n "${ASAN_DSO}" ]; then
 | 
			
		||||
  BUILD_OPTS+=("--build-arg" "ASAN_DSO=${ASAN_DSO}")
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if [ -n "${SANITIZER_PRINT_SUPPRESSIONS}" ]; then
 | 
			
		||||
  BUILD_OPTS+=("--build-arg" "SANITIZER_PRINT_SUPPRESSIONS=${SANITIZER_PRINT_SUPPRESSIONS}")
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if [ -n "${UBSAN_BUILD}" ]; then
 | 
			
		||||
  BUILD_OPTS+=("--build-arg" "UBSAN_BUILD=${UBSAN_BUILD}")
 | 
			
		||||
fi
 | 
			
		||||
| 
						 | 
				
			
			@ -87,6 +100,10 @@ if [ -n "${TEST_INSTALL}" ]; then
 | 
			
		|||
  BUILD_OPTS+=("--build-arg" "TEST_INSTALL=${TEST_INSTALL}")
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if [ -n "${RUN_API_EXAMPLES}" ]; then
 | 
			
		||||
  BUILD_OPTS+=("--build-arg" "RUN_API_EXAMPLES=${RUN_API_EXAMPLES}")
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if [ -n "${RUN_SYSTEM_TESTS}" ]; then
 | 
			
		||||
  BUILD_OPTS+=("--build-arg" "RUN_SYSTEM_TESTS=${RUN_SYSTEM_TESTS}")
 | 
			
		||||
fi
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,26 +6,8 @@ set -x
 | 
			
		|||
set -e
 | 
			
		||||
set -o pipefail
 | 
			
		||||
 | 
			
		||||
# Set defaults
 | 
			
		||||
# FIXME: Refactor this so we don't need to stay in sync with
 | 
			
		||||
# `z3_build.Dockerfile`.
 | 
			
		||||
export ASAN_BUILD="${ASAN_BUILD:-0}"
 | 
			
		||||
export BUILD_DOCS="${BUILD_DOCS:-0}"
 | 
			
		||||
export C_COMPILER="${C_COMPILER:-clang}"
 | 
			
		||||
export CXX_COMPILER="${CXX_COMPILER:-clang++}"
 | 
			
		||||
export DOTNET_BINDINGS="${DOTNET_BINDINGS:-1}"
 | 
			
		||||
export JAVA_BINDINGS="${JAVA_BINDINGS:-1}"
 | 
			
		||||
export NO_SUPPRESS_OUTPUT="${NO_SUPPRESS_OUTPUT:-0}"
 | 
			
		||||
export PYTHON_BINDINGS="${PYTHON_BINDINGS:-1}"
 | 
			
		||||
export PYTHON_EXECUTABLE="$(which python)"
 | 
			
		||||
export RUN_SYSTEM_TESTS="${RUN_SYSTEM_TESTS:-1}"
 | 
			
		||||
export RUN_UNIT_TESTS="${RUN_UNIT_TESTS:-1}"
 | 
			
		||||
export TARGET_ARCH="${TARGET_ARCH:-x86_64}"
 | 
			
		||||
export TEST_INSTALL="${TEST_INSTALL:-1}"
 | 
			
		||||
export UBSAN_BUILD="${UBSAN_BUILD:-0}"
 | 
			
		||||
export USE_LIBGMP="${USE_LIBGMP:-0}"
 | 
			
		||||
export USE_LTO="${USE_LTO:-0}"
 | 
			
		||||
export USE_OPENMP="${USE_OPENMP:-1}"
 | 
			
		||||
# Get defaults
 | 
			
		||||
source "${SCRIPT_DIR}/ci_defaults.sh"
 | 
			
		||||
 | 
			
		||||
if [ -z "${TRAVIS_BUILD_DIR}" ]; then
 | 
			
		||||
  echo "TRAVIS_BUILD_DIR must be set to root of Z3 repository"
 | 
			
		||||
| 
						 | 
				
			
			@ -37,15 +19,12 @@ if [ ! -d "${TRAVIS_BUILD_DIR}" ]; then
 | 
			
		|||
  exit 1
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# These variables are specific to the macOS TravisCI
 | 
			
		||||
# implementation and are not set in `ci_defaults.sh`.
 | 
			
		||||
export PYTHON_EXECUTABLE="${PYTHON_EXECUTABLE:-$(which python)}"
 | 
			
		||||
export Z3_SRC_DIR="${TRAVIS_BUILD_DIR}"
 | 
			
		||||
export Z3_BUILD_DIR="${Z3_SRC_DIR}/build"
 | 
			
		||||
export Z3_BUILD_TYPE="${Z3_BUILD_TYPE:-RelWithDebInfo}"
 | 
			
		||||
export Z3_CMAKE_GENERATOR="${Z3_CMAKE_GENERATOR:-Ninja}"
 | 
			
		||||
export Z3_INSTALL_PREFIX="${Z3_INSTALL_PREFIX:-/usr/local}"
 | 
			
		||||
export Z3_STATIC_BUILD="${Z3_STATIC_BUILD:-0}"
 | 
			
		||||
export Z3_SYSTEM_TEST_DIR="${Z3_SRC_DIR}/z3_system_test"
 | 
			
		||||
export Z3_WARNINGS_AS_ERRORS="${Z3_WARNINGS_AS_ERRORS:-SERIOUS_ONLY}"
 | 
			
		||||
export Z3_VERBOSE_BUILD_OUTPUT="${Z3_VERBOSE_BUILD_OUTPUT:-0}"
 | 
			
		||||
 | 
			
		||||
# Overwrite whatever what set in TravisCI
 | 
			
		||||
export CC="${C_COMPILER}"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										7
									
								
								contrib/suppressions/README.md
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								contrib/suppressions/README.md
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,7 @@
 | 
			
		|||
# Suppression files
 | 
			
		||||
 | 
			
		||||
This directory contains suppression files used by various
 | 
			
		||||
program analysis tools.
 | 
			
		||||
 | 
			
		||||
Suppression files tell a program analysis tool to suppress
 | 
			
		||||
various warnings/errors.
 | 
			
		||||
							
								
								
									
										3
									
								
								contrib/suppressions/maintainers.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								contrib/suppressions/maintainers.txt
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,3 @@
 | 
			
		|||
# Maintainers
 | 
			
		||||
 | 
			
		||||
- Dan Liew (@delcypher)
 | 
			
		||||
							
								
								
									
										4
									
								
								contrib/suppressions/sanitizers/README.md
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								contrib/suppressions/sanitizers/README.md
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,4 @@
 | 
			
		|||
# Sanitizer supression files
 | 
			
		||||
 | 
			
		||||
This directory contains files used to suppress
 | 
			
		||||
ASan/LSan/UBSan warnings/errors.
 | 
			
		||||
							
								
								
									
										1
									
								
								contrib/suppressions/sanitizers/asan.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								contrib/suppressions/sanitizers/asan.txt
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
# AddressSanitizer suppression file
 | 
			
		||||
							
								
								
									
										5
									
								
								contrib/suppressions/sanitizers/lsan.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								contrib/suppressions/sanitizers/lsan.txt
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,5 @@
 | 
			
		|||
# LeakSanitizer suppression file
 | 
			
		||||
 | 
			
		||||
# Ignore Clang OpenMP leaks.
 | 
			
		||||
# See https://github.com/Z3Prover/z3/issues/1308
 | 
			
		||||
leak:___kmp_allocate
 | 
			
		||||
							
								
								
									
										7
									
								
								contrib/suppressions/sanitizers/ubsan.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								contrib/suppressions/sanitizers/ubsan.txt
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,7 @@
 | 
			
		|||
# UndefinedBehavior sanitizer suppression file
 | 
			
		||||
# FIXME: UBSan doesn't usually have false positives so we need to fix all of these!
 | 
			
		||||
 | 
			
		||||
# Occurs when running tptp example
 | 
			
		||||
# See https://github.com/Z3Prover/z3/issues/964
 | 
			
		||||
null:rational.h
 | 
			
		||||
null:mpq.h
 | 
			
		||||
| 
						 | 
				
			
			@ -188,7 +188,7 @@ try:
 | 
			
		|||
 | 
			
		||||
    if Z3PY_ENABLED:
 | 
			
		||||
        print("Z3Py documentation enabled")
 | 
			
		||||
        doxygen_config_substitutions['PYTHON_API_FILES'] = 'z3.py'
 | 
			
		||||
        doxygen_config_substitutions['PYTHON_API_FILES'] = 'z3*.py'
 | 
			
		||||
    else:
 | 
			
		||||
        print("Z3Py documentation disabled")
 | 
			
		||||
        doxygen_config_substitutions['PYTHON_API_FILES'] = ''
 | 
			
		||||
| 
						 | 
				
			
			@ -288,8 +288,21 @@ try:
 | 
			
		|||
        # Put z3py at the beginning of the search path to try to avoid picking up
 | 
			
		||||
        # an installed copy of Z3py.
 | 
			
		||||
        sys.path.insert(0, os.path.dirname(Z3PY_PACKAGE_PATH))
 | 
			
		||||
        pydoc.writedoc('z3')
 | 
			
		||||
        shutil.move('z3.html', os.path.join(OUTPUT_DIRECTORY, 'html', 'z3.html'))
 | 
			
		||||
        for modulename in (
 | 
			
		||||
                'z3',
 | 
			
		||||
                'z3.z3consts',
 | 
			
		||||
                'z3.z3core',
 | 
			
		||||
                'z3.z3num',
 | 
			
		||||
                'z3.z3poly',
 | 
			
		||||
                'z3.z3printer',
 | 
			
		||||
                'z3.z3rcf',
 | 
			
		||||
                'z3.z3types',
 | 
			
		||||
                'z3.z3util',
 | 
			
		||||
                ):
 | 
			
		||||
            pydoc.writedoc(modulename)
 | 
			
		||||
            doc = modulename + '.html'
 | 
			
		||||
            shutil.move(doc, os.path.join(OUTPUT_DIRECTORY, 'html', doc))
 | 
			
		||||
 | 
			
		||||
        print("Generated pydoc Z3Py documentation.")
 | 
			
		||||
 | 
			
		||||
    if ML_ENABLED:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,6 +7,30 @@ else()
 | 
			
		|||
  set(EXTERNAL_PROJECT_BUILD_ALWAYS_ARG "")
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
option(Z3_C_EXAMPLES_FORCE_CXX_LINKER
 | 
			
		||||
  "Force C++ linker when building C example projects" OFF)
 | 
			
		||||
 | 
			
		||||
if (Z3_C_EXAMPLES_FORCE_CXX_LINKER)
 | 
			
		||||
  # HACK: This is a workaround for UBSan.
 | 
			
		||||
  message(STATUS "Forcing C++ linker to be used when building example C projects")
 | 
			
		||||
  set(EXTERNAL_C_PROJ_USE_CXX_LINKER_ARG
 | 
			
		||||
    "-DFORCE_CXX_LINKER=ON"
 | 
			
		||||
  )
 | 
			
		||||
else()
 | 
			
		||||
  set(EXTERNAL_C_PROJ_USE_CXX_LINKER_ARG "")
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
if (DEFINED CMAKE_CONFIGURATION_TYPES)
 | 
			
		||||
  message(WARNING
 | 
			
		||||
    "Cannot set built type of external project when building with a "
 | 
			
		||||
    "multi-configuration generator")
 | 
			
		||||
  set(EXTERNAL_PROJECT_CMAKE_BUILD_TYPE_ARG "")
 | 
			
		||||
else()
 | 
			
		||||
  set(EXTERNAL_PROJECT_CMAKE_BUILD_TYPE_ARG
 | 
			
		||||
    "-DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}"
 | 
			
		||||
  )
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
# Build example project using libz3's C API as an external project
 | 
			
		||||
################################################################################
 | 
			
		||||
| 
						 | 
				
			
			@ -14,7 +38,10 @@ ExternalProject_Add(c_example
 | 
			
		|||
  DEPENDS libz3
 | 
			
		||||
  # Configure step
 | 
			
		||||
  SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/c"
 | 
			
		||||
  CMAKE_ARGS "-DZ3_DIR=${CMAKE_BINARY_DIR}"
 | 
			
		||||
  CMAKE_ARGS
 | 
			
		||||
    "-DZ3_DIR=${CMAKE_BINARY_DIR}"
 | 
			
		||||
    "${EXTERNAL_C_PROJ_USE_CXX_LINKER_ARG}"
 | 
			
		||||
    "${EXTERNAL_PROJECT_CMAKE_BUILD_TYPE_ARG}"
 | 
			
		||||
  # Build step
 | 
			
		||||
  ${EXTERNAL_PROJECT_BUILD_ALWAYS_ARG}
 | 
			
		||||
  BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/c_example_build_dir"
 | 
			
		||||
| 
						 | 
				
			
			@ -30,7 +57,10 @@ ExternalProject_Add(c_maxsat_example
 | 
			
		|||
  DEPENDS libz3
 | 
			
		||||
  # Configure step
 | 
			
		||||
  SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/maxsat"
 | 
			
		||||
  CMAKE_ARGS "-DZ3_DIR=${CMAKE_BINARY_DIR}"
 | 
			
		||||
  CMAKE_ARGS
 | 
			
		||||
    "-DZ3_DIR=${CMAKE_BINARY_DIR}"
 | 
			
		||||
    "${EXTERNAL_C_PROJ_USE_CXX_LINKER_ARG}"
 | 
			
		||||
    "${EXTERNAL_PROJECT_CMAKE_BUILD_TYPE_ARG}"
 | 
			
		||||
  # Build step
 | 
			
		||||
  ${EXTERNAL_PROJECT_BUILD_ALWAYS_ARG}
 | 
			
		||||
  BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/c_maxsat_example_build_dir"
 | 
			
		||||
| 
						 | 
				
			
			@ -47,7 +77,9 @@ ExternalProject_Add(cpp_example
 | 
			
		|||
  DEPENDS libz3
 | 
			
		||||
  # Configure step
 | 
			
		||||
  SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/c++"
 | 
			
		||||
  CMAKE_ARGS "-DZ3_DIR=${CMAKE_BINARY_DIR}"
 | 
			
		||||
  CMAKE_ARGS
 | 
			
		||||
    "-DZ3_DIR=${CMAKE_BINARY_DIR}"
 | 
			
		||||
    "${EXTERNAL_PROJECT_CMAKE_BUILD_TYPE_ARG}"
 | 
			
		||||
  # Build step
 | 
			
		||||
  ${EXTERNAL_PROJECT_BUILD_ALWAYS_ARG}
 | 
			
		||||
  BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/cpp_example_build_dir"
 | 
			
		||||
| 
						 | 
				
			
			@ -63,7 +95,9 @@ ExternalProject_Add(z3_tptp5
 | 
			
		|||
  DEPENDS libz3
 | 
			
		||||
  # Configure step
 | 
			
		||||
  SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/tptp"
 | 
			
		||||
  CMAKE_ARGS "-DZ3_DIR=${CMAKE_BINARY_DIR}"
 | 
			
		||||
  CMAKE_ARGS
 | 
			
		||||
    "-DZ3_DIR=${CMAKE_BINARY_DIR}"
 | 
			
		||||
    "${EXTERNAL_PROJECT_CMAKE_BUILD_TYPE_ARG}"
 | 
			
		||||
  # Build step
 | 
			
		||||
  ${EXTERNAL_PROJECT_BUILD_ALWAYS_ARG}
 | 
			
		||||
  BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/tptp_build_dir"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,6 +22,17 @@ message(STATUS "Found Z3 ${Z3_VERSION_STRING}")
 | 
			
		|||
message(STATUS "Z3_DIR: ${Z3_DIR}")
 | 
			
		||||
 | 
			
		||||
add_executable(c_example test_capi.c)
 | 
			
		||||
 | 
			
		||||
option(FORCE_CXX_LINKER "Force linker with C++ linker" OFF)
 | 
			
		||||
if (FORCE_CXX_LINKER)
 | 
			
		||||
  # This is a hack for avoiding UBSan linking errors
 | 
			
		||||
  message(STATUS "Forcing use of C++ linker")
 | 
			
		||||
  set_target_properties(c_example
 | 
			
		||||
    PROPERTIES
 | 
			
		||||
    LINKER_LANGUAGE CXX
 | 
			
		||||
  )
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
target_include_directories(c_example PRIVATE ${Z3_C_INCLUDE_DIRS})
 | 
			
		||||
target_link_libraries(c_example PRIVATE ${Z3_LIBRARIES})
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -65,6 +65,15 @@ void throw_z3_error(Z3_context c, Z3_error_code e)
 | 
			
		|||
    longjmp(g_catch_buffer, e);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
   \brief Error handling that depends on checking an error code on the context.
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
void nothrow_z3_error(Z3_context c, Z3_error_code e) {
 | 
			
		||||
    // no-op
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
   \brief Create a logical context.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1592,18 +1601,16 @@ void error_code_example1()
 | 
			
		|||
void error_code_example2() {
 | 
			
		||||
    Z3_config cfg;
 | 
			
		||||
    Z3_context ctx = NULL;
 | 
			
		||||
    int r;
 | 
			
		||||
    Z3_error_code e;
 | 
			
		||||
 | 
			
		||||
    printf("\nerror_code_example2\n");
 | 
			
		||||
    LOG_MSG("error_code_example2");
 | 
			
		||||
 | 
			
		||||
    /* low tech try&catch */
 | 
			
		||||
    r = setjmp(g_catch_buffer);
 | 
			
		||||
    if (r == 0) {
 | 
			
		||||
    if (1) {
 | 
			
		||||
        Z3_ast x, y, app;
 | 
			
		||||
 | 
			
		||||
        cfg = Z3_mk_config();
 | 
			
		||||
        ctx = mk_context_custom(cfg, throw_z3_error);
 | 
			
		||||
        ctx = mk_context_custom(cfg, nothrow_z3_error);
 | 
			
		||||
        Z3_del_config(cfg);
 | 
			
		||||
 | 
			
		||||
        x   = mk_int_var(ctx, "x");
 | 
			
		||||
| 
						 | 
				
			
			@ -1611,11 +1618,14 @@ void error_code_example2() {
 | 
			
		|||
        printf("before Z3_mk_iff\n");
 | 
			
		||||
        /* the next call will produce an error */
 | 
			
		||||
        app = Z3_mk_iff(ctx, x, y);
 | 
			
		||||
        e = Z3_get_error_code(ctx);
 | 
			
		||||
        if (e != Z3_OK) goto err;
 | 
			
		||||
        unreachable();
 | 
			
		||||
        Z3_del_context(ctx);
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
      printf("Z3 error: %s.\n", Z3_get_error_msg(ctx, (Z3_error_code)r));
 | 
			
		||||
    err:
 | 
			
		||||
        printf("Z3 error: %s.\n", Z3_get_error_msg(ctx, e));
 | 
			
		||||
        if (ctx != NULL) {
 | 
			
		||||
            Z3_del_context(ctx);
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -1781,15 +1791,14 @@ void parser_example5() {
 | 
			
		|||
    Z3_config  cfg;
 | 
			
		||||
    Z3_context ctx = NULL;
 | 
			
		||||
    Z3_solver s = NULL;
 | 
			
		||||
    int r;
 | 
			
		||||
    Z3_error_code e;
 | 
			
		||||
 | 
			
		||||
    printf("\nparser_example5\n");
 | 
			
		||||
    LOG_MSG("parser_example5");
 | 
			
		||||
 | 
			
		||||
    r = setjmp(g_catch_buffer);
 | 
			
		||||
    if (r == 0) {
 | 
			
		||||
    if (1) {
 | 
			
		||||
        cfg = Z3_mk_config();
 | 
			
		||||
        ctx = mk_context_custom(cfg, throw_z3_error);
 | 
			
		||||
        ctx = mk_context_custom(cfg, nothrow_z3_error);
 | 
			
		||||
        s   = mk_solver(ctx);
 | 
			
		||||
        Z3_del_config(cfg);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1798,12 +1807,15 @@ void parser_example5() {
 | 
			
		|||
                               "(benchmark tst :extrafuns ((x Int (y Int)) :formula (> x y) :formula (> x 0))",
 | 
			
		||||
                               0, 0, 0,
 | 
			
		||||
                               0, 0, 0);
 | 
			
		||||
        e = Z3_get_error_code(ctx);
 | 
			
		||||
        if (e != Z3_OK) goto err;
 | 
			
		||||
        unreachable();
 | 
			
		||||
	del_solver(ctx, s);
 | 
			
		||||
        Z3_del_context(ctx);
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
      printf("Z3 error: %s.\n", Z3_get_error_msg(ctx, (Z3_error_code)r));
 | 
			
		||||
    err:
 | 
			
		||||
        printf("Z3 error: %s.\n", Z3_get_error_msg(ctx, e));
 | 
			
		||||
        if (ctx != NULL) {
 | 
			
		||||
            printf("Error message: '%s'.\n",Z3_get_smtlib_error(ctx));
 | 
			
		||||
	    del_solver(ctx, s);
 | 
			
		||||
| 
						 | 
				
			
			@ -2639,6 +2651,7 @@ void smt2parser_example() {
 | 
			
		|||
    ctx = mk_context();
 | 
			
		||||
    fs  = Z3_parse_smtlib2_string(ctx, "(declare-fun a () (_ BitVec 8)) (assert (bvuge a #x10)) (assert (bvule a #xf0))", 0, 0, 0, 0, 0, 0);
 | 
			
		||||
    printf("formulas: %s\n", Z3_ast_to_string(ctx, fs));
 | 
			
		||||
 | 
			
		||||
    Z3_del_context(ctx);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,6 +25,16 @@ add_executable(c_maxsat_example maxsat.c)
 | 
			
		|||
target_include_directories(c_maxsat_example PRIVATE ${Z3_C_INCLUDE_DIRS})
 | 
			
		||||
target_link_libraries(c_maxsat_example PRIVATE ${Z3_LIBRARIES})
 | 
			
		||||
 | 
			
		||||
option(FORCE_CXX_LINKER "Force linker with C++ linker" OFF)
 | 
			
		||||
if (FORCE_CXX_LINKER)
 | 
			
		||||
  # This is a hack for avoiding UBSan linking errors
 | 
			
		||||
  message(STATUS "Forcing use of C++ linker")
 | 
			
		||||
  set_target_properties(c_maxsat_example
 | 
			
		||||
    PROPERTIES
 | 
			
		||||
    LINKER_LANGUAGE CXX
 | 
			
		||||
  )
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
if ("${CMAKE_SYSTEM_NAME}" MATCHES "[Ww]indows")
 | 
			
		||||
  # On Windows we need to copy the Z3 libraries
 | 
			
		||||
  # into the same directory as the executable
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1913,7 +1913,11 @@ class MLComponent(Component):
 | 
			
		|||
            src_dir = self.to_src_dir
 | 
			
		||||
            mk_dir(os.path.join(BUILD_DIR, self.sub_dir))
 | 
			
		||||
            api_src = get_component(API_COMPONENT).to_src_dir
 | 
			
		||||
            out.write('CXXFLAGS_OCAML=$(CXXFLAGS:/GL=)\n') # remove /GL; the ocaml tools don't like it.
 | 
			
		||||
            # remove /GL and -std=c++11; the ocaml tools don't like them.
 | 
			
		||||
            if IS_WINDOWS:                
 | 
			
		||||
                out.write('CXXFLAGS_OCAML=$(CXXFLAGS:/GL=)\n')
 | 
			
		||||
            else:
 | 
			
		||||
                out.write('CXXFLAGS_OCAML=$(subst -std=c++11,,$(CXXFLAGS))\n')
 | 
			
		||||
 | 
			
		||||
            if IS_WINDOWS:
 | 
			
		||||
                prefix_lib = '-L' + os.path.abspath(BUILD_DIR).replace('\\', '\\\\')
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -34,6 +34,19 @@ extern "C" {
 | 
			
		|||
        Z3_CATCH_RETURN(0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Z3_sort Z3_API Z3_mk_array_sort_n(Z3_context c, unsigned n, Z3_sort const* domain, Z3_sort range) {
 | 
			
		||||
        Z3_TRY;
 | 
			
		||||
        LOG_Z3_mk_array_sort_n(c, n, domain, range);
 | 
			
		||||
        RESET_ERROR_CODE();
 | 
			
		||||
        vector<parameter> params;
 | 
			
		||||
        for (unsigned i = 0; i < n; ++i) params.push_back(parameter(to_sort(domain[i])));
 | 
			
		||||
        params.push_back(parameter(to_sort(range)));
 | 
			
		||||
        sort * ty =  mk_c(c)->m().mk_sort(mk_c(c)->get_array_fid(), ARRAY_SORT, params.size(), params.c_ptr());
 | 
			
		||||
        mk_c(c)->save_ast_trail(ty);
 | 
			
		||||
        RETURN_Z3(of_sort(ty));
 | 
			
		||||
        Z3_CATCH_RETURN(0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Z3_ast Z3_API Z3_mk_select(Z3_context c, Z3_ast a, Z3_ast i) {
 | 
			
		||||
        Z3_TRY;
 | 
			
		||||
        LOG_Z3_mk_select(c, a, i);
 | 
			
		||||
| 
						 | 
				
			
			@ -57,6 +70,35 @@ extern "C" {
 | 
			
		|||
        Z3_CATCH_RETURN(0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Z3_ast Z3_API Z3_mk_select_n(Z3_context c, Z3_ast a, unsigned n, Z3_ast const* idxs) {
 | 
			
		||||
        Z3_TRY;
 | 
			
		||||
        LOG_Z3_mk_select_n(c, a, n, idxs);
 | 
			
		||||
        RESET_ERROR_CODE();
 | 
			
		||||
        ast_manager & m = mk_c(c)->m();
 | 
			
		||||
        expr * _a        = to_expr(a);
 | 
			
		||||
        // expr * _i        = to_expr(i);
 | 
			
		||||
        sort * a_ty = m.get_sort(_a);
 | 
			
		||||
        // sort * i_ty = m.get_sort(_i);
 | 
			
		||||
        if (a_ty->get_family_id() != mk_c(c)->get_array_fid()) {
 | 
			
		||||
            SET_ERROR_CODE(Z3_SORT_ERROR);
 | 
			
		||||
            RETURN_Z3(0);
 | 
			
		||||
        }
 | 
			
		||||
        ptr_vector<sort> domain;
 | 
			
		||||
        ptr_vector<expr> args;
 | 
			
		||||
        args.push_back(_a);
 | 
			
		||||
        domain.push_back(a_ty);
 | 
			
		||||
        for (unsigned i = 0; i < n; ++i) {
 | 
			
		||||
            args.push_back(to_expr(idxs[i]));
 | 
			
		||||
            domain.push_back(m.get_sort(to_expr(idxs[i])));
 | 
			
		||||
        }
 | 
			
		||||
        func_decl * d   = m.mk_func_decl(mk_c(c)->get_array_fid(), OP_SELECT, 2, a_ty->get_parameters(), domain.size(), domain.c_ptr());
 | 
			
		||||
        app * r        = m.mk_app(d, args.size(), args.c_ptr());
 | 
			
		||||
        mk_c(c)->save_ast_trail(r);
 | 
			
		||||
        check_sorts(c, r);
 | 
			
		||||
        RETURN_Z3(of_ast(r));
 | 
			
		||||
        Z3_CATCH_RETURN(0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Z3_ast Z3_API Z3_mk_store(Z3_context c, Z3_ast a, Z3_ast i, Z3_ast v) {
 | 
			
		||||
        Z3_TRY;
 | 
			
		||||
        LOG_Z3_mk_store(c, a, i, v);
 | 
			
		||||
| 
						 | 
				
			
			@ -82,6 +124,37 @@ extern "C" {
 | 
			
		|||
        Z3_CATCH_RETURN(0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Z3_ast Z3_API Z3_mk_store_n(Z3_context c, Z3_ast a, unsigned n, Z3_ast const* idxs, Z3_ast v) {
 | 
			
		||||
        Z3_TRY;
 | 
			
		||||
        LOG_Z3_mk_store_n(c, a, n, idxs, v);
 | 
			
		||||
        RESET_ERROR_CODE();
 | 
			
		||||
        ast_manager & m = mk_c(c)->m();
 | 
			
		||||
        expr * _a        = to_expr(a);
 | 
			
		||||
        expr * _v        = to_expr(v);
 | 
			
		||||
        sort * a_ty = m.get_sort(_a);
 | 
			
		||||
        sort * v_ty = m.get_sort(_v);
 | 
			
		||||
        if (a_ty->get_family_id() != mk_c(c)->get_array_fid()) {
 | 
			
		||||
            SET_ERROR_CODE(Z3_SORT_ERROR);
 | 
			
		||||
            RETURN_Z3(0);
 | 
			
		||||
        }
 | 
			
		||||
        ptr_vector<sort> domain;
 | 
			
		||||
        ptr_vector<expr> args;
 | 
			
		||||
        args.push_back(_a);
 | 
			
		||||
        domain.push_back(a_ty);
 | 
			
		||||
        for (unsigned i = 0; i < n; ++i) {
 | 
			
		||||
            args.push_back(to_expr(idxs[i]));
 | 
			
		||||
            domain.push_back(m.get_sort(to_expr(idxs[i])));
 | 
			
		||||
        }
 | 
			
		||||
        args.push_back(_v);
 | 
			
		||||
        domain.push_back(v_ty);
 | 
			
		||||
        func_decl * d   = m.mk_func_decl(mk_c(c)->get_array_fid(), OP_STORE, 2, a_ty->get_parameters(), domain.size(), domain.c_ptr());
 | 
			
		||||
        app * r        = m.mk_app(d, args.size(), args.c_ptr());
 | 
			
		||||
        mk_c(c)->save_ast_trail(r);
 | 
			
		||||
        check_sorts(c, r);
 | 
			
		||||
        RETURN_Z3(of_ast(r));
 | 
			
		||||
        Z3_CATCH_RETURN(0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Z3_ast Z3_API Z3_mk_map(Z3_context c, Z3_func_decl f, unsigned n, Z3_ast const* args) {
 | 
			
		||||
        Z3_TRY;
 | 
			
		||||
        LOG_Z3_mk_map(c, f, n, args);
 | 
			
		||||
| 
						 | 
				
			
			@ -188,6 +261,18 @@ extern "C" {
 | 
			
		|||
    MK_BINARY(Z3_mk_set_subset, mk_c(c)->get_array_fid(), OP_SET_SUBSET, SKIP);
 | 
			
		||||
    MK_BINARY(Z3_mk_array_ext, mk_c(c)->get_array_fid(), OP_ARRAY_EXT, SKIP);
 | 
			
		||||
 | 
			
		||||
    Z3_ast Z3_API Z3_mk_as_array(Z3_context c, Z3_func_decl f) {
 | 
			
		||||
        Z3_TRY;
 | 
			
		||||
        LOG_Z3_mk_as_array(c, f);
 | 
			
		||||
        RESET_ERROR_CODE();
 | 
			
		||||
        ast_manager & m = mk_c(c)->m();
 | 
			
		||||
        array_util a(m);
 | 
			
		||||
        app * r = a.mk_as_array(to_func_decl(f));
 | 
			
		||||
        mk_c(c)->save_ast_trail(r);
 | 
			
		||||
        return of_ast(r);
 | 
			
		||||
        Z3_CATCH_RETURN(0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Z3_ast Z3_mk_set_member(Z3_context c, Z3_ast elem, Z3_ast set) {
 | 
			
		||||
        return Z3_mk_select(c, set, elem);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -222,7 +307,8 @@ extern "C" {
 | 
			
		|||
        CHECK_VALID_AST(t, 0);
 | 
			
		||||
        if (to_sort(t)->get_family_id() == mk_c(c)->get_array_fid() &&
 | 
			
		||||
            to_sort(t)->get_decl_kind() == ARRAY_SORT) {
 | 
			
		||||
            Z3_sort r = reinterpret_cast<Z3_sort>(to_sort(t)->get_parameter(1).get_ast());
 | 
			
		||||
            unsigned n = to_sort(t)->get_num_parameters();
 | 
			
		||||
            Z3_sort r = reinterpret_cast<Z3_sort>(to_sort(t)->get_parameter(n-1).get_ast());
 | 
			
		||||
            RETURN_Z3(r);
 | 
			
		||||
        }
 | 
			
		||||
        SET_ERROR_CODE(Z3_INVALID_ARG);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1204,12 +1204,8 @@ extern "C" {
 | 
			
		|||
            case OP_FPA_TO_SBV: return Z3_OP_FPA_TO_SBV;
 | 
			
		||||
            case OP_FPA_TO_REAL: return Z3_OP_FPA_TO_REAL;
 | 
			
		||||
            case OP_FPA_TO_IEEE_BV: return Z3_OP_FPA_TO_IEEE_BV;
 | 
			
		||||
            case OP_FPA_MIN_I: return Z3_OP_FPA_MIN_I;
 | 
			
		||||
            case OP_FPA_MAX_I: return Z3_OP_FPA_MAX_I;
 | 
			
		||||
            case OP_FPA_BVWRAP: return Z3_OP_FPA_BVWRAP;
 | 
			
		||||
            case OP_FPA_BV2RM: return Z3_OP_FPA_BV2RM;
 | 
			
		||||
            case OP_FPA_MIN_UNSPECIFIED: return Z3_OP_FPA_MIN_UNSPECIFIED;
 | 
			
		||||
            case OP_FPA_MAX_UNSPECIFIED: return Z3_OP_FPA_MAX_UNSPECIFIED;
 | 
			
		||||
                return Z3_OP_UNINTERPRETED;
 | 
			
		||||
            default:
 | 
			
		||||
                return Z3_OP_INTERNAL;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -283,15 +283,16 @@ extern "C" {
 | 
			
		|||
        Z3_optimize opt,
 | 
			
		||||
        std::istream& s) {
 | 
			
		||||
        ast_manager& m = mk_c(c)->m();
 | 
			
		||||
        cmd_context ctx(false, &m);
 | 
			
		||||
        install_opt_cmds(ctx, to_optimize_ptr(opt));
 | 
			
		||||
        ctx.set_ignore_check(true);
 | 
			
		||||
        if (!parse_smt2_commands(ctx, s)) {
 | 
			
		||||
        scoped_ptr<cmd_context> ctx = alloc(cmd_context, false, &m);
 | 
			
		||||
        install_opt_cmds(*ctx.get(), to_optimize_ptr(opt));
 | 
			
		||||
        ctx->set_ignore_check(true);
 | 
			
		||||
        if (!parse_smt2_commands(*ctx.get(), s)) {
 | 
			
		||||
            ctx = nullptr;
 | 
			
		||||
            SET_ERROR_CODE(Z3_PARSER_ERROR);
 | 
			
		||||
            return;
 | 
			
		||||
        }        
 | 
			
		||||
        ptr_vector<expr>::const_iterator it  = ctx.begin_assertions();
 | 
			
		||||
        ptr_vector<expr>::const_iterator end = ctx.end_assertions();
 | 
			
		||||
        ptr_vector<expr>::const_iterator it  = ctx->begin_assertions();
 | 
			
		||||
        ptr_vector<expr>::const_iterator end = ctx->end_assertions();
 | 
			
		||||
        for (; it != end; ++it) {
 | 
			
		||||
            to_optimize_ptr(opt)->add_hard_constraint(*it);
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -320,9 +321,6 @@ extern "C" {
 | 
			
		|||
            std::ostringstream strm;
 | 
			
		||||
            strm << "Could not open file " << s;
 | 
			
		||||
            throw default_exception(strm.str());
 | 
			
		||||
 | 
			
		||||
            SET_ERROR_CODE(Z3_PARSER_ERROR);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        Z3_optimize_from_stream(c, d, is);
 | 
			
		||||
        Z3_CATCH;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -56,19 +56,20 @@ extern "C" {
 | 
			
		|||
                                       Z3_func_decl const decls[]) {
 | 
			
		||||
        Z3_TRY;
 | 
			
		||||
        LOG_Z3_parse_smtlib_string(c, str, num_sorts, sort_names, sorts, num_decls, decl_names, decls);
 | 
			
		||||
        std::ostringstream outs;
 | 
			
		||||
        scoped_ptr<std::ostringstream> outs = alloc(std::ostringstream);
 | 
			
		||||
        bool ok = false;
 | 
			
		||||
 | 
			
		||||
        RESET_ERROR_CODE();
 | 
			
		||||
        init_smtlib_parser(c, num_sorts, sort_names, sorts, num_decls, decl_names, decls);
 | 
			
		||||
        mk_c(c)->m_smtlib_parser->set_error_stream(outs);
 | 
			
		||||
        mk_c(c)->m_smtlib_parser->set_error_stream(*outs);
 | 
			
		||||
        try {
 | 
			
		||||
            ok = mk_c(c)->m_smtlib_parser->parse_string(str);        
 | 
			
		||||
        }
 | 
			
		||||
        catch (...) {
 | 
			
		||||
            ok = false;
 | 
			
		||||
        }
 | 
			
		||||
        mk_c(c)->m_smtlib_error_buffer = outs.str();
 | 
			
		||||
        mk_c(c)->m_smtlib_error_buffer = outs->str();
 | 
			
		||||
        outs = nullptr;
 | 
			
		||||
        if (!ok) {
 | 
			
		||||
            mk_c(c)->reset_parser();
 | 
			
		||||
            SET_ERROR_CODE(Z3_PARSER_ERROR);
 | 
			
		||||
| 
						 | 
				
			
			@ -88,16 +89,17 @@ extern "C" {
 | 
			
		|||
        LOG_Z3_parse_smtlib_file(c, file_name, num_sorts, sort_names, types, num_decls, decl_names, decls);
 | 
			
		||||
        bool ok = false;
 | 
			
		||||
        RESET_ERROR_CODE();
 | 
			
		||||
        std::ostringstream outs;
 | 
			
		||||
        scoped_ptr<std::ostringstream> outs = alloc(std::ostringstream);
 | 
			
		||||
        init_smtlib_parser(c, num_sorts, sort_names, types, num_decls, decl_names, decls);
 | 
			
		||||
        mk_c(c)->m_smtlib_parser->set_error_stream(outs);
 | 
			
		||||
        mk_c(c)->m_smtlib_parser->set_error_stream(*outs);
 | 
			
		||||
        try {
 | 
			
		||||
            ok = mk_c(c)->m_smtlib_parser->parse_file(file_name);
 | 
			
		||||
        }
 | 
			
		||||
        catch(...) {
 | 
			
		||||
            ok = false;
 | 
			
		||||
        }
 | 
			
		||||
        mk_c(c)->m_smtlib_error_buffer = outs.str();
 | 
			
		||||
        mk_c(c)->m_smtlib_error_buffer = outs->str();
 | 
			
		||||
        outs = nullptr;
 | 
			
		||||
        if (!ok) {
 | 
			
		||||
            mk_c(c)->reset_parser();
 | 
			
		||||
            SET_ERROR_CODE(Z3_PARSER_ERROR);
 | 
			
		||||
| 
						 | 
				
			
			@ -260,21 +262,22 @@ extern "C" {
 | 
			
		|||
                                Z3_symbol const decl_names[],
 | 
			
		||||
                                Z3_func_decl const decls[]) {
 | 
			
		||||
        Z3_TRY;
 | 
			
		||||
        cmd_context ctx(false, &(mk_c(c)->m()));
 | 
			
		||||
        ctx.set_ignore_check(true);
 | 
			
		||||
        scoped_ptr<cmd_context> ctx = alloc(cmd_context, false, &(mk_c(c)->m()));
 | 
			
		||||
        ctx->set_ignore_check(true);
 | 
			
		||||
        for (unsigned i = 0; i < num_decls; ++i) {
 | 
			
		||||
           ctx.insert(to_symbol(decl_names[i]), to_func_decl(decls[i]));
 | 
			
		||||
            ctx->insert(to_symbol(decl_names[i]), to_func_decl(decls[i]));
 | 
			
		||||
        }
 | 
			
		||||
        for (unsigned i = 0; i < num_sorts; ++i) {
 | 
			
		||||
            psort* ps = ctx.pm().mk_psort_cnst(to_sort(sorts[i]));
 | 
			
		||||
            ctx.insert(ctx.pm().mk_psort_user_decl(0, to_symbol(sort_names[i]), ps));
 | 
			
		||||
            psort* ps = ctx->pm().mk_psort_cnst(to_sort(sorts[i]));
 | 
			
		||||
            ctx->insert(ctx->pm().mk_psort_user_decl(0, to_symbol(sort_names[i]), ps));
 | 
			
		||||
        }
 | 
			
		||||
        if (!parse_smt2_commands(ctx, is)) {
 | 
			
		||||
        if (!parse_smt2_commands(*ctx.get(), is)) {
 | 
			
		||||
            ctx = nullptr;
 | 
			
		||||
            SET_ERROR_CODE(Z3_PARSER_ERROR);
 | 
			
		||||
            return of_ast(mk_c(c)->m().mk_true());
 | 
			
		||||
        }
 | 
			
		||||
        ptr_vector<expr>::const_iterator it  = ctx.begin_assertions();
 | 
			
		||||
        ptr_vector<expr>::const_iterator end = ctx.end_assertions();
 | 
			
		||||
        ptr_vector<expr>::const_iterator it  = ctx->begin_assertions();
 | 
			
		||||
        ptr_vector<expr>::const_iterator end = ctx->end_assertions();
 | 
			
		||||
        unsigned size = static_cast<unsigned>(end - it);
 | 
			
		||||
        return of_ast(mk_c(c)->mk_and(size, it));
 | 
			
		||||
        Z3_CATCH_RETURN(0);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -63,9 +63,11 @@ extern "C" {
 | 
			
		|||
        RESET_ERROR_CODE();
 | 
			
		||||
        if (!mk_c(c)->m().is_bool(to_expr(body))) {
 | 
			
		||||
            SET_ERROR_CODE(Z3_SORT_ERROR);
 | 
			
		||||
            return nullptr;
 | 
			
		||||
        }
 | 
			
		||||
        if (num_patterns > 0 && num_no_patterns > 0) {
 | 
			
		||||
            SET_ERROR_CODE(Z3_INVALID_USAGE);
 | 
			
		||||
            return nullptr;
 | 
			
		||||
        }
 | 
			
		||||
        expr * const* ps = reinterpret_cast<expr * const*>(patterns);
 | 
			
		||||
        expr * const* no_ps = reinterpret_cast<expr * const*>(no_patterns);
 | 
			
		||||
| 
						 | 
				
			
			@ -76,7 +78,7 @@ extern "C" {
 | 
			
		|||
            for (unsigned i = 0; i < num_patterns; i++) {
 | 
			
		||||
                if (!v(num_decls, ps[i], 0, 0)) {
 | 
			
		||||
                    SET_ERROR_CODE(Z3_INVALID_PATTERN);
 | 
			
		||||
                    return 0;
 | 
			
		||||
                    return nullptr;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -442,6 +442,7 @@ extern "C" {
 | 
			
		|||
        unsigned sz = __assumptions.size();
 | 
			
		||||
        for (unsigned i = 0; i < sz; ++i) {
 | 
			
		||||
            if (!is_expr(__assumptions[i])) {
 | 
			
		||||
                _assumptions.finalize(); _consequences.finalize(); _variables.finalize();
 | 
			
		||||
                SET_ERROR_CODE(Z3_INVALID_USAGE);
 | 
			
		||||
                return Z3_L_UNDEF;
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -451,6 +452,7 @@ extern "C" {
 | 
			
		|||
        sz = __variables.size();
 | 
			
		||||
        for (unsigned i = 0; i < sz; ++i) {
 | 
			
		||||
            if (!is_expr(__variables[i])) {
 | 
			
		||||
                _assumptions.finalize(); _consequences.finalize(); _variables.finalize();
 | 
			
		||||
                SET_ERROR_CODE(Z3_INVALID_USAGE);
 | 
			
		||||
                return Z3_L_UNDEF;
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -471,6 +473,7 @@ extern "C" {
 | 
			
		|||
            }
 | 
			
		||||
            catch (z3_exception & ex) {
 | 
			
		||||
                to_solver_ref(s)->set_reason_unknown(eh);
 | 
			
		||||
                _assumptions.finalize(); _consequences.finalize(); _variables.finalize();
 | 
			
		||||
                mk_c(c)->handle_exception(ex);
 | 
			
		||||
                return Z3_L_UNDEF;
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -140,18 +140,17 @@ namespace z3 {
 | 
			
		|||
    class context {
 | 
			
		||||
        bool       m_enable_exceptions;
 | 
			
		||||
        Z3_context m_ctx;
 | 
			
		||||
        static void error_handler(Z3_context /*c*/, Z3_error_code /*e*/) { /* do nothing */ }
 | 
			
		||||
        void init(config & c) {
 | 
			
		||||
            m_ctx = Z3_mk_context_rc(c);
 | 
			
		||||
            m_enable_exceptions = true;
 | 
			
		||||
            Z3_set_error_handler(m_ctx, error_handler);
 | 
			
		||||
            Z3_set_error_handler(m_ctx, 0);
 | 
			
		||||
            Z3_set_ast_print_mode(m_ctx, Z3_PRINT_SMTLIB2_COMPLIANT);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void init_interp(config & c) {
 | 
			
		||||
            m_ctx = Z3_mk_interpolation_context(c);
 | 
			
		||||
            m_enable_exceptions = true;
 | 
			
		||||
            Z3_set_error_handler(m_ctx, error_handler);
 | 
			
		||||
            Z3_set_error_handler(m_ctx, 0);
 | 
			
		||||
            Z3_set_ast_print_mode(m_ctx, Z3_PRINT_SMTLIB2_COMPLIANT);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -251,6 +250,8 @@ namespace z3 {
 | 
			
		|||
           Example: Given a context \c c, <tt>c.array_sort(c.int_sort(), c.bool_sort())</tt> is an array sort from integer to Boolean.
 | 
			
		||||
        */
 | 
			
		||||
        sort array_sort(sort d, sort r);
 | 
			
		||||
        sort array_sort(sort_vector const& d, sort r);
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
           \brief Return an enumeration sort: enum_names[0], ..., enum_names[n-1].
 | 
			
		||||
           \c cs and \c ts are output parameters. The method stores in \c cs the constants corresponding to the enumerated elements,
 | 
			
		||||
| 
						 | 
				
			
			@ -354,7 +355,7 @@ namespace z3 {
 | 
			
		|||
        Z3_error_code check_error() const { return m_ctx->check_error(); }
 | 
			
		||||
        friend void check_context(object const & a, object const & b);
 | 
			
		||||
    };
 | 
			
		||||
    inline void check_context(object const & a, object const & b) { assert(a.m_ctx == b.m_ctx); }
 | 
			
		||||
    inline void check_context(object const & a, object const & b) { (void)a; (void)b; assert(a.m_ctx == b.m_ctx); }
 | 
			
		||||
 | 
			
		||||
    class symbol : public object {
 | 
			
		||||
        Z3_symbol m_sym;
 | 
			
		||||
| 
						 | 
				
			
			@ -2328,6 +2329,11 @@ namespace z3 {
 | 
			
		|||
    inline sort context::re_sort(sort& s) { Z3_sort r = Z3_mk_re_sort(m_ctx, s); check_error(); return sort(*this, r); }
 | 
			
		||||
 | 
			
		||||
    inline sort context::array_sort(sort d, sort r) { Z3_sort s = Z3_mk_array_sort(m_ctx, d, r); check_error(); return sort(*this, s); }
 | 
			
		||||
    inline sort context::array_sort(sort_vector const& d, sort r) {
 | 
			
		||||
        array<Z3_sort> dom(d);
 | 
			
		||||
        Z3_sort s = Z3_mk_array_sort_n(m_ctx, dom.size(), dom.ptr(), r); check_error(); return sort(*this, s); 
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    inline sort context::enumeration_sort(char const * name, unsigned n, char const * const * enum_names, func_decl_vector & cs, func_decl_vector & ts) {
 | 
			
		||||
        array<Z3_symbol> _enum_names(n);
 | 
			
		||||
        for (unsigned i = 0; i < n; i++) { _enum_names[i] = Z3_mk_string_symbol(*this, enum_names[i]); }
 | 
			
		||||
| 
						 | 
				
			
			@ -2574,11 +2580,32 @@ namespace z3 {
 | 
			
		|||
        a.check_error();
 | 
			
		||||
        return expr(a.ctx(), r);
 | 
			
		||||
    }
 | 
			
		||||
    inline expr select(expr const & a, expr_vector const & i) {
 | 
			
		||||
        check_context(a, i);
 | 
			
		||||
        array<Z3_ast> idxs(i);
 | 
			
		||||
        Z3_ast r = Z3_mk_select_n(a.ctx(), a, idxs.size(), idxs.ptr());
 | 
			
		||||
        a.check_error();
 | 
			
		||||
        return expr(a.ctx(), r);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    inline expr store(expr const & a, int i, expr const & v) { return store(a, a.ctx().num_val(i, a.get_sort().array_domain()), v); }
 | 
			
		||||
    inline expr store(expr const & a, expr i, int v) { return store(a, i, a.ctx().num_val(v, a.get_sort().array_range())); }
 | 
			
		||||
    inline expr store(expr const & a, int i, int v) {
 | 
			
		||||
        return store(a, a.ctx().num_val(i, a.get_sort().array_domain()), a.ctx().num_val(v, a.get_sort().array_range()));
 | 
			
		||||
    }
 | 
			
		||||
    inline expr store(expr const & a, expr_vector const & i, expr const & v) {
 | 
			
		||||
        check_context(a, i); check_context(a, v);
 | 
			
		||||
        array<Z3_ast> idxs(i);
 | 
			
		||||
        Z3_ast r = Z3_mk_store_n(a.ctx(), a, idxs.size(), idxs.ptr(), v);
 | 
			
		||||
        a.check_error();
 | 
			
		||||
        return expr(a.ctx(), r);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    inline expr as_array(func_decl & f) { 
 | 
			
		||||
        Z3_ast r = Z3_mk_as_array(f.ctx(), f); 
 | 
			
		||||
        f.check_error();  
 | 
			
		||||
        return expr(f.ctx(), r); 
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#define MK_EXPR1(_fn, _arg)                     \
 | 
			
		||||
    Z3_ast r = _fn(_arg.ctx(), _arg);           \
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -63,6 +63,13 @@ namespace Microsoft.Z3
 | 
			
		|||
            Contract.Requires(domain != null);
 | 
			
		||||
            Contract.Requires(range != null);
 | 
			
		||||
        }
 | 
			
		||||
        internal ArraySort(Context ctx, Sort[] domain, Sort range)
 | 
			
		||||
            : base(ctx, Native.Z3_mk_array_sort_n(ctx.nCtx, (uint)domain.Length, AST.ArrayToNative(domain), range.NativeObject))
 | 
			
		||||
        {
 | 
			
		||||
            Contract.Requires(ctx != null);
 | 
			
		||||
            Contract.Requires(domain != null);
 | 
			
		||||
            Contract.Requires(range != null);
 | 
			
		||||
        }
 | 
			
		||||
        #endregion
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -274,6 +274,20 @@ namespace Microsoft.Z3
 | 
			
		|||
            return new ArraySort(this, domain, range);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Create a new n-ary array sort.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public ArraySort MkArraySort(Sort[] domain, Sort range)
 | 
			
		||||
        {
 | 
			
		||||
            Contract.Requires(domain != null);
 | 
			
		||||
            Contract.Requires(range != null);
 | 
			
		||||
            Contract.Ensures(Contract.Result<ArraySort>() != null);
 | 
			
		||||
 | 
			
		||||
            CheckContextMatch<Sort>(domain);
 | 
			
		||||
            CheckContextMatch(range);
 | 
			
		||||
            return new ArraySort(this, domain, range);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Create a new tuple sort.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
| 
						 | 
				
			
			@ -2113,6 +2127,7 @@ namespace Microsoft.Z3
 | 
			
		|||
            return (ArrayExpr)MkConst(MkSymbol(name), MkArraySort(domain, range));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Array read.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
| 
						 | 
				
			
			@ -2123,8 +2138,8 @@ namespace Microsoft.Z3
 | 
			
		|||
        /// The node <c>a</c> must have an array sort <c>[domain -> range]</c>,
 | 
			
		||||
        /// and <c>i</c> must have the sort <c>domain</c>.
 | 
			
		||||
        /// The sort of the result is <c>range</c>.
 | 
			
		||||
        /// <seealso cref="MkArraySort"/>
 | 
			
		||||
        /// <seealso cref="MkStore"/>
 | 
			
		||||
        /// <seealso cref="MkArraySort(Sort, Sort)"/>
 | 
			
		||||
        /// <seealso cref="MkStore(ArrayExpr, Expr, Expr)"/>
 | 
			
		||||
        /// </remarks>
 | 
			
		||||
        public Expr MkSelect(ArrayExpr a, Expr i)
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -2137,6 +2152,30 @@ namespace Microsoft.Z3
 | 
			
		|||
            return Expr.Create(this, Native.Z3_mk_select(nCtx, a.NativeObject, i.NativeObject));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Array read.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <remarks>
 | 
			
		||||
        /// The argument <c>a</c> is the array and <c>args</c> are the indices
 | 
			
		||||
        /// of the array that gets read.
 | 
			
		||||
        ///
 | 
			
		||||
        /// The node <c>a</c> must have an array sort <c>[domain1,..,domaink -> range]</c>,
 | 
			
		||||
        /// and <c>args</c> must have the sort <c>domain1,..,domaink</c>.
 | 
			
		||||
        /// The sort of the result is <c>range</c>.
 | 
			
		||||
        /// <seealso cref="MkArraySort(Sort, Sort)"/>
 | 
			
		||||
        /// <seealso cref="MkStore(ArrayExpr, Expr, Expr)"/>
 | 
			
		||||
        /// </remarks>
 | 
			
		||||
        public Expr MkSelect(ArrayExpr a, params Expr[] args)
 | 
			
		||||
        {
 | 
			
		||||
            Contract.Requires(a != null);
 | 
			
		||||
            Contract.Requires(args != null && Contract.ForAll(args, n => n != null));
 | 
			
		||||
            Contract.Ensures(Contract.Result<Expr>() != null);
 | 
			
		||||
 | 
			
		||||
            CheckContextMatch(a);
 | 
			
		||||
            CheckContextMatch<Expr>(args);
 | 
			
		||||
            return Expr.Create(this, Native.Z3_mk_select_n(nCtx, a.NativeObject, AST.ArrayLength(args), AST.ArrayToNative(args)));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Array update.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
| 
						 | 
				
			
			@ -2151,8 +2190,9 @@ namespace Microsoft.Z3
 | 
			
		|||
        /// on all indices except for <c>i</c>, where it maps to <c>v</c>
 | 
			
		||||
        /// (and the <c>select</c> of <c>a</c> with
 | 
			
		||||
        /// respect to <c>i</c> may be a different value).
 | 
			
		||||
        /// <seealso cref="MkArraySort"/>
 | 
			
		||||
        /// <seealso cref="MkSelect"/>
 | 
			
		||||
        /// <seealso cref="MkArraySort(Sort, Sort)"/>
 | 
			
		||||
        /// <seealso cref="MkSelect(ArrayExpr, Expr)"/>
 | 
			
		||||
        /// <seealso cref="MkSelect(ArrayExpr, Expr[])"/>
 | 
			
		||||
        /// </remarks>
 | 
			
		||||
        public ArrayExpr MkStore(ArrayExpr a, Expr i, Expr v)
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -2167,14 +2207,45 @@ namespace Microsoft.Z3
 | 
			
		|||
            return new ArrayExpr(this, Native.Z3_mk_store(nCtx, a.NativeObject, i.NativeObject, v.NativeObject));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Array update.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <remarks>
 | 
			
		||||
        /// The node <c>a</c> must have an array sort <c>[domain1,..,domaink -> range]</c>,
 | 
			
		||||
        /// <c>args</c> must have sort <c>domain1,..,domaink</c>,
 | 
			
		||||
        /// <c>v</c> must have sort range. The sort of the result is <c>[domain -> range]</c>.
 | 
			
		||||
        /// The semantics of this function is given by the theory of arrays described in the SMT-LIB
 | 
			
		||||
        /// standard. See http://smtlib.org for more details.
 | 
			
		||||
        /// The result of this function is an array that is equal to <c>a</c>
 | 
			
		||||
        /// (with respect to <c>select</c>)
 | 
			
		||||
        /// on all indices except for <c>args</c>, where it maps to <c>v</c>
 | 
			
		||||
        /// (and the <c>select</c> of <c>a</c> with
 | 
			
		||||
        /// respect to <c>args</c> may be a different value).
 | 
			
		||||
        /// <seealso cref="MkArraySort(Sort, Sort)"/>
 | 
			
		||||
        /// <seealso cref="MkSelect(ArrayExpr, Expr)"/>
 | 
			
		||||
        /// <seealso cref="MkSelect(ArrayExpr, Expr[])"/>
 | 
			
		||||
        /// </remarks>
 | 
			
		||||
        public ArrayExpr MkStore(ArrayExpr a, Expr[] args, Expr v)
 | 
			
		||||
        {
 | 
			
		||||
            Contract.Requires(a != null);
 | 
			
		||||
            Contract.Requires(args != null);
 | 
			
		||||
            Contract.Requires(v != null);
 | 
			
		||||
            Contract.Ensures(Contract.Result<ArrayExpr>() != null);
 | 
			
		||||
 | 
			
		||||
            CheckContextMatch<Expr>(args);
 | 
			
		||||
            CheckContextMatch(a);
 | 
			
		||||
            CheckContextMatch(v);
 | 
			
		||||
            return new ArrayExpr(this, Native.Z3_mk_store_n(nCtx, a.NativeObject, AST.ArrayLength(args), AST.ArrayToNative(args), v.NativeObject));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Create a constant array.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <remarks>
 | 
			
		||||
        /// The resulting term is an array, such that a <c>select</c>on an arbitrary index
 | 
			
		||||
        /// produces the value <c>v</c>.
 | 
			
		||||
        /// <seealso cref="MkArraySort"/>
 | 
			
		||||
        /// <seealso cref="MkSelect"/>
 | 
			
		||||
        /// <seealso cref="MkArraySort(Sort, Sort)"/>
 | 
			
		||||
        /// <seealso cref="MkSelect(ArrayExpr, Expr)"/>
 | 
			
		||||
        /// </remarks>
 | 
			
		||||
        public ArrayExpr MkConstArray(Sort domain, Expr v)
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -2194,9 +2265,9 @@ namespace Microsoft.Z3
 | 
			
		|||
        /// Eeach element of <c>args</c> must be of an array sort <c>[domain_i -> range_i]</c>.
 | 
			
		||||
        /// The function declaration <c>f</c> must have type <c> range_1 .. range_n -> range</c>.
 | 
			
		||||
        /// <c>v</c> must have sort range. The sort of the result is <c>[domain_i -> range]</c>.
 | 
			
		||||
        /// <seealso cref="MkArraySort"/>
 | 
			
		||||
        /// <seealso cref="MkSelect"/>
 | 
			
		||||
        /// <seealso cref="MkStore"/>
 | 
			
		||||
        /// <seealso cref="MkArraySort(Sort, Sort)"/>
 | 
			
		||||
        /// <seealso cref="MkSelect(ArrayExpr, Expr)"/>
 | 
			
		||||
        /// <seealso cref="MkStore(ArrayExpr, Expr, Expr)"/>
 | 
			
		||||
        /// </remarks>
 | 
			
		||||
        public ArrayExpr MkMap(FuncDecl f, params ArrayExpr[] args)
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -56,4 +56,10 @@ public class ArraySort extends Sort
 | 
			
		|||
        super(ctx, Native.mkArraySort(ctx.nCtx(), domain.getNativeObject(),
 | 
			
		||||
                range.getNativeObject()));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ArraySort(Context ctx, Sort[] domains, Sort range)
 | 
			
		||||
    {
 | 
			
		||||
        super(ctx, Native.mkArraySortN(ctx.nCtx(), domains.length, AST.arrayToNative(domains),
 | 
			
		||||
                range.getNativeObject()));
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -224,6 +224,17 @@ public class Context implements AutoCloseable {
 | 
			
		|||
        return new ArraySort(this, domain, range);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a new array sort.
 | 
			
		||||
     **/
 | 
			
		||||
    public ArraySort mkArraySort(Sort[] domains, Sort range)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(domains);
 | 
			
		||||
        checkContextMatch(range);
 | 
			
		||||
        return new ArraySort(this, domains, range);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a new string sort
 | 
			
		||||
     **/
 | 
			
		||||
| 
						 | 
				
			
			@ -414,7 +425,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
     * that is passed in as argument is updated with value v,
 | 
			
		||||
     * the remaining fields of t are unchanged.
 | 
			
		||||
     **/
 | 
			
		||||
    public Expr MkUpdateField(FuncDecl field, Expr t, Expr v) 
 | 
			
		||||
    public Expr mkUpdateField(FuncDecl field, Expr t, Expr v) 
 | 
			
		||||
        throws Z3Exception
 | 
			
		||||
    {
 | 
			
		||||
        return Expr.create (this, 
 | 
			
		||||
| 
						 | 
				
			
			@ -706,7 +717,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Mk an expression representing {@code not(a)}.
 | 
			
		||||
     * Create an expression representing {@code not(a)}.
 | 
			
		||||
     **/
 | 
			
		||||
    public BoolExpr mkNot(BoolExpr a)
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			@ -1679,6 +1690,28 @@ public class Context implements AutoCloseable {
 | 
			
		|||
                        i.getNativeObject()));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Array read.
 | 
			
		||||
     * Remarks:  The argument {@code a} is the array and
 | 
			
		||||
     * {@code args} are the indices of the array that gets read.
 | 
			
		||||
     * 
 | 
			
		||||
     * The node {@code a} must have an array sort
 | 
			
		||||
     * {@code [domains -> range]}, and {@code args} must have the sorts
 | 
			
		||||
     * {@code domains}. The sort of the result is {@code range}.
 | 
			
		||||
     * 
 | 
			
		||||
     * @see #mkArraySort
 | 
			
		||||
     * @see #mkStore
 | 
			
		||||
 | 
			
		||||
     **/
 | 
			
		||||
    public Expr mkSelect(ArrayExpr a, Expr[] args)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(a);
 | 
			
		||||
        checkContextMatch(args);
 | 
			
		||||
        return Expr.create(
 | 
			
		||||
                this,
 | 
			
		||||
                Native.mkSelectN(nCtx(), a.getNativeObject(), args.length, AST.arrayToNative(args)));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Array update.
 | 
			
		||||
     * Remarks:  The node {@code a} must have an array sort
 | 
			
		||||
| 
						 | 
				
			
			@ -1704,6 +1737,31 @@ public class Context implements AutoCloseable {
 | 
			
		|||
                i.getNativeObject(), v.getNativeObject()));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Array update.
 | 
			
		||||
     * Remarks:  The node {@code a} must have an array sort
 | 
			
		||||
     * {@code [domains -> range]}, {@code i} must have sort
 | 
			
		||||
     * {@code domain}, {@code v} must have sort range. The sort of the
 | 
			
		||||
     * result is {@code [domains -> range]}. The semantics of this function
 | 
			
		||||
     * is given by the theory of arrays described in the SMT-LIB standard. See
 | 
			
		||||
     * http://smtlib.org for more details. The result of this function is an
 | 
			
		||||
     * array that is equal to {@code a} (with respect to
 | 
			
		||||
     * {@code select}) on all indices except for {@code args}, where it
 | 
			
		||||
     * maps to {@code v} (and the {@code select} of {@code a}
 | 
			
		||||
     * with respect to {@code args} may be a different value). 
 | 
			
		||||
     * @see #mkArraySort
 | 
			
		||||
     * @see #mkSelect
 | 
			
		||||
 | 
			
		||||
     **/
 | 
			
		||||
    public ArrayExpr mkStore(ArrayExpr a, Expr[] args, Expr v)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(a);
 | 
			
		||||
        checkContextMatch(args);
 | 
			
		||||
        checkContextMatch(v);
 | 
			
		||||
        return new ArrayExpr(this, Native.mkStoreN(nCtx(), a.getNativeObject(),
 | 
			
		||||
                             args.length, AST.arrayToNative(args), v.getNativeObject()));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a constant array.
 | 
			
		||||
     * Remarks:  The resulting term is an array, such
 | 
			
		||||
| 
						 | 
				
			
			@ -2104,7 +2162,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Create a range expression.
 | 
			
		||||
     */
 | 
			
		||||
    public ReExpr MkRange(SeqExpr lo, SeqExpr hi) 
 | 
			
		||||
    public ReExpr mkRange(SeqExpr lo, SeqExpr hi) 
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(lo, hi);
 | 
			
		||||
        return (ReExpr) Expr.create(this, Native.mkReRange(nCtx(), lo.getNativeObject(), hi.getNativeObject()));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -120,7 +120,7 @@ def _get_args(args):
 | 
			
		|||
    try:
 | 
			
		||||
        if len(args) == 1 and (isinstance(args[0], tuple) or isinstance(args[0], list)):
 | 
			
		||||
            return args[0]
 | 
			
		||||
        elif len(args) == 1 and isinstance(args[0], set):
 | 
			
		||||
        elif len(args) == 1 and (isinstance(args[0], set) or isinstance(args[0], AstVector)):
 | 
			
		||||
            return [arg for arg in args[0]]
 | 
			
		||||
        else:
 | 
			
		||||
            return args
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -993,18 +993,6 @@ typedef enum
 | 
			
		|||
            3 = 011 = Z3_OP_FPA_RM_TOWARD_NEGATIVE,
 | 
			
		||||
            4 = 100 = Z3_OP_FPA_RM_TOWARD_ZERO.
 | 
			
		||||
 | 
			
		||||
      - Z3_OP_FPA_MIN_I: The same as Z3_OP_FPA_MIN, but the arguments are
 | 
			
		||||
        expected not to be zeroes with different signs.
 | 
			
		||||
 | 
			
		||||
      - Z3_OP_FPA_MAX_I: The same as Z3_OP_FPA_MAX, but the arguments are
 | 
			
		||||
        expected not to be zeroes with different signs.
 | 
			
		||||
 | 
			
		||||
      - Z3_OP_FPA_MIN_UNSPECIFIED: The same as Z3_OP_FPA_MIN, but the
 | 
			
		||||
        arguments are expected to be zeroes with different signs.
 | 
			
		||||
 | 
			
		||||
      - Z3_OP_FPA_MAX_UNSPECIFIED: The same as Z3_OP_FPA_MAX, but the
 | 
			
		||||
        arguments are expected to be zeroes with different signs.
 | 
			
		||||
 | 
			
		||||
      - Z3_OP_INTERNAL: internal (often interpreted) symbol, but no additional
 | 
			
		||||
        information is exposed. Tools may use the string representation of the
 | 
			
		||||
        function declaration to obtain more information.
 | 
			
		||||
| 
						 | 
				
			
			@ -1291,13 +1279,8 @@ typedef enum {
 | 
			
		|||
 | 
			
		||||
    Z3_OP_FPA_TO_IEEE_BV,
 | 
			
		||||
 | 
			
		||||
    Z3_OP_FPA_MIN_I,
 | 
			
		||||
    Z3_OP_FPA_MAX_I,
 | 
			
		||||
 | 
			
		||||
    Z3_OP_FPA_BVWRAP,
 | 
			
		||||
    Z3_OP_FPA_BV2RM,
 | 
			
		||||
    Z3_OP_FPA_MIN_UNSPECIFIED,
 | 
			
		||||
    Z3_OP_FPA_MAX_UNSPECIFIED,
 | 
			
		||||
 | 
			
		||||
    Z3_OP_INTERNAL,
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1898,6 +1881,17 @@ extern "C" {
 | 
			
		|||
    */
 | 
			
		||||
    Z3_sort Z3_API Z3_mk_array_sort(Z3_context c, Z3_sort domain, Z3_sort range);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
       \brief Create an array type with N arguments
 | 
			
		||||
 | 
			
		||||
       \sa Z3_mk_select_n
 | 
			
		||||
       \sa Z3_mk_store_n
 | 
			
		||||
 | 
			
		||||
       def_API('Z3_mk_array_sort_n', SORT, (_in(CONTEXT), _in(UINT), _in_array(1, SORT), _in(SORT)))
 | 
			
		||||
    */
 | 
			
		||||
    Z3_sort Z3_API Z3_mk_array_sort_n(Z3_context c, unsigned n, Z3_sort const * domain, Z3_sort range);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
       \brief Create a tuple type.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2990,6 +2984,15 @@ extern "C" {
 | 
			
		|||
    */
 | 
			
		||||
    Z3_ast Z3_API Z3_mk_select(Z3_context c, Z3_ast a, Z3_ast i);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
       \brief n-ary Array read.
 | 
			
		||||
       The argument \c a is the array and \c idxs are the indices of the array that gets read.
 | 
			
		||||
 | 
			
		||||
       def_API('Z3_mk_select_n', AST, (_in(CONTEXT), _in(AST), _in(UINT), _in_array(2, AST)))
 | 
			
		||||
 | 
			
		||||
    */
 | 
			
		||||
    Z3_ast Z3_API Z3_mk_select_n(Z3_context c, Z3_ast a, unsigned n, Z3_ast const* idxs);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
       \brief Array update.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3008,6 +3011,14 @@ extern "C" {
 | 
			
		|||
    */
 | 
			
		||||
    Z3_ast Z3_API Z3_mk_store(Z3_context c, Z3_ast a, Z3_ast i, Z3_ast v);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
       \brief n-ary Array update.
 | 
			
		||||
 | 
			
		||||
       def_API('Z3_mk_store_n', AST, (_in(CONTEXT), _in(AST), _in(UINT), _in_array(2, AST), _in(AST)))
 | 
			
		||||
 | 
			
		||||
    */
 | 
			
		||||
    Z3_ast Z3_API Z3_mk_store_n(Z3_context c, Z3_ast a, unsigned n, Z3_ast const* idxs, Z3_ast v);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
        \brief Create the constant array.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3048,6 +3059,15 @@ extern "C" {
 | 
			
		|||
        def_API('Z3_mk_array_default', AST, (_in(CONTEXT), _in(AST)))
 | 
			
		||||
    */
 | 
			
		||||
    Z3_ast Z3_API Z3_mk_array_default(Z3_context c, Z3_ast array);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
       \brief Create array with the same interpretation as a function.
 | 
			
		||||
       The array satisfies the property (f x) = (select (_ as-array f) x) 
 | 
			
		||||
       for every argument x.
 | 
			
		||||
 | 
			
		||||
       def_API('Z3_mk_as_array', AST, (_in(CONTEXT), _in(FUNC_DECL)))
 | 
			
		||||
     */
 | 
			
		||||
    Z3_ast Z3_API Z3_mk_as_array(Z3_context c, Z3_func_decl f);
 | 
			
		||||
    /*@}*/
 | 
			
		||||
 | 
			
		||||
    /** @name Sets */
 | 
			
		||||
| 
						 | 
				
			
			@ -3871,6 +3891,7 @@ extern "C" {
 | 
			
		|||
 | 
			
		||||
    /**
 | 
			
		||||
       \brief Return the domain of the given array sort.
 | 
			
		||||
       In the case of a multi-dimensional array, this function returns the sort of the first dimension.
 | 
			
		||||
 | 
			
		||||
       \pre Z3_get_sort_kind(c, t) == Z3_ARRAY_SORT
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -197,4 +197,4 @@ extern "C" {
 | 
			
		|||
}
 | 
			
		||||
#endif // __cplusplus
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -242,7 +242,9 @@ func_decl* array_decl_plugin::mk_select(unsigned arity, sort * const * domain) {
 | 
			
		|||
    parameter const* parameters = s->get_parameters();
 | 
			
		||||
 
 | 
			
		||||
    if (num_parameters != arity) {
 | 
			
		||||
        m_manager->raise_exception("select requires as many arguments as the size of the domain");
 | 
			
		||||
        std::stringstream strm;
 | 
			
		||||
        strm << "select requires " << num_parameters << " arguments, but was provided with " << arity << " arguments";
 | 
			
		||||
        m_manager->raise_exception(strm.str().c_str());
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
    ptr_buffer<sort> new_domain; // we need this because of coercions.
 | 
			
		||||
| 
						 | 
				
			
			@ -314,7 +316,7 @@ func_decl * array_decl_plugin::mk_array_ext(unsigned arity, sort * const * domai
 | 
			
		|||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
    sort * r = to_sort(s->get_parameter(i).get_ast());
 | 
			
		||||
    parameter param(s);
 | 
			
		||||
    parameter param(i);
 | 
			
		||||
    return m_manager->mk_func_decl(m_array_ext_sym, arity, domain, r, func_decl_info(m_family_id, OP_ARRAY_EXT, 1, ¶m));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -592,3 +594,9 @@ sort * array_util::mk_array_sort(unsigned arity, sort* const* domain, sort* rang
 | 
			
		|||
    params.push_back(parameter(range));
 | 
			
		||||
    return m_manager.mk_sort(m_fid, ARRAY_SORT, params.size(), params.c_ptr());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func_decl* array_util::mk_array_ext(sort *domain, unsigned i) {    
 | 
			
		||||
    sort * domains[2] = { domain, domain };
 | 
			
		||||
    parameter p(i);
 | 
			
		||||
    return m_manager.mk_func_decl(m_fid, OP_ARRAY_EXT, 1, &p, 2, domains);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -143,6 +143,7 @@ public:
 | 
			
		|||
    bool is_const(expr* n) const { return is_app_of(n, m_fid, OP_CONST_ARRAY); }
 | 
			
		||||
    bool is_map(expr* n) const { return is_app_of(n, m_fid, OP_ARRAY_MAP); }
 | 
			
		||||
    bool is_as_array(expr * n) const { return is_app_of(n, m_fid, OP_AS_ARRAY); }
 | 
			
		||||
    bool is_as_array(expr * n, func_decl*& f) const { return is_as_array(n) && (f = get_as_array_func_decl(n), true); }
 | 
			
		||||
    bool is_select(func_decl* f) const { return is_decl_of(f, m_fid, OP_SELECT); }
 | 
			
		||||
    bool is_store(func_decl* f) const { return is_decl_of(f, m_fid, OP_STORE); }
 | 
			
		||||
    bool is_const(func_decl* f) const { return is_decl_of(f, m_fid, OP_CONST_ARRAY); }
 | 
			
		||||
| 
						 | 
				
			
			@ -182,13 +183,15 @@ public:
 | 
			
		|||
        return mk_const_array(s, m_manager.mk_true());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    func_decl * mk_array_ext(sort* domain, unsigned i);
 | 
			
		||||
 | 
			
		||||
    sort * mk_array_sort(sort* dom, sort* range) { return mk_array_sort(1, &dom, range); }
 | 
			
		||||
 | 
			
		||||
    sort * mk_array_sort(unsigned arity, sort* const* domain, sort* range);
 | 
			
		||||
 | 
			
		||||
    app * mk_as_array(sort * s, func_decl * f) {
 | 
			
		||||
    app * mk_as_array(func_decl * f) {
 | 
			
		||||
        parameter param(f);
 | 
			
		||||
        return m_manager.mk_app(m_fid, OP_AS_ARRAY, 1, ¶m, 0, 0, s);
 | 
			
		||||
        return m_manager.mk_app(m_fid, OP_AS_ARRAY, 1, ¶m, 0, 0, 0);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -471,6 +471,9 @@ bool compare_nodes(ast const * n1, ast const * n2) {
 | 
			
		|||
            compare_arrays(to_quantifier(n1)->get_decl_sorts(),
 | 
			
		||||
                           to_quantifier(n2)->get_decl_sorts(),
 | 
			
		||||
                           to_quantifier(n1)->get_num_decls()) &&
 | 
			
		||||
            compare_arrays(to_quantifier(n1)->get_decl_names(),
 | 
			
		||||
                           to_quantifier(n2)->get_decl_names(),
 | 
			
		||||
                           to_quantifier(n1)->get_num_decls()) &&
 | 
			
		||||
            to_quantifier(n1)->get_expr()            == to_quantifier(n2)->get_expr() &&
 | 
			
		||||
            to_quantifier(n1)->get_weight()          == to_quantifier(n2)->get_weight() &&
 | 
			
		||||
            to_quantifier(n1)->get_num_patterns() == to_quantifier(n2)->get_num_patterns() &&
 | 
			
		||||
| 
						 | 
				
			
			@ -765,7 +768,7 @@ func_decl * basic_decl_plugin::mk_compressed_proof_decl(char const * name, basic
 | 
			
		|||
 | 
			
		||||
func_decl * basic_decl_plugin::mk_proof_decl(char const * name, basic_op_kind k, unsigned num_parents, ptr_vector<func_decl> & cache) {
 | 
			
		||||
    if (num_parents >= cache.size()) {
 | 
			
		||||
        cache.resize(num_parents+1, 0);
 | 
			
		||||
        cache.resize(num_parents+1);
 | 
			
		||||
    }
 | 
			
		||||
    if (cache[num_parents] == 0) {
 | 
			
		||||
        cache[num_parents] = mk_proof_decl(name, k, num_parents);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -121,6 +121,20 @@ public:
 | 
			
		|||
    explicit parameter(unsigned ext_id, bool):m_kind(PARAM_EXTERNAL), m_ext_id(ext_id) {}
 | 
			
		||||
    parameter(parameter const&);
 | 
			
		||||
 | 
			
		||||
    parameter(parameter && other) : m_kind(other.m_kind) {
 | 
			
		||||
        switch (other.m_kind) {
 | 
			
		||||
        case PARAM_INT: m_int = other.get_int(); break;
 | 
			
		||||
        case PARAM_AST: m_ast = other.get_ast(); break;
 | 
			
		||||
        case PARAM_SYMBOL: m_symbol = other.m_symbol; break;
 | 
			
		||||
        case PARAM_RATIONAL: m_rational = 0; std::swap(m_rational, other.m_rational); break;
 | 
			
		||||
        case PARAM_DOUBLE: m_dval = other.m_dval; break;
 | 
			
		||||
        case PARAM_EXTERNAL: m_ext_id = other.m_ext_id; break;
 | 
			
		||||
        default:
 | 
			
		||||
            UNREACHABLE();
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ~parameter();
 | 
			
		||||
 | 
			
		||||
    parameter& operator=(parameter const& other);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -584,6 +584,8 @@ class smt2_printer {
 | 
			
		|||
            string_buffer<> buf;
 | 
			
		||||
            buf.append("(:var ");
 | 
			
		||||
            buf.append(v->get_idx());
 | 
			
		||||
            //buf.append(" ");
 | 
			
		||||
            //buf.append(v->get_sort()->get_name().str().c_str());
 | 
			
		||||
            buf.append(")");
 | 
			
		||||
            f = mk_string(m(), buf.c_str());
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -863,8 +863,7 @@ app * bv_util::mk_numeral(rational const & val, sort* s) const {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
app * bv_util::mk_numeral(rational const & val, unsigned bv_size) const {
 | 
			
		||||
    parameter p1(val);
 | 
			
		||||
    parameter p[2] = { p1, parameter(static_cast<int>(bv_size)) };
 | 
			
		||||
    parameter p[2] = { parameter(val), parameter(static_cast<int>(bv_size)) };
 | 
			
		||||
    return m_manager.mk_app(get_fid(), OP_BV_NUM, 2, p, 0, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,6 +19,7 @@ Notes:
 | 
			
		|||
 | 
			
		||||
#include "ast/expr_abstract.h"
 | 
			
		||||
#include "util/map.h"
 | 
			
		||||
#include "ast/ast_pp.h"
 | 
			
		||||
 | 
			
		||||
void expr_abstractor::operator()(unsigned base, unsigned num_bound, expr* const* bound, expr* n, expr_ref& result) {
 | 
			
		||||
    
 | 
			
		||||
| 
						 | 
				
			
			@ -109,6 +110,9 @@ void expr_abstractor::operator()(unsigned base, unsigned num_bound, expr* const*
 | 
			
		|||
void expr_abstract(ast_manager& m, unsigned base, unsigned num_bound, expr* const* bound, expr* n, expr_ref&  result) {
 | 
			
		||||
    expr_abstractor abs(m);
 | 
			
		||||
    abs(base, num_bound, bound, n, result);
 | 
			
		||||
    TRACE("expr_abstract",
 | 
			
		||||
          tout << expr_ref(n, m) << "\n";
 | 
			
		||||
          tout << result << "\n";);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
expr_ref mk_quantifier(bool is_forall, ast_manager& m, unsigned num_bound, app* const* bound, expr* n) {
 | 
			
		||||
| 
						 | 
				
			
			@ -123,6 +127,11 @@ expr_ref mk_quantifier(bool is_forall, ast_manager& m, unsigned num_bound, app*
 | 
			
		|||
        }
 | 
			
		||||
        result = m.mk_quantifier(is_forall, num_bound, sorts.c_ptr(), names.c_ptr(), result);
 | 
			
		||||
    }
 | 
			
		||||
    TRACE("expr_abstract",
 | 
			
		||||
          tout << expr_ref(n, m) << "\n";
 | 
			
		||||
          for (unsigned i = 0; i < num_bound; ++i) tout << expr_ref(bound[i], m) << " ";
 | 
			
		||||
          tout << "\n";
 | 
			
		||||
          tout << result << "\n";);
 | 
			
		||||
    return result;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,8 +16,9 @@ Author:
 | 
			
		|||
Notes:
 | 
			
		||||
 | 
			
		||||
--*/
 | 
			
		||||
#include "ast/expr_substitution.h"
 | 
			
		||||
#include "util/ref_util.h"
 | 
			
		||||
#include "ast/expr_substitution.h"
 | 
			
		||||
#include "ast/ast_pp.h"
 | 
			
		||||
 | 
			
		||||
typedef obj_map<expr, proof*> expr2proof;
 | 
			
		||||
typedef obj_map<expr, expr_dependency*> expr2expr_dependency;
 | 
			
		||||
| 
						 | 
				
			
			@ -56,6 +57,13 @@ expr_substitution::~expr_substitution() {
 | 
			
		|||
    reset();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::ostream& expr_substitution::display(std::ostream& out) {
 | 
			
		||||
    for (auto & kv : m_subst) {
 | 
			
		||||
        out << mk_pp(kv.m_key, m()) << " |-> " << mk_pp(kv.m_value, m()) << "\n";
 | 
			
		||||
    }
 | 
			
		||||
    return out;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void expr_substitution::insert(expr * c, expr * def, proof * def_pr, expr_dependency * def_dep) {
 | 
			
		||||
    obj_map<expr, expr*>::obj_map_entry * entry = m_subst.insert_if_not_there2(c, 0); 
 | 
			
		||||
    if (entry->get_data().m_value == 0) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -50,6 +50,8 @@ public:
 | 
			
		|||
    bool contains(expr * s);
 | 
			
		||||
    void reset();
 | 
			
		||||
    void cleanup();
 | 
			
		||||
 | 
			
		||||
    std::ostream& display(std::ostream& out);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class scoped_expr_substitution {
 | 
			
		||||
| 
						 | 
				
			
			@ -78,12 +80,14 @@ public:
 | 
			
		|||
            m_trail_lim.resize(new_sz); 
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    unsigned scope_level() const { return m_trail_lim.size(); }
 | 
			
		||||
    bool empty() const { return m_subst.empty(); }
 | 
			
		||||
    expr* find(expr * e) { proof* pr; expr* d = 0; if (find(e, d, pr)) return d; else return e; }
 | 
			
		||||
    bool find(expr * s, expr * & def, proof * & def_pr) { return m_subst.find(s, def, def_pr); }
 | 
			
		||||
    bool find(expr * s, expr * & def, proof * & def_pr, expr_dependency * & def_dep) { return m_subst.find(s, def, def_pr, def_dep); }
 | 
			
		||||
    bool contains(expr * s) { return m_subst.contains(s); }
 | 
			
		||||
    void cleanup() { m_subst.cleanup(); }
 | 
			
		||||
    std::ostream& display(std::ostream& out) { return m_subst.display(out); }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -62,8 +62,8 @@ bv2fpa_converter::bv2fpa_converter(ast_manager & m, fpa2bv_converter & conv) :
 | 
			
		|||
        m.inc_ref(it->m_key);
 | 
			
		||||
        m.inc_ref(it->m_value);
 | 
			
		||||
    }
 | 
			
		||||
    for (obj_map<func_decl, std::pair<app*, app*> >::iterator it = conv.m_min_max_specials.begin();
 | 
			
		||||
        it != conv.m_min_max_specials.end();
 | 
			
		||||
    for (obj_map<func_decl, std::pair<app*, app*> >::iterator it = conv.m_min_max_ufs.begin();
 | 
			
		||||
        it != conv.m_min_max_ufs.end();
 | 
			
		||||
        it++) {
 | 
			
		||||
        m_specials.insert(it->m_key, it->m_value);
 | 
			
		||||
        m.inc_ref(it->m_key);
 | 
			
		||||
| 
						 | 
				
			
			@ -250,7 +250,7 @@ bv2fpa_converter::array_model bv2fpa_converter::convert_array_func_interp(model_
 | 
			
		|||
    am.new_float_fd = m.mk_fresh_func_decl(arity, array_domain.c_ptr(), rng);
 | 
			
		||||
    am.new_float_fi = convert_func_interp(mc, am.new_float_fd, bv_f);
 | 
			
		||||
    am.bv_fd = bv_f;
 | 
			
		||||
    am.result = arr_util.mk_as_array(f->get_range(), am.new_float_fd);
 | 
			
		||||
    am.result = arr_util.mk_as_array(am.new_float_fd);
 | 
			
		||||
    return am;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -230,39 +230,7 @@ void fpa2bv_converter::mk_var(unsigned base_inx, sort * srt, expr_ref & result)
 | 
			
		|||
    result = m_util.mk_fp(sgn, e, s);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void fpa2bv_converter::mk_function_output(sort * rng, func_decl * fbv, expr * const * new_args, expr_ref & result) {
 | 
			
		||||
    if (m_util.is_float(rng)) {
 | 
			
		||||
        unsigned ebits = m_util.get_ebits(rng);
 | 
			
		||||
        unsigned sbits = m_util.get_sbits(rng);
 | 
			
		||||
        unsigned bv_sz = ebits + sbits;
 | 
			
		||||
 | 
			
		||||
        app_ref na(m);
 | 
			
		||||
        na = m.mk_app(fbv, fbv->get_arity(), new_args);
 | 
			
		||||
        result = m_util.mk_fp(m_bv_util.mk_extract(bv_sz - 1, bv_sz - 1, na),
 | 
			
		||||
                              m_bv_util.mk_extract(bv_sz - 2, sbits - 1, na),
 | 
			
		||||
                              m_bv_util.mk_extract(sbits - 2, 0, na));
 | 
			
		||||
    }
 | 
			
		||||
    else if (m_util.is_rm(rng)) {
 | 
			
		||||
        app_ref na(m);
 | 
			
		||||
        na = m.mk_app(fbv, fbv->get_arity(), new_args);
 | 
			
		||||
        result = m_util.mk_bv2rm(na);
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
        result = m.mk_app(fbv, fbv->get_arity(), new_args);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func_decl * fpa2bv_converter::get_bv_uf(func_decl * f, sort * bv_rng, unsigned arity) {
 | 
			
		||||
    func_decl * res;
 | 
			
		||||
    if (!m_uf2bvuf.find(f, res)) {
 | 
			
		||||
        res = m.mk_fresh_func_decl(f->get_name(), symbol("bv"), arity, f->get_domain(), bv_rng);
 | 
			
		||||
        m_uf2bvuf.insert(f, res);
 | 
			
		||||
        m.inc_ref(f);
 | 
			
		||||
        m.inc_ref(res);
 | 
			
		||||
        TRACE("fpa2bv", tout << "New UF func_decl: " << std::endl << mk_ismt2_pp(res, m) << std::endl;);
 | 
			
		||||
    }
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
void fpa2bv_converter::mk_function(func_decl * f, unsigned num, expr * const * args, expr_ref & result)
 | 
			
		||||
void fpa2bv_converter::mk_uf(func_decl * f, unsigned num, expr * const * args, expr_ref & result)
 | 
			
		||||
{
 | 
			
		||||
    TRACE("fpa2bv", tout << "UF: " << mk_ismt2_pp(f, m) << std::endl; );
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -278,7 +246,7 @@ void fpa2bv_converter::mk_function(func_decl * f, unsigned num, expr * const * a
 | 
			
		|||
        unsigned sbits = m_util.get_sbits(rng);
 | 
			
		||||
        unsigned bv_sz = ebits+sbits;
 | 
			
		||||
        bv_rng = m_bv_util.mk_sort(bv_sz);
 | 
			
		||||
        func_decl * bv_f = get_bv_uf(f, bv_rng, num);
 | 
			
		||||
        func_decl * bv_f = mk_bv_uf(f, f->get_domain(), bv_rng);
 | 
			
		||||
        bv_app = m.mk_app(bv_f, num, args);
 | 
			
		||||
        flt_app = m_util.mk_fp(m_bv_util.mk_extract(bv_sz-1, bv_sz-1, bv_app),
 | 
			
		||||
                               m_bv_util.mk_extract(sbits+ebits-2, sbits-1, bv_app),
 | 
			
		||||
| 
						 | 
				
			
			@ -291,7 +259,7 @@ void fpa2bv_converter::mk_function(func_decl * f, unsigned num, expr * const * a
 | 
			
		|||
        sort_ref bv_rng(m);
 | 
			
		||||
        expr_ref new_eq(m);
 | 
			
		||||
        bv_rng = m_bv_util.mk_sort(3);
 | 
			
		||||
        func_decl * bv_f = get_bv_uf(f, bv_rng, num);
 | 
			
		||||
        func_decl * bv_f = mk_bv_uf(f, f->get_domain(), bv_rng);
 | 
			
		||||
        bv_app = m.mk_app(bv_f, num, args);
 | 
			
		||||
        flt_app = m_util.mk_bv2rm(bv_app);
 | 
			
		||||
        new_eq = m.mk_eq(fapp, flt_app);
 | 
			
		||||
| 
						 | 
				
			
			@ -1211,61 +1179,85 @@ void fpa2bv_converter::mk_abs(sort * s, expr_ref & x, expr_ref & result) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
void fpa2bv_converter::mk_min(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
 | 
			
		||||
    expr_ref x(m), y(m);
 | 
			
		||||
    x = args[0];
 | 
			
		||||
    y = args[1];
 | 
			
		||||
 | 
			
		||||
    expr_ref x_is_zero(m), y_is_zero(m), both_are_zero(m);
 | 
			
		||||
    x_is_zero = m_util.mk_is_zero(x);
 | 
			
		||||
    y_is_zero = m_util.mk_is_zero(y);
 | 
			
		||||
    both_are_zero = m.mk_and(x_is_zero, y_is_zero);
 | 
			
		||||
 | 
			
		||||
    expr_ref x_is_positive(m), x_is_negative(m), y_is_positive(m), y_is_negative(m), pn(m), np(m), pn_or_np(m);
 | 
			
		||||
    x_is_positive = m_util.mk_is_positive(x);
 | 
			
		||||
    x_is_negative = m_util.mk_is_negative(x);
 | 
			
		||||
    y_is_positive = m_util.mk_is_positive(y);
 | 
			
		||||
    y_is_negative = m_util.mk_is_negative(y);
 | 
			
		||||
    pn = m.mk_and(x_is_positive, y_is_negative);
 | 
			
		||||
    np = m.mk_and(x_is_negative, y_is_positive);
 | 
			
		||||
    pn_or_np = m.mk_or(pn, np);
 | 
			
		||||
 | 
			
		||||
    expr_ref c(m), v(m);
 | 
			
		||||
    c = m.mk_and(both_are_zero, pn_or_np);
 | 
			
		||||
    v = m.mk_app(m_util.get_family_id(), OP_FPA_MIN_UNSPECIFIED, x, y);
 | 
			
		||||
 | 
			
		||||
    // Note: This requires BR_REWRITE_FULL afterwards.
 | 
			
		||||
    expr_ref min_i(m);
 | 
			
		||||
    min_i = m.mk_app(m_util.get_family_id(), OP_FPA_MIN_I, x, y);
 | 
			
		||||
    m_simp.mk_ite(c, v, min_i, result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void fpa2bv_converter::mk_min_i(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
 | 
			
		||||
    SASSERT(num == 2);
 | 
			
		||||
 | 
			
		||||
    expr * x = args[0], * y = args[1];
 | 
			
		||||
 | 
			
		||||
    expr * x_sgn, * x_sig, * x_exp;
 | 
			
		||||
    expr * y_sgn, * y_sig, * y_exp;
 | 
			
		||||
    expr * x_sgn, *x_sig, *x_exp;
 | 
			
		||||
    expr * y_sgn, *y_sig, *y_exp;
 | 
			
		||||
    split_fp(x, x_sgn, x_exp, x_sig);
 | 
			
		||||
    split_fp(y, y_sgn, y_exp, y_sig);
 | 
			
		||||
 | 
			
		||||
    expr_ref x_is_nan(m), y_is_nan(m), x_is_zero(m), y_is_zero(m), both_zero(m), pzero(m);
 | 
			
		||||
    mk_is_zero(x, x_is_zero);
 | 
			
		||||
    mk_is_zero(y, y_is_zero);
 | 
			
		||||
    m_simp.mk_and(x_is_zero, y_is_zero, both_zero);
 | 
			
		||||
    expr_ref bv0(m), bv1(m);
 | 
			
		||||
    bv0 = m_bv_util.mk_numeral(0, 1);
 | 
			
		||||
    bv1 = m_bv_util.mk_numeral(1, 1);
 | 
			
		||||
 | 
			
		||||
    expr_ref x_is_nan(m), y_is_nan(m), x_is_zero(m), y_is_zero(m), xy_are_zero(m);
 | 
			
		||||
    mk_is_nan(x, x_is_nan);
 | 
			
		||||
    mk_is_nan(y, y_is_nan);
 | 
			
		||||
    mk_pzero(f, pzero);
 | 
			
		||||
    mk_is_zero(x, x_is_zero);
 | 
			
		||||
    mk_is_zero(y, y_is_zero);
 | 
			
		||||
    xy_are_zero = m.mk_and(x_is_zero, y_is_zero);
 | 
			
		||||
 | 
			
		||||
    expr_ref sgn_eq(m), sgn_diff(m);
 | 
			
		||||
    sgn_eq = m.mk_eq(x_sgn, y_sgn);
 | 
			
		||||
    sgn_diff = m.mk_not(sgn_eq);
 | 
			
		||||
    expr_ref x_is_pos(m), x_is_neg(m);
 | 
			
		||||
    expr_ref y_is_pos(m), y_is_neg(m);
 | 
			
		||||
    expr_ref pn(m), np(m), pn_or_np_zeros(m);
 | 
			
		||||
    mk_is_pos(x, x_is_pos);
 | 
			
		||||
    mk_is_pos(y, y_is_pos);
 | 
			
		||||
    mk_is_neg(x, x_is_neg);
 | 
			
		||||
    mk_is_neg(y, y_is_neg);
 | 
			
		||||
    pn_or_np_zeros = m.mk_and(xy_are_zero, m.mk_not(m.mk_eq(x_sgn, y_sgn)));
 | 
			
		||||
 | 
			
		||||
    expr_ref lt(m);
 | 
			
		||||
    mk_float_lt(f, num, args, lt);
 | 
			
		||||
    expr_ref unspec(m);
 | 
			
		||||
    unspec = mk_min_max_unspecified(f, x, y);
 | 
			
		||||
 | 
			
		||||
    mk_ite(lt, x, y, result);
 | 
			
		||||
    mk_ite(both_zero, y, result, result);
 | 
			
		||||
    expr_ref x_lt_y(m);
 | 
			
		||||
    mk_float_lt(f, num, args, x_lt_y);
 | 
			
		||||
 | 
			
		||||
    mk_ite(x_lt_y, x, y, result);
 | 
			
		||||
    mk_ite(xy_are_zero, y, result, result);
 | 
			
		||||
    mk_ite(pn_or_np_zeros, unspec, result, result);
 | 
			
		||||
    mk_ite(y_is_nan, x, result, result);
 | 
			
		||||
    mk_ite(x_is_nan, y, result, result);
 | 
			
		||||
 | 
			
		||||
    SASSERT(is_well_sorted(m, result));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void fpa2bv_converter::mk_max(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
 | 
			
		||||
    SASSERT(num == 2);
 | 
			
		||||
 | 
			
		||||
    expr * x = args[0], *y = args[1];
 | 
			
		||||
 | 
			
		||||
    expr * x_sgn, *x_sig, *x_exp;
 | 
			
		||||
    expr * y_sgn, *y_sig, *y_exp;
 | 
			
		||||
    split_fp(x, x_sgn, x_exp, x_sig);
 | 
			
		||||
    split_fp(y, y_sgn, y_exp, y_sig);
 | 
			
		||||
 | 
			
		||||
    expr_ref x_is_nan(m), y_is_nan(m), x_is_zero(m), y_is_zero(m), xy_are_zero(m);
 | 
			
		||||
    mk_is_nan(x, x_is_nan);
 | 
			
		||||
    mk_is_nan(y, y_is_nan);
 | 
			
		||||
    mk_is_zero(x, x_is_zero);
 | 
			
		||||
    mk_is_zero(y, y_is_zero);
 | 
			
		||||
    xy_are_zero = m.mk_and(x_is_zero, y_is_zero);
 | 
			
		||||
 | 
			
		||||
    expr_ref x_is_pos(m), x_is_neg(m);
 | 
			
		||||
    expr_ref y_is_pos(m), y_is_neg(m);
 | 
			
		||||
    expr_ref pn(m), np(m), pn_or_np_zeros(m);
 | 
			
		||||
    mk_is_pos(x, x_is_pos);
 | 
			
		||||
    mk_is_pos(y, y_is_pos);
 | 
			
		||||
    mk_is_neg(x, x_is_neg);
 | 
			
		||||
    mk_is_neg(y, y_is_neg);
 | 
			
		||||
    pn_or_np_zeros = m.mk_and(xy_are_zero, m.mk_not(m.mk_eq(x_sgn, y_sgn)));
 | 
			
		||||
 | 
			
		||||
    expr_ref unspec(m);
 | 
			
		||||
    unspec = mk_min_max_unspecified(f, x, y);
 | 
			
		||||
 | 
			
		||||
    expr_ref x_gt_y(m);
 | 
			
		||||
    mk_float_gt(f, num, args, x_gt_y);
 | 
			
		||||
 | 
			
		||||
    mk_ite(x_gt_y, x, y, result);
 | 
			
		||||
    mk_ite(xy_are_zero, y, result, result);
 | 
			
		||||
    mk_ite(pn_or_np_zeros, unspec, result, result);
 | 
			
		||||
    mk_ite(y_is_nan, x, result, result);
 | 
			
		||||
    mk_ite(x_is_nan, y, result, result);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1281,10 +1273,10 @@ expr_ref fpa2bv_converter::mk_min_max_unspecified(func_decl * f, expr * x, expr
 | 
			
		|||
    // There is no "hardware interpretation" for fp.min/fp.max.
 | 
			
		||||
 | 
			
		||||
    std::pair<app*, app*> decls(0, 0);
 | 
			
		||||
    if (!m_min_max_specials.find(f, decls)) {
 | 
			
		||||
    if (!m_min_max_ufs.find(f, decls)) {
 | 
			
		||||
        decls.first = m.mk_fresh_const(0, m_bv_util.mk_sort(1));
 | 
			
		||||
        decls.second = m.mk_fresh_const(0, m_bv_util.mk_sort(1));
 | 
			
		||||
        m_min_max_specials.insert(f, decls);
 | 
			
		||||
        m_min_max_ufs.insert(f, decls);
 | 
			
		||||
        m.inc_ref(f);
 | 
			
		||||
        m.inc_ref(decls.first);
 | 
			
		||||
        m.inc_ref(decls.second);
 | 
			
		||||
| 
						 | 
				
			
			@ -1303,68 +1295,6 @@ expr_ref fpa2bv_converter::mk_min_max_unspecified(func_decl * f, expr * x, expr
 | 
			
		|||
    return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void fpa2bv_converter::mk_max(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
 | 
			
		||||
    expr_ref x(m), y(m);
 | 
			
		||||
    x = args[0];
 | 
			
		||||
    y = args[1];
 | 
			
		||||
 | 
			
		||||
    expr_ref x_is_zero(m), y_is_zero(m), both_are_zero(m);
 | 
			
		||||
    x_is_zero = m_util.mk_is_zero(x);
 | 
			
		||||
    y_is_zero = m_util.mk_is_zero(y);
 | 
			
		||||
    both_are_zero = m.mk_and(x_is_zero, y_is_zero);
 | 
			
		||||
 | 
			
		||||
    expr_ref x_is_positive(m), x_is_negative(m), y_is_positive(m), y_is_negative(m), pn(m), np(m), pn_or_np(m);
 | 
			
		||||
    x_is_positive = m_util.mk_is_positive(x);
 | 
			
		||||
    x_is_negative = m_util.mk_is_negative(x);
 | 
			
		||||
    y_is_positive = m_util.mk_is_positive(y);
 | 
			
		||||
    y_is_negative = m_util.mk_is_negative(y);
 | 
			
		||||
    pn = m.mk_and(x_is_positive, y_is_negative);
 | 
			
		||||
    np = m.mk_and(x_is_negative, y_is_positive);
 | 
			
		||||
    pn_or_np = m.mk_or(pn, np);
 | 
			
		||||
 | 
			
		||||
    expr_ref c(m), v(m);
 | 
			
		||||
    c = m.mk_and(both_are_zero, pn_or_np);
 | 
			
		||||
    v = m.mk_app(m_util.get_family_id(), OP_FPA_MAX_UNSPECIFIED, x, y);
 | 
			
		||||
 | 
			
		||||
    // Note: This requires BR_REWRITE_FULL afterwards.
 | 
			
		||||
    expr_ref max_i(m);
 | 
			
		||||
    max_i = m.mk_app(m_util.get_family_id(), OP_FPA_MAX_I, x, y);
 | 
			
		||||
    m_simp.mk_ite(c, v, max_i, result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void fpa2bv_converter::mk_max_i(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
 | 
			
		||||
    SASSERT(num == 2);
 | 
			
		||||
 | 
			
		||||
    expr * x = args[0], *y = args[1];
 | 
			
		||||
 | 
			
		||||
    expr * x_sgn, *x_sig, *x_exp;
 | 
			
		||||
    expr * y_sgn, *y_sig, *y_exp;
 | 
			
		||||
    split_fp(x, x_sgn, x_exp, x_sig);
 | 
			
		||||
    split_fp(y, y_sgn, y_exp, y_sig);
 | 
			
		||||
 | 
			
		||||
    expr_ref x_is_nan(m), y_is_nan(m), x_is_zero(m), y_is_zero(m), both_zero(m), pzero(m);
 | 
			
		||||
    mk_is_zero(x, x_is_zero);
 | 
			
		||||
    mk_is_zero(y, y_is_zero);
 | 
			
		||||
    m_simp.mk_and(x_is_zero, y_is_zero, both_zero);
 | 
			
		||||
    mk_is_nan(x, x_is_nan);
 | 
			
		||||
    mk_is_nan(y, y_is_nan);
 | 
			
		||||
    mk_pzero(f, pzero);
 | 
			
		||||
 | 
			
		||||
    expr_ref sgn_diff(m), sgn_eq(m);
 | 
			
		||||
    sgn_eq = m.mk_eq(x_sgn, y_sgn);
 | 
			
		||||
    sgn_diff = m.mk_not(sgn_eq);
 | 
			
		||||
 | 
			
		||||
    expr_ref gt(m);
 | 
			
		||||
    mk_float_gt(f, num, args, gt);
 | 
			
		||||
 | 
			
		||||
    mk_ite(gt, x, y, result);
 | 
			
		||||
    mk_ite(both_zero, y, result, result);
 | 
			
		||||
    mk_ite(y_is_nan, x, result, result);
 | 
			
		||||
    mk_ite(x_is_nan, y, result, result);
 | 
			
		||||
 | 
			
		||||
    SASSERT(is_well_sorted(m, result));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void fpa2bv_converter::mk_fma(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
 | 
			
		||||
    SASSERT(num == 4);
 | 
			
		||||
    SASSERT(m_util.is_bv2rm(args[0]));
 | 
			
		||||
| 
						 | 
				
			
			@ -3147,22 +3077,13 @@ void fpa2bv_converter::mk_to_ieee_bv(func_decl * f, unsigned num, expr * const *
 | 
			
		|||
    mk_is_nan(x, x_is_nan);
 | 
			
		||||
 | 
			
		||||
    sort * fp_srt = m.get_sort(x);
 | 
			
		||||
    unsigned ebits = m_util.get_ebits(fp_srt);
 | 
			
		||||
    unsigned sbits = m_util.get_sbits(fp_srt);
 | 
			
		||||
 | 
			
		||||
    expr_ref nanv(m);
 | 
			
		||||
    if (m_hi_fp_unspecified)
 | 
			
		||||
        // The "hardware interpretation" is 01...10...01.
 | 
			
		||||
        nanv = m_bv_util.mk_concat(m_bv_util.mk_numeral(0, 1),
 | 
			
		||||
            m_bv_util.mk_concat(m_bv_util.mk_numeral(-1, ebits),
 | 
			
		||||
                m_bv_util.mk_concat(m_bv_util.mk_numeral(0, sbits - 2),
 | 
			
		||||
                    m_bv_util.mk_numeral(1, 1))));
 | 
			
		||||
    else
 | 
			
		||||
        mk_to_ieee_bv_unspecified(f, num, args, nanv);
 | 
			
		||||
    expr_ref unspec(m);
 | 
			
		||||
    mk_to_ieee_bv_unspecified(f, num, args, unspec);
 | 
			
		||||
 | 
			
		||||
    expr_ref sgn_e_s(m);
 | 
			
		||||
    join_fp(x, sgn_e_s);
 | 
			
		||||
    m_simp.mk_ite(x_is_nan, nanv, sgn_e_s, result);
 | 
			
		||||
    m_simp.mk_ite(x_is_nan, unspec, sgn_e_s, result);
 | 
			
		||||
 | 
			
		||||
    TRACE("fpa2bv_to_ieee_bv", tout << "result=" << mk_ismt2_pp(result, m) << std::endl;);
 | 
			
		||||
    SASSERT(is_well_sorted(m, result));
 | 
			
		||||
| 
						 | 
				
			
			@ -3174,26 +3095,15 @@ void fpa2bv_converter::mk_to_ieee_bv_unspecified(func_decl * f, unsigned num, ex
 | 
			
		|||
    unsigned ebits = f->get_domain()[0]->get_parameter(0).get_int();
 | 
			
		||||
    unsigned sbits = f->get_domain()[0]->get_parameter(1).get_int();
 | 
			
		||||
 | 
			
		||||
    if (m_hi_fp_unspecified) {
 | 
			
		||||
        result = m_bv_util.mk_concat(m_bv_util.mk_concat(
 | 
			
		||||
                    m_bv_util.mk_numeral(0, 1),
 | 
			
		||||
                    m_bv_util.mk_numeral(-1, ebits)),
 | 
			
		||||
                    m_bv_util.mk_numeral(1, sbits-1));
 | 
			
		||||
    }
 | 
			
		||||
    if (m_hi_fp_unspecified)
 | 
			
		||||
        mk_nan(f->get_range(), result);
 | 
			
		||||
    else {
 | 
			
		||||
        expr * n = args[0];
 | 
			
		||||
        expr_ref n_bv(m);
 | 
			
		||||
        join_fp(n, n_bv);
 | 
			
		||||
 | 
			
		||||
        func_decl * f_bv;
 | 
			
		||||
        if (!m_uf2bvuf.find(f, f_bv)) {
 | 
			
		||||
            sort * domain[2] = { m.get_sort(n_bv) };
 | 
			
		||||
            f_bv = m.mk_fresh_func_decl(0, 1, domain, f->get_range());
 | 
			
		||||
            m_uf2bvuf.insert(f, f_bv);
 | 
			
		||||
            m.inc_ref(f);
 | 
			
		||||
            m.inc_ref(f_bv);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        sort * domain[1] = { m.get_sort(n_bv) };
 | 
			
		||||
        func_decl * f_bv = mk_bv_uf(f, domain, f->get_range());
 | 
			
		||||
        result = m.mk_app(f_bv, n_bv);
 | 
			
		||||
 | 
			
		||||
        expr_ref exp_bv(m), exp_all_ones(m);
 | 
			
		||||
| 
						 | 
				
			
			@ -3382,14 +3292,8 @@ void fpa2bv_converter::mk_to_bv_unspecified(func_decl * f, unsigned num, expr *
 | 
			
		|||
        expr_ref n_bv(m);
 | 
			
		||||
        join_fp(n, n_bv);
 | 
			
		||||
 | 
			
		||||
        func_decl * f_bv;
 | 
			
		||||
        if (!m_uf2bvuf.find(f, f_bv)) {
 | 
			
		||||
            sort * domain[2] = { m.get_sort(rm_bv), m.get_sort(n_bv) };
 | 
			
		||||
            f_bv = m.mk_fresh_func_decl(0, 2, domain, f->get_range());
 | 
			
		||||
            m_uf2bvuf.insert(f, f_bv);
 | 
			
		||||
            m.inc_ref(f);
 | 
			
		||||
            m.inc_ref(f_bv);
 | 
			
		||||
        }
 | 
			
		||||
        sort * domain[2] = { m.get_sort(rm_bv), m.get_sort(n_bv) };
 | 
			
		||||
        func_decl * f_bv = mk_bv_uf(f, domain, f->get_range());
 | 
			
		||||
        result = m.mk_app(f_bv, rm_bv, n_bv);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3407,14 +3311,8 @@ void fpa2bv_converter::mk_to_real_unspecified(func_decl * f, unsigned num, expr
 | 
			
		|||
        expr_ref n_bv(m);
 | 
			
		||||
        join_fp(n, n_bv);
 | 
			
		||||
 | 
			
		||||
        func_decl * f_bv;
 | 
			
		||||
        if (!m_uf2bvuf.find(f, f_bv)) {
 | 
			
		||||
            sort * domain[2] = { m.get_sort(n_bv) };
 | 
			
		||||
            f_bv = m.mk_fresh_func_decl(0, 1, domain, f->get_range());
 | 
			
		||||
            m_uf2bvuf.insert(f, f_bv);
 | 
			
		||||
            m.inc_ref(f);
 | 
			
		||||
            m.inc_ref(f_bv);
 | 
			
		||||
        }
 | 
			
		||||
        sort * domain[1] = { m.get_sort(n_bv) };
 | 
			
		||||
        func_decl * f_bv = mk_bv_uf(f, domain, f->get_range());
 | 
			
		||||
        result = m.mk_app(f_bv, n_bv);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -4190,13 +4088,25 @@ void fpa2bv_converter::reset(void) {
 | 
			
		|||
    dec_ref_map_key_values(m, m_const2bv);
 | 
			
		||||
    dec_ref_map_key_values(m, m_rm_const2bv);
 | 
			
		||||
    dec_ref_map_key_values(m, m_uf2bvuf);
 | 
			
		||||
    for (obj_map<func_decl, std::pair<app*, app*> >::iterator it = m_min_max_specials.begin();
 | 
			
		||||
        it != m_min_max_specials.end();
 | 
			
		||||
    for (obj_map<func_decl, std::pair<app*, app*> >::iterator it = m_min_max_ufs.begin();
 | 
			
		||||
        it != m_min_max_ufs.end();
 | 
			
		||||
        it++) {
 | 
			
		||||
        m.dec_ref(it->m_key);
 | 
			
		||||
        m.dec_ref(it->m_value.first);
 | 
			
		||||
        m.dec_ref(it->m_value.second);
 | 
			
		||||
    }
 | 
			
		||||
    m_min_max_specials.reset();
 | 
			
		||||
    m_min_max_ufs.reset();
 | 
			
		||||
    m_extra_assertions.reset();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func_decl * fpa2bv_converter::mk_bv_uf(func_decl * f, sort * const * domain, sort * range) {
 | 
			
		||||
    func_decl * res;
 | 
			
		||||
    if (!m_uf2bvuf.find(f, res)) {
 | 
			
		||||
        res = m.mk_fresh_func_decl(0, f->get_arity(), domain, range);
 | 
			
		||||
        m_uf2bvuf.insert(f, res);
 | 
			
		||||
        m.inc_ref(f);
 | 
			
		||||
        m.inc_ref(res);
 | 
			
		||||
        TRACE("fpa2bv", tout << "New UF func_decl: " << std::endl << mk_ismt2_pp(res, m) << std::endl;);
 | 
			
		||||
    }
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -53,7 +53,7 @@ protected:
 | 
			
		|||
    const2bv_t                 m_const2bv;
 | 
			
		||||
    const2bv_t                 m_rm_const2bv;
 | 
			
		||||
    uf2bvuf_t                  m_uf2bvuf;
 | 
			
		||||
    special_t                  m_min_max_specials;
 | 
			
		||||
    special_t                  m_min_max_ufs;
 | 
			
		||||
 | 
			
		||||
    friend class fpa2bv_model_converter;
 | 
			
		||||
    friend class bv2fpa_converter;
 | 
			
		||||
| 
						 | 
				
			
			@ -87,7 +87,7 @@ public:
 | 
			
		|||
    void mk_numeral(sort * s, mpf const & v, expr_ref & result);
 | 
			
		||||
    virtual void mk_const(func_decl * f, expr_ref & result);
 | 
			
		||||
    virtual void mk_rm_const(func_decl * f, expr_ref & result);
 | 
			
		||||
    virtual void mk_function(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
 | 
			
		||||
    virtual void mk_uf(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
 | 
			
		||||
    void mk_var(unsigned base_inx, sort * srt, expr_ref & result);
 | 
			
		||||
 | 
			
		||||
    void mk_pinf(func_decl * f, expr_ref & result);
 | 
			
		||||
| 
						 | 
				
			
			@ -147,18 +147,15 @@ public:
 | 
			
		|||
    void set_unspecified_fp_hi(bool v) { m_hi_fp_unspecified = v; }
 | 
			
		||||
 | 
			
		||||
    void mk_min(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
 | 
			
		||||
    void mk_min_i(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
 | 
			
		||||
    virtual expr_ref mk_min_max_unspecified(func_decl * f, expr * x, expr * y);
 | 
			
		||||
 | 
			
		||||
    void mk_max(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
 | 
			
		||||
    void mk_max_i(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
 | 
			
		||||
    expr_ref mk_min_max_unspecified(func_decl * f, expr * x, expr * y);
 | 
			
		||||
 | 
			
		||||
    void reset(void);
 | 
			
		||||
 | 
			
		||||
    void dbg_decouple(const char * prefix, expr_ref & e);
 | 
			
		||||
    expr_ref_vector m_extra_assertions;
 | 
			
		||||
 | 
			
		||||
    special_t const & get_min_max_specials() const { return m_min_max_specials; };
 | 
			
		||||
    special_t const & get_min_max_specials() const { return m_min_max_ufs; };
 | 
			
		||||
    const2bv_t const & get_const2bv() const { return m_const2bv; };
 | 
			
		||||
    const2bv_t const & get_rm_const2bv() const { return m_rm_const2bv; };
 | 
			
		||||
    uf2bvuf_t const & get_uf2bvuf() const { return m_uf2bvuf; };
 | 
			
		||||
| 
						 | 
				
			
			@ -202,12 +199,6 @@ protected:
 | 
			
		|||
 | 
			
		||||
    void mk_to_bv(func_decl * f, unsigned num, expr * const * args, bool is_signed, expr_ref & result);
 | 
			
		||||
 | 
			
		||||
    sort_ref replace_float_sorts(sort * s);
 | 
			
		||||
    func_decl_ref replace_function(func_decl * f);
 | 
			
		||||
    expr_ref replace_float_arg(expr * a);
 | 
			
		||||
    void mk_function_output(sort * rng, func_decl * fbv, expr * const * new_args, expr_ref & result);
 | 
			
		||||
    func_decl * get_bv_uf(func_decl * f, sort * bv_rng, unsigned arity);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    void mk_nan(sort * s, expr_ref & result);
 | 
			
		||||
    void mk_nzero(sort * s, expr_ref & result);
 | 
			
		||||
| 
						 | 
				
			
			@ -226,6 +217,8 @@ private:
 | 
			
		|||
    void mk_round_to_integral(sort * s, expr_ref & rm, expr_ref & x, expr_ref & result);
 | 
			
		||||
 | 
			
		||||
    void mk_to_fp_float(sort * s, expr * rm, expr * x, expr_ref & result);
 | 
			
		||||
 | 
			
		||||
    func_decl * mk_bv_uf(func_decl * f, sort * const * domain, sort * range);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -124,6 +124,8 @@ br_status fpa2bv_rewriter_cfg::reduce_app(func_decl * f, unsigned num, expr * co
 | 
			
		|||
        case OP_FPA_DIV: m_conv.mk_div(f, num, args, result); return BR_DONE;
 | 
			
		||||
        case OP_FPA_REM: m_conv.mk_rem(f, num, args, result); return BR_DONE;
 | 
			
		||||
        case OP_FPA_ABS: m_conv.mk_abs(f, num, args, result); return BR_DONE;
 | 
			
		||||
        case OP_FPA_MIN: m_conv.mk_min(f, num, args, result); return BR_DONE;
 | 
			
		||||
        case OP_FPA_MAX: m_conv.mk_max(f, num, args, result); return BR_DONE;
 | 
			
		||||
        case OP_FPA_FMA: m_conv.mk_fma(f, num, args, result); return BR_DONE;
 | 
			
		||||
        case OP_FPA_SQRT: m_conv.mk_sqrt(f, num, args, result); return BR_DONE;
 | 
			
		||||
        case OP_FPA_ROUND_TO_INTEGRAL: m_conv.mk_round_to_integral(f, num, args, result); return BR_DONE;
 | 
			
		||||
| 
						 | 
				
			
			@ -147,14 +149,6 @@ br_status fpa2bv_rewriter_cfg::reduce_app(func_decl * f, unsigned num, expr * co
 | 
			
		|||
        case OP_FPA_TO_REAL: m_conv.mk_to_real(f, num, args, result); return BR_DONE;
 | 
			
		||||
        case OP_FPA_TO_IEEE_BV: m_conv.mk_to_ieee_bv(f, num, args, result); return BR_DONE;
 | 
			
		||||
 | 
			
		||||
        case OP_FPA_MIN: m_conv.mk_min(f, num, args, result); return BR_REWRITE_FULL;
 | 
			
		||||
        case OP_FPA_MAX: m_conv.mk_max(f, num, args, result); return BR_REWRITE_FULL;
 | 
			
		||||
 | 
			
		||||
        case OP_FPA_MIN_UNSPECIFIED:
 | 
			
		||||
        case OP_FPA_MAX_UNSPECIFIED: result = m_conv.mk_min_max_unspecified(f, args[0], args[1]); return BR_DONE;
 | 
			
		||||
        case OP_FPA_MIN_I: m_conv.mk_min_i(f, num, args, result); return BR_DONE;
 | 
			
		||||
        case OP_FPA_MAX_I: m_conv.mk_max_i(f, num, args, result); return BR_DONE;
 | 
			
		||||
 | 
			
		||||
        case OP_FPA_BVWRAP:
 | 
			
		||||
        case OP_FPA_BV2RM:
 | 
			
		||||
                return BR_FAILED;
 | 
			
		||||
| 
						 | 
				
			
			@ -169,7 +163,7 @@ br_status fpa2bv_rewriter_cfg::reduce_app(func_decl * f, unsigned num, expr * co
 | 
			
		|||
    {
 | 
			
		||||
        SASSERT(!m_conv.is_float_family(f));
 | 
			
		||||
        if (m_conv.fu().contains_floats(f)) {
 | 
			
		||||
            m_conv.mk_function(f, num, args, result);
 | 
			
		||||
            m_conv.mk_uf(f, num, args, result);
 | 
			
		||||
            return BR_DONE;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -361,10 +361,6 @@ func_decl * fpa_decl_plugin::mk_binary_decl(decl_kind k, unsigned num_parameters
 | 
			
		|||
    case OP_FPA_REM: name = "fp.rem"; break;
 | 
			
		||||
    case OP_FPA_MIN: name = "fp.min"; break;
 | 
			
		||||
    case OP_FPA_MAX: name = "fp.max"; break;
 | 
			
		||||
    case OP_FPA_MIN_I: name = "fp.min_i"; break;
 | 
			
		||||
    case OP_FPA_MAX_I: name = "fp.max_i"; break;
 | 
			
		||||
    case OP_FPA_MIN_UNSPECIFIED: name = "fp.min_unspecified"; break;
 | 
			
		||||
    case OP_FPA_MAX_UNSPECIFIED: name = "fp.max_unspecified"; break;
 | 
			
		||||
    default:
 | 
			
		||||
        UNREACHABLE();
 | 
			
		||||
        break;
 | 
			
		||||
| 
						 | 
				
			
			@ -781,12 +777,6 @@ func_decl * fpa_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters,
 | 
			
		|||
    case OP_FPA_BV2RM:
 | 
			
		||||
        return mk_bv2rm(k, num_parameters, parameters, arity, domain, range);
 | 
			
		||||
 | 
			
		||||
    case OP_FPA_MIN_I:
 | 
			
		||||
    case OP_FPA_MAX_I:
 | 
			
		||||
    case OP_FPA_MIN_UNSPECIFIED:
 | 
			
		||||
    case OP_FPA_MAX_UNSPECIFIED:
 | 
			
		||||
        return mk_binary_decl(k, num_parameters, parameters, arity, domain, range);
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
        m_manager->raise_exception("unsupported floating point operator");
 | 
			
		||||
        return 0;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -89,11 +89,6 @@ enum fpa_op_kind {
 | 
			
		|||
    OP_FPA_BVWRAP,
 | 
			
		||||
    OP_FPA_BV2RM,
 | 
			
		||||
 | 
			
		||||
    OP_FPA_MIN_I,
 | 
			
		||||
    OP_FPA_MAX_I,
 | 
			
		||||
    OP_FPA_MIN_UNSPECIFIED,
 | 
			
		||||
    OP_FPA_MAX_UNSPECIFIED,
 | 
			
		||||
 | 
			
		||||
    LAST_FLOAT_OP
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -351,21 +346,12 @@ public:
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    bool is_bvwrap(expr const * e) const { return is_app_of(e, get_family_id(), OP_FPA_BVWRAP); }
 | 
			
		||||
    bool is_bvwrap(func_decl const * f) const { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_BVWRAP; }
 | 
			
		||||
    bool is_bv2rm(expr const * e) const { return is_app_of(e, get_family_id(), OP_FPA_BV2RM); }
 | 
			
		||||
    bool is_bv2rm(func_decl const * f) const { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_BV2RM; }
 | 
			
		||||
 | 
			
		||||
    bool is_min_interpreted(expr const * e) const { return is_app_of(e, get_family_id(), OP_FPA_MIN_I); }
 | 
			
		||||
    bool is_min_unspecified(expr const * e) const { return is_app_of(e, get_family_id(), OP_FPA_MIN_UNSPECIFIED); }
 | 
			
		||||
    bool is_max_interpreted(expr const * e) const { return is_app_of(e, get_family_id(), OP_FPA_MAX_I); }
 | 
			
		||||
    bool is_max_unspecified(expr const * e) const { return is_app_of(e, get_family_id(), OP_FPA_MAX_UNSPECIFIED); }
 | 
			
		||||
    bool is_to_ubv(expr const * e) const { return is_app_of(e, get_family_id(), OP_FPA_TO_UBV); }
 | 
			
		||||
    bool is_to_sbv(expr const * e) const { return is_app_of(e, get_family_id(), OP_FPA_TO_SBV); }
 | 
			
		||||
 | 
			
		||||
    bool is_min_interpreted(func_decl const * f) const { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_MIN_I; }
 | 
			
		||||
    bool is_min_unspecified(func_decl const * f) const { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_MIN_UNSPECIFIED; }
 | 
			
		||||
    bool is_max_interpreted(func_decl const * f) const { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_MAX_I; }
 | 
			
		||||
    bool is_max_unspecified(func_decl const * f) const { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_MAX_UNSPECIFIED; }
 | 
			
		||||
    bool is_bvwrap(func_decl const * f) const { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_BVWRAP; }
 | 
			
		||||
    bool is_bv2rm(func_decl const * f) const { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_BV2RM; }
 | 
			
		||||
    bool is_to_ubv(func_decl const * f) const { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_TO_UBV; }
 | 
			
		||||
    bool is_to_sbv(func_decl const * f) const { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_TO_SBV; }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -40,7 +40,7 @@ enum nnf_mode {
 | 
			
		|||
                   transformation will be in skolem normal form.
 | 
			
		||||
                   If a formula is too expensive to be put into NNF,
 | 
			
		||||
                   then nested quantifiers and labels are renamed.
 | 
			
		||||
                   
 | 
			
		||||
 | 
			
		||||
                   This mode is sufficient when using E-matching.
 | 
			
		||||
                */
 | 
			
		||||
    NNF_QUANT, /* A subformula is put into NNF if it contains
 | 
			
		||||
| 
						 | 
				
			
			@ -48,7 +48,7 @@ enum nnf_mode {
 | 
			
		|||
                  quantifier. The result of the transformation will be
 | 
			
		||||
                  in skolem normal form, and the body of quantifiers
 | 
			
		||||
                  will be in NNF. If a ground formula is too expensive to
 | 
			
		||||
                  be put into NNF, then nested quantifiers and labels 
 | 
			
		||||
                  be put into NNF, then nested quantifiers and labels
 | 
			
		||||
                  are renamed.
 | 
			
		||||
 | 
			
		||||
                  This mode is sufficient when using Superposition
 | 
			
		||||
| 
						 | 
				
			
			@ -89,7 +89,7 @@ class skolemizer {
 | 
			
		|||
        }
 | 
			
		||||
 | 
			
		||||
        TRACE("skolemizer", tout << "skid: " << q->get_skid() << "\n";);
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        expr_ref_vector substitution(m());
 | 
			
		||||
        unsigned num_decls = q->get_num_decls();
 | 
			
		||||
        for (unsigned i = num_decls; i > 0; ) {
 | 
			
		||||
| 
						 | 
				
			
			@ -111,7 +111,7 @@ class skolemizer {
 | 
			
		|||
                substitution.push_back(0);
 | 
			
		||||
        }
 | 
			
		||||
        //
 | 
			
		||||
        // (VAR num_decls) ... (VAR num_decls+sz-1) 
 | 
			
		||||
        // (VAR num_decls) ... (VAR num_decls+sz-1)
 | 
			
		||||
        // are in positions num_decls .. num_decls+sz-1
 | 
			
		||||
        //
 | 
			
		||||
        std::reverse(substitution.c_ptr(), substitution.c_ptr() + substitution.size());
 | 
			
		||||
| 
						 | 
				
			
			@ -139,7 +139,7 @@ class skolemizer {
 | 
			
		|||
        s(body, substitution.size(), substitution.c_ptr(), r);
 | 
			
		||||
        p = 0;
 | 
			
		||||
        if (m().proofs_enabled()) {
 | 
			
		||||
            if (q->is_forall()) 
 | 
			
		||||
            if (q->is_forall())
 | 
			
		||||
                p = m().mk_skolemization(m().mk_not(q), m().mk_not(r));
 | 
			
		||||
            else
 | 
			
		||||
                p = m().mk_skolemization(q, r);
 | 
			
		||||
| 
						 | 
				
			
			@ -175,7 +175,7 @@ public:
 | 
			
		|||
                m_cache_pr.insert(q, p);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    bool is_sk_hack(expr * p) const {
 | 
			
		||||
        SASSERT(m().is_pattern(p));
 | 
			
		||||
        if (to_app(p)->get_num_args() != 1)
 | 
			
		||||
| 
						 | 
				
			
			@ -204,11 +204,11 @@ struct nnf::imp {
 | 
			
		|||
        unsigned  m_i:28;
 | 
			
		||||
        unsigned  m_pol:1;  // pos/neg polarity
 | 
			
		||||
        unsigned  m_in_q:1; // true if m_curr is nested in a quantifier
 | 
			
		||||
        unsigned  m_new_child:1; 
 | 
			
		||||
        unsigned  m_new_child:1;
 | 
			
		||||
        unsigned  m_cache_result:1;
 | 
			
		||||
        unsigned  m_spos;   // top of the result stack, when the frame was created.
 | 
			
		||||
        frame(expr_ref& n, bool pol, bool in_q, bool cache_res, unsigned spos):
 | 
			
		||||
            m_curr(n),
 | 
			
		||||
        frame(expr_ref && n, bool pol, bool in_q, bool cache_res, unsigned spos):
 | 
			
		||||
            m_curr(std::move(n)),
 | 
			
		||||
            m_i(0),
 | 
			
		||||
            m_pol(pol),
 | 
			
		||||
            m_in_q(in_q),
 | 
			
		||||
| 
						 | 
				
			
			@ -216,6 +216,16 @@ struct nnf::imp {
 | 
			
		|||
            m_cache_result(cache_res),
 | 
			
		||||
            m_spos(spos) {
 | 
			
		||||
        }
 | 
			
		||||
        frame(frame && other):
 | 
			
		||||
            m_curr(std::move(other.m_curr)),
 | 
			
		||||
            m_i(other.m_i),
 | 
			
		||||
            m_pol(other.m_pol),
 | 
			
		||||
            m_in_q(other.m_in_q),
 | 
			
		||||
            m_new_child(other.m_new_child),
 | 
			
		||||
            m_cache_result(other.m_cache_result),
 | 
			
		||||
            m_spos(other.m_spos) {            
 | 
			
		||||
        }
 | 
			
		||||
            
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // There are four caches:
 | 
			
		||||
| 
						 | 
				
			
			@ -223,22 +233,22 @@ struct nnf::imp {
 | 
			
		|||
#define POS_NQ_CIDX 1   // positive polarity and not nested in a quantifier
 | 
			
		||||
#define NEG_Q_CIDX  2   // negative polarity and nested in a quantifier
 | 
			
		||||
#define POS_Q_CIDX  3   // positive polarity and nested in a quantifier
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    ast_manager &          m_manager;
 | 
			
		||||
    vector<frame>          m_frame_stack;
 | 
			
		||||
    expr_ref_vector        m_result_stack;
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    typedef act_cache      cache;
 | 
			
		||||
    cache *                m_cache[4];
 | 
			
		||||
 | 
			
		||||
    expr_ref_vector        m_todo_defs;
 | 
			
		||||
    proof_ref_vector       m_todo_proofs;
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    // proof generation goodness ----
 | 
			
		||||
    proof_ref_vector       m_result_pr_stack;
 | 
			
		||||
    cache *                m_cache_pr[4];
 | 
			
		||||
    // ------------------------------
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    skolemizer             m_skolemizer;
 | 
			
		||||
 | 
			
		||||
    // configuration ----------------
 | 
			
		||||
| 
						 | 
				
			
			@ -249,7 +259,7 @@ struct nnf::imp {
 | 
			
		|||
 | 
			
		||||
    name_exprs *           m_name_nested_formulas;
 | 
			
		||||
    name_exprs *           m_name_quant;
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    unsigned long long     m_max_memory; // in bytes
 | 
			
		||||
 | 
			
		||||
    imp(ast_manager & m, defined_names & n, params_ref const & p):
 | 
			
		||||
| 
						 | 
				
			
			@ -292,9 +302,9 @@ struct nnf::imp {
 | 
			
		|||
            m_mode = NNF_FULL;
 | 
			
		||||
        else if (mode_sym == "quantifiers")
 | 
			
		||||
            m_mode = NNF_QUANT;
 | 
			
		||||
        else 
 | 
			
		||||
        else
 | 
			
		||||
            throw nnf_params_exception("invalid NNF mode");
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        TRACE("nnf", tout << "nnf-mode: " << m_mode << " " << mode_sym << "\n" << _p << "\n";);
 | 
			
		||||
 | 
			
		||||
        m_ignore_labels    = p.ignore_labels();
 | 
			
		||||
| 
						 | 
				
			
			@ -324,12 +334,11 @@ struct nnf::imp {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    void push_frame(expr * t, bool pol, bool in_q, bool cache_res) {
 | 
			
		||||
        expr_ref tr(t, m());
 | 
			
		||||
        m_frame_stack.push_back(frame(tr, pol, in_q, cache_res, m_result_stack.size()));
 | 
			
		||||
        m_frame_stack.push_back(frame(expr_ref(t, m()), pol, in_q, cache_res, m_result_stack.size()));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static unsigned get_cache_idx(bool pol, bool in_q) { 
 | 
			
		||||
        return static_cast<unsigned>(in_q) * 2 + static_cast<unsigned>(pol); 
 | 
			
		||||
    static unsigned get_cache_idx(bool pol, bool in_q) {
 | 
			
		||||
        return static_cast<unsigned>(in_q) * 2 + static_cast<unsigned>(pol);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void cache_result(expr * t, bool pol, bool in_q, expr * v, proof * pr) {
 | 
			
		||||
| 
						 | 
				
			
			@ -339,8 +348,8 @@ struct nnf::imp {
 | 
			
		|||
            m_cache_pr[idx]->insert(t, pr);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    expr * get_cached(expr * t, bool pol, bool in_q) const { 
 | 
			
		||||
        return m_cache[get_cache_idx(pol, in_q)]->find(t); 
 | 
			
		||||
    expr * get_cached(expr * t, bool pol, bool in_q) const {
 | 
			
		||||
        return m_cache[get_cache_idx(pol, in_q)]->find(t);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    proof * get_cached_pr(expr * t, bool pol, bool in_q) const {
 | 
			
		||||
| 
						 | 
				
			
			@ -368,12 +377,12 @@ struct nnf::imp {
 | 
			
		|||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    void checkpoint() {
 | 
			
		||||
        cooperate("nnf");
 | 
			
		||||
        if (memory::get_allocation_size() > m_max_memory)
 | 
			
		||||
            throw nnf_exception(Z3_MAX_MEMORY_MSG);
 | 
			
		||||
        if (m().canceled()) 
 | 
			
		||||
        if (m().canceled())
 | 
			
		||||
            throw nnf_exception(m().limit().get_cancel_msg());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -382,11 +391,11 @@ struct nnf::imp {
 | 
			
		|||
            m_frame_stack.back().m_new_child = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void set_new_child_flag(expr * old_t, expr * new_t) { 
 | 
			
		||||
        if (old_t != new_t) 
 | 
			
		||||
            set_new_child_flag(); 
 | 
			
		||||
    void set_new_child_flag(expr * old_t, expr * new_t) {
 | 
			
		||||
        if (old_t != new_t)
 | 
			
		||||
            set_new_child_flag();
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    void skip(expr * t, bool pol) {
 | 
			
		||||
        expr * r = pol ? t : m().mk_not(t);
 | 
			
		||||
        m_result_stack.push_back(r);
 | 
			
		||||
| 
						 | 
				
			
			@ -448,10 +457,10 @@ struct nnf::imp {
 | 
			
		|||
        if (pol) {
 | 
			
		||||
            if (old_e->get_decl() == new_e->get_decl())
 | 
			
		||||
                return m().mk_oeq_congruence(old_e, new_e, num_parents, parents);
 | 
			
		||||
            else 
 | 
			
		||||
            else
 | 
			
		||||
                return m().mk_nnf_pos(old_e, new_e, num_parents, parents);
 | 
			
		||||
        }
 | 
			
		||||
        else 
 | 
			
		||||
        else
 | 
			
		||||
            return m().mk_nnf_neg(old_e, new_e, num_parents, parents);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -468,7 +477,7 @@ struct nnf::imp {
 | 
			
		|||
            r = m().mk_and(t->get_num_args(), m_result_stack.c_ptr() + fr.m_spos);
 | 
			
		||||
        else
 | 
			
		||||
            r = m().mk_or(t->get_num_args(), m_result_stack.c_ptr() + fr.m_spos);
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        m_result_stack.shrink(fr.m_spos);
 | 
			
		||||
        m_result_stack.push_back(r);
 | 
			
		||||
        if (proofs_enabled()) {
 | 
			
		||||
| 
						 | 
				
			
			@ -520,7 +529,7 @@ struct nnf::imp {
 | 
			
		|||
            r = m().mk_or(2, m_result_stack.c_ptr() + fr.m_spos);
 | 
			
		||||
        else
 | 
			
		||||
            r = m().mk_and(2, m_result_stack.c_ptr() + fr.m_spos);
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        m_result_stack.shrink(fr.m_spos);
 | 
			
		||||
        m_result_stack.push_back(r);
 | 
			
		||||
        if (proofs_enabled()) {
 | 
			
		||||
| 
						 | 
				
			
			@ -554,7 +563,7 @@ struct nnf::imp {
 | 
			
		|||
        default:
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        expr * const * rs = m_result_stack.c_ptr() + fr.m_spos;
 | 
			
		||||
        expr * _cond      = rs[0];
 | 
			
		||||
        expr * _not_cond  = rs[1];
 | 
			
		||||
| 
						 | 
				
			
			@ -574,7 +583,7 @@ struct nnf::imp {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    bool is_eq(app * t) const { return m().is_eq(t) || m().is_iff(t); }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    bool process_iff_xor(app * t, frame & fr) {
 | 
			
		||||
        SASSERT(t->get_num_args() == 2);
 | 
			
		||||
        switch (fr.m_i) {
 | 
			
		||||
| 
						 | 
				
			
			@ -605,7 +614,7 @@ struct nnf::imp {
 | 
			
		|||
        expr * not_rhs  = rs[3];
 | 
			
		||||
 | 
			
		||||
        app * r;
 | 
			
		||||
        if (is_eq(t) == fr.m_pol) 
 | 
			
		||||
        if (is_eq(t) == fr.m_pol)
 | 
			
		||||
            r = m().mk_and(m().mk_or(not_lhs, rhs), m().mk_or(lhs, not_rhs));
 | 
			
		||||
        else
 | 
			
		||||
            r = m().mk_and(m().mk_or(lhs, rhs), m().mk_or(not_lhs, not_rhs));
 | 
			
		||||
| 
						 | 
				
			
			@ -626,7 +635,7 @@ struct nnf::imp {
 | 
			
		|||
        else
 | 
			
		||||
            return process_default(t, fr);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    bool process_default(app * t, frame & fr) {
 | 
			
		||||
        SASSERT(fr.m_i == 0);
 | 
			
		||||
        if (m_mode == NNF_FULL || t->has_quantifiers() || t->has_labels()) {
 | 
			
		||||
| 
						 | 
				
			
			@ -636,10 +645,10 @@ struct nnf::imp {
 | 
			
		|||
                m_name_nested_formulas->operator()(t, m_todo_defs, m_todo_proofs, n2, pr2);
 | 
			
		||||
            else
 | 
			
		||||
                m_name_quant->operator()(t, m_todo_defs, m_todo_proofs, n2, pr2);
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
            if (!fr.m_pol)
 | 
			
		||||
                n2 = m().mk_not(n2);
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            m_result_stack.push_back(n2);
 | 
			
		||||
            if (proofs_enabled()) {
 | 
			
		||||
                if (!fr.m_pol) {
 | 
			
		||||
| 
						 | 
				
			
			@ -666,10 +675,10 @@ struct nnf::imp {
 | 
			
		|||
        expr * arg = m_result_stack.back();
 | 
			
		||||
        proof * arg_pr = proofs_enabled() ? m_result_pr_stack.back() : 0;
 | 
			
		||||
 | 
			
		||||
        if (m_ignore_labels && !proofs_enabled()) 
 | 
			
		||||
        if (m_ignore_labels && !proofs_enabled())
 | 
			
		||||
            return true; // the result is already on the stack
 | 
			
		||||
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        buffer<symbol> names;
 | 
			
		||||
        bool pos;
 | 
			
		||||
        m().is_label(t, pos, names);
 | 
			
		||||
| 
						 | 
				
			
			@ -684,7 +693,7 @@ struct nnf::imp {
 | 
			
		|||
                pr = m().mk_transitivity(mk_proof(fr.m_pol, 1, &arg_pr, t, to_app(aux)),
 | 
			
		||||
                                         m().mk_iff_oeq(m().mk_rewrite(aux, r)));
 | 
			
		||||
            }
 | 
			
		||||
        }    
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            r = arg;
 | 
			
		||||
            if (proofs_enabled()) {
 | 
			
		||||
| 
						 | 
				
			
			@ -692,7 +701,7 @@ struct nnf::imp {
 | 
			
		|||
                pr = m().mk_transitivity(p1, arg_pr);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        m_result_stack.pop_back();
 | 
			
		||||
        m_result_stack.push_back(r);
 | 
			
		||||
        if (proofs_enabled()) {
 | 
			
		||||
| 
						 | 
				
			
			@ -729,7 +738,7 @@ struct nnf::imp {
 | 
			
		|||
        if (m().is_label(t)) {
 | 
			
		||||
            return process_label(t, fr);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        return process_default(t, fr);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -737,7 +746,7 @@ struct nnf::imp {
 | 
			
		|||
        skip(v, fr.m_pol);
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    bool process_quantifier(quantifier * q, frame & fr) {
 | 
			
		||||
        expr_ref  r(m());
 | 
			
		||||
        proof_ref pr(m());
 | 
			
		||||
| 
						 | 
				
			
			@ -757,7 +766,7 @@ struct nnf::imp {
 | 
			
		|||
        if (q->is_forall() == fr.m_pol || !m_skolemize) {
 | 
			
		||||
            expr * new_expr     = m_result_stack.back();
 | 
			
		||||
            proof * new_expr_pr = proofs_enabled() ? m_result_pr_stack.back() : 0;
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            ptr_buffer<expr> new_patterns;
 | 
			
		||||
 | 
			
		||||
            if (q->is_forall() == fr.m_pol) {
 | 
			
		||||
| 
						 | 
				
			
			@ -773,7 +782,7 @@ struct nnf::imp {
 | 
			
		|||
                // New quantifier has existential force.
 | 
			
		||||
                // So, ignore patterns
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            quantifier * new_q = 0;
 | 
			
		||||
            proof * new_q_pr   = 0;
 | 
			
		||||
            if (fr.m_pol) {
 | 
			
		||||
| 
						 | 
				
			
			@ -786,7 +795,7 @@ struct nnf::imp {
 | 
			
		|||
                if (proofs_enabled())
 | 
			
		||||
                    new_q_pr = m().mk_nnf_neg(q, new_q, 1, &new_expr_pr);
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            m_result_stack.pop_back();
 | 
			
		||||
            m_result_stack.push_back(new_q);
 | 
			
		||||
            if (proofs_enabled()) {
 | 
			
		||||
| 
						 | 
				
			
			@ -809,7 +818,7 @@ struct nnf::imp {
 | 
			
		|||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    void recover_result(expr * t, expr_ref & result, proof_ref & result_pr) {
 | 
			
		||||
        // recover result from the top of the stack.
 | 
			
		||||
        result = m_result_stack.back();
 | 
			
		||||
| 
						 | 
				
			
			@ -873,7 +882,7 @@ struct nnf::imp {
 | 
			
		|||
        process(n, r, pr);
 | 
			
		||||
        unsigned old_sz1 = new_defs.size();
 | 
			
		||||
        unsigned old_sz2 = new_def_proofs.size();
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        for (unsigned i = 0; i < m_todo_defs.size(); i++) {
 | 
			
		||||
            expr_ref  dr(m());
 | 
			
		||||
            proof_ref dpr(m());
 | 
			
		||||
| 
						 | 
				
			
			@ -881,7 +890,7 @@ struct nnf::imp {
 | 
			
		|||
            new_defs.push_back(dr);
 | 
			
		||||
            if (proofs_enabled()) {
 | 
			
		||||
                proof * new_pr = m().mk_modus_ponens(m_todo_proofs.get(i), dpr);
 | 
			
		||||
                new_def_proofs.push_back(new_pr); 
 | 
			
		||||
                new_def_proofs.push_back(new_pr);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        std::reverse(new_defs.c_ptr() + old_sz1, new_defs.c_ptr() + new_defs.size());
 | 
			
		||||
| 
						 | 
				
			
			@ -898,7 +907,7 @@ nnf::nnf(ast_manager & m, defined_names & n, params_ref const & p) {
 | 
			
		|||
nnf::~nnf() {
 | 
			
		||||
    dealloc(m_imp);
 | 
			
		||||
}
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
void nnf::operator()(expr * n, expr_ref_vector & new_defs, proof_ref_vector & new_def_proofs, expr_ref & r,  proof_ref & p) {
 | 
			
		||||
    m_imp->operator()(n, new_defs, new_def_proofs, r, p);
 | 
			
		||||
    TRACE("nnf_result", tout << mk_ismt2_pp(n, m_imp->m()) << "\nNNF result:\n" << mk_ismt2_pp(r, m_imp->m()) << "\n";);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -179,11 +179,11 @@ expr_pattern_match::compile(expr* q)
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    if (m_regs.size() <= max_reg) {
 | 
			
		||||
        m_regs.resize(max_reg+1, 0);
 | 
			
		||||
        m_regs.resize(max_reg+1);
 | 
			
		||||
    }
 | 
			
		||||
    if (m_bound_dom.size() <= num_bound) {
 | 
			
		||||
        m_bound_dom.resize(num_bound+1, 0);
 | 
			
		||||
        m_bound_rng.resize(num_bound+1, 0);
 | 
			
		||||
        m_bound_dom.resize(num_bound+1);
 | 
			
		||||
        m_bound_rng.resize(num_bound+1);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    instr.m_kind = YIELD;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -272,7 +272,7 @@ void bit_blaster_tpl<Cfg>::mk_multiplier(unsigned sz, expr * const * a_bits, exp
 | 
			
		|||
        zero = m().mk_false();
 | 
			
		||||
 | 
			
		||||
        vector< expr_ref_vector > pps;
 | 
			
		||||
        pps.resize(sz, m());
 | 
			
		||||
        pps.resize(sz, expr_ref_vector(m()));
 | 
			
		||||
               
 | 
			
		||||
        for (unsigned i = 0; i < sz; i++) {
 | 
			
		||||
            checkpoint();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -94,12 +94,6 @@ br_status fpa_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * con
 | 
			
		|||
    case OP_FPA_TO_IEEE_BV: SASSERT(num_args == 1); st = mk_to_ieee_bv(f, args[0], result); break;
 | 
			
		||||
    case OP_FPA_TO_REAL:   SASSERT(num_args == 1); st = mk_to_real(args[0], result); break;
 | 
			
		||||
 | 
			
		||||
    case OP_FPA_MIN_I:SASSERT(num_args == 2); st = mk_min_i(f, args[0], args[1], result); break;
 | 
			
		||||
    case OP_FPA_MAX_I: SASSERT(num_args == 2); st = mk_max_i(f, args[0], args[1], result); break;
 | 
			
		||||
    case OP_FPA_MIN_UNSPECIFIED:
 | 
			
		||||
    case OP_FPA_MAX_UNSPECIFIED:
 | 
			
		||||
        SASSERT(num_args == 2); st = BR_FAILED; break;
 | 
			
		||||
 | 
			
		||||
    case OP_FPA_BVWRAP: SASSERT(num_args == 1); st = mk_bvwrap(args[0], result); break;
 | 
			
		||||
    case OP_FPA_BV2RM: SASSERT(num_args == 1); st = mk_bv2rm(args[0], result); break;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -131,11 +125,10 @@ br_status fpa_rewriter::mk_to_fp(func_decl * f, unsigned num_args, expr * const
 | 
			
		|||
            const mpz & sm1 = m_fm.m_powers2(sbits - 1);
 | 
			
		||||
            const mpz & em1 = m_fm.m_powers2(ebits);
 | 
			
		||||
 | 
			
		||||
            scoped_mpq q(mpqm);
 | 
			
		||||
            mpqm.set(q, r1.to_mpq());
 | 
			
		||||
            SASSERT(mpzm.is_one(q.get().denominator()));
 | 
			
		||||
            const mpq & q = r1.to_mpq();
 | 
			
		||||
            SASSERT(mpzm.is_one(q.denominator()));
 | 
			
		||||
            scoped_mpz z(mpzm);
 | 
			
		||||
            z = q.get().numerator();
 | 
			
		||||
            z = q.numerator();
 | 
			
		||||
 | 
			
		||||
            mpzm.rem(z, sm1, sig);
 | 
			
		||||
            mpzm.div(z, sm1, z);
 | 
			
		||||
| 
						 | 
				
			
			@ -385,38 +378,13 @@ br_status fpa_rewriter::mk_min(expr * arg1, expr * arg2, expr_ref & result) {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    scoped_mpf v1(m_fm), v2(m_fm);
 | 
			
		||||
    if (m_util.is_numeral(arg1, v1) && m_util.is_numeral(arg2, v2)) {
 | 
			
		||||
        if (m_fm.is_zero(v1) && m_fm.is_zero(v2) && m_fm.sgn(v1) != m_fm.sgn(v2)) {
 | 
			
		||||
            result = m().mk_app(get_fid(), OP_FPA_MIN_UNSPECIFIED, arg1, arg2);
 | 
			
		||||
            return BR_REWRITE1;
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            scoped_mpf r(m_fm);
 | 
			
		||||
            m_fm.minimum(v1, v2, r);
 | 
			
		||||
            result = m_util.mk_value(r);
 | 
			
		||||
            return BR_DONE;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        expr_ref c(m()), v(m());
 | 
			
		||||
        c = m().mk_and(m().mk_and(m_util.mk_is_zero(arg1), m_util.mk_is_zero(arg2)),
 | 
			
		||||
                                  m().mk_or(m().mk_and(m_util.mk_is_positive(arg1), m_util.mk_is_negative(arg2)),
 | 
			
		||||
                                            m().mk_and(m_util.mk_is_negative(arg1), m_util.mk_is_positive(arg2))));
 | 
			
		||||
        v = m().mk_app(get_fid(), OP_FPA_MIN_UNSPECIFIED, arg1, arg2);
 | 
			
		||||
 | 
			
		||||
        result = m().mk_ite(c, v, m().mk_app(get_fid(), OP_FPA_MIN_I, arg1, arg2));
 | 
			
		||||
        return BR_REWRITE_FULL;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
br_status fpa_rewriter::mk_min_i(func_decl * f, expr * arg1, expr * arg2, expr_ref & result) {
 | 
			
		||||
    scoped_mpf v1(m_fm), v2(m_fm);
 | 
			
		||||
 | 
			
		||||
    if (m_util.is_numeral(arg1, v1) && m_util.is_numeral(arg2, v2)) {
 | 
			
		||||
        if (m_fm.is_zero(v1) && m_fm.is_zero(v2) && m_fm.sgn(v1) != m_fm.sgn(v2))
 | 
			
		||||
            result = m().mk_app(get_fid(), OP_FPA_MIN_UNSPECIFIED, arg1, arg2);
 | 
			
		||||
        else
 | 
			
		||||
            result = m_util.mk_min(arg1, arg2);
 | 
			
		||||
            return BR_FAILED;
 | 
			
		||||
 | 
			
		||||
        scoped_mpf r(m_fm);
 | 
			
		||||
        m_fm.minimum(v1, v2, r);
 | 
			
		||||
        result = m_util.mk_value(r);
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -434,38 +402,13 @@ br_status fpa_rewriter::mk_max(expr * arg1, expr * arg2, expr_ref & result) {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    scoped_mpf v1(m_fm), v2(m_fm);
 | 
			
		||||
    if (m_util.is_numeral(arg1, v1) && m_util.is_numeral(arg2, v2)) {
 | 
			
		||||
        if (m_fm.is_zero(v1) && m_fm.is_zero(v2) && m_fm.sgn(v1) != m_fm.sgn(v2)) {
 | 
			
		||||
            result = m().mk_app(get_fid(), OP_FPA_MAX_UNSPECIFIED, arg1, arg2);
 | 
			
		||||
            return BR_REWRITE1;
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            scoped_mpf r(m_fm);
 | 
			
		||||
            m_fm.maximum(v1, v2, r);
 | 
			
		||||
            result = m_util.mk_value(r);
 | 
			
		||||
            return BR_DONE;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        expr_ref c(m()), v(m());
 | 
			
		||||
        c = m().mk_and(m().mk_and(m_util.mk_is_zero(arg1), m_util.mk_is_zero(arg2)),
 | 
			
		||||
            m().mk_or(m().mk_and(m_util.mk_is_positive(arg1), m_util.mk_is_negative(arg2)),
 | 
			
		||||
                m().mk_and(m_util.mk_is_negative(arg1), m_util.mk_is_positive(arg2))));
 | 
			
		||||
        v = m().mk_app(get_fid(), OP_FPA_MAX_UNSPECIFIED, arg1, arg2);
 | 
			
		||||
 | 
			
		||||
        result = m().mk_ite(c, v, m().mk_app(get_fid(), OP_FPA_MAX_I, arg1, arg2));
 | 
			
		||||
        return BR_REWRITE_FULL;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
br_status fpa_rewriter::mk_max_i(func_decl * f, expr * arg1, expr * arg2, expr_ref & result) {
 | 
			
		||||
    scoped_mpf v1(m_fm), v2(m_fm);
 | 
			
		||||
 | 
			
		||||
    if (m_util.is_numeral(arg1, v1) && m_util.is_numeral(arg2, v2)) {
 | 
			
		||||
        if (m_fm.is_zero(v1) && m_fm.is_zero(v2) && m_fm.sgn(v1) != m_fm.sgn(v2))
 | 
			
		||||
            result = m().mk_app(get_fid(), OP_FPA_MIN_UNSPECIFIED, arg1, arg2);
 | 
			
		||||
        else
 | 
			
		||||
            result = m_util.mk_max(arg1, arg2);
 | 
			
		||||
            return BR_FAILED;
 | 
			
		||||
 | 
			
		||||
        scoped_mpf r(m_fm);
 | 
			
		||||
        m_fm.maximum(v1, v2, r);
 | 
			
		||||
        result = m_util.mk_value(r);
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -54,13 +54,13 @@ br_status maximize_ac_sharing::reduce_app(func_decl * f, unsigned num_args, expr
 | 
			
		|||
    TRACE("ac_sharing_detail", tout << "args: "; for (unsigned i = 0; i < num_args; i++) tout << mk_pp(_args[i], m) << "\n";);
 | 
			
		||||
    try_to_reuse:
 | 
			
		||||
    if (num_args > 1 && num_args < MAX_NUM_ARGS_FOR_OPT) {
 | 
			
		||||
        for (unsigned i = 0; i < num_args - 1; i++) {
 | 
			
		||||
        for (unsigned i = 0; i + 1 < num_args; i++) {
 | 
			
		||||
            for (unsigned j = i + 1; j < num_args; j++) {
 | 
			
		||||
                if (contains(f, _args[i], _args[j])) {
 | 
			
		||||
                    TRACE("ac_sharing_detail", tout << "reusing args: " << i << " " << j << "\n";);
 | 
			
		||||
                    _args[i] = m.mk_app(f, _args[i], _args[j]);
 | 
			
		||||
                    SASSERT(num_args > 1);
 | 
			
		||||
                    for (unsigned w = j; w < num_args - 1; w++) {
 | 
			
		||||
                    for (unsigned w = j; w + 1 < num_args; w++) {
 | 
			
		||||
                        _args[w] = _args[w+1];
 | 
			
		||||
                    }
 | 
			
		||||
                    num_args--;
 | 
			
		||||
| 
						 | 
				
			
			@ -144,6 +144,7 @@ void maximize_ac_sharing::restore_entries(unsigned old_lim) {
 | 
			
		|||
    while (i != old_lim) {
 | 
			
		||||
        --i;
 | 
			
		||||
        entry * e = m_entries[i];
 | 
			
		||||
        m_cache.remove(e);
 | 
			
		||||
        m.dec_ref(e->m_arg1);
 | 
			
		||||
        m.dec_ref(e->m_arg2);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -151,11 +152,7 @@ void maximize_ac_sharing::restore_entries(unsigned old_lim) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
void maximize_ac_sharing::reset() {
 | 
			
		||||
    restore_entries(0);
 | 
			
		||||
    m_entries.reset();
 | 
			
		||||
    m_cache.reset();
 | 
			
		||||
    m_region.reset();
 | 
			
		||||
    m_scopes.reset();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void maximize_bv_sharing::init_core() {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -42,6 +42,10 @@ void rewriter_tpl<Config>::process_var(var * v) {
 | 
			
		|||
            unsigned index = m_bindings.size() - idx - 1;
 | 
			
		||||
            var * r = (var*)(m_bindings[index]);
 | 
			
		||||
            if (r != 0) {
 | 
			
		||||
                CTRACE("rewriter", v->get_sort() != m().get_sort(r),
 | 
			
		||||
                       tout << expr_ref(v, m()) << ":" << sort_ref(v->get_sort(), m()) << " != " << expr_ref(r, m()) << ":" << sort_ref(m().get_sort(r), m());
 | 
			
		||||
                       tout << "index " << index << " bindings " << m_bindings.size() << "\n";
 | 
			
		||||
                       display_bindings(tout););
 | 
			
		||||
                SASSERT(v->get_sort() == m().get_sort(r));
 | 
			
		||||
                if (!is_ground(r) && m_shifts[index] != m_bindings.size()) {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -256,7 +256,7 @@ void substitution_tree::insert(expr * new_expr) {
 | 
			
		|||
        sort * s    = to_var(new_expr)->get_sort();
 | 
			
		||||
        unsigned id = s->get_decl_id();
 | 
			
		||||
        if (id >= m_vars.size())
 | 
			
		||||
            m_vars.resize(id+1, 0);
 | 
			
		||||
            m_vars.resize(id+1);
 | 
			
		||||
        if (m_vars[id] == 0)
 | 
			
		||||
            m_vars[id] = alloc(var_ref_vector, m_manager);
 | 
			
		||||
        var_ref_vector * v = m_vars[id];
 | 
			
		||||
| 
						 | 
				
			
			@ -277,7 +277,7 @@ void substitution_tree::insert(app * new_expr) {
 | 
			
		|||
    unsigned id   = d->get_decl_id();
 | 
			
		||||
    
 | 
			
		||||
    if (id >= m_roots.size()) 
 | 
			
		||||
        m_roots.resize(id+1, 0);
 | 
			
		||||
        m_roots.resize(id+1);
 | 
			
		||||
 | 
			
		||||
    if (!m_roots[id]) {
 | 
			
		||||
        // there is no tree for the function symbol heading new_expr
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -58,7 +58,7 @@ void used_vars::process(expr * n, unsigned delta) {
 | 
			
		|||
            if (idx >= delta) {
 | 
			
		||||
                idx = idx - delta;
 | 
			
		||||
                if (idx >= m_found_vars.size())
 | 
			
		||||
                    m_found_vars.resize(idx + 1, 0);
 | 
			
		||||
                    m_found_vars.resize(idx + 1);
 | 
			
		||||
                m_found_vars[idx] = to_var(n)->get_sort();
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -202,7 +202,7 @@ func_decl * func_decls::find(unsigned arity, sort * const * domain, sort * range
 | 
			
		|||
        if (f->get_arity() != arity)
 | 
			
		||||
            continue;
 | 
			
		||||
        unsigned i = 0;
 | 
			
		||||
        for (i = 0; i < arity; i++) {
 | 
			
		||||
        for (i = 0; domain && i < arity; i++) {
 | 
			
		||||
            if (f->get_domain(i) != domain[i])
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -774,7 +774,6 @@ bool cmd_context::is_func_decl(symbol const & s) const {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
void cmd_context::insert(symbol const & s, func_decl * f) {
 | 
			
		||||
    m_check_sat_result = 0;
 | 
			
		||||
    if (!m_check_logic(f)) {
 | 
			
		||||
        throw cmd_exception(m_check_logic.get_last_error());
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -805,7 +804,6 @@ void cmd_context::insert(symbol const & s, func_decl * f) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
void cmd_context::insert(symbol const & s, psort_decl * p) {
 | 
			
		||||
    m_check_sat_result = 0;
 | 
			
		||||
    if (m_psort_decls.contains(s)) {
 | 
			
		||||
        throw cmd_exception("sort already defined ", s);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -819,7 +817,6 @@ void cmd_context::insert(symbol const & s, psort_decl * p) {
 | 
			
		|||
 | 
			
		||||
void cmd_context::insert(symbol const & s, unsigned arity, sort *const* domain, expr * t) {
 | 
			
		||||
    expr_ref _t(t, m());
 | 
			
		||||
    m_check_sat_result = 0;
 | 
			
		||||
    if (m_builtin_decls.contains(s)) {
 | 
			
		||||
        throw cmd_exception("invalid macro/named expression, builtin symbol ", s);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -870,6 +867,12 @@ void cmd_context::insert_rec_fun(func_decl* f, expr_ref_vector const& binding, s
 | 
			
		|||
    lhs = m().mk_app(f, binding.size(), binding.c_ptr());
 | 
			
		||||
    eq  = m().mk_eq(lhs, e);
 | 
			
		||||
    if (!ids.empty()) {
 | 
			
		||||
        if (is_var(e)) {
 | 
			
		||||
            ptr_vector<sort> domain;
 | 
			
		||||
            for (expr* b : binding) domain.push_back(m().get_sort(b));
 | 
			
		||||
            insert_macro(f->get_name(), domain.size(), domain.c_ptr(), e);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        if (!is_app(e)) {
 | 
			
		||||
            throw cmd_exception("Z3 only supports recursive definitions that are proper terms (not binders or variables)");
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -937,7 +940,7 @@ static builtin_decl const & peek_builtin_decl(builtin_decl const & first, family
 | 
			
		|||
func_decl * cmd_context::find_func_decl(symbol const & s, unsigned num_indices, unsigned const * indices,
 | 
			
		||||
                                        unsigned arity, sort * const * domain, sort * range) const {
 | 
			
		||||
    builtin_decl d;
 | 
			
		||||
    if (m_builtin_decls.find(s, d)) {
 | 
			
		||||
    if (domain && m_builtin_decls.find(s, d)) {
 | 
			
		||||
        family_id fid = d.m_fid;
 | 
			
		||||
        decl_kind k   = d.m_decl;
 | 
			
		||||
        // Hack: if d.m_next != 0, we use domain[0] (if available) to decide which plugin we use.
 | 
			
		||||
| 
						 | 
				
			
			@ -961,7 +964,7 @@ func_decl * cmd_context::find_func_decl(symbol const & s, unsigned num_indices,
 | 
			
		|||
        return f;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (contains_macro(s, arity, domain))
 | 
			
		||||
    if (domain && contains_macro(s, arity, domain))
 | 
			
		||||
        throw cmd_exception("invalid function declaration reference, named expressions (aka macros) cannot be referenced ", s);
 | 
			
		||||
 | 
			
		||||
    if (num_indices > 0)
 | 
			
		||||
| 
						 | 
				
			
			@ -1545,6 +1548,26 @@ void cmd_context::reset_assertions() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void cmd_context::display_dimacs() {
 | 
			
		||||
    if (m_solver) {
 | 
			
		||||
        try {
 | 
			
		||||
            gparams::set("sat.dimacs.display", "true");
 | 
			
		||||
            params_ref p;
 | 
			
		||||
            m_solver->updt_params(p);
 | 
			
		||||
            m_solver->check_sat(0, nullptr);
 | 
			
		||||
        }
 | 
			
		||||
        catch (...) {
 | 
			
		||||
            gparams::set("sat.dimacs.display", "false");        
 | 
			
		||||
            params_ref p;
 | 
			
		||||
            m_solver->updt_params(p);
 | 
			
		||||
            throw;
 | 
			
		||||
        }
 | 
			
		||||
        gparams::set("sat.dimacs.display", "false");        
 | 
			
		||||
        params_ref p;
 | 
			
		||||
        m_solver->updt_params(p);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cmd_context::display_model(model_ref& mdl) {
 | 
			
		||||
    if (mdl) {
 | 
			
		||||
        model_params p;
 | 
			
		||||
| 
						 | 
				
			
			@ -1582,7 +1605,9 @@ void cmd_context::validate_check_sat_result(lbool r) {
 | 
			
		|||
            throw cmd_exception("check annotation that says unsat");
 | 
			
		||||
#else
 | 
			
		||||
            diagnostic_stream() << "BUG: incompleteness" << std::endl;
 | 
			
		||||
            exit(ERR_INCOMPLETENESS);
 | 
			
		||||
            // WORKAROUND: `exit()` causes LSan to be invoked and produce
 | 
			
		||||
            // many false positives.
 | 
			
		||||
            _Exit(ERR_INCOMPLETENESS);
 | 
			
		||||
#endif
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
| 
						 | 
				
			
			@ -1592,7 +1617,9 @@ void cmd_context::validate_check_sat_result(lbool r) {
 | 
			
		|||
            throw cmd_exception("check annotation that says sat");
 | 
			
		||||
#else
 | 
			
		||||
            diagnostic_stream() << "BUG: unsoundness" << std::endl;
 | 
			
		||||
            exit(ERR_UNSOUNDNESS);
 | 
			
		||||
            // WORKAROUND: `exit()` causes LSan to be invoked and produce
 | 
			
		||||
            // many false positives.
 | 
			
		||||
            _Exit(ERR_UNSOUNDNESS);
 | 
			
		||||
#endif
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
| 
						 | 
				
			
			@ -1743,6 +1770,7 @@ void cmd_context::validate_model() {
 | 
			
		|||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
                try {
 | 
			
		||||
                    for_each_expr(contains_underspecified, a);
 | 
			
		||||
                    for_each_expr(contains_underspecified, r);
 | 
			
		||||
                }
 | 
			
		||||
                catch (contains_underspecified_op_proc::found) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -419,6 +419,7 @@ public:
 | 
			
		|||
 | 
			
		||||
    void display_assertions();
 | 
			
		||||
    void display_statistics(bool show_total_time = false, double total_time = 0.0);
 | 
			
		||||
    void display_dimacs();
 | 
			
		||||
    void reset(bool finalize = false);
 | 
			
		||||
    void assert_expr(expr * t);
 | 
			
		||||
    void assert_expr(symbol const & name, expr * t);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,7 +31,6 @@ Notes:
 | 
			
		|||
#include "ast/rewriter/var_subst.h"
 | 
			
		||||
#include "util/gparams.h"
 | 
			
		||||
 | 
			
		||||
#ifndef _EXTERNAL_RELEASE
 | 
			
		||||
 | 
			
		||||
BINARY_SYM_CMD(get_quantifier_body_cmd,
 | 
			
		||||
               "dbg-get-qbody",
 | 
			
		||||
| 
						 | 
				
			
			@ -343,10 +342,19 @@ public:
 | 
			
		|||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
class print_dimacs_cmd : public cmd {
 | 
			
		||||
public:
 | 
			
		||||
    print_dimacs_cmd():cmd("display-dimacs") {}
 | 
			
		||||
    virtual char const * get_usage() const { return ""; }
 | 
			
		||||
    virtual char const * get_descr(cmd_context & ctx) const { return "print benchmark in DIMACS format"; }
 | 
			
		||||
    virtual unsigned get_arity() const { return 0; }
 | 
			
		||||
    virtual void prepare(cmd_context & ctx) {}
 | 
			
		||||
    virtual void execute(cmd_context & ctx) { ctx.display_dimacs(); }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void install_dbg_cmds(cmd_context & ctx) {
 | 
			
		||||
#ifndef _EXTERNAL_RELEASE
 | 
			
		||||
    ctx.insert(alloc(print_dimacs_cmd));
 | 
			
		||||
    ctx.insert(alloc(get_quantifier_body_cmd));
 | 
			
		||||
    ctx.insert(alloc(set_cmd));
 | 
			
		||||
    ctx.insert(alloc(pp_var_cmd));
 | 
			
		||||
| 
						 | 
				
			
			@ -369,5 +377,4 @@ void install_dbg_cmds(cmd_context & ctx) {
 | 
			
		|||
    ctx.insert(alloc(instantiate_cmd));
 | 
			
		||||
    ctx.insert(alloc(instantiate_nested_cmd));
 | 
			
		||||
    ctx.insert(alloc(set_next_id));
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -33,9 +33,11 @@
 | 
			
		|||
#include <fstream>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <ostream>
 | 
			
		||||
#include <sstream>
 | 
			
		||||
 | 
			
		||||
#include "ast/expr_abstract.h"
 | 
			
		||||
#include "util/params.h"
 | 
			
		||||
#include "ast/used_vars.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
using namespace stl_ext;
 | 
			
		||||
| 
						 | 
				
			
			@ -938,3 +940,30 @@ void iz3mgr::get_bound_substitutes(stl_ext::hash_map<ast,bool> &memo, const ast
 | 
			
		|||
 
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
unsigned  iz3mgr::num_free_variables(const ast &e){
 | 
			
		||||
    used_vars uv;
 | 
			
		||||
    uv(to_expr(e.raw()));
 | 
			
		||||
    return uv.get_num_vars();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
iz3mgr::ast iz3mgr::close_universally (ast e){
 | 
			
		||||
   used_vars uv;
 | 
			
		||||
   uv(to_expr(e.raw()));
 | 
			
		||||
   std::vector<ast> bvs;
 | 
			
		||||
   stl_ext::hash_map<ast,ast> subst_memo;
 | 
			
		||||
   for (unsigned i = 0; i < uv.get_max_found_var_idx_plus_1(); i++){
 | 
			
		||||
       if (uv.get(i)) {
 | 
			
		||||
           std::ostringstream os;
 | 
			
		||||
           os << "%%" << i;
 | 
			
		||||
           ast c = make_var(os.str(),uv.get(i));
 | 
			
		||||
           ast v = cook(m().mk_var(i,uv.get(i)));
 | 
			
		||||
           subst_memo[v] = c;
 | 
			
		||||
           bvs.push_back(c);
 | 
			
		||||
       }
 | 
			
		||||
   }
 | 
			
		||||
   e = subst(subst_memo,e);
 | 
			
		||||
   for (unsigned i = 0; i < bvs.size(); i++)
 | 
			
		||||
       e = apply_quant(Forall,bvs[i],e);
 | 
			
		||||
   return e;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -96,7 +96,7 @@ class ast_r : public ast_i {
 | 
			
		|||
 | 
			
		||||
 ast_r(const ast_r &other) : ast_i(other) {
 | 
			
		||||
        _m = other._m;
 | 
			
		||||
        _m->inc_ref(_ast);
 | 
			
		||||
        if (_m) _m->inc_ref(_ast);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ast_r &operator=(const ast_r &other) {
 | 
			
		||||
| 
						 | 
				
			
			@ -104,7 +104,7 @@ class ast_r : public ast_i {
 | 
			
		|||
            _m->dec_ref(_ast);
 | 
			
		||||
        _ast = other._ast;
 | 
			
		||||
        _m = other._m;
 | 
			
		||||
        _m->inc_ref(_ast);
 | 
			
		||||
        if (_m) _m->inc_ref(_ast);
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -661,6 +661,12 @@ class iz3mgr  {
 | 
			
		|||
 | 
			
		||||
    ast apply_quant(opr quantifier, ast var, ast e);
 | 
			
		||||
 | 
			
		||||
    // Universally quantify all the free variables in a formula.
 | 
			
		||||
    // Makes up names for the quntifiers.
 | 
			
		||||
 | 
			
		||||
    ast close_universally (ast e);
 | 
			
		||||
 | 
			
		||||
    unsigned num_free_variables(const ast &e);
 | 
			
		||||
 | 
			
		||||
    /** For debugging */
 | 
			
		||||
    void show(ast);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2968,9 +2968,9 @@ class iz3proof_itp_impl : public iz3proof_itp {
 | 
			
		|||
    ast interpolate(const node &pf){
 | 
			
		||||
        // proof of false must be a formula, with quantified symbols
 | 
			
		||||
#ifndef BOGUS_QUANTS
 | 
			
		||||
        return add_quants(z3_simplify(pf));
 | 
			
		||||
        return close_universally(add_quants(z3_simplify(pf)));
 | 
			
		||||
#else
 | 
			
		||||
        return z3_simplify(pf);
 | 
			
		||||
        return close_universally(z3_simplify(pf));
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -234,6 +234,11 @@ public:
 | 
			
		|||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // if(!range_is_empty(rng)){
 | 
			
		||||
            //     if (num_free_variables(con) > 0)
 | 
			
		||||
            //         rng = range_empty();
 | 
			
		||||
            // }
 | 
			
		||||
 | 
			
		||||
            if(res == INT_MAX){
 | 
			
		||||
                if(range_is_empty(rng))
 | 
			
		||||
                    res = -1;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,6 +24,7 @@ Revision History:
 | 
			
		|||
 | 
			
		||||
#include "math/automata/symbolic_automata.h"
 | 
			
		||||
#include "util/hashtable.h"
 | 
			
		||||
#include "util/vector.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -311,7 +312,7 @@ symbolic_automata<T, M>::mk_determinstic_param(automaton_t& a, bool flip_accepta
 | 
			
		|||
    s2id.insert(set, p_state_id++);               // the index to the initial state is 0
 | 
			
		||||
    id2s.push_back(set);
 | 
			
		||||
    
 | 
			
		||||
    svector<uint_set> todo; //States to visit
 | 
			
		||||
    ::vector<uint_set> todo; //States to visit
 | 
			
		||||
    todo.push_back(set);
 | 
			
		||||
    
 | 
			
		||||
    uint_set state;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -162,7 +162,7 @@ private:
 | 
			
		|||
    void checkpoint();
 | 
			
		||||
 | 
			
		||||
public:    
 | 
			
		||||
    interval_manager(reslimit& lim, C const & c);
 | 
			
		||||
    interval_manager(reslimit& lim, C && c);
 | 
			
		||||
    ~interval_manager();
 | 
			
		||||
 | 
			
		||||
    numeral_manager & m() const { return m_c.m(); }    
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,7 +31,7 @@ Revision History:
 | 
			
		|||
// #define TRACE_NTH_ROOT
 | 
			
		||||
 | 
			
		||||
template<typename C>
 | 
			
		||||
interval_manager<C>::interval_manager(reslimit& lim, C const & c): m_limit(lim), m_c(c) {
 | 
			
		||||
interval_manager<C>::interval_manager(reslimit& lim, C && c): m_limit(lim), m_c(std::move(c)) {
 | 
			
		||||
    m().set(m_minus_one, -1);
 | 
			
		||||
    m().set(m_one, 1);
 | 
			
		||||
    m_pi_n = 0;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2632,10 +2632,14 @@ namespace algebraic_numbers {
 | 
			
		|||
                scoped_mpz neg_n(qm());
 | 
			
		||||
                qm().set(neg_n, v.numerator());
 | 
			
		||||
                qm().neg(neg_n);
 | 
			
		||||
                mpz const coeffs[2] = { neg_n.get(), v.denominator() };
 | 
			
		||||
                unsynch_mpz_manager zmgr;
 | 
			
		||||
                // FIXME: remove these copies
 | 
			
		||||
                mpz coeffs[2] = { zmgr.dup(neg_n.get()), zmgr.dup(v.denominator()) };
 | 
			
		||||
                out << "(";
 | 
			
		||||
                upm().display(out, 2, coeffs, "#");
 | 
			
		||||
                out << ", 1)"; // first root of the polynomial d*# - n
 | 
			
		||||
                zmgr.del(coeffs[0]);
 | 
			
		||||
                zmgr.del(coeffs[1]);
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
                algebraic_cell * c = a.to_algebraic();
 | 
			
		||||
| 
						 | 
				
			
			@ -2678,10 +2682,14 @@ namespace algebraic_numbers {
 | 
			
		|||
                scoped_mpz neg_n(qm());
 | 
			
		||||
                qm().set(neg_n, v.numerator());
 | 
			
		||||
                qm().neg(neg_n);
 | 
			
		||||
                mpz const coeffs[2] = { neg_n.get(), v.denominator() };
 | 
			
		||||
                unsynch_mpz_manager zmgr;
 | 
			
		||||
                // FIXME: remove these copies
 | 
			
		||||
                mpz coeffs[2] = { zmgr.dup(neg_n.get()), zmgr.dup(v.denominator()) };
 | 
			
		||||
                out << "(root-obj ";
 | 
			
		||||
                upm().display_smt2(out, 2, coeffs, "x");
 | 
			
		||||
                out << " 1)"; // first root of the polynomial d*# - n
 | 
			
		||||
                zmgr.del(coeffs[0]);
 | 
			
		||||
                zmgr.del(coeffs[1]);
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
                algebraic_cell * c = a.to_algebraic();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3536,10 +3536,11 @@ namespace polynomial {
 | 
			
		|||
            iccp(p, max_var(p), i, c, pp);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void pp(polynomial const * p, var x, polynomial_ref & pp) {
 | 
			
		||||
        polynomial_ref pp(polynomial const * p, var x) {
 | 
			
		||||
            scoped_numeral i(m_manager);
 | 
			
		||||
            polynomial_ref c(pm());
 | 
			
		||||
            iccp(p, x, i, c, pp);
 | 
			
		||||
            polynomial_ref c(pm()), result(pm());
 | 
			
		||||
            iccp(p, x, i, c, result);
 | 
			
		||||
            return result;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        bool is_primitive(polynomial const * p, var x) {
 | 
			
		||||
| 
						 | 
				
			
			@ -3598,7 +3599,7 @@ namespace polynomial {
 | 
			
		|||
                if (is_zero(rem)) {
 | 
			
		||||
                    TRACE("polynomial", tout << "rem is zero...\npp_v: " << pp_v << "\n";);
 | 
			
		||||
                    flip_sign_if_lm_neg(pp_v);
 | 
			
		||||
                    pp(pp_v, x, r);
 | 
			
		||||
                    r = pp(pp_v, x);
 | 
			
		||||
                    r = mul(d_a, d_r, r);
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
| 
						 | 
				
			
			@ -3849,7 +3850,7 @@ namespace polynomial {
 | 
			
		|||
                        TRACE("mgcd", tout << "new combined:\n" << C_star << "\n";);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                pp(C_star, x, candidate);
 | 
			
		||||
                candidate = pp(C_star, x);
 | 
			
		||||
                TRACE("mgcd", tout << "candidate:\n" << candidate << "\n";);
 | 
			
		||||
                scoped_numeral lc_candidate(m());
 | 
			
		||||
                lc_candidate = univ_coeff(candidate, degree(candidate, x));
 | 
			
		||||
| 
						 | 
				
			
			@ -4821,10 +4822,9 @@ namespace polynomial {
 | 
			
		|||
 | 
			
		||||
        polynomial * mk_x_minus_y(var x, var y) {
 | 
			
		||||
            numeral zero(0);
 | 
			
		||||
            numeral one(1);
 | 
			
		||||
            numeral minus_one; // It is not safe to initialize with -1 when numeral_manager is GF_2
 | 
			
		||||
            m_manager.set(minus_one, -1);
 | 
			
		||||
            numeral as[2] = { one, minus_one };
 | 
			
		||||
            numeral as[2] = { numeral(1), std::move(minus_one) };
 | 
			
		||||
            var     xs[2] = { x, y };
 | 
			
		||||
            return mk_linear(2, as, xs, zero);
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -4844,8 +4844,7 @@ namespace polynomial {
 | 
			
		|||
 | 
			
		||||
        polynomial * mk_x_plus_y(var x, var y) {
 | 
			
		||||
            numeral zero(0);
 | 
			
		||||
            numeral one(1);
 | 
			
		||||
            numeral as[2] = { one, one };
 | 
			
		||||
            numeral as[2] = { numeral(1), numeral(1) };
 | 
			
		||||
            var     xs[2] = { x, y };
 | 
			
		||||
            return mk_linear(2, as, xs, zero);
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -6619,8 +6618,8 @@ namespace polynomial {
 | 
			
		|||
                  polynomial_ref cf1(pm()); m_wrapper.content(f1, x, cf1);
 | 
			
		||||
                  polynomial_ref cf2(pm()); m_wrapper.content(f2, x, cf2);
 | 
			
		||||
                  tout << "content(f1): " << cf1 << "\ncontent(f2): " << cf2 << "\n";);
 | 
			
		||||
            pp(f1, x, f1);
 | 
			
		||||
            pp(f2, x, f2);
 | 
			
		||||
            f1 = pp(f1, x);
 | 
			
		||||
            f2 = pp(f2, x);
 | 
			
		||||
            TRACE("factor", tout << "f1: " << f1 << "\nf2: " << f2 << "\n";);
 | 
			
		||||
            DEBUG_CODE({
 | 
			
		||||
                polynomial_ref f1f2(pm());
 | 
			
		||||
| 
						 | 
				
			
			@ -7150,7 +7149,7 @@ namespace polynomial {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    void manager::primitive(polynomial const * p, var x, polynomial_ref & pp) {
 | 
			
		||||
        m_imp->pp(p, x, pp);
 | 
			
		||||
        pp = m_imp->pp(p, x);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void manager::icpp(polynomial const * p, var x, numeral & i, polynomial_ref & c, polynomial_ref & pp) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -45,7 +45,7 @@ namespace upolynomial {
 | 
			
		|||
        for (unsigned i = 0; i < p.size(); ++ i) {
 | 
			
		||||
            numeral p_i; // no need to delete, we keep it pushed in zp_p
 | 
			
		||||
            zp_nm.set(p_i, p[i]);
 | 
			
		||||
            zp_p.push_back(p_i);
 | 
			
		||||
            zp_p.push_back(std::move(p_i));
 | 
			
		||||
        }
 | 
			
		||||
        zp_upm.trim(zp_p);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,7 +35,7 @@ namespace simplex {
 | 
			
		|||
        struct row_entry {
 | 
			
		||||
            numeral         m_coeff;
 | 
			
		||||
            var_t           m_var;
 | 
			
		||||
            row_entry(numeral const& c, var_t v): m_coeff(c), m_var(v) {}
 | 
			
		||||
            row_entry(numeral && c, var_t v) : m_coeff(std::move(c)), m_var(v) {}
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
| 
						 | 
				
			
			@ -61,7 +61,7 @@ namespace simplex {
 | 
			
		|||
                int     m_col_idx;
 | 
			
		||||
                int     m_next_free_row_entry_idx;
 | 
			
		||||
            };            
 | 
			
		||||
            _row_entry(numeral const & c, var_t v): row_entry(c, v), m_col_idx(0) {}
 | 
			
		||||
            _row_entry(numeral && c, var_t v) : row_entry(std::move(c), v), m_col_idx(0) {}
 | 
			
		||||
            _row_entry() : row_entry(numeral(), dead_id), m_col_idx(0) {}
 | 
			
		||||
            bool is_dead() const { return row_entry::m_var == dead_id; }
 | 
			
		||||
        };
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -739,7 +739,7 @@ void context_t<C>::del_sum(polynomial * p) {
 | 
			
		|||
 | 
			
		||||
template<typename C>
 | 
			
		||||
var context_t<C>::mk_sum(numeral const & c, unsigned sz, numeral const * as, var const * xs) {
 | 
			
		||||
    m_num_buffer.reserve(num_vars(), numeral());
 | 
			
		||||
    m_num_buffer.reserve(num_vars());
 | 
			
		||||
    for (unsigned i = 0; i < sz; i++) {
 | 
			
		||||
        SASSERT(xs[i] < num_vars());
 | 
			
		||||
        nm().set(m_num_buffer[xs[i]], as[i]);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -117,7 +117,7 @@ bool func_interp::is_fi_entry_expr(expr * e, ptr_vector<expr> & args) {
 | 
			
		|||
        (m_arity > 1 && (!m().is_and(c) || to_app(c)->get_num_args() != m_arity)))
 | 
			
		||||
        return false;
 | 
			
		||||
 | 
			
		||||
    args.resize(m_arity, 0);
 | 
			
		||||
    args.resize(m_arity);
 | 
			
		||||
    for (unsigned i = 0; i < m_arity; i++) {
 | 
			
		||||
        expr * ci = (m_arity == 1 && i == 0) ? c : to_app(c)->get_arg(i);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -140,7 +140,6 @@ void func_interp::set_else(expr * e) {
 | 
			
		|||
        return;
 | 
			
		||||
 | 
			
		||||
    reset_interp_cache();
 | 
			
		||||
 | 
			
		||||
    ptr_vector<expr> args;
 | 
			
		||||
    while (e && is_fi_entry_expr(e, args)) {
 | 
			
		||||
        TRACE("func_interp", tout << "fi entry expr: " << mk_ismt2_pp(e, m()) << std::endl;);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -86,18 +86,22 @@ void model_core::register_decl(func_decl * d, func_interp * fi) {
 | 
			
		|||
void model_core::unregister_decl(func_decl * d) {
 | 
			
		||||
    decl2expr::obj_map_entry * ec = m_interp.find_core(d);
 | 
			
		||||
    if (ec && ec->get_data().m_value != 0) {
 | 
			
		||||
        m_manager.dec_ref(ec->get_data().m_key);
 | 
			
		||||
        m_manager.dec_ref(ec->get_data().m_value);
 | 
			
		||||
        auto k = ec->get_data().m_key;
 | 
			
		||||
        auto v = ec->get_data().m_value;
 | 
			
		||||
        m_interp.remove(d);
 | 
			
		||||
        m_const_decls.erase(d);
 | 
			
		||||
        m_manager.dec_ref(k);
 | 
			
		||||
        m_manager.dec_ref(v);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    decl2finterp::obj_map_entry * ef = m_finterp.find_core(d);
 | 
			
		||||
    if (ef && ef->get_data().m_value != 0) {
 | 
			
		||||
        m_manager.dec_ref(ef->get_data().m_key);
 | 
			
		||||
        dealloc(ef->get_data().m_value);
 | 
			
		||||
        auto k = ef->get_data().m_key;
 | 
			
		||||
        auto v = ef->get_data().m_value;
 | 
			
		||||
        m_finterp.remove(d);
 | 
			
		||||
        m_func_decls.erase(d);
 | 
			
		||||
        m_manager.dec_ref(k);
 | 
			
		||||
        dealloc(v);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -453,7 +453,8 @@ namespace datalog {
 | 
			
		|||
        return new_pred;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  void context::add_rule(expr* rl, symbol const& name, unsigned bound) {
 | 
			
		||||
    void context::add_rule(expr* rl, symbol const& name, unsigned bound) {
 | 
			
		||||
        SASSERT(rl);
 | 
			
		||||
        m_rule_fmls.push_back(rl);
 | 
			
		||||
        m_rule_names.push_back(name);
 | 
			
		||||
        m_rule_bounds.push_back(bound);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -192,10 +192,15 @@ namespace datalog {
 | 
			
		|||
            for (unsigned i = 0; i < new_tbvs.size(); ++i) {
 | 
			
		||||
                tbv const& nt = *new_tbvs[i];
 | 
			
		||||
                IF_VERBOSE(10, m_tbv.display(verbose_stream() << "insert: ", nt); verbose_stream() << "\n";);
 | 
			
		||||
                if (contains(nt)) continue;
 | 
			
		||||
                ddnf_node* n = alloc(ddnf_node, *this, m_tbv, nt, m_noderefs.size());
 | 
			
		||||
                m_noderefs.push_back(n);
 | 
			
		||||
                m_nodes.insert(n);
 | 
			
		||||
                ddnf_node* n;
 | 
			
		||||
                if (contains(nt)) {
 | 
			
		||||
                    n = find(nt);
 | 
			
		||||
                }
 | 
			
		||||
                else {
 | 
			
		||||
                    n = alloc(ddnf_node, *this, m_tbv, nt, m_noderefs.size());
 | 
			
		||||
                    m_noderefs.push_back(n);
 | 
			
		||||
                    m_nodes.insert(n);
 | 
			
		||||
                }
 | 
			
		||||
                insert(*m_root, n, new_tbvs);
 | 
			
		||||
            }
 | 
			
		||||
            return find(t);
 | 
			
		||||
| 
						 | 
				
			
			@ -275,13 +280,17 @@ namespace datalog {
 | 
			
		|||
        void insert(ddnf_node& root, ddnf_node* new_n, ptr_vector<tbv const>& new_intersections) {
 | 
			
		||||
            tbv const& new_tbv = new_n->get_tbv();
 | 
			
		||||
            
 | 
			
		||||
            IF_VERBOSE(10, m_tbv.display(verbose_stream() << "root: ", root.get_tbv()); 
 | 
			
		||||
                       m_tbv.display(verbose_stream() << " new node ", new_tbv); verbose_stream() << "\n";);
 | 
			
		||||
            SASSERT(m_tbv.contains(root.get_tbv(), new_tbv));
 | 
			
		||||
            if (&root == new_n) return;
 | 
			
		||||
            if (m_eq(&root, new_n)) return;
 | 
			
		||||
            ++m_stats.m_num_inserts;
 | 
			
		||||
            bool inserted = false;
 | 
			
		||||
            for (unsigned i = 0; i < root.num_children(); ++i) {
 | 
			
		||||
                ddnf_node& child = *(root[i]);
 | 
			
		||||
                ++m_stats.m_num_comparisons;
 | 
			
		||||
                IF_VERBOSE(10, m_tbv.display(verbose_stream() << "child ", child.get_tbv()); 
 | 
			
		||||
                           verbose_stream() << " contains: " << m_tbv.contains(child.get_tbv(), new_tbv) << "\n";);
 | 
			
		||||
                if (m_tbv.contains(child.get_tbv(), new_tbv)) {
 | 
			
		||||
                    inserted = true;
 | 
			
		||||
                    insert(child, new_n, new_intersections);
 | 
			
		||||
| 
						 | 
				
			
			@ -299,11 +308,13 @@ namespace datalog {
 | 
			
		|||
                // checking for subset
 | 
			
		||||
                if (m_tbv.contains(new_tbv, child.get_tbv())) {
 | 
			
		||||
                    subset_children.push_back(&child);
 | 
			
		||||
                    IF_VERBOSE(10, m_tbv.display(verbose_stream() << "contains child", child.get_tbv()); verbose_stream() << "\n";);
 | 
			
		||||
                    ++m_stats.m_num_comparisons;
 | 
			
		||||
                }
 | 
			
		||||
                else if (m_tbv.intersect(child.get_tbv(), new_tbv, *intr)) {
 | 
			
		||||
                    // this means there is a non-full intersection
 | 
			
		||||
                    new_intersections.push_back(intr);
 | 
			
		||||
                    IF_VERBOSE(10, m_tbv.display(verbose_stream() << "intersect child ", child.get_tbv()); verbose_stream() << "\n";);
 | 
			
		||||
                    intr = m_tbv.allocate();
 | 
			
		||||
                    m_stats.m_num_comparisons += 2;
 | 
			
		||||
                }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -189,11 +189,12 @@ public:
 | 
			
		|||
        m_bound = bound;
 | 
			
		||||
        m_arg_idx++;
 | 
			
		||||
    }
 | 
			
		||||
    virtual void reset(cmd_context & ctx) { m_dl_ctx->reset(); prepare(ctx); }
 | 
			
		||||
    virtual void reset(cmd_context & ctx) { m_dl_ctx->reset(); prepare(ctx); m_t = nullptr; }
 | 
			
		||||
    virtual void prepare(cmd_context& ctx) { m_arg_idx = 0; m_name = symbol::null; m_bound = UINT_MAX; }
 | 
			
		||||
    virtual void finalize(cmd_context & ctx) { 
 | 
			
		||||
    }
 | 
			
		||||
    virtual void execute(cmd_context & ctx) {
 | 
			
		||||
        if (!m_t) throw cmd_exception("invalid rule, expected formula");
 | 
			
		||||
        m_dl_ctx->add_rule(m_t, m_name, m_bound);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -128,7 +128,7 @@ namespace datalog {
 | 
			
		|||
        void set_reg(reg_idx i, reg_type val) {
 | 
			
		||||
            if (i >= m_registers.size()) {
 | 
			
		||||
                check_overflow(i);
 | 
			
		||||
                m_registers.resize(i+1,0);
 | 
			
		||||
                m_registers.resize(i+1);
 | 
			
		||||
            }
 | 
			
		||||
            if (m_registers[i]) {
 | 
			
		||||
                m_registers[i]->deallocate();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -465,7 +465,7 @@ namespace datalog {
 | 
			
		|||
 | 
			
		||||
            unsigned sz = r.get_signature().size();
 | 
			
		||||
            ptr_vector<expr> subst_arg;
 | 
			
		||||
            subst_arg.resize(sz, 0);
 | 
			
		||||
            subst_arg.resize(sz);
 | 
			
		||||
            unsigned ofs = sz-1;
 | 
			
		||||
            for (unsigned i=0; i<sz; i++) {
 | 
			
		||||
                SASSERT(!r.is_undefined(i) || !contains_var(m_new_rule, i));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -111,8 +111,8 @@ namespace datalog {
 | 
			
		|||
 | 
			
		||||
        void filter_interpreted(app* cond) {
 | 
			
		||||
            rational one(1), mone(-1);
 | 
			
		||||
            expr* e1, *e2, *en;
 | 
			
		||||
            var* v, *w;
 | 
			
		||||
            expr* e1 = 0, *e2 = 0, *en = 0;
 | 
			
		||||
            var* v = 0, *w = 0;
 | 
			
		||||
            rational n1, n2;
 | 
			
		||||
            expr_ref_vector conjs(m);
 | 
			
		||||
            flatten_and(cond, conjs);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -74,8 +74,7 @@ tbv* tbv_manager::allocate(tbv const& bv) {
 | 
			
		|||
}
 | 
			
		||||
tbv* tbv_manager::allocate(uint64 val) {
 | 
			
		||||
    tbv* v = allocate0();
 | 
			
		||||
    for (unsigned bit = num_tbits(); bit > 0;) {
 | 
			
		||||
        --bit;
 | 
			
		||||
    for (unsigned bit = std::min(64u, num_tbits()); bit-- > 0;) {
 | 
			
		||||
        if (val & (1ULL << bit)) {                        
 | 
			
		||||
            set(*v, bit, BIT_1);
 | 
			
		||||
        } else {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -66,7 +66,6 @@ class peq {
 | 
			
		|||
    app_ref             m_peq;      // partial equality application
 | 
			
		||||
    app_ref             m_eq;       // equivalent std equality using def. of partial eq
 | 
			
		||||
    array_util          m_arr_u;
 | 
			
		||||
    ast_eq_proc         m_eq_proc;  // for checking if two asts are equal
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    static const char* PARTIAL_EQ;
 | 
			
		||||
| 
						 | 
				
			
			@ -102,7 +101,7 @@ peq::peq (app* p, ast_manager& m):
 | 
			
		|||
    VERIFY (is_partial_eq (p));
 | 
			
		||||
    SASSERT (m_arr_u.is_array (m_lhs) &&
 | 
			
		||||
             m_arr_u.is_array (m_rhs) &&
 | 
			
		||||
             m_eq_proc (m.get_sort (m_lhs), m.get_sort (m_rhs)));
 | 
			
		||||
             ast_eq_proc() (m.get_sort (m_lhs), m.get_sort (m_rhs)));
 | 
			
		||||
    for (unsigned i = 2; i < p->get_num_args (); i++) {
 | 
			
		||||
        m_diff_indices.push_back (p->get_arg (i));
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -121,7 +120,7 @@ peq::peq (expr* lhs, expr* rhs, unsigned num_indices, expr * const * diff_indice
 | 
			
		|||
{
 | 
			
		||||
    SASSERT (m_arr_u.is_array (lhs) &&
 | 
			
		||||
             m_arr_u.is_array (rhs) &&
 | 
			
		||||
             m_eq_proc (m.get_sort (lhs), m.get_sort (rhs)));
 | 
			
		||||
             ast_eq_proc() (m.get_sort (lhs), m.get_sort (rhs)));
 | 
			
		||||
    ptr_vector<sort> sorts;
 | 
			
		||||
    sorts.push_back (m.get_sort (m_lhs));
 | 
			
		||||
    sorts.push_back (m.get_sort (m_rhs));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -398,8 +398,8 @@ namespace datalog {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    bool mk_interp_tail_simplifier::propagate_variable_equivalences(rule * r, rule_ref& res) {
 | 
			
		||||
      if (!m_context.get_params ().xform_tail_simplifier_pve ())
 | 
			
		||||
        return false;
 | 
			
		||||
        if (!m_context.get_params ().xform_tail_simplifier_pve ())
 | 
			
		||||
            return false;
 | 
			
		||||
        unsigned u_len = r->get_uninterpreted_tail_size();
 | 
			
		||||
        unsigned len = r->get_tail_size();
 | 
			
		||||
        if (u_len == len) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,6 +24,7 @@ Revision History:
 | 
			
		|||
#include "ast/ast_pp.h"
 | 
			
		||||
#include "ast/well_sorted.h"
 | 
			
		||||
#include "ast/rewriter/rewriter.h"
 | 
			
		||||
#include "ast/rewriter/var_subst.h"
 | 
			
		||||
#include "ast/has_free_vars.h"
 | 
			
		||||
#include "ast/ast_smt2_pp.h"
 | 
			
		||||
#include "parsers/smt2/smt2parser.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -68,6 +69,7 @@ namespace smt2 {
 | 
			
		|||
 | 
			
		||||
        scoped_ptr<bv_util>               m_bv_util;
 | 
			
		||||
        scoped_ptr<arith_util>            m_arith_util;
 | 
			
		||||
        scoped_ptr<datatype_util>         m_datatype_util;
 | 
			
		||||
        scoped_ptr<seq_util>              m_seq_util;      
 | 
			
		||||
        scoped_ptr<pattern_validator>     m_pattern_validator;
 | 
			
		||||
        scoped_ptr<var_shifter>           m_var_shifter;
 | 
			
		||||
| 
						 | 
				
			
			@ -108,6 +110,7 @@ namespace smt2 {
 | 
			
		|||
        symbol               m_check_sat_assuming;
 | 
			
		||||
        symbol               m_define_fun_rec;
 | 
			
		||||
        symbol               m_define_funs_rec;
 | 
			
		||||
        symbol               m_match;
 | 
			
		||||
        symbol               m_underscore;
 | 
			
		||||
 | 
			
		||||
        typedef std::pair<symbol, expr*> named_expr;
 | 
			
		||||
| 
						 | 
				
			
			@ -135,7 +138,7 @@ namespace smt2 {
 | 
			
		|||
 | 
			
		||||
        typedef psort_frame sort_frame;
 | 
			
		||||
 | 
			
		||||
        enum expr_frame_kind { EF_APP, EF_LET, EF_LET_DECL, EF_QUANT, EF_ATTR_EXPR, EF_PATTERN };
 | 
			
		||||
        enum expr_frame_kind { EF_APP, EF_LET, EF_LET_DECL, EF_MATCH, EF_QUANT, EF_ATTR_EXPR, EF_PATTERN };
 | 
			
		||||
 | 
			
		||||
        struct expr_frame {
 | 
			
		||||
            expr_frame_kind m_kind;
 | 
			
		||||
| 
						 | 
				
			
			@ -172,6 +175,10 @@ namespace smt2 {
 | 
			
		|||
                m_expr_spos(expr_spos) {}
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        struct match_frame : public expr_frame {
 | 
			
		||||
            match_frame():expr_frame(EF_MATCH) {}
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        struct let_frame : public expr_frame {
 | 
			
		||||
            bool     m_in_decls;
 | 
			
		||||
            unsigned m_sym_spos;
 | 
			
		||||
| 
						 | 
				
			
			@ -275,6 +282,12 @@ namespace smt2 {
 | 
			
		|||
            return *(m_arith_util.get());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        datatype_util & dtutil() {
 | 
			
		||||
            if (m_datatype_util.get() == 0)
 | 
			
		||||
                m_datatype_util = alloc(datatype_util, m());
 | 
			
		||||
            return *(m_datatype_util.get());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        seq_util & sutil() {
 | 
			
		||||
            if (m_seq_util.get() == 0)
 | 
			
		||||
                m_seq_util = alloc(seq_util, m());
 | 
			
		||||
| 
						 | 
				
			
			@ -389,6 +402,7 @@ namespace smt2 {
 | 
			
		|||
 | 
			
		||||
        bool curr_id_is_underscore() const { SASSERT(curr_is_identifier()); return curr_id() == m_underscore; }
 | 
			
		||||
        bool curr_id_is_as() const { SASSERT(curr_is_identifier()); return curr_id() == m_as; }
 | 
			
		||||
        bool curr_id_is_match() const { SASSERT(curr_is_identifier()); return curr_id() == m_match; }
 | 
			
		||||
        bool curr_id_is_forall() const { SASSERT(curr_is_identifier()); return curr_id() == m_forall; }
 | 
			
		||||
        bool curr_id_is_exists() const { SASSERT(curr_is_identifier()); return curr_id() == m_exists; }
 | 
			
		||||
        bool curr_id_is_bang() const { SASSERT(curr_is_identifier()); return curr_id() == m_bang; }
 | 
			
		||||
| 
						 | 
				
			
			@ -430,7 +444,10 @@ namespace smt2 {
 | 
			
		|||
                m_ctx.regular_stream()<< "line " << line << " column " << pos << ": " << escaped(msg, true) << "\")" << std::endl;
 | 
			
		||||
            }
 | 
			
		||||
            if (m_ctx.exit_on_error()) {
 | 
			
		||||
                exit(1);
 | 
			
		||||
                // WORKAROUND: ASan's LeakSanitizer reports many false positives when
 | 
			
		||||
                // calling `exit()` so call `_Exit()` instead which avoids invoking leak
 | 
			
		||||
                // checking.
 | 
			
		||||
                _Exit(1);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1258,6 +1275,23 @@ namespace smt2 {
 | 
			
		|||
            return num;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void push_let_frame() {
 | 
			
		||||
            next();
 | 
			
		||||
            check_lparen_next("invalid let declaration, '(' expected");
 | 
			
		||||
            void * mem = m_stack.allocate(sizeof(let_frame));
 | 
			
		||||
            new (mem) let_frame(symbol_stack().size(), expr_stack().size());
 | 
			
		||||
            m_num_expr_frames++;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void push_bang_frame(expr_frame * curr) {
 | 
			
		||||
            TRACE("consume_attributes", tout << "begin bang, expr_stack.size(): " << expr_stack().size() << "\n";);
 | 
			
		||||
            next();
 | 
			
		||||
            void * mem = m_stack.allocate(sizeof(attr_expr_frame));
 | 
			
		||||
            new (mem) attr_expr_frame(curr, symbol_stack().size(), expr_stack().size());
 | 
			
		||||
            m_num_expr_frames++;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        void push_quant_frame(bool is_forall) {
 | 
			
		||||
            SASSERT(curr_is_identifier());
 | 
			
		||||
            SASSERT(curr_id_is_forall() || curr_id_is_exists());
 | 
			
		||||
| 
						 | 
				
			
			@ -1273,6 +1307,202 @@ namespace smt2 {
 | 
			
		|||
                throw parser_exception("invalid quantifier, list of sorted variables is empty");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * SMT-LIB 2.6 pattern matches are of the form
 | 
			
		||||
         * (match t ((p1 t1) ... (pm+1 tm+1)))         
 | 
			
		||||
         */
 | 
			
		||||
        void push_match_frame() {
 | 
			
		||||
            SASSERT(curr_is_identifier());
 | 
			
		||||
            SASSERT(curr_id() == m_match);
 | 
			
		||||
            next();
 | 
			
		||||
            void * mem = m_stack.allocate(sizeof(match_frame));
 | 
			
		||||
            new (mem) match_frame();
 | 
			
		||||
            unsigned num_frames = m_num_expr_frames;
 | 
			
		||||
 | 
			
		||||
            parse_expr();
 | 
			
		||||
            expr_ref t(expr_stack().back(), m());
 | 
			
		||||
            expr_stack().pop_back();
 | 
			
		||||
            expr_ref_vector patterns(m()), cases(m());
 | 
			
		||||
            sort* srt = m().get_sort(t);
 | 
			
		||||
 | 
			
		||||
            check_lparen_next("pattern bindings should be enclosed in a parenthesis");
 | 
			
		||||
            while (!curr_is_rparen()) {
 | 
			
		||||
                m_env.begin_scope();
 | 
			
		||||
                unsigned num_bindings = m_num_bindings;
 | 
			
		||||
                check_lparen_next("invalid pattern binding, '(' expected");
 | 
			
		||||
                parse_match_pattern(srt);  
 | 
			
		||||
                patterns.push_back(expr_stack().back());
 | 
			
		||||
                expr_stack().pop_back();
 | 
			
		||||
                parse_expr();
 | 
			
		||||
                cases.push_back(expr_stack().back());
 | 
			
		||||
                expr_stack().pop_back();
 | 
			
		||||
                m_num_bindings = num_bindings;
 | 
			
		||||
                m_env.end_scope();
 | 
			
		||||
                check_rparen_next("invalid pattern binding, ')' expected");
 | 
			
		||||
            }
 | 
			
		||||
            next();
 | 
			
		||||
            m_num_expr_frames = num_frames + 1;
 | 
			
		||||
            expr_stack().push_back(compile_patterns(t, patterns, cases));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void pop_match_frame(match_frame* fr) {
 | 
			
		||||
            m_stack.deallocate(fr);
 | 
			
		||||
            m_num_expr_frames--;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        expr_ref compile_patterns(expr* t, expr_ref_vector const& patterns, expr_ref_vector const& cases) {
 | 
			
		||||
            expr_ref result(m());
 | 
			
		||||
            var_subst sub(m(), false);
 | 
			
		||||
            TRACE("parse_expr", tout << "term\n" << expr_ref(t, m()) << "\npatterns\n" << patterns << "\ncases\n" << cases << "\n";);
 | 
			
		||||
            check_patterns(patterns, m().get_sort(t));
 | 
			
		||||
            for (unsigned i = patterns.size(); i > 0; ) {
 | 
			
		||||
                --i;
 | 
			
		||||
                expr_ref_vector subst(m());
 | 
			
		||||
                expr_ref cond = bind_match(t, patterns[i], subst);
 | 
			
		||||
                expr_ref new_case(m());
 | 
			
		||||
                if (subst.empty()) {
 | 
			
		||||
                    new_case = cases[i];
 | 
			
		||||
                }
 | 
			
		||||
                else {
 | 
			
		||||
                    sub(cases[i], subst.size(), subst.c_ptr(), new_case);
 | 
			
		||||
                    inv_var_shifter inv(m());
 | 
			
		||||
                    inv(new_case, subst.size(), new_case);
 | 
			
		||||
                }
 | 
			
		||||
                if (result) {
 | 
			
		||||
                    result = m().mk_ite(cond, new_case, result);
 | 
			
		||||
                }
 | 
			
		||||
                else {
 | 
			
		||||
                    // pattern match binding is ignored.
 | 
			
		||||
                    result = new_case;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            TRACE("parse_expr", tout << result << "\n";);
 | 
			
		||||
            return result;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void check_patterns(expr_ref_vector const& patterns, sort* s) {
 | 
			
		||||
            if (!dtutil().is_datatype(s)) 
 | 
			
		||||
                throw parser_exception("pattern matching is only supported for algebraic datatypes");
 | 
			
		||||
            ptr_vector<func_decl> const& cons = *dtutil().get_datatype_constructors(s);
 | 
			
		||||
            for (expr * arg : patterns) if (is_var(arg)) return;
 | 
			
		||||
            if (patterns.size() < cons.size()) 
 | 
			
		||||
                throw parser_exception("non-exhaustive pattern match");
 | 
			
		||||
            ast_fast_mark1 marked;
 | 
			
		||||
            for (expr * arg : patterns) 
 | 
			
		||||
                marked.mark(to_app(arg)->get_decl(), true);
 | 
			
		||||
            for (func_decl * f : cons) 
 | 
			
		||||
                if (!marked.is_marked(f)) 
 | 
			
		||||
                    throw parser_exception("a constructor is missing from pattern match");        
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // compute match condition and substitution
 | 
			
		||||
        // t is shifted by size of subst.
 | 
			
		||||
        expr_ref bind_match(expr* t, expr* pattern, expr_ref_vector& subst) {
 | 
			
		||||
            expr_ref tsh(m());
 | 
			
		||||
            if (is_var(pattern)) {
 | 
			
		||||
                shifter()(t, 1, tsh);
 | 
			
		||||
                subst.push_back(tsh);
 | 
			
		||||
                return expr_ref(m().mk_true(), m());
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
                SASSERT(is_app(pattern));
 | 
			
		||||
                func_decl * f = to_app(pattern)->get_decl();
 | 
			
		||||
                func_decl * r = dtutil().get_constructor_recognizer(f);
 | 
			
		||||
                ptr_vector<func_decl> const * acc = dtutil().get_constructor_accessors(f);
 | 
			
		||||
                shifter()(t, acc->size(), tsh);
 | 
			
		||||
                for (func_decl* a : *acc) {
 | 
			
		||||
                    subst.push_back(m().mk_app(a, tsh));
 | 
			
		||||
                }
 | 
			
		||||
                return expr_ref(m().mk_app(r, t), m());
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * parse a match pattern
 | 
			
		||||
         * (C x1 .... xn)
 | 
			
		||||
         * C
 | 
			
		||||
         * _
 | 
			
		||||
         * x
 | 
			
		||||
         */
 | 
			
		||||
 | 
			
		||||
        bool parse_constructor_pattern(sort * srt) {
 | 
			
		||||
            if (!curr_is_lparen()) {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
            next();
 | 
			
		||||
            svector<symbol> vars;
 | 
			
		||||
            expr_ref_vector args(m());
 | 
			
		||||
            symbol C(check_identifier_next("constructor symbol expected"));
 | 
			
		||||
            while (!curr_is_rparen()) {
 | 
			
		||||
                symbol v(check_identifier_next("variable symbol expected"));
 | 
			
		||||
                if (v != m_underscore && vars.contains(v)) {
 | 
			
		||||
                    throw parser_exception("unexpected repeated variable in pattern expression");
 | 
			
		||||
                } 
 | 
			
		||||
                vars.push_back(v);
 | 
			
		||||
            }                
 | 
			
		||||
            next();
 | 
			
		||||
            
 | 
			
		||||
            // now have C, vars
 | 
			
		||||
            // look up constructor C, 
 | 
			
		||||
            // create bound variables based on constructor type.
 | 
			
		||||
            // store expression in expr_stack().
 | 
			
		||||
            // ensure that bound variables are adjusted to vars
 | 
			
		||||
            
 | 
			
		||||
            func_decl* f = m_ctx.find_func_decl(C, 0, nullptr, vars.size(), nullptr, srt);
 | 
			
		||||
            if (!f) {
 | 
			
		||||
                throw parser_exception("expecting a constructor that has been declared");
 | 
			
		||||
            }
 | 
			
		||||
            if (!dtutil().is_constructor(f)) {
 | 
			
		||||
                throw parser_exception("expecting a constructor");
 | 
			
		||||
            }
 | 
			
		||||
            if (f->get_arity() != vars.size()) {
 | 
			
		||||
                throw parser_exception("mismatching number of variables supplied to constructor");
 | 
			
		||||
            }
 | 
			
		||||
            m_num_bindings += vars.size();
 | 
			
		||||
            for (unsigned i = 0; i < vars.size(); ++i) {
 | 
			
		||||
                var * v = m().mk_var(i, f->get_domain(i));
 | 
			
		||||
                args.push_back(v);
 | 
			
		||||
                if (vars[i] != m_underscore) {
 | 
			
		||||
                    m_env.insert(vars[i], local(v, m_num_bindings));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            expr_stack().push_back(m().mk_app(f, args.size(), args.c_ptr()));
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void parse_match_pattern(sort* srt) {
 | 
			
		||||
            if (parse_constructor_pattern(srt)) {
 | 
			
		||||
                // done
 | 
			
		||||
            }
 | 
			
		||||
            else if (curr_id() == m_underscore) {
 | 
			
		||||
                // we have a wild-card.                
 | 
			
		||||
                // store dummy variable in expr_stack()
 | 
			
		||||
                next();
 | 
			
		||||
                var* v = m().mk_var(0, srt);
 | 
			
		||||
                expr_stack().push_back(v);
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
                symbol xC(check_identifier_next("constructor symbol or variable expected"));            
 | 
			
		||||
                // check if xC is a constructor, otherwise make it a variable
 | 
			
		||||
                // of sort srt.
 | 
			
		||||
                try {
 | 
			
		||||
                    func_decl* f = m_ctx.find_func_decl(xC, 0, nullptr, 0, nullptr, srt);
 | 
			
		||||
                    if (!dtutil().is_constructor(f)) {
 | 
			
		||||
                        throw parser_exception("expecting a constructor, got a previously declared function");
 | 
			
		||||
                    }
 | 
			
		||||
                    if (f->get_arity() > 0) {
 | 
			
		||||
                        throw parser_exception("constructor expects arguments, but no arguments were supplied in pattern");
 | 
			
		||||
                    }
 | 
			
		||||
                    expr_stack().push_back(m().mk_const(f));
 | 
			
		||||
                }
 | 
			
		||||
                catch (cmd_exception &) {
 | 
			
		||||
                    var* v = m().mk_var(0, srt);
 | 
			
		||||
                    expr_stack().push_back(v);
 | 
			
		||||
                    m_env.insert(xC, local(v, m_num_bindings++));            
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        symbol parse_indexed_identifier_core() {
 | 
			
		||||
            check_underscore_next("invalid indexed identifier, '_' expected");
 | 
			
		||||
            check_identifier("invalid indexed identifier, symbol expected");
 | 
			
		||||
| 
						 | 
				
			
			@ -1564,8 +1794,7 @@ namespace smt2 {
 | 
			
		|||
            new (mem) app_frame(f, expr_spos, param_spos, has_as);
 | 
			
		||||
            m_num_expr_frames++;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // return true if a new frame was created.
 | 
			
		||||
        
 | 
			
		||||
        void push_expr_frame(expr_frame * curr) {
 | 
			
		||||
            SASSERT(curr_is_lparen());
 | 
			
		||||
            next();
 | 
			
		||||
| 
						 | 
				
			
			@ -1573,11 +1802,7 @@ namespace smt2 {
 | 
			
		|||
            if (curr_is_identifier()) {
 | 
			
		||||
                TRACE("push_expr_frame", tout << "push_expr_frame(), curr_id(): " << curr_id() << "\n";);
 | 
			
		||||
                if (curr_id_is_let()) {
 | 
			
		||||
                    next();
 | 
			
		||||
                    check_lparen_next("invalid let declaration, '(' expected");
 | 
			
		||||
                    void * mem = m_stack.allocate(sizeof(let_frame));
 | 
			
		||||
                    new (mem) let_frame(symbol_stack().size(), expr_stack().size());
 | 
			
		||||
                    m_num_expr_frames++;
 | 
			
		||||
                    push_let_frame();
 | 
			
		||||
                }
 | 
			
		||||
                else if (curr_id_is_forall()) {
 | 
			
		||||
                    push_quant_frame(true);
 | 
			
		||||
| 
						 | 
				
			
			@ -1586,19 +1811,17 @@ namespace smt2 {
 | 
			
		|||
                    push_quant_frame(false);
 | 
			
		||||
                }
 | 
			
		||||
                else if (curr_id_is_bang()) {
 | 
			
		||||
                    TRACE("consume_attributes", tout << "begin bang, expr_stack.size(): " << expr_stack().size() << "\n";);
 | 
			
		||||
                    next();
 | 
			
		||||
                    void * mem = m_stack.allocate(sizeof(attr_expr_frame));
 | 
			
		||||
                    new (mem) attr_expr_frame(curr, symbol_stack().size(), expr_stack().size());
 | 
			
		||||
                    m_num_expr_frames++;
 | 
			
		||||
                    push_bang_frame(curr);
 | 
			
		||||
                }
 | 
			
		||||
                else if (curr_id_is_as() || curr_id_is_underscore()) {
 | 
			
		||||
                    TRACE("push_expr_frame", tout << "push_expr_frame(): parse_qualified_name\n";);
 | 
			
		||||
                    parse_qualified_name();
 | 
			
		||||
                }
 | 
			
		||||
                else if (curr_id_is_root_obj()) {
 | 
			
		||||
                    parse_root_obj();
 | 
			
		||||
                }
 | 
			
		||||
                else if (curr_id_is_match()) {
 | 
			
		||||
                    push_match_frame();
 | 
			
		||||
                }
 | 
			
		||||
                else {
 | 
			
		||||
                    push_app_frame();
 | 
			
		||||
                }
 | 
			
		||||
| 
						 | 
				
			
			@ -1658,6 +1881,8 @@ namespace smt2 {
 | 
			
		|||
                // the resultant expression is on the top of the stack
 | 
			
		||||
                TRACE("let_frame", tout << "let result expr: " << mk_pp(expr_stack().back(), m()) << "\n";);
 | 
			
		||||
                expr_ref r(m());
 | 
			
		||||
                if (expr_stack().empty())
 | 
			
		||||
                    throw parser_exception("invalid let expression");
 | 
			
		||||
                r = expr_stack().back();
 | 
			
		||||
                expr_stack().pop_back();
 | 
			
		||||
                // remove local declarations from the stack
 | 
			
		||||
| 
						 | 
				
			
			@ -1773,6 +1998,9 @@ namespace smt2 {
 | 
			
		|||
                m_stack.deallocate(static_cast<let_decl_frame*>(fr));
 | 
			
		||||
                m_num_expr_frames--;
 | 
			
		||||
                break;
 | 
			
		||||
            case EF_MATCH:
 | 
			
		||||
                pop_match_frame(static_cast<match_frame*>(fr));
 | 
			
		||||
                break;
 | 
			
		||||
            case EF_QUANT:
 | 
			
		||||
                pop_quant_frame(static_cast<quant_frame*>(fr));
 | 
			
		||||
                break;
 | 
			
		||||
| 
						 | 
				
			
			@ -2232,8 +2460,10 @@ namespace smt2 {
 | 
			
		|||
                throw cmd_exception("invalid assert command, expression required as argument");
 | 
			
		||||
            }
 | 
			
		||||
            expr * f = expr_stack().back();
 | 
			
		||||
            if (!m().is_bool(f))
 | 
			
		||||
            if (!m().is_bool(f)) {
 | 
			
		||||
                TRACE("smt2parser", tout << expr_ref(f, m()) << "\n";);
 | 
			
		||||
                throw cmd_exception("invalid assert command, term is not Boolean");
 | 
			
		||||
            }
 | 
			
		||||
            if (f == m_last_named_expr.second) {
 | 
			
		||||
                m_ctx.assert_expr(m_last_named_expr.first, f);
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -2730,6 +2960,7 @@ namespace smt2 {
 | 
			
		|||
            m_check_sat_assuming("check-sat-assuming"),
 | 
			
		||||
            m_define_fun_rec("define-fun-rec"),
 | 
			
		||||
            m_define_funs_rec("define-funs-rec"),
 | 
			
		||||
            m_match("match"),
 | 
			
		||||
            m_underscore("_"),
 | 
			
		||||
            m_num_open_paren(0),
 | 
			
		||||
            m_current_file(filename) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -124,7 +124,7 @@ namespace smt2 {
 | 
			
		|||
        next();
 | 
			
		||||
        bool is_float = false;
 | 
			
		||||
 | 
			
		||||
        while (true) {
 | 
			
		||||
        while (!m_at_eof) {
 | 
			
		||||
            char c = curr();
 | 
			
		||||
            if ('0' <= c && c <= '9') {
 | 
			
		||||
                m_number = rational(10)*m_number + rational(c - '0');
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1272,7 +1272,7 @@ namespace qe {
 | 
			
		|||
        family_id fid = p->get_family_id();
 | 
			
		||||
        SASSERT(fid != null_family_id);
 | 
			
		||||
        if (static_cast<int>(m_plugins.size()) <= fid) {
 | 
			
		||||
            m_plugins.resize(fid+1,0);
 | 
			
		||||
            m_plugins.resize(fid+1);
 | 
			
		||||
        }
 | 
			
		||||
        SASSERT(!m_plugins[fid]);
 | 
			
		||||
        m_plugins[fid] = p;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -105,10 +105,10 @@ namespace qe {
 | 
			
		|||
                rational r;
 | 
			
		||||
                app* alit = to_app(lit);
 | 
			
		||||
                vector<std::pair<expr*,rational> > nums;
 | 
			
		||||
                for (unsigned i = 0; i < alit->get_num_args(); ++i) {
 | 
			
		||||
                    val = eval(alit->get_arg(i));
 | 
			
		||||
                for (expr* arg : *alit) {
 | 
			
		||||
                    val = eval(arg);
 | 
			
		||||
                    if (!a.is_numeral(val, r)) return false;
 | 
			
		||||
                    nums.push_back(std::make_pair(alit->get_arg(i), r));
 | 
			
		||||
                    nums.push_back(std::make_pair(arg, r));
 | 
			
		||||
                }
 | 
			
		||||
                std::sort(nums.begin(), nums.end(), compare_second());
 | 
			
		||||
                for (unsigned i = 0; i + 1 < nums.size(); ++i) {
 | 
			
		||||
| 
						 | 
				
			
			@ -168,8 +168,8 @@ namespace qe {
 | 
			
		|||
            }
 | 
			
		||||
            else if (a.is_add(t)) {
 | 
			
		||||
                app* ap = to_app(t);
 | 
			
		||||
                for (unsigned i = 0; i < ap->get_num_args(); ++i) {
 | 
			
		||||
                    linearize(mbo, eval, mul, ap->get_arg(i), c, fmls, ts, tids);
 | 
			
		||||
                for (expr* arg : *ap) {
 | 
			
		||||
                    linearize(mbo, eval, mul, arg, c, fmls, ts, tids);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else if (a.is_sub(t, t1, t2)) {
 | 
			
		||||
| 
						 | 
				
			
			@ -226,16 +226,16 @@ namespace qe {
 | 
			
		|||
            else if (a.is_mul(t)) {
 | 
			
		||||
                app* ap = to_app(t);
 | 
			
		||||
                r = rational(1);
 | 
			
		||||
                for (unsigned i = 0; i < ap->get_num_args(); ++i) {
 | 
			
		||||
                    if (!is_numeral(ap->get_arg(i), r1)) return false;
 | 
			
		||||
                for (expr * arg : *ap) {
 | 
			
		||||
                    if (!is_numeral(arg, r1)) return false;
 | 
			
		||||
                    r *= r1;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else if (a.is_add(t)) {
 | 
			
		||||
                app* ap = to_app(t);
 | 
			
		||||
                r = rational(0);
 | 
			
		||||
                for (unsigned i = 0; i < ap->get_num_args(); ++i) {
 | 
			
		||||
                    if (!is_numeral(ap->get_arg(i), r1)) return false;
 | 
			
		||||
                for (expr * arg : *ap) {
 | 
			
		||||
                    if (!is_numeral(arg, r1)) return false;
 | 
			
		||||
                    r += r1;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -297,6 +297,7 @@ namespace qe {
 | 
			
		|||
 | 
			
		||||
            opt::model_based_opt mbo;
 | 
			
		||||
            obj_map<expr, unsigned> tids;
 | 
			
		||||
            expr_ref_vector pinned(m);
 | 
			
		||||
            unsigned j = 0;
 | 
			
		||||
            for (unsigned i = 0; i < fmls.size(); ++i) {
 | 
			
		||||
                expr* fml = fmls[i].get();
 | 
			
		||||
| 
						 | 
				
			
			@ -308,6 +309,7 @@ namespace qe {
 | 
			
		|||
                }
 | 
			
		||||
                else {
 | 
			
		||||
                    TRACE("qe", tout << mk_pp(fml, m) << "\n";);
 | 
			
		||||
                    pinned.push_back(fml);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            fmls.resize(j);
 | 
			
		||||
| 
						 | 
				
			
			@ -321,8 +323,7 @@ namespace qe {
 | 
			
		|||
            // return those to fmls.
 | 
			
		||||
 | 
			
		||||
            expr_mark var_mark, fmls_mark;
 | 
			
		||||
            for (unsigned i = 0; i < vars.size(); ++i) {
 | 
			
		||||
                app* v = vars[i].get();
 | 
			
		||||
            for (app * v : vars) {
 | 
			
		||||
                var_mark.mark(v);
 | 
			
		||||
                if (is_arith(v) && !tids.contains(v)) {
 | 
			
		||||
                    rational r;
 | 
			
		||||
| 
						 | 
				
			
			@ -332,17 +333,16 @@ namespace qe {
 | 
			
		|||
                    tids.insert(v, mbo.add_var(r, a.is_int(v)));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            for (unsigned i = 0; i < fmls.size(); ++i) {
 | 
			
		||||
                fmls_mark.mark(fmls[i].get());
 | 
			
		||||
            for (expr* fml : fmls) {
 | 
			
		||||
                fmls_mark.mark(fml);
 | 
			
		||||
            }
 | 
			
		||||
            obj_map<expr, unsigned>::iterator it = tids.begin(), end = tids.end();
 | 
			
		||||
            ptr_vector<expr> index2expr;
 | 
			
		||||
            for (; it != end; ++it) {
 | 
			
		||||
                expr* e = it->m_key;
 | 
			
		||||
            for (auto& kv : tids) {
 | 
			
		||||
                expr* e = kv.m_key;
 | 
			
		||||
                if (!var_mark.is_marked(e)) {
 | 
			
		||||
                    mark_rec(fmls_mark, e);
 | 
			
		||||
                }
 | 
			
		||||
                index2expr.setx(it->m_value, e, 0);
 | 
			
		||||
                index2expr.setx(kv.m_value, e, 0);
 | 
			
		||||
            }
 | 
			
		||||
            j = 0;
 | 
			
		||||
            unsigned_vector real_vars;
 | 
			
		||||
| 
						 | 
				
			
			@ -360,8 +360,7 @@ namespace qe {
 | 
			
		|||
            }
 | 
			
		||||
            vars.resize(j);
 | 
			
		||||
            TRACE("qe", tout << "remaining vars: " << vars << "\n"; 
 | 
			
		||||
                  for (unsigned i = 0; i < real_vars.size(); ++i) {
 | 
			
		||||
                      unsigned v = real_vars[i];
 | 
			
		||||
                  for (unsigned v : real_vars) {
 | 
			
		||||
                      tout << "v" << v << " " << mk_pp(index2expr[v], m) << "\n";
 | 
			
		||||
                  }
 | 
			
		||||
                  mbo.display(tout););
 | 
			
		||||
| 
						 | 
				
			
			@ -449,8 +448,8 @@ namespace qe {
 | 
			
		|||
 | 
			
		||||
            // extract linear constraints
 | 
			
		||||
            
 | 
			
		||||
            for (unsigned i = 0; i < fmls.size(); ++i) {
 | 
			
		||||
                linearize(mbo, eval, fmls[i].get(), fmls, tids);
 | 
			
		||||
            for (expr * fml : fmls) {
 | 
			
		||||
                linearize(mbo, eval, fml, fmls, tids);
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            // find optimal value
 | 
			
		||||
| 
						 | 
				
			
			@ -459,11 +458,10 @@ namespace qe {
 | 
			
		|||
 | 
			
		||||
            // update model to use new values that satisfy optimality
 | 
			
		||||
            ptr_vector<expr> vars;
 | 
			
		||||
            obj_map<expr, unsigned>::iterator it = tids.begin(), end = tids.end();
 | 
			
		||||
            for (; it != end; ++it) {
 | 
			
		||||
                expr* e = it->m_key;
 | 
			
		||||
            for (auto& kv : tids) {
 | 
			
		||||
                expr* e = kv.m_key;
 | 
			
		||||
                if (is_uninterp_const(e)) {
 | 
			
		||||
                    unsigned id = it->m_value;
 | 
			
		||||
                    unsigned id = kv.m_value;
 | 
			
		||||
                    func_decl* f = to_app(e)->get_decl();
 | 
			
		||||
                    expr_ref val(a.mk_numeral(mbo.get_value(id), false), m);
 | 
			
		||||
                    mdl.register_decl(f, val);
 | 
			
		||||
| 
						 | 
				
			
			@ -509,10 +507,9 @@ namespace qe {
 | 
			
		|||
        void extract_coefficients(opt::model_based_opt& mbo, model_evaluator& eval, obj_map<expr, rational> const& ts, obj_map<expr, unsigned>& tids, vars& coeffs) {
 | 
			
		||||
            coeffs.reset();
 | 
			
		||||
            eval.set_model_completion(true);
 | 
			
		||||
            obj_map<expr, rational>::iterator it = ts.begin(), end = ts.end();
 | 
			
		||||
            for (; it != end; ++it) {
 | 
			
		||||
            for (auto& kv : ts) {
 | 
			
		||||
                unsigned id;
 | 
			
		||||
                expr* v = it->m_key;
 | 
			
		||||
                expr* v = kv.m_key;
 | 
			
		||||
                if (!tids.find(v, id)) {
 | 
			
		||||
                    rational r;
 | 
			
		||||
                    expr_ref val = eval(v);
 | 
			
		||||
| 
						 | 
				
			
			@ -520,9 +517,9 @@ namespace qe {
 | 
			
		|||
                    id = mbo.add_var(r, a.is_int(v));
 | 
			
		||||
                    tids.insert(v, id);
 | 
			
		||||
                }
 | 
			
		||||
                CTRACE("qe", it->m_value.is_zero(), tout << mk_pp(v, m) << " has coefficeint 0\n";);
 | 
			
		||||
                if (!it->m_value.is_zero()) {
 | 
			
		||||
                    coeffs.push_back(var(id, it->m_value));                
 | 
			
		||||
                CTRACE("qe", kv.m_value.is_zero(), tout << mk_pp(v, m) << " has coefficeint 0\n";);
 | 
			
		||||
                if (!kv.m_value.is_zero()) {
 | 
			
		||||
                    coeffs.push_back(var(id, kv.m_value));                
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,7 +35,7 @@ namespace sat {
 | 
			
		|||
        m_glue("glue"),
 | 
			
		||||
        m_glue_psm("glue_psm"),
 | 
			
		||||
        m_psm_glue("psm_glue") {
 | 
			
		||||
        m_num_parallel = 1;
 | 
			
		||||
        m_num_parallel = 1;        
 | 
			
		||||
        updt_params(p); 
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -114,6 +114,7 @@ namespace sat {
 | 
			
		|||
        m_core_minimize   = p.core_minimize();
 | 
			
		||||
        m_core_minimize_partial   = p.core_minimize_partial();
 | 
			
		||||
        m_dyn_sub_res     = p.dyn_sub_res();
 | 
			
		||||
        m_dimacs_display  = p.dimacs_display();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void config::collect_param_descrs(param_descrs & r) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -74,6 +74,7 @@ namespace sat {
 | 
			
		|||
        bool               m_core_minimize;
 | 
			
		||||
        bool               m_core_minimize_partial;
 | 
			
		||||
 | 
			
		||||
        bool               m_dimacs_display;
 | 
			
		||||
 | 
			
		||||
        symbol             m_always_true;
 | 
			
		||||
        symbol             m_always_false;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,4 +23,5 @@ def_module_params('sat',
 | 
			
		|||
                          ('core.minimize', BOOL, False, 'minimize computed core'),
 | 
			
		||||
                          ('core.minimize_partial', BOOL, False, 'apply partial (cheap) core minimization'),
 | 
			
		||||
                          ('parallel_threads', UINT, 1, 'number of parallel threads to use'),
 | 
			
		||||
                          ('dimacs.core', BOOL, False, 'extract core from DIMACS benchmarks')))
 | 
			
		||||
                          ('dimacs.core', BOOL, False, 'extract core from DIMACS benchmarks'),
 | 
			
		||||
                          ('dimacs.display', BOOL, False, 'display SAT instance in DIMACS format and return unknown instead of solving')))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
Some files were not shown because too many files have changed in this diff Show more
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue