mirror of
https://github.com/Z3Prover/z3
synced 2025-08-27 21:48:56 +00:00
Add pointer assertion
This commit is contained in:
parent
194f4d4e5e
commit
c92ab91a5e
2 changed files with 34 additions and 62 deletions
|
@ -178,6 +178,10 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
|
||||||
ctxs.forEach(other => assert('ctx' in other ? ctx === other.ctx : ctx === other, 'Context mismatch'));
|
ctxs.forEach(other => assert('ctx' in other ? ctx === other.ctx : ctx === other, 'Context mismatch'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _assertPtr<T extends Number>(ptr: T | null): asserts ptr is T {
|
||||||
|
if (ptr == null) throw new TypeError('Expected non-null pointer');
|
||||||
|
}
|
||||||
|
|
||||||
// call this after every nontrivial call to the underlying API
|
// call this after every nontrivial call to the underlying API
|
||||||
function throwIfError() {
|
function throwIfError() {
|
||||||
if (Z3.get_error_code(contextPtr) !== Z3_error_code.Z3_OK) {
|
if (Z3.get_error_code(contextPtr) !== Z3_error_code.Z3_OK) {
|
||||||
|
@ -1235,18 +1239,17 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
|
||||||
toString() {
|
toString() {
|
||||||
return this.sexpr();
|
return this.sexpr();
|
||||||
}
|
}
|
||||||
|
|
||||||
release() {
|
|
||||||
Z3.dec_ref(contextPtr, this.ast);
|
|
||||||
cleanup.unregister(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class SolverImpl implements Solver<Name> {
|
class SolverImpl implements Solver<Name> {
|
||||||
declare readonly __typename: Solver['__typename'];
|
declare readonly __typename: Solver['__typename'];
|
||||||
|
|
||||||
readonly ptr: Z3_solver;
|
|
||||||
readonly ctx: Context<Name>;
|
readonly ctx: Context<Name>;
|
||||||
|
private _ptr: Z3_solver | null;
|
||||||
|
get ptr(): Z3_solver {
|
||||||
|
_assertPtr(this._ptr);
|
||||||
|
return this._ptr;
|
||||||
|
}
|
||||||
|
|
||||||
constructor(ptr: Z3_solver | string = Z3.mk_solver(contextPtr)) {
|
constructor(ptr: Z3_solver | string = Z3.mk_solver(contextPtr)) {
|
||||||
this.ctx = ctx;
|
this.ctx = ctx;
|
||||||
|
@ -1256,7 +1259,7 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
|
||||||
} else {
|
} else {
|
||||||
myPtr = ptr;
|
myPtr = ptr;
|
||||||
}
|
}
|
||||||
this.ptr = myPtr;
|
this._ptr = myPtr;
|
||||||
Z3.solver_inc_ref(contextPtr, myPtr);
|
Z3.solver_inc_ref(contextPtr, myPtr);
|
||||||
cleanup.register(this, () => Z3.solver_dec_ref(contextPtr, myPtr), this);
|
cleanup.register(this, () => Z3.solver_dec_ref(contextPtr, myPtr), this);
|
||||||
}
|
}
|
||||||
|
@ -1335,6 +1338,8 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
|
||||||
|
|
||||||
release() {
|
release() {
|
||||||
Z3.solver_dec_ref(contextPtr, this.ptr);
|
Z3.solver_dec_ref(contextPtr, this.ptr);
|
||||||
|
// Mark the ptr as null to prevent double free
|
||||||
|
this._ptr = null;
|
||||||
cleanup.unregister(this);
|
cleanup.unregister(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1342,14 +1347,18 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
|
||||||
class OptimizeImpl implements Optimize<Name> {
|
class OptimizeImpl implements Optimize<Name> {
|
||||||
declare readonly __typename: Optimize['__typename'];
|
declare readonly __typename: Optimize['__typename'];
|
||||||
|
|
||||||
readonly ptr: Z3_optimize;
|
|
||||||
readonly ctx: Context<Name>;
|
readonly ctx: Context<Name>;
|
||||||
|
private _ptr: Z3_optimize | null;
|
||||||
|
get ptr(): Z3_optimize {
|
||||||
|
_assertPtr(this._ptr);
|
||||||
|
return this._ptr;
|
||||||
|
}
|
||||||
|
|
||||||
constructor(ptr: Z3_optimize = Z3.mk_optimize(contextPtr)) {
|
constructor(ptr: Z3_optimize = Z3.mk_optimize(contextPtr)) {
|
||||||
this.ctx = ctx;
|
this.ctx = ctx;
|
||||||
let myPtr: Z3_optimize;
|
let myPtr: Z3_optimize;
|
||||||
myPtr = ptr;
|
myPtr = ptr;
|
||||||
this.ptr = myPtr;
|
this._ptr = myPtr;
|
||||||
Z3.optimize_inc_ref(contextPtr, myPtr);
|
Z3.optimize_inc_ref(contextPtr, myPtr);
|
||||||
cleanup.register(this, () => Z3.optimize_dec_ref(contextPtr, myPtr), this);
|
cleanup.register(this, () => Z3.optimize_dec_ref(contextPtr, myPtr), this);
|
||||||
}
|
}
|
||||||
|
@ -1373,11 +1382,11 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
addSoft(expr: Bool<Name>, weight: number | bigint | string | CoercibleRational, id: number | string = "") {
|
addSoft(expr: Bool<Name>, weight: number | bigint | string | CoercibleRational, id: number | string = '') {
|
||||||
if (isCoercibleRational(weight)) {
|
if (isCoercibleRational(weight)) {
|
||||||
weight = `${weight.numerator}/${weight.denominator}`;
|
weight = `${weight.numerator}/${weight.denominator}`;
|
||||||
}
|
}
|
||||||
check(Z3.optimize_assert_soft(contextPtr, this.ptr, expr.ast, weight.toString(), _toSymbol(id)))
|
check(Z3.optimize_assert_soft(contextPtr, this.ptr, expr.ast, weight.toString(), _toSymbol(id)));
|
||||||
}
|
}
|
||||||
|
|
||||||
addAndTrack(expr: Bool<Name>, constant: Bool<Name> | string) {
|
addAndTrack(expr: Bool<Name>, constant: Bool<Name> | string) {
|
||||||
|
@ -1405,9 +1414,7 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
|
||||||
_assertContext(expr);
|
_assertContext(expr);
|
||||||
return expr.ast;
|
return expr.ast;
|
||||||
});
|
});
|
||||||
const result = await asyncMutex.runExclusive(() =>
|
const result = await asyncMutex.runExclusive(() => check(Z3.optimize_check(contextPtr, this.ptr, assumptions)));
|
||||||
check(Z3.optimize_check(contextPtr, this.ptr, assumptions)),
|
|
||||||
);
|
|
||||||
switch (result) {
|
switch (result) {
|
||||||
case Z3_lbool.Z3_L_FALSE:
|
case Z3_lbool.Z3_L_FALSE:
|
||||||
return 'unsat';
|
return 'unsat';
|
||||||
|
@ -1442,9 +1449,15 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
|
||||||
class ModelImpl implements Model<Name> {
|
class ModelImpl implements Model<Name> {
|
||||||
declare readonly __typename: Model['__typename'];
|
declare readonly __typename: Model['__typename'];
|
||||||
readonly ctx: Context<Name>;
|
readonly ctx: Context<Name>;
|
||||||
|
private _ptr: Z3_model | null;
|
||||||
|
get ptr(): Z3_model {
|
||||||
|
_assertPtr(this._ptr);
|
||||||
|
return this._ptr;
|
||||||
|
}
|
||||||
|
|
||||||
constructor(readonly ptr: Z3_model = Z3.mk_model(contextPtr)) {
|
constructor(ptr: Z3_model = Z3.mk_model(contextPtr)) {
|
||||||
this.ctx = ctx;
|
this.ctx = ctx;
|
||||||
|
this._ptr = ptr;
|
||||||
Z3.model_inc_ref(contextPtr, ptr);
|
Z3.model_inc_ref(contextPtr, ptr);
|
||||||
cleanup.register(this, () => Z3.model_dec_ref(contextPtr, ptr), this);
|
cleanup.register(this, () => Z3.model_dec_ref(contextPtr, ptr), this);
|
||||||
}
|
}
|
||||||
|
@ -1611,6 +1624,7 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
|
||||||
|
|
||||||
release() {
|
release() {
|
||||||
Z3.model_dec_ref(contextPtr, this.ptr);
|
Z3.model_dec_ref(contextPtr, this.ptr);
|
||||||
|
this._ptr = null;
|
||||||
cleanup.unregister(this);
|
cleanup.unregister(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1675,11 +1689,6 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
|
||||||
assert(this.arity() === argsVec.length(), "Number of arguments in entry doesn't match function arity");
|
assert(this.arity() === argsVec.length(), "Number of arguments in entry doesn't match function arity");
|
||||||
check(Z3.func_interp_add_entry(contextPtr, this.ptr, argsVec.ptr, value.ptr as Z3_ast));
|
check(Z3.func_interp_add_entry(contextPtr, this.ptr, argsVec.ptr, value.ptr as Z3_ast));
|
||||||
}
|
}
|
||||||
|
|
||||||
release() {
|
|
||||||
Z3.func_interp_dec_ref(contextPtr, this.ptr);
|
|
||||||
cleanup.unregister(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class SortImpl extends AstImpl<Z3_sort> implements Sort<Name> {
|
class SortImpl extends AstImpl<Z3_sort> implements Sort<Name> {
|
||||||
|
@ -1948,11 +1957,6 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
|
||||||
Z3.tactic_inc_ref(contextPtr, myPtr);
|
Z3.tactic_inc_ref(contextPtr, myPtr);
|
||||||
cleanup.register(this, () => Z3.tactic_dec_ref(contextPtr, myPtr), this);
|
cleanup.register(this, () => Z3.tactic_dec_ref(contextPtr, myPtr), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
release() {
|
|
||||||
Z3.tactic_dec_ref(contextPtr, this.ptr);
|
|
||||||
cleanup.unregister(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ArithSortImpl extends SortImpl implements ArithSort<Name> {
|
class ArithSortImpl extends SortImpl implements ArithSort<Name> {
|
||||||
|
@ -2704,11 +2708,6 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
|
||||||
sexpr(): string {
|
sexpr(): string {
|
||||||
return check(Z3.ast_vector_to_string(contextPtr, this.ptr));
|
return check(Z3.ast_vector_to_string(contextPtr, this.ptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
release() {
|
|
||||||
Z3.ast_vector_dec_ref(contextPtr, this.ptr);
|
|
||||||
cleanup.unregister(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class AstMapImpl<Key extends AnyAst<Name>, Value extends AnyAst<Name>> implements AstMap<Name, Key, Value> {
|
class AstMapImpl<Key extends AnyAst<Name>, Value extends AnyAst<Name>> implements AstMap<Name, Key, Value> {
|
||||||
|
@ -2768,11 +2767,6 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
|
||||||
sexpr(): string {
|
sexpr(): string {
|
||||||
return check(Z3.ast_map_to_string(contextPtr, this.ptr));
|
return check(Z3.ast_map_to_string(contextPtr, this.ptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
release() {
|
|
||||||
Z3.ast_map_dec_ref(contextPtr, this.ptr);
|
|
||||||
cleanup.unregister(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function substitute(t: Expr<Name>, ...substitutions: [Expr<Name>, Expr<Name>][]): Expr<Name> {
|
function substitute(t: Expr<Name>, ...substitutions: [Expr<Name>, Expr<Name>][]): Expr<Name> {
|
||||||
|
|
|
@ -703,6 +703,11 @@ export interface Optimize<Name extends string = 'main'> {
|
||||||
|
|
||||||
model(): Model<Name>;
|
model(): Model<Name>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manually decrease the reference count of the optimize
|
||||||
|
* This is automatically done when the optimize is garbage collected,
|
||||||
|
* but calling this eagerly can help release memory sooner.
|
||||||
|
*/
|
||||||
release(): void;
|
release(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -839,13 +844,6 @@ export interface FuncInterp<Name extends string = 'main'> {
|
||||||
entry(i: number): FuncEntry<Name>;
|
entry(i: number): FuncEntry<Name>;
|
||||||
|
|
||||||
addEntry(args: Expr<Name>[], value: Expr<Name>): void;
|
addEntry(args: Expr<Name>[], value: Expr<Name>): void;
|
||||||
|
|
||||||
/**
|
|
||||||
* Manually decrease the reference count of the func interp
|
|
||||||
* This is automatically done when the func interp is garbage collected,
|
|
||||||
* but calling this eagerly can help release memory sooner.
|
|
||||||
*/
|
|
||||||
release(): void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @hidden */
|
/** @hidden */
|
||||||
|
@ -1630,13 +1628,6 @@ export interface Tactic<Name extends string = 'main'> {
|
||||||
|
|
||||||
readonly ctx: Context<Name>;
|
readonly ctx: Context<Name>;
|
||||||
readonly ptr: Z3_tactic;
|
readonly ptr: Z3_tactic;
|
||||||
|
|
||||||
/**
|
|
||||||
* Manually decrease the reference count of the tactic
|
|
||||||
* This is automatically done when the tactic is garbage collected,
|
|
||||||
* but calling this eagerly can help release memory sooner.
|
|
||||||
*/
|
|
||||||
release(): void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @hidden */
|
/** @hidden */
|
||||||
|
@ -1688,12 +1679,6 @@ export interface AstVector<Name extends string = 'main', Item extends Ast<Name>
|
||||||
has(v: Item): boolean;
|
has(v: Item): boolean;
|
||||||
|
|
||||||
sexpr(): string;
|
sexpr(): string;
|
||||||
/**
|
|
||||||
* Manually decrease the reference count of the ast vector
|
|
||||||
* This is automatically done when the ast vector is garbage collected,
|
|
||||||
* but calling this eagerly can help release memory sooner.
|
|
||||||
*/
|
|
||||||
release(): void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @hidden */
|
/** @hidden */
|
||||||
|
@ -1752,13 +1737,6 @@ export interface AstMap<
|
||||||
has(key: Key): boolean;
|
has(key: Key): boolean;
|
||||||
|
|
||||||
sexpr(): string;
|
sexpr(): string;
|
||||||
|
|
||||||
/**
|
|
||||||
* Manually decrease the reference count of the ast map
|
|
||||||
* This is automatically done when the ast map is garbage collected,
|
|
||||||
* but calling this eagerly can help release memory sooner.
|
|
||||||
*/
|
|
||||||
release(): void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue