mirror of
				https://github.com/Z3Prover/z3
				synced 2025-11-03 21:09:11 +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