3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2026-02-17 14:21:45 +00:00

Fix Go bindings and enable in CI

- Fix all compilation errors in Go bindings
- Add missing type definitions (Pattern, ASTVector, ParamDescrs)
- Fix boolean comparisons to use bool() casts
- Fix Z3_app type casts using unsafe.Pointer
- Fix null symbol handling to use nil
- Fix unused variable in basic_example.go
- Fix CMake test target to run from examples/go directory
- Restore CI steps to build and test Go bindings

Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot] 2026-02-16 06:05:58 +00:00
parent bbc1e501ab
commit 3f4bd11f00
6 changed files with 92 additions and 37 deletions

View file

@ -46,7 +46,8 @@ if(Z3_BUILD_GO_BINDINGS)
CGO_LDFLAGS=${CGO_LDFLAGS_VALUE}
LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}:$ENV{LD_LIBRARY_PATH}
PATH=${CMAKE_BINARY_DIR}$<SEMICOLON>$ENV{PATH}
${GO_EXECUTABLE} run ${CMAKE_SOURCE_DIR}/examples/go/basic_example.go
${GO_EXECUTABLE} run basic_example.go
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/examples/go
COMMENT "Running Go examples"
DEPENDS libz3
VERBATIM

View file

@ -70,7 +70,7 @@ func (f *Fixedpoint) AddRule(rule *Expr, name *Symbol) {
if name != nil {
namePtr = name.ptr
} else {
namePtr = 0
namePtr = nil
}
C.Z3_fixedpoint_add_rule(f.ctx.ptr, f.ptr, rule.ptr, namePtr)
}
@ -132,7 +132,7 @@ func (f *Fixedpoint) UpdateRule(rule *Expr, name *Symbol) {
if name != nil {
namePtr = name.ptr
} else {
namePtr = 0
namePtr = nil
}
C.Z3_fixedpoint_update_rule(f.ctx.ptr, f.ptr, rule.ptr, namePtr)
}
@ -253,12 +253,12 @@ func (s *Statistics) GetKey(idx int) string {
// IsUint returns true if the statistical data at the given index is unsigned integer
func (s *Statistics) IsUint(idx int) bool {
return C.Z3_stats_is_uint(s.ctx.ptr, s.ptr, C.uint(idx)) != 0
return bool(C.Z3_stats_is_uint(s.ctx.ptr, s.ptr, C.uint(idx)))
}
// IsDouble returns true if the statistical data at the given index is double
func (s *Statistics) IsDouble(idx int) bool {
return C.Z3_stats_is_double(s.ctx.ptr, s.ptr, C.uint(idx)) != 0
return bool(C.Z3_stats_is_double(s.ctx.ptr, s.ptr, C.uint(idx)))
}
// GetUintValue returns the unsigned integer value at the given index

View file

@ -28,7 +28,7 @@ func OpenLog(filename string) bool {
defer C.free(unsafe.Pointer(cFilename))
result := C.Z3_open_log(cFilename)
if result != 0 {
if bool(result) {
isLogOpen = true
return true
}

View file

@ -7,7 +7,6 @@ package z3
import "C"
import (
"runtime"
"unsafe"
)
// Status represents the result of a satisfiability check.

View file

@ -119,6 +119,11 @@ ctx *Context
ptr C.Z3_symbol
}
// newSymbol creates a new Symbol.
func newSymbol(ctx *Context, ptr C.Z3_symbol) *Symbol {
return &Symbol{ctx: ctx, ptr: ptr}
}
// MkIntSymbol creates an integer symbol.
func (c *Context) MkIntSymbol(i int) *Symbol {
return &Symbol{
@ -253,6 +258,55 @@ func (e *Expr) GetSort() *Sort {
return newSort(e.ctx, C.Z3_get_sort(e.ctx.ptr, e.ptr))
}
// Pattern represents a Z3 pattern for quantifier instantiation.
type Pattern struct {
ctx *Context
ptr C.Z3_pattern
}
// newPattern creates a new Pattern and manages its reference count.
func newPattern(ctx *Context, ptr C.Z3_pattern) *Pattern {
p := &Pattern{ctx: ctx, ptr: ptr}
// Patterns are ASTs in the C API
C.Z3_inc_ref(ctx.ptr, (C.Z3_ast)(unsafe.Pointer(ptr)))
runtime.SetFinalizer(p, func(pat *Pattern) {
C.Z3_dec_ref(pat.ctx.ptr, (C.Z3_ast)(unsafe.Pointer(pat.ptr)))
})
return p
}
// ASTVector represents a vector of Z3 ASTs.
type ASTVector struct {
ctx *Context
ptr C.Z3_ast_vector
}
// newASTVector creates a new ASTVector and manages its reference count.
func newASTVector(ctx *Context, ptr C.Z3_ast_vector) *ASTVector {
v := &ASTVector{ctx: ctx, ptr: ptr}
C.Z3_ast_vector_inc_ref(ctx.ptr, ptr)
runtime.SetFinalizer(v, func(vec *ASTVector) {
C.Z3_ast_vector_dec_ref(vec.ctx.ptr, vec.ptr)
})
return v
}
// ParamDescrs represents parameter descriptions for Z3 objects.
type ParamDescrs struct {
ctx *Context
ptr C.Z3_param_descrs
}
// newParamDescrs creates a new ParamDescrs and manages its reference count.
func newParamDescrs(ctx *Context, ptr C.Z3_param_descrs) *ParamDescrs {
pd := &ParamDescrs{ctx: ctx, ptr: ptr}
C.Z3_param_descrs_inc_ref(ctx.ptr, ptr)
runtime.SetFinalizer(pd, func(descrs *ParamDescrs) {
C.Z3_param_descrs_dec_ref(descrs.ctx.ptr, descrs.ptr)
})
return pd
}
// MkTrue creates the Boolean constant true.
func (c *Context) MkTrue() *Expr {
return newExpr(c, C.Z3_mk_true(c.ptr))
@ -434,28 +488,30 @@ return newExpr(c, C.Z3_mk_app(c.ptr, decl.ptr, C.uint(len(args)), argsPtr))
// MkForall creates a universal quantifier.
func (c *Context) MkForall(bound []*Expr, body *Expr) *Expr {
cBound := make([]C.Z3_ast, len(bound))
for i, b := range bound {
cBound[i] = b.ptr
}
var boundPtr *C.Z3_ast
if len(bound) > 0 {
boundPtr = &cBound[0]
}
return newExpr(c, C.Z3_mk_forall_const(c.ptr, 0, C.uint(len(bound)), boundPtr, 0, nil, body.ptr))
cBound := make([]C.Z3_app, len(bound))
for i, b := range bound {
// Z3_app is a subtype of Z3_ast; constants are apps
cBound[i] = (C.Z3_app)(unsafe.Pointer(b.ptr))
}
var boundPtr *C.Z3_app
if len(bound) > 0 {
boundPtr = &cBound[0]
}
return newExpr(c, C.Z3_mk_forall_const(c.ptr, 0, C.uint(len(bound)), boundPtr, 0, nil, body.ptr))
}
// MkExists creates an existential quantifier.
func (c *Context) MkExists(bound []*Expr, body *Expr) *Expr {
cBound := make([]C.Z3_ast, len(bound))
for i, b := range bound {
cBound[i] = b.ptr
}
var boundPtr *C.Z3_ast
if len(bound) > 0 {
boundPtr = &cBound[0]
}
return newExpr(c, C.Z3_mk_exists_const(c.ptr, 0, C.uint(len(bound)), boundPtr, 0, nil, body.ptr))
cBound := make([]C.Z3_app, len(bound))
for i, b := range bound {
// Z3_app is a subtype of Z3_ast; constants are apps
cBound[i] = (C.Z3_app)(unsafe.Pointer(b.ptr))
}
var boundPtr *C.Z3_app
if len(bound) > 0 {
boundPtr = &cBound[0]
}
return newExpr(c, C.Z3_mk_exists_const(c.ptr, 0, C.uint(len(bound)), boundPtr, 0, nil, body.ptr))
}
// Simplify simplifies an expression.
@ -491,12 +547,12 @@ return newExpr(q.ctx, q.ptr)
// IsUniversal returns true if this is a universal quantifier (forall)
func (q *Quantifier) IsUniversal() bool {
return C.Z3_is_quantifier_forall(q.ctx.ptr, q.ptr) != 0
return bool(C.Z3_is_quantifier_forall(q.ctx.ptr, q.ptr))
}
// IsExistential returns true if this is an existential quantifier (exists)
func (q *Quantifier) IsExistential() bool {
return C.Z3_is_quantifier_exists(q.ctx.ptr, q.ptr) != 0
return bool(C.Z3_is_quantifier_exists(q.ctx.ptr, q.ptr))
}
// GetWeight returns the weight of the quantifier
@ -523,7 +579,7 @@ return int(C.Z3_get_quantifier_num_no_patterns(q.ctx.ptr, q.ptr))
// GetNoPattern returns the no-pattern at the given index
func (q *Quantifier) GetNoPattern(idx int) *Pattern {
ptr := C.Z3_get_quantifier_no_pattern_ast(q.ctx.ptr, q.ptr, C.uint(idx))
return newPattern(q.ctx, ptr)
return newPattern(q.ctx, (C.Z3_pattern)(unsafe.Pointer(ptr)))
}
// GetNumBound returns the number of bound variables
@ -556,11 +612,11 @@ return q.AsExpr().String()
// MkQuantifier creates a quantifier with patterns
func (c *Context) MkQuantifier(isForall bool, weight int, sorts []*Sort, names []*Symbol, body *Expr, patterns []*Pattern) *Quantifier {
var forallInt C.int
var forallInt C.bool
if isForall {
forallInt = 1
forallInt = true
} else {
forallInt = 0
forallInt = false
}
numBound := len(sorts)
@ -604,11 +660,11 @@ return newQuantifier(c, ptr)
// MkQuantifierConst creates a quantifier using constant bound variables
func (c *Context) MkQuantifierConst(isForall bool, weight int, bound []*Expr, body *Expr, patterns []*Pattern) *Quantifier {
var forallInt C.int
var forallInt C.bool
if isForall {
forallInt = 1
forallInt = true
} else {
forallInt = 0
forallInt = false
}
numBound := len(bound)
@ -617,7 +673,7 @@ var boundPtr *C.Z3_app
if numBound > 0 {
cBound = make([]C.Z3_app, numBound)
for i := 0; i < numBound; i++ {
cBound[i] = C.Z3_app(bound[i].ptr)
cBound[i] = (C.Z3_app)(unsafe.Pointer(bound[i].ptr))
}
boundPtr = &cBound[0]
}
@ -723,7 +779,7 @@ var boundPtr *C.Z3_app
if numBound > 0 {
cBound = make([]C.Z3_app, numBound)
for i := 0; i < numBound; i++ {
cBound[i] = C.Z3_app(bound[i].ptr)
cBound[i] = (C.Z3_app)(unsafe.Pointer(bound[i].ptr))
}
boundPtr = &cBound[0]
}