3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-08 10:25:18 +00:00
z3/lib/z3_solver.h
Leonardo de Moura e9eab22e5c Z3 sources
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
2012-10-02 11:35:25 -07:00

1008 lines
29 KiB
C++

/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
z3_solver.h
Abstract:
Native ast parser.
Author:
Nikolaj Bjorner (nbjorner) 2007-07-17
Revision History:
--*/
/**
\defgroup z3native Z3 low level input format
This format is mainly used for generating logs. These logs
capture the expressions created using the Z3 API, and
the main commands available there.
It is very low-level and follows
some of the conventions found in the DIMACS format for SAT problems
and by the <a class="el" href="http://www.cs.ubc.ca/~babic/index_spear.htm">Spear</a>
input format.
The format is extensible, as the grammar allows for
selecting solvers and adding \emph{semantic attachments}
with constructors. The <a class="el" href="http://www.smtlib.org">SMT-LIB</a> and Simplify text formats are easier to
write and read for a human consumer.
Every line consists of a command that gets interpreted
as a declaration of a node in anbstract syntax tree, or as
a control instruction to Z3, such as to augment the current
context with constraints or check for satisfiability.
\nicebox{
<i>command</i> :=
| <i>ast</i>
| <i>control </i>
| <i> ; commented line </i>
}
White spaces are implicit in the production rules.
The legal white-spaces have the ASCII representations
\nicebox{
' ' | \ t | \ r
}
Comment lines start with \c ;.
All characters up to the newline \ n are ignored.
We use <i>id</i> for identifiers in general.
Identifiers associated with certain semantic categories,
such as \emph{ast} nodes, or \emph{type}s are
prefixed by the category and suffixed by \emph{id}.
For example, we have:
\nicebox{
ast-id - identifier for ast nodes
type-id - identifier for type nodes
parameter-id - identifier for ast
name-id - identifier for a function/type name
decl-id - identifier for declaration node
context-id - identifier for Boolean context
}
Identifiers can be any sequence of non-whitespace
and non-newline characters whose first character
is not one of the decimal digits.
Identifiers enclosed in quotes ''...''
are treated specially: the quotes are stripped.
Thus, the identifier consisting of zero characters
is written ''''. The identifier ''null''
is allowed for <em>skolem-id</em> and <em>quant-id</em>.
\section nativecontrol Control commands
To load a theory solver for integer linear arithmetic,
include a line of the form \ty{Solver LIA}. To load the
mixed integer/real solver include instead a line of the
form \ty{Solver LRA}
Use \ty{Push} and \ty{Pop} to push/pop contexts
(constraints that are asserted
under a \ty{Push} are removed after a \ty{Pop}).
To reset the state entirely, use \ty{Reset}.
To assert a constraint use \ty{Assert} \emph{ast-id},
where the \emph{ast-id} is an identifier declared
for a boolean typed term.
To check for satisfiability of all asserted constraints
use \ty{Check}.
\nicebox{
<i>control</i> :=
| Solver <i>solver</i> - load specified theory solver
| Assert <i>ast-id</i> - assert constraint
| Check - check for satisfiability of asserts
| Push - push a context
| Pop - pop a context
| Version <i>major minor build-number revision</i> - specify Z3 version
<i>solver</i> :=
| LRA - mixed integer/real arithmetic
| LIA - integer arithmetic}
\section z3nativeast Abstract syntax trees
Every node in the abstract syntax trees understood by Z3
is declared by using a syntax category identifier, followed
by a (unique) identifier that names the node. The
node identifier is followed by a description of the node.
In overview abstract syntax tree nodes are declared using the commands:
\nicebox{
<i>ast</i> :=
| Type <i>id</i> <i>type</i>
| Dec <i>id</i> <i>declaration</i>
| Const <i>id</i> <i>constant</i>
| Fun <i>id</i> <i>function</i>
| App <i>id</i> <i>built-in</i>
| Num <i>id</i> <i>numeral</i>
| Qua <i>id</i> <i>quantifier</i>
| Var <i>id</i> <i>bound-variable</i>
| Ctx <i>id</i> <i>local-context</i>
| Lab <i>id</i> <i>label-term</i>
| Pat <i>id</i> <i>pattern</i>
}
\subsection z3nativetypes Types
Types are created from a name and optional parameters.
A number of names are reserved for built-in theories.
These names are:
\nicebox{
Int Real Bool bv array
}
When the name of a type is one of these, the type is automatically
associated with the respective theory.
The \ty{bv} type takes one numeric parameter (the bit-width of the
bit-vector), and \ty{array} takes <i>n+1</i> parameters (the <i>n</i>
types for the domain of the array and the last parameter for the
range of the array.
\nicebox{
<i>type</i> := <i>name</i> '[' <i>parameter</i>* ']'
<i>parameter</i> := <i>number</i> | <i>ast-id</i> | <i>symbol</i>
}
A parameter can either be an integer, an identifier used for
another defined term or type, or a symbol. Symbols are given as
strings. The parser first attempts to identify a parameter as
a previously defined term or type, and if there is no
such previously defined term/type, then it treats the string
as a symbol.
\subsection nativez3Fuctions Function and constant declarations
In Z3, functions are constants that take more than zero arguments,
thus, everything is treated as a constant.
Constant declarations comprise of a name, followed by
a non-empty list of types, all but the first types
are the domain of the function (there are no domain
types for 0-ary constants), the last type is the range.
A constant declaration is followed by optional
theory specific information.
The codes used in the theory specific information is described under \ref theories
The theory specific information indicates
whether the constant is associative/commutative/injective;
a list of parameters may also be used to indicate
auxiliary information for the constant declarations.
\nicebox{
<i>declaration</i> := <i>name-id</i> <i>type-id</i>* [<i>const-info</i>]
<i>const-info</i> := BUILTIN <i>theory</i> <i>kind-num</i> (:assoc | :comm | :inj | <i>parameter</i>)*
<i>theory</i> :=
| basic - built-in types and operations
| arith - arithmetical
| bv - bit-vectors
| array - arrays
| datatype - datatypes
}
\subsection z3nativeterms Terms
Terms are built from constants, function applications,
labeling, context formation, quantification
and bound variables.
A constant consists of a declarations, functions consist of
a declaration followed by a non-empty list of term identifiers.
All constants and function applications can be constructed using
the \ty{Fun} construct. However, two shortcuts are available.
<ul>
<li> \ty{Const}:
Constants may be defined directly by supplying the name and the type of the constant.
</li>
<li> \ty{App}:
Built-in arithmetic, array, bit-vector, and Boolean operations may be applied directly
to their arguments without first providing function declarations.
</li>
</ul>
\nicebox{
<i>constant</i> := <i>name-id</i> <i>type-id</i>
<i>function</i> := <i>decl-id</i> <i>ast-id</i>*
<i>built-in</i> := <i>name-id</i> [<i> [</i> <i>parameter</i>* ]</i> </i>] <i>ast-id</i>*
}
Labeled terms consist of a polarity (\ty{LBLPOS} for positive
context, \ty{LBLNEG} for negative contexts), a name, and a
term identifier.
\nicebox{
<i>label-term</i> := (LBLPOS | LBLNEG) <i>label-name</i> <i>ast-id</i>
}
Local contexts consist of an identifier for the underlying
term, followed by a predicate summarizing the context in
which the term is interpreted.
\nicebox{
<i>local-context</i> := <i>ast-id</i> <i>context-id</i>
}
A quantifier consists of
<ul>
<li>
A number indiciating the
weight of the quantifier (for matching precedence),
<li>
A skolem identifier, used for Boogie quantifier instantiation,
<li>
A quantifier identifier, used for profiling instantiations,
<li>
A number indicating how many variables are bound by the quantifier, followed
by the bound variables, which are
<ul>
<li> A name for the bound variable.
<li> An identifier for the type of the bound variable.
</ul>
<li>
A number indicating how many patterns are associated with the quantifier,
followed by the patterns, which are
<ul>
<li> An identifier for the pattern.
</ul>
<li> An identifier for the body of the quantifier.
</ul>
\nicebox{
<i>quantifier</i> :=
(FORALL | EXISTS)
<i>weight-num</i>
<i>skolem-id</i>
<i>quant-id</i>
<i>decls-num</i>
(<i>name-id</i> <i>type-id</i>)*
<i>pattern-num</i>
<i>pattern-id</i>*
<i>ast-id</i>
}
A bound variable consists of a de-Brujin index for the bound
variable together with the type of the bound variable.
While the type can be computed by matching the index of
the de-Brujin index with the associated quantifier,
Patterns comprise of a list of terms.
\nicebox{
<i>bound-variable</i> := <i>index-num</i> <i>type-id</i>
<i>numeral</i> := <i>rational</i> <i>type-id</i>
<i>rational</i> := <i>number</i> [/<i>number</i>]
<i>number</i> := [0-9]+
<i>pattern</i> := <i>id</i> <i>ast-id</i>*
}
\section z3nativeexamples Examples
\subsection z3nativearithmetic Integer Arithmetic
Suppose we wish to check whether
\nicebox{
z0 >= 0 && z1 >= 0 && z2 >= 1 && z1 >= z2 && z2 >= z0
}
is satisfiable for <pre>z0, z1, z2</pre> integers.
With the low-level input format, we may specify this by:
\nicebox{
Type INT Int
Type BOOL Bool
Const z0 z0 INT
Const z1 z1 INT
Const z2 z2 INT
Num 0 0 INT
Num 1 1 INT
App c0 >= z0 0
Assert c0
App c1 >= z1 0
Assert c1
App c2 >= z2 1
Assert c2
App c3 >= z1 z2
Assert c3
App c4 >= z2 z0
Assert c4
Check
}
Notice that the identifiers may be arbitrary strings, including numerals.
So for instance, we used 1 to represent integer 1.
\subsection z3nativebv Bit-vectors
We can check whether 32-bit addition is commutative. Z3 reports \ty{unsat}
in for the first check. The second satisfiable check illustrates the use of parameters
(\ty{extract} takes two integer parameters for the range of bits extracted
from the bit-vectors).
\nicebox{
Type bool Bool
Type bv32 bv [ 32 ]
Type bv64 bv [ 64 ]
Num 0 0 bv32
Num 1 1 bv32
Const x0 x0 bv32
Const x1 x1 bv32
Const x2 x2 bv64
App a bvadd x0 x1
App b bvadd x1 x0
App eq = a b
App constraint1 not eq
Push
Assert constraint1
Check
Pop
App c extract [ 31 0 ] x2
App eq2 = a c
App constraint2 not eq2
Push
Assert constraint2
Check
Pop
}
We added the declarations of bit-vector constants 0 and 1. Like integers,
these are also numerals, but with bit-vector type.
\subsection z3nativeexarray Arrays
The low-level version of:
\nicebox{
store(f1,i1,v1) = store(f2,i2,v2) && i1 != i3 && i2 != i3 && select(f1,i3) != select(f2,i3)
}
is:
\nicebox{
Type Index Index
Type Elem Elem
Type Array array [ Index Elem ]
Type bool Bool
Const i1 i1 Index
Const i2 i2 Index
Const i3 i3 Index
Const v1 v1 Elem
Const v2 v2 Elem
Const f1 f1 Array
Const f2 f2 Array
App n1 store f1 i1 v1
App n2 store f2 i2 v2
App n3 = n1 n2
App n4 = i1 i3
App n5 not n4
App n6 = i2 i3
App n7 not n6
App n8 select f1 i3
App n9 select f2 i3
App n10 = n8 n9
App n11 not n10
Assert n3
Assert n5
Assert n7
Assert n11
Check
}
\subsection z3nativeexdatatype Data-types
To check projection over tuples
\nicebox{
(= x (first (mk_tuple x y)))
}
we write:
\nicebox{
Type int Int
Type pair tuple [ mk_tuple first int second int ]
Const x x int
Const y y int
Const p p pair
App n1 mk_tuple x y
App n2 first n1
App n3 = n2 x
App n4 not n3
Assert n4
Check
}
*/
/**
\defgroup theories Z3 theories
\section theorisbasics Basics
There is a single basic sort, \ty{bool}, which has op-code 0.
The basic operators are, listed with their codes in the table below.
<table border cellspacing=5 cellpadding=10>
<tr>
<th>Op-code</th>
<th>Mnmonics</th>
<th>Description</th>
</tr>
<tr><td>0</td><td> \ty{true} </td><td> the constant \emph{true} </td></tr>
<tr><td>1</td><td> \ty{false} </td><td> the constant \emph{false} </td></tr>
<tr><td>2</td><td> \ty{=} </td><td> equality</td></tr>
<tr><td>3</td><td> \ty{distinct} </td><td> distincinctness </td></tr>
<tr><td>4</td><td> \ty{ite} </td><td> if-then-else </td></tr>
<tr><td>5</td><td> \ty{and} </td><td> n-ary conjunction </td></tr>
<tr><td>6</td><td> \ty{or} </td><td> n-ary disjunction </td></tr>
<tr><td>7</td><td> \ty{iff} </td><td> bi-impliciation </td></tr>
<tr><td>8</td><td> \ty{xor} </td><td> exclusive or </td></tr>
<tr><td>9</td><td> \ty{not} </td><td> negation </td></tr>
<tr><td>10</td><td> \ty{implies} </td><td> implication </td></tr>
</table>
\section theoriesarithmetic Arithmetic
\subsection tharithbuiltin Built-in operators
Arithmetical expression can be built from reals or integers.
The arithmetical sorts are listed below
and the supported operations are listed in the table thereafter.
<table border cellspacing=5 cellpadding=10>
<tr>
<th>Op-code</th>
<th>Mnmonics</th>
<th>Description</th>
</tr>
<tr><td>0</td> <td>\ty{real}</td> <td> sort of reals</td></tr>
<tr><td>1</td> <td>\ty{int}</td> <td> sort of integers</td></tr>
</table>
<table border cellspacing=5 cellpadding=10>
<tr>
<th>Op-code</th>
<th>Mnmonics</th>
<th>Description</th>
</tr>
<tr><td>0</td> <td> \ty{<=} </td><td> less-than or equal </td></tr>
<tr><td>1</td> <td> \ty{>=} </td><td> greater-than or equal </td></tr>
<tr><td>2</td> <td> \ty{<} </td><td> less-than </td></tr>
<tr><td>3</td> <td> \ty{>} </td><td> greater-than </td></tr>
<tr><td>4</td> <td> \ty{+} </td><td> n-ary addition </td></tr>
<tr><td>5</td> <td> \ty{-} </td><td> binary minus </td></tr>
<tr><td>6</td> <td> \ty{~} </td><td> unary minus </td></tr>
<tr><td>7</td> <td> \ty{*} </td><td> n-ary multiplication </td></tr>
<tr><td>8</td> <td> \ty{/} </td><td> rational division </td></tr>
<tr><td>9</td> <td> \ty{div} </td><td> integer division </td></tr>
<tr><td>10</td> <td> \ty{rem} </td><td> integer remainder </td></tr>
<tr><td>11</td> <td> \ty{mod} </td><td> integer modulus </td></tr>
</table>
\section theoriesbv Bit-vectors
To indicate the bit-vector length one adds a numeral parameter
with the number of bits the bit-vector holds.
For instance, a declaration of the form:
\nicebox{
Type $1 bv [ 32 ]
}
declares a 32-bit bit-vector type.
<table border cellspacing=5 cellpadding=10>
<tr>
<th>Op-code</th>
<th>Mnmonics</th>
<th>Parameters</th>
<th>Description</th>
</tr>
<tr><td>0</td> <td> \ty{bit1} </td> <td></td> <td>constant comprising of a single bit set to 1</td></tr>
<tr><td>1 </td><td> \ty{bit0} </td><td> </td><td> constant comprising of a single bit set to 0. </td></tr>
<tr><td>2 </td><td> \ty{bvneg} </td><td> </td><td> Unary subtraction. </td></tr>
<tr><td>3 </td><td> \ty{bvadd} </td><td> </td><td> addition. </td></tr>
<tr><td>4 </td><td> \ty{bvsub} </td><td> </td><td> subtraction. </td></tr>
<tr><td>5 </td><td> \ty{bvmul} </td><td> </td><td> multiplication. </td></tr>
<tr><td>6 </td><td> \ty{bvsdiv} </td><td> </td><td> signed division. </td></tr>
<tr><td>7 </td><td> \ty{bvudiv} </td><td> </td><td> unsigned division.
The operands are treated as unsigned numbers. </td></tr>
<tr><td>8 </td><td> \ty{bvsrem} </td><td> </td><td> signed remainder. </td></tr>
<tr><td>9 </td><td> \ty{bvurem} </td><td> </td><td> unsigned remainder. </td></tr>
<tr><td>10 </td><td> \ty{bvsmod} </td><td> </td><td> signed modulus. </td></tr>
<tr><td>11 </td><td> \ty{bvule} </td><td> </td><td> unsigned \ty{<=}. </td></tr>
<tr><td>12 </td><td> \ty{bvsle} </td><td> </td><td> signed \ty{<=}. </td></tr>
<tr><td>13</td><td> \ty{bvuge} </td><td> </td><td> unsigned \ty{>=}. </td></tr>
<tr><td>14 </td><td> \ty{bvsge} </td><td> </td><td> signed \ty{>=}. </td></tr>
<tr><td>15 </td><td> \ty{bvult} </td><td> </td><td> unsigned \ty{<}. </td></tr>
<tr><td>16 </td><td> \ty{bvslt} </td><td> </td><td> signed \ty{<}. </td></tr>
<tr><td>17 </td><td> \ty{bvugt} </td><td> </td><td> unsigned \ty{>}. </td></tr>
<tr><td>18 </td><td> \ty{bvsgt} </td><td> </td><td> signed \ty{>}. </td></tr>
<tr><td>19 </td><td> \ty{bvand} </td><td> </td><td> n-ary (associative/commutative) bit-wise and. </td></tr>
<tr><td>20 </td><td> \ty{bvor} </td><td> </td><td> n-ary (associative/commutative) bit-wise or. </td></tr>
<tr><td>21 </td><td> \ty{bvnot} </td><td> </td><td> bit-wise not. </td></tr>
<tr><td>22 </td><td> \ty{bvxor} </td><td> </td><td> n-ary bit-wise xor. </td></tr>
<tr><td>23 </td><td> \ty{bvnand} </td><td> </td><td> bit-wise nand. </td></tr>
<tr><td>24 </td><td> \ty{bvnor} </td><td> </td><td> bit-wise nor. </td></tr>
<tr><td>25 </td><td> \ty{bvxnor} </td><td> </td><td> bit-wise exclusive nor. </td></tr>
<tr><td>26 </td><td> \ty{concat} </td><td> </td><td> bit-vector concatentaion. </td></tr>
<tr><td>27 </td><td> \ty{sign\_extend} </td><td> \emph{n}</td><td> \emph{n}-bit sign extension. </td></tr>
<tr><td>28</td><td> \ty{zero\_extend} </td><td> \emph{n}</td><td> \emph{n}-bit zero extension. </td></tr>
<tr><td>29 </td><td> \ty{extract} </td><td> \emph{hi:low} </td><td> \emph{hi}-\emph{low} bit-extraction. </td></tr>
<tr><td>30 </td><td> \ty{repeat} </td><td> \emph{n} </td><td> repeat $n$ times. </td></tr>
<tr><td>31 </td><td> \ty{bvredor} </td><td> </td><td> or-reduction. </td></tr>
<tr><td>32 </td><td> \ty{bvredand} </td><td> </td><td> and-reducdtion. </td></tr>
<tr><td>33 </td><td> \ty{bvcomp} </td><td> </td><td> bit-vector comparison. </td></tr>
<tr><td>34 </td><td> \ty{bvshl} </td><td> </td><td> shift-left. </td></tr>
<tr><td>35 </td><td> \ty{bvlshr} </td><td> </td><td> logical shift-right. </td></tr>
<tr><td>36 </td><td> \ty{bvrshr} </td><td> </td><td> arithmetical shift-right. </td></tr>
<tr><td>37 </td><td> \ty{bvrotate\_left} </td><td> \emph{n} </td><td> \emph{n}-bit left rotation. </td></tr>
<tr><td>38 </td><td> \ty{bvrotate\_right} </td><td>\emph{n} </td><td> \emph{n}-bit right rotation. </td></tr>
</table>
\section theoriesarrays Arrays
\subsection tharraybuiltinops Built-in operators
There is a single built-in sort constructor for arrays with code 0.
It is followed by a sequence of parameters indicating the domain
sorts and the range of the array.
<table border cellspacing=5 cellpadding=10>
<tr>
<th>Op-code</th>
<th>Mnmonics</th>
<th>Description</th>
</tr>
<tr><td>0</td><td> \ty{store} </td><td> array store </td></tr>
<tr><td>1</td><td> \ty{select} </td><td> array select </td></tr>
<!---
<tr><td></td><td> \ty{const} </td><td> array returning constant value </td></tr>
%\begin{internal}
<tr><td></td><td> \ty{store\_ite} </td><td> ternary non-pointwise store</td></tr>
<tr><td></td><td> \ty{set\_union} </td><td> set union A u B </td></tr>
<tr><td></td><td> \ty{set\_intersect} </td><td> set intersection A n B </td></tr>
<tr><td></td><td> \ty{set\_difference} </td><td> set difference A \ B </td></tr>
<tr><td></td><td> \ty{set\_complement} </td><td> set complement C(A) </td></tr>
<tr><td></td><td> \ty{is\_subset} </td><td> non-strict subset: A <= B </td></tr>
--->
</table>
In the low-level input format, array types
are accompanied by a sequence of identifiers corresponding
to the domain and range of the array the operations operate
upon.
In more detail, the contract is that the supplied parameters
to the type declaration of an array are of the form:
<ul>
<li> parameter_0 - 1'st dimension
<li> parameter_{n-1} - n'th dimension
<li> parameter_n - range
</ul>
The constant array function symbol \ty{const} needs a parameter
in order to infer the types of the indices of the constant array.
We pass the array type as the parameter to \ty{const}.
The other array operations do not need parameters.
We summarize the arities and semantics of the operators:
<ul>
<li> \ty{store} -
Updates an array at a given index with a value:
\ty{store}(A, i0, ... i_{n-1}, v) has the same contents as A, except on
index i0, ... , i_{n-1}, where the value is v.
<li> \ty{select} -
Selects the value from an array:
\ty{select}(A, i0, ... , i_{n-}) selects the value stored at
index i0, ... , i_{n-1}.
</ul>
<!---
\\
{\tt const} \\
\>
\begin{minipage}[t]{5in}
Creates a constant array: ${\tt const}(v)$ maps every index in the domain of the array to $v$.
\end{minipage}
\internalonly{
\\
{\tt store\_ite} \\
\>
\begin{minipage}[t]{5in}
Creates an array using a test and two other arrays:
\[
\begin{array}{lll}
{\tt select}(A,\overline{i}) = {\tt select}(B, \overline{i}) & \rightarrow &
{\tt select}({\tt store\_ite}(A,B,C), \overline{i}) = {\tt select}(C,\overline{i}) \ \
{\tt select}(A,\overline{i}) \neq {\tt select}(B, \overline{i}) & \rightarrow &
{\tt select}({\tt store\_ite}(A,B,C), \overline{i}) = {\tt select}(B,\overline{i})
\end{array}
\]
\end{minipage}
\\
{\tt set\_union}, {\tt set\_intersect} \\
\>
\begin{minipage}[t]{5in}
Creates the union, intersection of the list of arguments. Each argument must be declared as an array of the same type,
and the range type must be {\tt bool}.
\end{minipage}
\\
{\tt set\_difference} \\
\>
\begin{minipage}[t]{5in}
Creates the set difference of two arrays. The arguments must be declared as arrays of the same type with range type {\tt bool}
\end{minipage}
\\
{\tt set\_complement}\\
\>
\begin{minipage}[t]{5in}
Set complement of one Boolean valued array.
\end{minipage}
\\
{\tt is\_subset} \\
\>
\begin{minipage}[t]{5in}
Subset test of two Boolean valued arrays of the same type.
\end{minipage}
} % internalonly
\end{tabbing}
--->
*/
#ifndef _Z3_SOLVER_H_
#define _Z3_SOLVER_H_
#include "ast.h"
#include "symbol_table.h"
#include "stream_buffer.h"
#include "warning.h"
#include "front_end_params.h"
#include "arith_decl_plugin.h"
#include "bv_decl_plugin.h"
#include "z3.h"
class z3_solver {
enum kind {
T_NUM,
T_VAR,
T_DEC,
T_FUNCTION_CONST,
T_GET_IMPLIED_EQUALITIES,
T_NULLARY_CONST,
T_BUILTIN_CONST,
T_TY,
T_TYPE,
T_QUA,
T_LAB,
T_CTX,
T_PAT,
T_SOLVER,
T_SIMPLIFY,
T_ASSERT,
T_CHECK,
T_CHECK_ASSUMPTIONS,
T_DBG_SAT,
T_DBG_UNSAT,
T_PUSH,
T_POP,
T_RESET,
T_ECHO,
T_VERSION,
T_COMMENT,
T_EOF,
T_ERR
};
struct builtin_info {
family_id m_fid;
decl_kind m_kind;
builtin_info(family_id fid, decl_kind k) : m_fid(fid), m_kind(k) {}
builtin_info(): m_fid(null_family_id), m_kind(null_decl_kind) {}
};
Z3_context m_context;
bool m_owns_context;
ast_manager& m_manager;
front_end_params& m_params;
symbol_table<ast*> m_table;
stream_buffer m_in;
std::ostream& m_out;
bool m_is_active;
expr_ref_vector m_assumptions;
unsigned_vector m_assumptions_lim;
unsigned m_num_checks;
std::string m_string;
bool m_eof;
unsigned m_line;
symbol_table<builtin_info> m_builtin_ops;
symbol_table<builtin_info> m_builtin_types;
arith_util m_arith;
bv_util m_bv;
ast_ref_vector m_pinned;
unsigned_vector m_pinned_lim;
Z3_lbool m_last_check_result;
public:
z3_solver(
Z3_context c,
std::istream& is,
std::ostream& os,
front_end_params & params,
bool is_active = true
);
z3_solver(
ast_manager& m,
std::istream& is,
std::ostream& os,
front_end_params & params
);
~z3_solver();
bool parse();
void get_assumptions(expr_ref_vector& v) { v.append(m_assumptions); }
void display_statistics(std::ostream& out, bool istats);
void set_error_handler(Z3_error_handler h) {
Z3_set_error_handler(m_context, h);
}
private:
template<typename T>
struct coerce {
virtual ~coerce() {}
virtual T* operator()(ast* a) const = 0;
};
struct sort_coerce : public coerce<sort> {
virtual sort* operator()(ast* a) const {
if (!a || a->get_kind() != AST_SORT) {
return 0;
}
return to_sort(a);
}
};
struct func_decl_coerce : public coerce<func_decl> {
virtual func_decl* operator()(ast* a) const {
if (!a || a->get_kind() != AST_FUNC_DECL) {
return 0;
}
return to_func_decl(a);
}
};
struct pattern_coerce : public coerce<app> {
ast_manager& m_manager;
pattern_coerce(ast_manager& m): m_manager(m) {}
virtual app* operator()(ast* a) const {
if (!a || a->get_kind() != AST_APP) {
return 0;
}
if (!m_manager.is_pattern(to_app(a))) {
return 0;
}
return to_app(a);
}
};
struct expr_coerce : public coerce<expr> {
virtual expr* operator()(ast* a) const {
if (!a) {
return 0;
}
ast_kind k = a->get_kind();
switch(k) {
case AST_APP:
case AST_QUANTIFIER:
case AST_VAR:
return reinterpret_cast<expr*>(a);
default:
return 0;
}
}
};
struct app_coerce : public coerce<app> {
virtual app* operator()(ast* a) const {
if (!a) {
return 0;
}
if (a->get_kind() == AST_APP) {
return to_app(a);
}
return 0;
}
};
template<typename T>
bool parse_ast(symbol id, T*& n, const coerce<T>& coerce)
{
ast* a;
if (!m_table.find(id, a)) {
warning_msg("line %d. Could not find id '%s'\n",
m_line, id.str().c_str());
return false;
}
n = coerce(a);
if (n == 0) {
warning_msg("line %d. Wrong kind %d for %s\n",
m_line, a->get_kind(), id.str().c_str());
return false;
}
return true;
}
template<typename T>
bool parse_ast(T*& n, const coerce<T>& coerce)
{
symbol id;
if (parse_id(id)) {
return parse_ast(id, n, coerce);
}
return false;
}
template<typename T>
bool parse_asts(ref_vector<T, ast_manager>& asts, const coerce<T>& c)
{
symbol id;
T* n;
while (m_string[0] != '\n') {
if (strcmp(m_string.c_str(), "BUILTIN") == 0) {
return true;
}
if (!parse_ast(n,c)) {
return false;
}
asts.push_back(n);
}
return true;
}
kind parse_kind();
bool next_token();
bool parse_id(symbol& id);
bool parse_rational(rational& r);
void skip_blank();
bool parse_eol();
bool parse_numeral();
bool parse_var();
bool parse_info(scoped_ptr<func_decl_info>& info);
bool parse_info(scoped_ptr<sort_info>& info);
bool parse_func_decl();
bool parse_func_decl(symbol& id, func_decl*& d);
bool parse_nullary_const();
bool parse_const();
bool parse_builtin_const();
bool parse_type();
bool parse_type_new();
bool parse_label();
bool parse_quantifier();
bool parse_pattern();
bool parse_int(int& i);
bool check_int(int& i);
bool parse_unsigned(unsigned& i);
bool check_unsigned(unsigned& i);
bool try_parse(char const* token);
bool parse_assert();
bool parse_simplify();
bool parse_check();
bool parse_check_assumptions();
bool parse_get_implied_equalities();
bool parse_dbg(bool expected_sat);
bool parse_push();
bool parse_comment();
bool parse_pop();
bool parse_reset();
bool parse_echo();
bool parse_version();
bool parse_solver();
bool parse_parameter(vector<parameter>& params);
bool parse_params(vector<parameter>& params);
bool find_builtin_op(symbol name, family_id & fid, decl_kind& kind);
bool find_builtin_type(symbol name, family_id & fid, decl_kind& kind);
void add_builtins(family_id fid);
void add_id(symbol const& id, ast* a);
family_id get_family_id(char const* s);
void dump_smtlib_benchmark(unsigned num_assumptions, expr* const* assumptions, Z3_lbool result);
};
#endif