13// Constructor represents a datatype constructor.
14type Constructor struct {
19// newConstructor creates a new Constructor and manages its reference count.
20func newConstructor(ctx *Context, ptr C.Z3_constructor) *Constructor {
21 c := &Constructor{ctx: ctx, ptr: ptr}
22 // Note: Z3_constructor doesn't use inc_ref/dec_ref pattern
23 // It uses Z3_del_constructor for cleanup
24 runtime.SetFinalizer(c, func(cons *Constructor) {
25 C.Z3_del_constructor(cons.ctx.ptr, cons.ptr)
30// MkConstructor creates a constructor for a datatype.
31// name is the constructor name, recognizer is the recognizer name,
32// fieldNames are the names of the fields, and fieldSorts are the sorts of the fields.
33// fieldSortRefs can be 0 for non-recursive fields or the datatype index for recursive fields.
34func (c *Context) MkConstructor(name, recognizer string, fieldNames []string, fieldSorts []*Sort, fieldSortRefs []uint) *Constructor {
35 cName := C.CString(name)
36 cRecognizer := C.CString(recognizer)
37 defer C.free(unsafe.Pointer(cName))
38 defer C.free(unsafe.Pointer(cRecognizer))
40 numFields := uint(len(fieldNames))
41 if numFields != uint(len(fieldSorts)) || numFields != uint(len(fieldSortRefs)) {
42 panic("fieldNames, fieldSorts, and fieldSortRefs must have the same length")
45 var cFieldNames *C.Z3_symbol
50 fieldSyms := make([]C.Z3_symbol, numFields)
51 for i, fname := range fieldNames {
52 fieldSyms[i] = c.MkStringSymbol(fname).ptr
54 cFieldNames = &fieldSyms[0]
56 sorts := make([]C.Z3_sort, numFields)
57 for i, s := range fieldSorts {
64 refs := make([]C.uint, numFields)
65 for i, r := range fieldSortRefs {
71 sym := c.MkStringSymbol(name)
72 recSym := c.MkStringSymbol(recognizer)
74 return newConstructor(c, C.Z3_mk_constructor(
85// ConstructorList represents a list of datatype constructors.
86type ConstructorList struct {
88 ptr C.Z3_constructor_list
91// newConstructorList creates a new ConstructorList and manages its reference count.
92func newConstructorList(ctx *Context, ptr C.Z3_constructor_list) *ConstructorList {
93 cl := &ConstructorList{ctx: ctx, ptr: ptr}
94 // Note: Z3_constructor_list doesn't use inc_ref/dec_ref pattern
95 // It uses Z3_del_constructor_list for cleanup
96 runtime.SetFinalizer(cl, func(list *ConstructorList) {
97 C.Z3_del_constructor_list(list.ctx.ptr, list.ptr)
102// MkConstructorList creates a list of constructors for a datatype.
103func (c *Context) MkConstructorList(constructors []*Constructor) *ConstructorList {
104 numCons := uint(len(constructors))
109 cons := make([]C.Z3_constructor, numCons)
110 for i, constr := range constructors {
114 return newConstructorList(c, C.Z3_mk_constructor_list(c.ptr, C.uint(numCons), &cons[0]))
117// MkDatatypeSort creates a datatype sort from a constructor list.
118func (c *Context) MkDatatypeSort(name string, constructors []*Constructor) *Sort {
119 sym := c.MkStringSymbol(name)
121 numCons := uint(len(constructors))
122 cons := make([]C.Z3_constructor, numCons)
123 for i, constr := range constructors {
127 return newSort(c, C.Z3_mk_datatype(c.ptr, sym.ptr, C.uint(numCons), &cons[0]))
130// MkDatatypeSorts creates multiple mutually recursive datatype sorts.
131func (c *Context) MkDatatypeSorts(names []string, constructorLists [][]*Constructor) []*Sort {
132 numTypes := uint(len(names))
133 if numTypes != uint(len(constructorLists)) {
134 panic("names and constructorLists must have the same length")
137 syms := make([]C.Z3_symbol, numTypes)
138 for i, name := range names {
139 syms[i] = c.MkStringSymbol(name).ptr
142 cLists := make([]C.Z3_constructor_list, numTypes)
143 for i, constrs := range constructorLists {
144 cons := make([]C.Z3_constructor, len(constrs))
145 for j, constr := range constrs {
148 cLists[i] = C.Z3_mk_constructor_list(c.ptr, C.uint(len(constrs)), &cons[0])
151 resultSorts := make([]C.Z3_sort, numTypes)
153 C.Z3_mk_datatypes(c.ptr, C.uint(numTypes), &syms[0], &resultSorts[0], &cLists[0])
155 // Clean up constructor lists
156 for i := range cLists {
157 C.Z3_del_constructor_list(c.ptr, cLists[i])
160 sorts := make([]*Sort, numTypes)
161 for i := range resultSorts {
162 sorts[i] = newSort(c, resultSorts[i])
168// GetDatatypeSortConstructor returns the i-th constructor of a datatype sort.
169func (c *Context) GetDatatypeSortConstructor(sort *Sort, i uint) *FuncDecl {
170 return newFuncDecl(c, C.Z3_get_datatype_sort_constructor(c.ptr, sort.ptr, C.uint(i)))
173// GetDatatypeSortRecognizer returns the i-th recognizer of a datatype sort.
174func (c *Context) GetDatatypeSortRecognizer(sort *Sort, i uint) *FuncDecl {
175 return newFuncDecl(c, C.Z3_get_datatype_sort_recognizer(c.ptr, sort.ptr, C.uint(i)))
178// GetDatatypeSortConstructorAccessor returns the accessor for the i-th field of the j-th constructor.
179func (c *Context) GetDatatypeSortConstructorAccessor(sort *Sort, constructorIdx, accessorIdx uint) *FuncDecl {
180 return newFuncDecl(c, C.Z3_get_datatype_sort_constructor_accessor(
181 c.ptr, sort.ptr, C.uint(constructorIdx), C.uint(accessorIdx)))
184// GetDatatypeSortNumConstructors returns the number of constructors in a datatype sort.
185func (c *Context) GetDatatypeSortNumConstructors(sort *Sort) uint {
186 return uint(C.Z3_get_datatype_sort_num_constructors(c.ptr, sort.ptr))
189// Tuple sorts (special case of datatypes)
191// MkTupleSort creates a tuple sort with the given field sorts.
192func (c *Context) MkTupleSort(name string, fieldNames []string, fieldSorts []*Sort) (*Sort, *FuncDecl, []*FuncDecl) {
193 sym := c.MkStringSymbol(name)
195 numFields := uint(len(fieldNames))
196 if numFields != uint(len(fieldSorts)) {
197 panic("fieldNames and fieldSorts must have the same length")
200 fieldSyms := make([]C.Z3_symbol, numFields)
201 for i, fname := range fieldNames {
202 fieldSyms[i] = c.MkStringSymbol(fname).ptr
205 sorts := make([]C.Z3_sort, numFields)
206 for i, s := range fieldSorts {
210 var mkTupleDecl C.Z3_func_decl
211 projDecls := make([]C.Z3_func_decl, numFields)
213 tupleSort := C.Z3_mk_tuple_sort(
223 projections := make([]*FuncDecl, numFields)
224 for i := range projDecls {
225 projections[i] = newFuncDecl(c, projDecls[i])
228 return newSort(c, tupleSort), newFuncDecl(c, mkTupleDecl), projections
231// Enumeration sorts (special case of datatypes)
233// MkEnumSort creates an enumeration sort with the given constants.
234func (c *Context) MkEnumSort(name string, enumNames []string) (*Sort, []*FuncDecl, []*FuncDecl) {
235 sym := c.MkStringSymbol(name)
237 numEnums := uint(len(enumNames))
238 enumSyms := make([]C.Z3_symbol, numEnums)
239 for i, ename := range enumNames {
240 enumSyms[i] = c.MkStringSymbol(ename).ptr
243 enumConsts := make([]C.Z3_func_decl, numEnums)
244 enumTesters := make([]C.Z3_func_decl, numEnums)
246 enumSort := C.Z3_mk_enumeration_sort(
255 consts := make([]*FuncDecl, numEnums)
256 for i := range enumConsts {
257 consts[i] = newFuncDecl(c, enumConsts[i])
260 testers := make([]*FuncDecl, numEnums)
261 for i := range enumTesters {
262 testers[i] = newFuncDecl(c, enumTesters[i])
265 return newSort(c, enumSort), consts, testers
268// List sorts (special case of datatypes)
270// MkListSort creates a list sort with the given element sort.
271func (c *Context) MkListSort(name string, elemSort *Sort) (*Sort, *FuncDecl, *FuncDecl, *FuncDecl, *FuncDecl, *FuncDecl, *FuncDecl) {
272 sym := c.MkStringSymbol(name)
274 var nilDecl, consDecl, isNilDecl, isConsDecl, headDecl, tailDecl C.Z3_func_decl
276 listSort := C.Z3_mk_list_sort(
288 return newSort(c, listSort),
289 newFuncDecl(c, nilDecl),
290 newFuncDecl(c, consDecl),
291 newFuncDecl(c, isNilDecl),
292 newFuncDecl(c, isConsDecl),
293 newFuncDecl(c, headDecl),
294 newFuncDecl(c, tailDecl)