mirror of
https://github.com/Z3Prover/z3
synced 2025-06-14 09:56:15 +00:00
JS/TS API Array support (#6393)
* feat: basic array support Still need deeper type support for Arrays * fixed broken format rules * spaces inside curly * feat: range sort type inference * feat: better type inference in model eval * doc: fixed some incorrect documentation * feat: domain type inference * feat: addressed suggestions * feat: addressed suggestions * chore: moved ts-expect from deps to dev-deps * test: added z3guide examples * fix: removed ts-expect from dependencies again * docs: fixed some documentation
This commit is contained in:
parent
d4885abdc0
commit
f175fcbb54
5 changed files with 1767 additions and 7335 deletions
8312
src/api/js/package-lock.json
generated
8312
src/api/js/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -35,7 +35,8 @@
|
||||||
"contributors": [
|
"contributors": [
|
||||||
"Kevin Gibbons <bakkot@gmail.com>",
|
"Kevin Gibbons <bakkot@gmail.com>",
|
||||||
"Nikolaj Bjorner",
|
"Nikolaj Bjorner",
|
||||||
"Olaf Tomalka <olaf@tomalka.me>"
|
"Olaf Tomalka <olaf@tomalka.me>",
|
||||||
|
"Walden Yan <waldenyan20@gmail.com>"
|
||||||
],
|
],
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/jest": "^27.5.1",
|
"@types/jest": "^27.5.1",
|
||||||
|
@ -49,6 +50,7 @@
|
||||||
"prettier": "^2.5.1",
|
"prettier": "^2.5.1",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"sprintf-js": "^1.1.2",
|
"sprintf-js": "^1.1.2",
|
||||||
|
"ts-expect": "^1.3.0",
|
||||||
"ts-jest": "^28.0.3",
|
"ts-jest": "^28.0.3",
|
||||||
"ts-node": "^10.8.0",
|
"ts-node": "^10.8.0",
|
||||||
"typedoc": "^0.22.17",
|
"typedoc": "^0.22.17",
|
||||||
|
|
|
@ -2,6 +2,7 @@ import assert from 'assert';
|
||||||
import asyncToArray from 'iter-tools/methods/async-to-array';
|
import asyncToArray from 'iter-tools/methods/async-to-array';
|
||||||
import { init, killThreads } from '../jest';
|
import { init, killThreads } from '../jest';
|
||||||
import { Arith, Bool, Model, Z3AssertionError, Z3HighLevel } from './types';
|
import { Arith, Bool, Model, Z3AssertionError, Z3HighLevel } from './types';
|
||||||
|
import { expectType } from "ts-expect";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate all possible solutions from given assumptions.
|
* Generate all possible solutions from given assumptions.
|
||||||
|
@ -113,7 +114,7 @@ describe('high-level', () => {
|
||||||
const { Solver, Not, Int } = api.Context('main');
|
const { Solver, Not, Int } = api.Context('main');
|
||||||
const solver = new Solver();
|
const solver = new Solver();
|
||||||
solver.fromString("(declare-const x Int) (assert (and (< x 2) (> x 0)))")
|
solver.fromString("(declare-const x Int) (assert (and (< x 2) (> x 0)))")
|
||||||
expect(await solver.check()).toStrictEqual('sat')
|
expect(await solver.check()).toStrictEqual('sat')
|
||||||
const x = Int.const('x')
|
const x = Int.const('x')
|
||||||
solver.add(Not(x.eq(1)))
|
solver.add(Not(x.eq(1)))
|
||||||
expect(await solver.check()).toStrictEqual('unsat')
|
expect(await solver.check()).toStrictEqual('unsat')
|
||||||
|
@ -211,6 +212,7 @@ describe('high-level', () => {
|
||||||
}
|
}
|
||||||
return cells;
|
return cells;
|
||||||
}
|
}
|
||||||
|
|
||||||
const INSTANCE = toSudoku(`
|
const INSTANCE = toSudoku(`
|
||||||
....94.3.
|
....94.3.
|
||||||
...51...7
|
...51...7
|
||||||
|
@ -390,6 +392,106 @@ describe('high-level', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('arrays', () => {
|
||||||
|
|
||||||
|
it('Example 1', async () => {
|
||||||
|
const Z3 = api.Context('main');
|
||||||
|
|
||||||
|
const arr = Z3.Array.const('arr', Z3.Int.sort(), Z3.Int.sort());
|
||||||
|
const [idx, val] = Z3.Int.consts('idx val');
|
||||||
|
|
||||||
|
const conjecture = (arr.store(idx, val).select(idx).eq(val));
|
||||||
|
await prove(conjecture);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('domain and range type inference', async () => {
|
||||||
|
const { BitVec, Array, isArray, isArraySort } = api.Context('main');
|
||||||
|
|
||||||
|
const arr = Array.const('arr', BitVec.sort(160), BitVec.sort(256));
|
||||||
|
|
||||||
|
const domain = arr.domain();
|
||||||
|
expect(domain.size()).toStrictEqual(160);
|
||||||
|
expect(arr.domain_n(0).size()).toStrictEqual(160);
|
||||||
|
const range = arr.range();
|
||||||
|
expect(range.size()).toStrictEqual(256);
|
||||||
|
|
||||||
|
assert(isArray(arr) && isArraySort(arr.sort));
|
||||||
|
|
||||||
|
const arr2 = Array.const('arr2', BitVec.sort(1), BitVec.sort(2), BitVec.sort(3));
|
||||||
|
const dom2 = arr2.domain_n(1);
|
||||||
|
|
||||||
|
// We can call size() on dom2 and see that it is two bits
|
||||||
|
// purely from type inference
|
||||||
|
expectType<2>(dom2.size());
|
||||||
|
|
||||||
|
// Won't let us create an array constant with only one of domain/range
|
||||||
|
// and is detected at compile time
|
||||||
|
// @ts-expect-error
|
||||||
|
const arr3 = Array.const('arr3', BitVec.sort(1));
|
||||||
|
})
|
||||||
|
|
||||||
|
it('can do simple proofs', async () => {
|
||||||
|
const { BitVec, Array, isArray, isArraySort, isConstArray, Eq, Not } = api.Context('main');
|
||||||
|
|
||||||
|
const idx = BitVec.const('idx', 160);
|
||||||
|
const val = BitVec.const('val', 256);
|
||||||
|
|
||||||
|
const FIVE_VAL = BitVec.val(5, 256);
|
||||||
|
|
||||||
|
const arr = Array.const('arr', BitVec.sort(160), BitVec.sort(256));
|
||||||
|
|
||||||
|
const constArr = Array.K(BitVec.sort(160), FIVE_VAL);
|
||||||
|
assert(isArray(arr) && isArraySort(arr.sort) && isConstArray(constArr));
|
||||||
|
|
||||||
|
const arr2 = arr.store(0, 5);
|
||||||
|
await prove(Eq(arr2.select(0), FIVE_VAL));
|
||||||
|
await prove(Not(Eq(arr2.select(0), BitVec.val(6, 256))));
|
||||||
|
await prove(Eq(arr2.store(idx, val).select(idx), constArr.store(idx, val).select(idx)));
|
||||||
|
|
||||||
|
// TODO: add in Quantifiers and better typing of arrays
|
||||||
|
// await prove(
|
||||||
|
// ForAll([idx], idx.add(1).ugt(idx).and(arr.select(idx.add(1)).ugt(arr.select(idx)))).implies(
|
||||||
|
// arr.select(0).ult(arr.select(1000))
|
||||||
|
// )
|
||||||
|
// );
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Finds arrays that differ but that sum to the same', async () => {
|
||||||
|
const Z3 = api.Context('main');
|
||||||
|
const { Array, BitVec } = Z3;
|
||||||
|
|
||||||
|
const mod = 1n << 32n;
|
||||||
|
|
||||||
|
const arr1 = Array.const('arr', BitVec.sort(2), BitVec.sort(32));
|
||||||
|
const arr2 = Array.const('arr2', BitVec.sort(2), BitVec.sort(32));
|
||||||
|
|
||||||
|
const same_sum = arr1.select(0)
|
||||||
|
.add(arr1.select(1))
|
||||||
|
.add(arr1.select(2))
|
||||||
|
.add(arr1.select(3))
|
||||||
|
.eq(
|
||||||
|
arr2.select(0)
|
||||||
|
.add(arr2.select(1))
|
||||||
|
.add(arr2.select(2))
|
||||||
|
.add(arr2.select(3))
|
||||||
|
);
|
||||||
|
|
||||||
|
const different = arr1.select(0).neq(arr2.select(0))
|
||||||
|
.or(arr1.select(1).neq(arr2.select(1)))
|
||||||
|
.or(arr1.select(2).neq(arr2.select(2)))
|
||||||
|
.or(arr1.select(3).neq(arr2.select(3)));
|
||||||
|
|
||||||
|
const model = await solve(same_sum.and(different));
|
||||||
|
|
||||||
|
const arr1Vals = [0, 1, 2, 3].map(i => model.eval(arr1.select(i)).value());
|
||||||
|
const arr2Vals = [0, 1, 2, 3].map(i => model.eval(arr2.select(i)).value());
|
||||||
|
expect((arr1Vals.reduce((a, b) => a + b, 0n) % mod) === arr2Vals.reduce((a, b) => a + b, 0n) % mod);
|
||||||
|
for (let i = 0; i < 4; i++) {
|
||||||
|
expect(arr1Vals[i] !== arr2Vals[i]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('Solver', () => {
|
describe('Solver', () => {
|
||||||
it('can use push and pop', async () => {
|
it('can use push and pop', async () => {
|
||||||
const { Solver, Int } = api.Context('main');
|
const { Solver, Int } = api.Context('main');
|
||||||
|
|
|
@ -37,7 +37,7 @@ import {
|
||||||
AnyExpr,
|
AnyExpr,
|
||||||
AnySort,
|
AnySort,
|
||||||
Arith,
|
Arith,
|
||||||
ArithSort,
|
ArithSort, ArrayIndexType,
|
||||||
Ast,
|
Ast,
|
||||||
AstMap,
|
AstMap,
|
||||||
AstMapCtor,
|
AstMapCtor,
|
||||||
|
@ -48,7 +48,7 @@ import {
|
||||||
BitVecSort,
|
BitVecSort,
|
||||||
Bool,
|
Bool,
|
||||||
BoolSort,
|
BoolSort,
|
||||||
CheckSatResult,
|
CheckSatResult, CoercibleFromMap,
|
||||||
CoercibleRational,
|
CoercibleRational,
|
||||||
CoercibleToBitVec,
|
CoercibleToBitVec,
|
||||||
CoercibleToExpr,
|
CoercibleToExpr,
|
||||||
|
@ -63,6 +63,8 @@ import {
|
||||||
Model,
|
Model,
|
||||||
Probe,
|
Probe,
|
||||||
RatNum,
|
RatNum,
|
||||||
|
SMTArray,
|
||||||
|
SMTArraySort,
|
||||||
Solver,
|
Solver,
|
||||||
Sort,
|
Sort,
|
||||||
SortToExprMap,
|
SortToExprMap,
|
||||||
|
@ -86,12 +88,11 @@ function isCoercibleRational(obj: any): obj is CoercibleRational {
|
||||||
(obj.denominator !== null &&
|
(obj.denominator !== null &&
|
||||||
(typeof obj.denominator === 'number' || typeof obj.denominator === 'bigint'))
|
(typeof obj.denominator === 'number' || typeof obj.denominator === 'bigint'))
|
||||||
);
|
);
|
||||||
r &&
|
r && assert(
|
||||||
assert(
|
(typeof obj!.numerator !== 'number' || Number.isSafeInteger(obj!.numerator)) &&
|
||||||
(typeof obj.numerator !== 'number' || Number.isSafeInteger(obj.numerator)) &&
|
(typeof obj!.denominator !== 'number' || Number.isSafeInteger(obj!.denominator)),
|
||||||
(typeof obj.denominator !== 'number' || Number.isSafeInteger(obj.denominator)),
|
'Fraction numerator and denominator must be integers',
|
||||||
'Fraction numerator and denominator must be integers',
|
);
|
||||||
);
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,7 +152,9 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
|
||||||
function createContext<Name extends string>(name: Name, options?: Record<string, any>): Context<Name> {
|
function createContext<Name extends string>(name: Name, options?: Record<string, any>): Context<Name> {
|
||||||
const cfg = Z3.mk_config();
|
const cfg = Z3.mk_config();
|
||||||
if (options != null) {
|
if (options != null) {
|
||||||
Object.entries(options).forEach(([key, value]) => check(Z3.set_param_value(cfg, key, value.toString())));
|
Object.entries(options).forEach(
|
||||||
|
([key, value]) => check(Z3.set_param_value(cfg, key, value.toString()))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
const contextPtr = Z3.mk_context_rc(cfg);
|
const contextPtr = Z3.mk_context_rc(cfg);
|
||||||
Z3.set_ast_print_mode(contextPtr, Z3_ast_print_mode.Z3_PRINT_SMTLIB2_COMPLIANT);
|
Z3.set_ast_print_mode(contextPtr, Z3_ast_print_mode.Z3_PRINT_SMTLIB2_COMPLIANT);
|
||||||
|
@ -216,20 +219,22 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
|
||||||
return new ArithSortImpl(ast);
|
return new ArithSortImpl(ast);
|
||||||
case Z3_sort_kind.Z3_BV_SORT:
|
case Z3_sort_kind.Z3_BV_SORT:
|
||||||
return new BitVecSortImpl(ast);
|
return new BitVecSortImpl(ast);
|
||||||
|
case Z3_sort_kind.Z3_ARRAY_SORT:
|
||||||
|
return new ArraySortImpl(ast);
|
||||||
default:
|
default:
|
||||||
return new SortImpl(ast);
|
return new SortImpl(ast);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function _toExpr(ast: Z3_ast): Bool<Name> | IntNum<Name> | RatNum<Name> | Arith<Name> | Expr<Name> {
|
function _toExpr(ast: Z3_ast): AnyExpr<Name> {
|
||||||
const kind = check(Z3.get_ast_kind(contextPtr, ast));
|
const kind = check(Z3.get_ast_kind(contextPtr, ast));
|
||||||
if (kind === Z3_ast_kind.Z3_QUANTIFIER_AST) {
|
if (kind === Z3_ast_kind.Z3_QUANTIFIER_AST) {
|
||||||
if (Z3.is_quantifier_forall(contextPtr, ast))
|
if (Z3.is_quantifier_forall(contextPtr, ast))
|
||||||
return new BoolImpl(ast);
|
return new BoolImpl(ast);
|
||||||
if (Z3.is_quantifier_exists(contextPtr, ast))
|
if (Z3.is_quantifier_exists(contextPtr, ast))
|
||||||
return new BoolImpl(ast);
|
return new BoolImpl(ast);
|
||||||
if (Z3.is_lambda(contextPtr, ast))
|
if (Z3.is_lambda(contextPtr, ast))
|
||||||
return new ExprImpl(ast);
|
return new ExprImpl(ast);
|
||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
const sortKind = check(Z3.get_sort_kind(contextPtr, Z3.get_sort(contextPtr, ast)));
|
const sortKind = check(Z3.get_sort_kind(contextPtr, Z3.get_sort(contextPtr, ast)));
|
||||||
|
@ -251,6 +256,8 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
|
||||||
return new BitVecNumImpl(ast);
|
return new BitVecNumImpl(ast);
|
||||||
}
|
}
|
||||||
return new BitVecImpl(ast);
|
return new BitVecImpl(ast);
|
||||||
|
case Z3_sort_kind.Z3_ARRAY_SORT:
|
||||||
|
return new ArrayImpl(ast);
|
||||||
default:
|
default:
|
||||||
return new ExprImpl(ast);
|
return new ExprImpl(ast);
|
||||||
}
|
}
|
||||||
|
@ -440,6 +447,22 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isArraySort(obj: unknown): obj is SMTArraySort<Name> {
|
||||||
|
const r = obj instanceof ArraySortImpl;
|
||||||
|
r && _assertContext(obj);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isArray(obj: unknown): obj is SMTArray<Name> {
|
||||||
|
const r = obj instanceof ArrayImpl;
|
||||||
|
r && _assertContext(obj);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isConstArray(obj: unknown): boolean {
|
||||||
|
return isAppOf(obj, Z3_decl_kind.Z3_OP_CONST_ARRAY);
|
||||||
|
}
|
||||||
|
|
||||||
function isProbe(obj: unknown): obj is Probe<Name> {
|
function isProbe(obj: unknown): obj is Probe<Name> {
|
||||||
const r = obj instanceof ProbeImpl;
|
const r = obj instanceof ProbeImpl;
|
||||||
r && _assertContext(obj);
|
r && _assertContext(obj);
|
||||||
|
@ -508,9 +531,9 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
|
||||||
// expression simplification //
|
// expression simplification //
|
||||||
///////////////////////////////
|
///////////////////////////////
|
||||||
|
|
||||||
async function simplify(e : Expr<Name>) {
|
async function simplify(e: Expr<Name>) {
|
||||||
const result = await Z3.simplify(contextPtr, e.ast)
|
const result = await Z3.simplify(contextPtr, e.ast)
|
||||||
return _toExpr(check(result));
|
return _toExpr(check(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////
|
/////////////
|
||||||
|
@ -677,6 +700,44 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
const Array = {
|
||||||
|
sort<DomainSort extends [AnySort<Name>, ...AnySort<Name>[]], RangeSort extends AnySort<Name>>(
|
||||||
|
...sig: [...DomainSort, RangeSort]
|
||||||
|
): SMTArraySort<Name, DomainSort, RangeSort> {
|
||||||
|
const arity = sig.length - 1;
|
||||||
|
const r = sig[arity];
|
||||||
|
const d = sig[0];
|
||||||
|
if (arity === 1) {
|
||||||
|
return new ArraySortImpl(Z3.mk_array_sort(contextPtr, d.ptr, r.ptr));
|
||||||
|
}
|
||||||
|
const dom = sig.slice(0, arity);
|
||||||
|
return new ArraySortImpl(Z3.mk_array_sort_n(contextPtr, dom.map(s => s.ptr), r.ptr));
|
||||||
|
},
|
||||||
|
const<DomainSort extends [AnySort<Name>, ...AnySort<Name>[]], RangeSort extends AnySort<Name>>(
|
||||||
|
name: string, ...sig: [...DomainSort, RangeSort]
|
||||||
|
): SMTArray<Name, DomainSort, RangeSort> {
|
||||||
|
return new ArrayImpl<DomainSort, RangeSort>(
|
||||||
|
check(Z3.mk_const(contextPtr, _toSymbol(name), Array.sort(...sig).ptr))
|
||||||
|
);
|
||||||
|
},
|
||||||
|
consts<DomainSort extends [AnySort<Name>, ...AnySort<Name>[]], RangeSort extends AnySort<Name>>(
|
||||||
|
names: string | string[],
|
||||||
|
...sig: [...DomainSort, RangeSort]
|
||||||
|
): SMTArray<Name, DomainSort, RangeSort>[] {
|
||||||
|
if (typeof names === 'string') {
|
||||||
|
names = names.split(' ');
|
||||||
|
}
|
||||||
|
return names.map(name => Array.const(name, ...sig));
|
||||||
|
},
|
||||||
|
K<DomainSort extends AnySort<Name>, RangeSort extends AnySort<Name>>(
|
||||||
|
domain: DomainSort,
|
||||||
|
value: SortToExprMap<RangeSort, Name>
|
||||||
|
): SMTArray<Name, [DomainSort], RangeSort> {
|
||||||
|
return new ArrayImpl<[DomainSort], RangeSort>(
|
||||||
|
check(Z3.mk_const_array(contextPtr, domain.ptr, value.ptr))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////
|
////////////////
|
||||||
// Operations //
|
// Operations //
|
||||||
|
@ -948,6 +1009,7 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
|
||||||
|
|
||||||
readonly ptr: Z3_solver;
|
readonly ptr: Z3_solver;
|
||||||
readonly ctx: Context<Name>;
|
readonly ctx: Context<Name>;
|
||||||
|
|
||||||
constructor(ptr: Z3_solver | string = Z3.mk_solver(contextPtr)) {
|
constructor(ptr: Z3_solver | string = Z3.mk_solver(contextPtr)) {
|
||||||
this.ctx = ctx;
|
this.ctx = ctx;
|
||||||
let myPtr: Z3_solver;
|
let myPtr: Z3_solver;
|
||||||
|
@ -964,21 +1026,26 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
|
||||||
push() {
|
push() {
|
||||||
Z3.solver_push(contextPtr, this.ptr);
|
Z3.solver_push(contextPtr, this.ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
pop(num: number = 1) {
|
pop(num: number = 1) {
|
||||||
Z3.solver_pop(contextPtr, this.ptr, num);
|
Z3.solver_pop(contextPtr, this.ptr, num);
|
||||||
}
|
}
|
||||||
|
|
||||||
numScopes() {
|
numScopes() {
|
||||||
return Z3.solver_get_num_scopes(contextPtr, this.ptr);
|
return Z3.solver_get_num_scopes(contextPtr, this.ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
reset() {
|
reset() {
|
||||||
Z3.solver_reset(contextPtr, this.ptr);
|
Z3.solver_reset(contextPtr, this.ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
add(...exprs: (Bool<Name> | AstVector<Name, Bool<Name>>)[]) {
|
add(...exprs: (Bool<Name> | AstVector<Name, Bool<Name>>)[]) {
|
||||||
_flattenArgs(exprs).forEach(expr => {
|
_flattenArgs(exprs).forEach(expr => {
|
||||||
_assertContext(expr);
|
_assertContext(expr);
|
||||||
check(Z3.solver_assert(contextPtr, this.ptr, expr.ast));
|
check(Z3.solver_assert(contextPtr, this.ptr, expr.ast));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
addAndTrack(expr: Bool<Name>, constant: Bool<Name> | string) {
|
addAndTrack(expr: Bool<Name>, constant: Bool<Name> | string) {
|
||||||
if (typeof constant === 'string') {
|
if (typeof constant === 'string') {
|
||||||
constant = Bool.const(constant);
|
constant = Bool.const(constant);
|
||||||
|
@ -1019,7 +1086,7 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
|
||||||
return check(Z3.solver_to_string(contextPtr, this.ptr));
|
return check(Z3.solver_to_string(contextPtr, this.ptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
fromString(s : string) {
|
fromString(s: string) {
|
||||||
Z3.solver_from_string(contextPtr, this.ptr, s);
|
Z3.solver_from_string(contextPtr, this.ptr, s);
|
||||||
throwIfError();
|
throwIfError();
|
||||||
}
|
}
|
||||||
|
@ -1043,20 +1110,20 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
|
||||||
return this.values();
|
return this.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
*entries(): IterableIterator<[number, FuncDecl<Name>]> {
|
* entries(): IterableIterator<[number, FuncDecl<Name>]> {
|
||||||
const length = this.length();
|
const length = this.length();
|
||||||
for (let i = 0; i < length; i++) {
|
for (let i = 0; i < length; i++) {
|
||||||
yield [i, this.get(i)];
|
yield [i, this.get(i)];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*keys(): IterableIterator<number> {
|
* keys(): IterableIterator<number> {
|
||||||
for (const [key] of this.entries()) {
|
for (const [key] of this.entries()) {
|
||||||
yield key;
|
yield key;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*values(): IterableIterator<FuncDecl<Name>> {
|
* values(): IterableIterator<FuncDecl<Name>> {
|
||||||
for (const [, value] of this.entries()) {
|
for (const [, value] of this.entries()) {
|
||||||
yield value;
|
yield value;
|
||||||
}
|
}
|
||||||
|
@ -1076,11 +1143,12 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
|
||||||
|
|
||||||
eval(expr: Bool<Name>, modelCompletion?: boolean): Bool<Name>;
|
eval(expr: Bool<Name>, modelCompletion?: boolean): Bool<Name>;
|
||||||
eval(expr: Arith<Name>, modelCompletion?: boolean): Arith<Name>;
|
eval(expr: Arith<Name>, modelCompletion?: boolean): Arith<Name>;
|
||||||
|
eval<Bits extends number = number>(expr: BitVec<Bits, Name>, modelCompletion?: boolean): BitVecNum<Bits, Name>;
|
||||||
eval(expr: Expr<Name>, modelCompletion: boolean = false) {
|
eval(expr: Expr<Name>, modelCompletion: boolean = false) {
|
||||||
_assertContext(expr);
|
_assertContext(expr);
|
||||||
const r = check(Z3.model_eval(contextPtr, this.ptr, expr.ast, modelCompletion));
|
const r = check(Z3.model_eval(contextPtr, this.ptr, expr.ast, modelCompletion));
|
||||||
if (r === null) {
|
if (r === null) {
|
||||||
throw new Z3Error('Failed to evaluatio expression in the model');
|
throw new Z3Error('Failed to evaluate expression in the model');
|
||||||
}
|
}
|
||||||
return _toExpr(r);
|
return _toExpr(r);
|
||||||
}
|
}
|
||||||
|
@ -1092,7 +1160,7 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
|
||||||
get(sort: Sort<Name>): AstVector<Name, AnyExpr<Name>>;
|
get(sort: Sort<Name>): AstVector<Name, AnyExpr<Name>>;
|
||||||
get(
|
get(
|
||||||
i: number | FuncDecl<Name> | Expr<Name> | Sort<Name>,
|
i: number | FuncDecl<Name> | Expr<Name> | Sort<Name>,
|
||||||
to?: number,
|
to?: number
|
||||||
): FuncDecl<Name> | FuncInterp<Name> | Expr<Name> | AstVector<Name, AnyAst<Name>> | FuncDecl<Name>[] {
|
): FuncDecl<Name> | FuncInterp<Name> | Expr<Name> | AstVector<Name, AnyAst<Name>> | FuncDecl<Name>[] {
|
||||||
assert(to === undefined || typeof i === 'number');
|
assert(to === undefined || typeof i === 'number');
|
||||||
if (typeof i === 'number') {
|
if (typeof i === 'number') {
|
||||||
|
@ -1362,15 +1430,22 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
|
||||||
not(): Bool<Name> {
|
not(): Bool<Name> {
|
||||||
return Not(this);
|
return Not(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
and(other: Bool<Name> | boolean): Bool<Name> {
|
and(other: Bool<Name> | boolean): Bool<Name> {
|
||||||
return And(this, other);
|
return And(this, other);
|
||||||
}
|
}
|
||||||
|
|
||||||
or(other: Bool<Name> | boolean): Bool<Name> {
|
or(other: Bool<Name> | boolean): Bool<Name> {
|
||||||
return Or(this, other);
|
return Or(this, other);
|
||||||
}
|
}
|
||||||
|
|
||||||
xor(other: Bool<Name> | boolean): Bool<Name> {
|
xor(other: Bool<Name> | boolean): Bool<Name> {
|
||||||
return Xor(this, other);
|
return Xor(this, other);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
implies(other: Bool<Name> | boolean): Bool<Name> {
|
||||||
|
return Implies(this, other);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ProbeImpl implements Probe<Name> {
|
class ProbeImpl implements Probe<Name> {
|
||||||
|
@ -1571,27 +1646,35 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
|
||||||
add(other: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
|
add(other: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
|
||||||
return new BitVecImpl<Bits>(check(Z3.mk_bvadd(contextPtr, this.ast, this.sort.cast(other).ast)));
|
return new BitVecImpl<Bits>(check(Z3.mk_bvadd(contextPtr, this.ast, this.sort.cast(other).ast)));
|
||||||
}
|
}
|
||||||
|
|
||||||
mul(other: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
|
mul(other: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
|
||||||
return new BitVecImpl<Bits>(check(Z3.mk_bvmul(contextPtr, this.ast, this.sort.cast(other).ast)));
|
return new BitVecImpl<Bits>(check(Z3.mk_bvmul(contextPtr, this.ast, this.sort.cast(other).ast)));
|
||||||
}
|
}
|
||||||
|
|
||||||
sub(other: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
|
sub(other: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
|
||||||
return new BitVecImpl<Bits>(check(Z3.mk_bvsub(contextPtr, this.ast, this.sort.cast(other).ast)));
|
return new BitVecImpl<Bits>(check(Z3.mk_bvsub(contextPtr, this.ast, this.sort.cast(other).ast)));
|
||||||
}
|
}
|
||||||
|
|
||||||
sdiv(other: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
|
sdiv(other: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
|
||||||
return new BitVecImpl<Bits>(check(Z3.mk_bvsdiv(contextPtr, this.ast, this.sort.cast(other).ast)));
|
return new BitVecImpl<Bits>(check(Z3.mk_bvsdiv(contextPtr, this.ast, this.sort.cast(other).ast)));
|
||||||
}
|
}
|
||||||
|
|
||||||
udiv(other: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
|
udiv(other: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
|
||||||
return new BitVecImpl<Bits>(check(Z3.mk_bvudiv(contextPtr, this.ast, this.sort.cast(other).ast)));
|
return new BitVecImpl<Bits>(check(Z3.mk_bvudiv(contextPtr, this.ast, this.sort.cast(other).ast)));
|
||||||
}
|
}
|
||||||
|
|
||||||
smod(other: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
|
smod(other: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
|
||||||
return new BitVecImpl<Bits>(check(Z3.mk_bvsmod(contextPtr, this.ast, this.sort.cast(other).ast)));
|
return new BitVecImpl<Bits>(check(Z3.mk_bvsmod(contextPtr, this.ast, this.sort.cast(other).ast)));
|
||||||
}
|
}
|
||||||
|
|
||||||
urem(other: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
|
urem(other: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
|
||||||
return new BitVecImpl<Bits>(check(Z3.mk_bvurem(contextPtr, this.ast, this.sort.cast(other).ast)));
|
return new BitVecImpl<Bits>(check(Z3.mk_bvurem(contextPtr, this.ast, this.sort.cast(other).ast)));
|
||||||
}
|
}
|
||||||
|
|
||||||
srem(other: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
|
srem(other: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
|
||||||
return new BitVecImpl<Bits>(check(Z3.mk_bvsrem(contextPtr, this.ast, this.sort.cast(other).ast)));
|
return new BitVecImpl<Bits>(check(Z3.mk_bvsrem(contextPtr, this.ast, this.sort.cast(other).ast)));
|
||||||
}
|
}
|
||||||
|
|
||||||
neg(): BitVec<Bits, Name> {
|
neg(): BitVec<Bits, Name> {
|
||||||
return new BitVecImpl<Bits>(check(Z3.mk_bvneg(contextPtr, this.ast)));
|
return new BitVecImpl<Bits>(check(Z3.mk_bvneg(contextPtr, this.ast)));
|
||||||
}
|
}
|
||||||
|
@ -1599,33 +1682,43 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
|
||||||
or(other: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
|
or(other: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
|
||||||
return new BitVecImpl<Bits>(check(Z3.mk_bvor(contextPtr, this.ast, this.sort.cast(other).ast)));
|
return new BitVecImpl<Bits>(check(Z3.mk_bvor(contextPtr, this.ast, this.sort.cast(other).ast)));
|
||||||
}
|
}
|
||||||
|
|
||||||
and(other: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
|
and(other: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
|
||||||
return new BitVecImpl<Bits>(check(Z3.mk_bvand(contextPtr, this.ast, this.sort.cast(other).ast)));
|
return new BitVecImpl<Bits>(check(Z3.mk_bvand(contextPtr, this.ast, this.sort.cast(other).ast)));
|
||||||
}
|
}
|
||||||
|
|
||||||
nand(other: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
|
nand(other: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
|
||||||
return new BitVecImpl<Bits>(check(Z3.mk_bvnand(contextPtr, this.ast, this.sort.cast(other).ast)));
|
return new BitVecImpl<Bits>(check(Z3.mk_bvnand(contextPtr, this.ast, this.sort.cast(other).ast)));
|
||||||
}
|
}
|
||||||
|
|
||||||
xor(other: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
|
xor(other: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
|
||||||
return new BitVecImpl<Bits>(check(Z3.mk_bvxor(contextPtr, this.ast, this.sort.cast(other).ast)));
|
return new BitVecImpl<Bits>(check(Z3.mk_bvxor(contextPtr, this.ast, this.sort.cast(other).ast)));
|
||||||
}
|
}
|
||||||
|
|
||||||
xnor(other: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
|
xnor(other: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
|
||||||
return new BitVecImpl<Bits>(check(Z3.mk_bvxnor(contextPtr, this.ast, this.sort.cast(other).ast)));
|
return new BitVecImpl<Bits>(check(Z3.mk_bvxnor(contextPtr, this.ast, this.sort.cast(other).ast)));
|
||||||
}
|
}
|
||||||
|
|
||||||
shr(count: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
|
shr(count: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
|
||||||
return new BitVecImpl<Bits>(check(Z3.mk_bvashr(contextPtr, this.ast, this.sort.cast(count).ast)));
|
return new BitVecImpl<Bits>(check(Z3.mk_bvashr(contextPtr, this.ast, this.sort.cast(count).ast)));
|
||||||
}
|
}
|
||||||
|
|
||||||
lshr(count: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
|
lshr(count: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
|
||||||
return new BitVecImpl<Bits>(check(Z3.mk_bvlshr(contextPtr, this.ast, this.sort.cast(count).ast)));
|
return new BitVecImpl<Bits>(check(Z3.mk_bvlshr(contextPtr, this.ast, this.sort.cast(count).ast)));
|
||||||
}
|
}
|
||||||
|
|
||||||
shl(count: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
|
shl(count: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
|
||||||
return new BitVecImpl<Bits>(check(Z3.mk_bvshl(contextPtr, this.ast, this.sort.cast(count).ast)));
|
return new BitVecImpl<Bits>(check(Z3.mk_bvshl(contextPtr, this.ast, this.sort.cast(count).ast)));
|
||||||
}
|
}
|
||||||
|
|
||||||
rotateRight(count: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
|
rotateRight(count: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
|
||||||
return new BitVecImpl<Bits>(check(Z3.mk_ext_rotate_right(contextPtr, this.ast, this.sort.cast(count).ast)));
|
return new BitVecImpl<Bits>(check(Z3.mk_ext_rotate_right(contextPtr, this.ast, this.sort.cast(count).ast)));
|
||||||
}
|
}
|
||||||
|
|
||||||
rotateLeft(count: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
|
rotateLeft(count: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
|
||||||
return new BitVecImpl<Bits>(check(Z3.mk_ext_rotate_left(contextPtr, this.ast, this.sort.cast(count).ast)));
|
return new BitVecImpl<Bits>(check(Z3.mk_ext_rotate_left(contextPtr, this.ast, this.sort.cast(count).ast)));
|
||||||
}
|
}
|
||||||
|
|
||||||
not(): BitVec<Bits, Name> {
|
not(): BitVec<Bits, Name> {
|
||||||
return new BitVecImpl<Bits>(check(Z3.mk_bvnot(contextPtr, this.ast)));
|
return new BitVecImpl<Bits>(check(Z3.mk_bvnot(contextPtr, this.ast)));
|
||||||
}
|
}
|
||||||
|
@ -1633,12 +1726,15 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
|
||||||
extract(high: number, low: number): BitVec<Bits, Name> {
|
extract(high: number, low: number): BitVec<Bits, Name> {
|
||||||
return new BitVecImpl<Bits>(check(Z3.mk_extract(contextPtr, high, low, this.ast)));
|
return new BitVecImpl<Bits>(check(Z3.mk_extract(contextPtr, high, low, this.ast)));
|
||||||
}
|
}
|
||||||
|
|
||||||
signExt(count: number): BitVec<Bits, Name> {
|
signExt(count: number): BitVec<Bits, Name> {
|
||||||
return new BitVecImpl<Bits>(check(Z3.mk_sign_ext(contextPtr, count, this.ast)));
|
return new BitVecImpl<Bits>(check(Z3.mk_sign_ext(contextPtr, count, this.ast)));
|
||||||
}
|
}
|
||||||
|
|
||||||
zeroExt(count: number): BitVec<Bits, Name> {
|
zeroExt(count: number): BitVec<Bits, Name> {
|
||||||
return new BitVecImpl<Bits>(check(Z3.mk_zero_ext(contextPtr, count, this.ast)));
|
return new BitVecImpl<Bits>(check(Z3.mk_zero_ext(contextPtr, count, this.ast)));
|
||||||
}
|
}
|
||||||
|
|
||||||
repeat(count: number): BitVec<Bits, Name> {
|
repeat(count: number): BitVec<Bits, Name> {
|
||||||
return new BitVecImpl<Bits>(check(Z3.mk_repeat(contextPtr, count, this.ast)));
|
return new BitVecImpl<Bits>(check(Z3.mk_repeat(contextPtr, count, this.ast)));
|
||||||
}
|
}
|
||||||
|
@ -1646,24 +1742,31 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
|
||||||
sle(other: CoercibleToBitVec<Bits, Name>): Bool<Name> {
|
sle(other: CoercibleToBitVec<Bits, Name>): Bool<Name> {
|
||||||
return new BoolImpl(check(Z3.mk_bvsle(contextPtr, this.ast, this.sort.cast(other).ast)));
|
return new BoolImpl(check(Z3.mk_bvsle(contextPtr, this.ast, this.sort.cast(other).ast)));
|
||||||
}
|
}
|
||||||
|
|
||||||
ule(other: CoercibleToBitVec<Bits, Name>): Bool<Name> {
|
ule(other: CoercibleToBitVec<Bits, Name>): Bool<Name> {
|
||||||
return new BoolImpl(check(Z3.mk_bvule(contextPtr, this.ast, this.sort.cast(other).ast)));
|
return new BoolImpl(check(Z3.mk_bvule(contextPtr, this.ast, this.sort.cast(other).ast)));
|
||||||
}
|
}
|
||||||
|
|
||||||
slt(other: CoercibleToBitVec<Bits, Name>): Bool<Name> {
|
slt(other: CoercibleToBitVec<Bits, Name>): Bool<Name> {
|
||||||
return new BoolImpl(check(Z3.mk_bvslt(contextPtr, this.ast, this.sort.cast(other).ast)));
|
return new BoolImpl(check(Z3.mk_bvslt(contextPtr, this.ast, this.sort.cast(other).ast)));
|
||||||
}
|
}
|
||||||
|
|
||||||
ult(other: CoercibleToBitVec<Bits, Name>): Bool<Name> {
|
ult(other: CoercibleToBitVec<Bits, Name>): Bool<Name> {
|
||||||
return new BoolImpl(check(Z3.mk_bvult(contextPtr, this.ast, this.sort.cast(other).ast)));
|
return new BoolImpl(check(Z3.mk_bvult(contextPtr, this.ast, this.sort.cast(other).ast)));
|
||||||
}
|
}
|
||||||
|
|
||||||
sge(other: CoercibleToBitVec<Bits, Name>): Bool<Name> {
|
sge(other: CoercibleToBitVec<Bits, Name>): Bool<Name> {
|
||||||
return new BoolImpl(check(Z3.mk_bvsge(contextPtr, this.ast, this.sort.cast(other).ast)));
|
return new BoolImpl(check(Z3.mk_bvsge(contextPtr, this.ast, this.sort.cast(other).ast)));
|
||||||
}
|
}
|
||||||
|
|
||||||
uge(other: CoercibleToBitVec<Bits, Name>): Bool<Name> {
|
uge(other: CoercibleToBitVec<Bits, Name>): Bool<Name> {
|
||||||
return new BoolImpl(check(Z3.mk_bvuge(contextPtr, this.ast, this.sort.cast(other).ast)));
|
return new BoolImpl(check(Z3.mk_bvuge(contextPtr, this.ast, this.sort.cast(other).ast)));
|
||||||
}
|
}
|
||||||
|
|
||||||
sgt(other: CoercibleToBitVec<Bits, Name>): Bool<Name> {
|
sgt(other: CoercibleToBitVec<Bits, Name>): Bool<Name> {
|
||||||
return new BoolImpl(check(Z3.mk_bvsgt(contextPtr, this.ast, this.sort.cast(other).ast)));
|
return new BoolImpl(check(Z3.mk_bvsgt(contextPtr, this.ast, this.sort.cast(other).ast)));
|
||||||
}
|
}
|
||||||
|
|
||||||
ugt(other: CoercibleToBitVec<Bits, Name>): Bool<Name> {
|
ugt(other: CoercibleToBitVec<Bits, Name>): Bool<Name> {
|
||||||
return new BoolImpl(check(Z3.mk_bvugt(contextPtr, this.ast, this.sort.cast(other).ast)));
|
return new BoolImpl(check(Z3.mk_bvugt(contextPtr, this.ast, this.sort.cast(other).ast)));
|
||||||
}
|
}
|
||||||
|
@ -1671,6 +1774,7 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
|
||||||
redAnd(): BitVec<Bits, Name> {
|
redAnd(): BitVec<Bits, Name> {
|
||||||
return new BitVecImpl<Bits>(check(Z3.mk_bvredand(contextPtr, this.ast)));
|
return new BitVecImpl<Bits>(check(Z3.mk_bvredand(contextPtr, this.ast)));
|
||||||
}
|
}
|
||||||
|
|
||||||
redOr(): BitVec<Bits, Name> {
|
redOr(): BitVec<Bits, Name> {
|
||||||
return new BitVecImpl<Bits>(check(Z3.mk_bvredor(contextPtr, this.ast)));
|
return new BitVecImpl<Bits>(check(Z3.mk_bvredor(contextPtr, this.ast)));
|
||||||
}
|
}
|
||||||
|
@ -1678,24 +1782,31 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
|
||||||
addNoOverflow(other: CoercibleToBitVec<Bits, Name>, isSigned: boolean): Bool<Name> {
|
addNoOverflow(other: CoercibleToBitVec<Bits, Name>, isSigned: boolean): Bool<Name> {
|
||||||
return new BoolImpl(check(Z3.mk_bvadd_no_overflow(contextPtr, this.ast, this.sort.cast(other).ast, isSigned)));
|
return new BoolImpl(check(Z3.mk_bvadd_no_overflow(contextPtr, this.ast, this.sort.cast(other).ast, isSigned)));
|
||||||
}
|
}
|
||||||
|
|
||||||
addNoUnderflow(other: CoercibleToBitVec<Bits, Name>): Bool<Name> {
|
addNoUnderflow(other: CoercibleToBitVec<Bits, Name>): Bool<Name> {
|
||||||
return new BoolImpl(check(Z3.mk_bvadd_no_underflow(contextPtr, this.ast, this.sort.cast(other).ast)));
|
return new BoolImpl(check(Z3.mk_bvadd_no_underflow(contextPtr, this.ast, this.sort.cast(other).ast)));
|
||||||
}
|
}
|
||||||
|
|
||||||
subNoOverflow(other: CoercibleToBitVec<Bits, Name>): Bool<Name> {
|
subNoOverflow(other: CoercibleToBitVec<Bits, Name>): Bool<Name> {
|
||||||
return new BoolImpl(check(Z3.mk_bvsub_no_overflow(contextPtr, this.ast, this.sort.cast(other).ast)));
|
return new BoolImpl(check(Z3.mk_bvsub_no_overflow(contextPtr, this.ast, this.sort.cast(other).ast)));
|
||||||
}
|
}
|
||||||
|
|
||||||
subNoUndeflow(other: CoercibleToBitVec<Bits, Name>, isSigned: boolean): Bool<Name> {
|
subNoUndeflow(other: CoercibleToBitVec<Bits, Name>, isSigned: boolean): Bool<Name> {
|
||||||
return new BoolImpl(check(Z3.mk_bvsub_no_underflow(contextPtr, this.ast, this.sort.cast(other).ast, isSigned)));
|
return new BoolImpl(check(Z3.mk_bvsub_no_underflow(contextPtr, this.ast, this.sort.cast(other).ast, isSigned)));
|
||||||
}
|
}
|
||||||
|
|
||||||
sdivNoOverflow(other: CoercibleToBitVec<Bits, Name>): Bool<Name> {
|
sdivNoOverflow(other: CoercibleToBitVec<Bits, Name>): Bool<Name> {
|
||||||
return new BoolImpl(check(Z3.mk_bvsdiv_no_overflow(contextPtr, this.ast, this.sort.cast(other).ast)));
|
return new BoolImpl(check(Z3.mk_bvsdiv_no_overflow(contextPtr, this.ast, this.sort.cast(other).ast)));
|
||||||
}
|
}
|
||||||
|
|
||||||
mulNoOverflow(other: CoercibleToBitVec<Bits, Name>, isSigned: boolean): Bool<Name> {
|
mulNoOverflow(other: CoercibleToBitVec<Bits, Name>, isSigned: boolean): Bool<Name> {
|
||||||
return new BoolImpl(check(Z3.mk_bvmul_no_overflow(contextPtr, this.ast, this.sort.cast(other).ast, isSigned)));
|
return new BoolImpl(check(Z3.mk_bvmul_no_overflow(contextPtr, this.ast, this.sort.cast(other).ast, isSigned)));
|
||||||
}
|
}
|
||||||
|
|
||||||
mulNoUndeflow(other: CoercibleToBitVec<Bits, Name>): Bool<Name> {
|
mulNoUndeflow(other: CoercibleToBitVec<Bits, Name>): Bool<Name> {
|
||||||
return new BoolImpl(check(Z3.mk_bvmul_no_underflow(contextPtr, this.ast, this.sort.cast(other).ast)));
|
return new BoolImpl(check(Z3.mk_bvmul_no_underflow(contextPtr, this.ast, this.sort.cast(other).ast)));
|
||||||
}
|
}
|
||||||
|
|
||||||
negNoOverflow(): Bool<Name> {
|
negNoOverflow(): Bool<Name> {
|
||||||
return new BoolImpl(check(Z3.mk_bvneg_no_overflow(contextPtr, this.ast)));
|
return new BoolImpl(check(Z3.mk_bvneg_no_overflow(contextPtr, this.ast)));
|
||||||
}
|
}
|
||||||
|
@ -1703,6 +1814,7 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
|
||||||
|
|
||||||
class BitVecNumImpl<Bits extends number> extends BitVecImpl<Bits> implements BitVecNum<Bits, Name> {
|
class BitVecNumImpl<Bits extends number> extends BitVecImpl<Bits> implements BitVecNum<Bits, Name> {
|
||||||
declare readonly __typename: BitVecNum['__typename'];
|
declare readonly __typename: BitVecNum['__typename'];
|
||||||
|
|
||||||
value() {
|
value() {
|
||||||
return BigInt(this.asString());
|
return BigInt(this.asString());
|
||||||
}
|
}
|
||||||
|
@ -1718,14 +1830,87 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
|
||||||
}
|
}
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
asString() {
|
asString() {
|
||||||
return Z3.get_numeral_string(contextPtr, this.ast);
|
return Z3.get_numeral_string(contextPtr, this.ast);
|
||||||
}
|
}
|
||||||
|
|
||||||
asBinaryString() {
|
asBinaryString() {
|
||||||
return Z3.get_numeral_binary_string(contextPtr, this.ast);
|
return Z3.get_numeral_binary_string(contextPtr, this.ast);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ArraySortImpl<DomainSort extends [AnySort<Name>, ...AnySort<Name>[]] = [Sort<Name>, ...Sort<Name>[]],
|
||||||
|
RangeSort extends AnySort<Name> = Sort<Name>>
|
||||||
|
extends SortImpl
|
||||||
|
implements SMTArraySort<Name, DomainSort, RangeSort> {
|
||||||
|
declare readonly __typename: SMTArraySort['__typename'];
|
||||||
|
|
||||||
|
domain(): DomainSort[0] {
|
||||||
|
return _toSort(check(Z3.get_array_sort_domain(contextPtr, this.ptr)));
|
||||||
|
}
|
||||||
|
|
||||||
|
domain_n<T extends number>(i: T): DomainSort[T] {
|
||||||
|
return _toSort(check(Z3.get_array_sort_domain_n(contextPtr, this.ptr, i)));
|
||||||
|
}
|
||||||
|
|
||||||
|
range(): RangeSort {
|
||||||
|
return _toSort(check(Z3.get_array_sort_range(contextPtr, this.ptr))) as RangeSort;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class ArrayImpl<
|
||||||
|
DomainSort extends [AnySort<Name>, ...AnySort<Name>[]] = [Sort<Name>, ...Sort<Name>[]],
|
||||||
|
RangeSort extends AnySort<Name> = Sort<Name>
|
||||||
|
> extends ExprImpl<Z3_ast, ArraySortImpl<DomainSort, RangeSort>>
|
||||||
|
implements SMTArray<Name, DomainSort, RangeSort> {
|
||||||
|
declare readonly __typename: SMTArray['__typename'];
|
||||||
|
|
||||||
|
domain(): DomainSort[0] {
|
||||||
|
return this.sort.domain();
|
||||||
|
}
|
||||||
|
|
||||||
|
domain_n<T extends number>(i: T): DomainSort[T] {
|
||||||
|
return this.sort.domain_n(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
range(): RangeSort {
|
||||||
|
return this.sort.range();
|
||||||
|
}
|
||||||
|
|
||||||
|
select(...indices: ArrayIndexType<Name, DomainSort>): SortToExprMap<RangeSort, Name> {
|
||||||
|
const args = indices.map((arg, i) => this.domain_n(i).cast(arg as any));
|
||||||
|
if (args.length === 1) {
|
||||||
|
return _toExpr(check(Z3.mk_select(contextPtr, this.ast, args[0].ast))) as SortToExprMap<RangeSort, Name>;
|
||||||
|
}
|
||||||
|
const _args = args.map(arg => arg.ast);
|
||||||
|
return _toExpr(check(Z3.mk_select_n(contextPtr, this.ast, _args))) as SortToExprMap<RangeSort, Name>;
|
||||||
|
}
|
||||||
|
|
||||||
|
store(
|
||||||
|
...indicesAndValue: [
|
||||||
|
...ArrayIndexType<Name, DomainSort>,
|
||||||
|
CoercibleFromMap<SortToExprMap<RangeSort, Name>, Name>
|
||||||
|
]
|
||||||
|
): SMTArray<Name, DomainSort, RangeSort> {
|
||||||
|
const args = indicesAndValue.map((arg, i) => {
|
||||||
|
if (i === indicesAndValue.length - 1) {
|
||||||
|
return this.range().cast(arg as CoercibleFromMap<SortToExprMap<RangeSort, Name>, Name>);
|
||||||
|
}
|
||||||
|
return this.domain_n(i).cast(arg as any);
|
||||||
|
});
|
||||||
|
if (args.length <= 1) {
|
||||||
|
throw new Z3Error("Array store requires both index and value arguments");
|
||||||
|
}
|
||||||
|
if (args.length === 2) {
|
||||||
|
return _toExpr(check(Z3.mk_store(contextPtr, this.ast, args[0].ast, args[1].ast))) as SMTArray<Name, DomainSort, RangeSort>;
|
||||||
|
}
|
||||||
|
const _idxs = args.slice(0, args.length - 1).map(arg => arg.ast);
|
||||||
|
return _toExpr(check(Z3.mk_store_n(contextPtr, this.ast, _idxs, args[args.length - 1].ast))) as SMTArray<Name, DomainSort, RangeSort>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class AstVectorImpl<Item extends AnyAst<Name>> {
|
class AstVectorImpl<Item extends AnyAst<Name>> {
|
||||||
declare readonly __typename: AstVector['__typename'];
|
declare readonly __typename: AstVector['__typename'];
|
||||||
readonly ctx: Context<Name>;
|
readonly ctx: Context<Name>;
|
||||||
|
@ -1744,20 +1929,20 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
|
||||||
return this.values();
|
return this.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
*entries(): IterableIterator<[number, Item]> {
|
* entries(): IterableIterator<[number, Item]> {
|
||||||
const length = this.length();
|
const length = this.length();
|
||||||
for (let i = 0; i < length; i++) {
|
for (let i = 0; i < length; i++) {
|
||||||
yield [i, this.get(i)];
|
yield [i, this.get(i)];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*keys(): IterableIterator<number> {
|
* keys(): IterableIterator<number> {
|
||||||
for (let [key] of this.entries()) {
|
for (let [key] of this.entries()) {
|
||||||
yield key;
|
yield key;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*values(): IterableIterator<Item> {
|
* values(): IterableIterator<Item> {
|
||||||
for (let [, value] of this.entries()) {
|
for (let [, value] of this.entries()) {
|
||||||
yield value;
|
yield value;
|
||||||
}
|
}
|
||||||
|
@ -1842,7 +2027,7 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
|
||||||
return Z3.ast_map_size(contextPtr, this.ptr);
|
return Z3.ast_map_size(contextPtr, this.ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
*entries(): IterableIterator<[Key, Value]> {
|
* entries(): IterableIterator<[Key, Value]> {
|
||||||
for (const key of this.keys()) {
|
for (const key of this.keys()) {
|
||||||
yield [key, this.get(key)];
|
yield [key, this.get(key)];
|
||||||
}
|
}
|
||||||
|
@ -1852,11 +2037,12 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
|
||||||
return new AstVectorImpl(Z3.ast_map_keys(contextPtr, this.ptr));
|
return new AstVectorImpl(Z3.ast_map_keys(contextPtr, this.ptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
*values(): IterableIterator<Value> {
|
* values(): IterableIterator<Value> {
|
||||||
for (const [_, value] of this.entries()) {
|
for (const [_, value] of this.entries()) {
|
||||||
yield value;
|
yield value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get(key: Key): Value {
|
get(key: Key): Value {
|
||||||
return _toAst(check(Z3.ast_map_find(contextPtr, this.ptr, key.ast))) as Value;
|
return _toAst(check(Z3.ast_map_find(contextPtr, this.ptr, key.ast))) as Value;
|
||||||
}
|
}
|
||||||
|
@ -1928,6 +2114,9 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
|
||||||
isBitVecSort,
|
isBitVecSort,
|
||||||
isBitVec,
|
isBitVec,
|
||||||
isBitVecVal, // TODO fix ordering
|
isBitVecVal, // TODO fix ordering
|
||||||
|
isArraySort,
|
||||||
|
isArray,
|
||||||
|
isConstArray,
|
||||||
isProbe,
|
isProbe,
|
||||||
isTactic,
|
isTactic,
|
||||||
isAstVector,
|
isAstVector,
|
||||||
|
@ -1946,6 +2135,7 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
|
||||||
Int,
|
Int,
|
||||||
Real,
|
Real,
|
||||||
BitVec,
|
BitVec,
|
||||||
|
Array,
|
||||||
|
|
||||||
////////////////
|
////////////////
|
||||||
// Operations //
|
// Operations //
|
||||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue