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// MkPolymorphicDatatypeSort creates a polymorphic datatype sort with explicit type parameters.
131// typeParams should be sorts created with MkTypeVariable.
132// Self-recursive field sorts should be passed as nil; use the fieldSortRefs parameter in
133// MkConstructor to indicate the recursive reference by index.
134func (c *Context) MkPolymorphicDatatypeSort(name string, typeParams []*Sort, constructors []*Constructor) *Sort {
135 sym := c.MkStringSymbol(name)
137 numParams := len(typeParams)
138 numCons := len(constructors)
140 var paramPtr *C.Z3_sort
142 paramPtrs := make([]C.Z3_sort, numParams)
143 for i, p := range typeParams {
146 paramPtr = ¶mPtrs[0]
149 var consPtr *C.Z3_constructor
151 consPtrs := make([]C.Z3_constructor, numCons)
152 for i, cons := range constructors {
153 consPtrs[i] = cons.ptr
155 consPtr = &consPtrs[0]
158 return newSort(c, C.Z3_mk_polymorphic_datatype(
160 C.uint(numParams), paramPtr,
161 C.uint(numCons), consPtr,
165// MkDatatypeSorts creates multiple mutually recursive datatype sorts.
166func (c *Context) MkDatatypeSorts(names []string, constructorLists [][]*Constructor) []*Sort {
167 numTypes := uint(len(names))
168 if numTypes != uint(len(constructorLists)) {
169 panic("names and constructorLists must have the same length")
172 syms := make([]C.Z3_symbol, numTypes)
173 for i, name := range names {
174 syms[i] = c.MkStringSymbol(name).ptr
177 cLists := make([]C.Z3_constructor_list, numTypes)
178 for i, constrs := range constructorLists {
179 cons := make([]C.Z3_constructor, len(constrs))
180 for j, constr := range constrs {
183 cLists[i] = C.Z3_mk_constructor_list(c.ptr, C.uint(len(constrs)), &cons[0])
186 resultSorts := make([]C.Z3_sort, numTypes)
188 C.Z3_mk_datatypes(c.ptr, C.uint(numTypes), &syms[0], &resultSorts[0], &cLists[0])
190 // Clean up constructor lists
191 for i := range cLists {
192 C.Z3_del_constructor_list(c.ptr, cLists[i])
195 sorts := make([]*Sort, numTypes)
196 for i := range resultSorts {
197 sorts[i] = newSort(c, resultSorts[i])
203// GetDatatypeSortConstructor returns the i-th constructor of a datatype sort.
204func (c *Context) GetDatatypeSortConstructor(sort *Sort, i uint) *FuncDecl {
205 return newFuncDecl(c, C.Z3_get_datatype_sort_constructor(c.ptr, sort.ptr, C.uint(i)))
208// GetDatatypeSortRecognizer returns the i-th recognizer of a datatype sort.
209func (c *Context) GetDatatypeSortRecognizer(sort *Sort, i uint) *FuncDecl {
210 return newFuncDecl(c, C.Z3_get_datatype_sort_recognizer(c.ptr, sort.ptr, C.uint(i)))
213// GetDatatypeSortConstructorAccessor returns the accessor for the i-th field of the j-th constructor.
214func (c *Context) GetDatatypeSortConstructorAccessor(sort *Sort, constructorIdx, accessorIdx uint) *FuncDecl {
215 return newFuncDecl(c, C.Z3_get_datatype_sort_constructor_accessor(
216 c.ptr, sort.ptr, C.uint(constructorIdx), C.uint(accessorIdx)))
219// GetDatatypeSortNumConstructors returns the number of constructors in a datatype sort.
220func (c *Context) GetDatatypeSortNumConstructors(sort *Sort) uint {
221 return uint(C.Z3_get_datatype_sort_num_constructors(c.ptr, sort.ptr))
224// Tuple sorts (special case of datatypes)
226// MkTupleSort creates a tuple sort with the given field sorts.
227func (c *Context) MkTupleSort(name string, fieldNames []string, fieldSorts []*Sort) (*Sort, *FuncDecl, []*FuncDecl) {
228 sym := c.MkStringSymbol(name)
230 numFields := uint(len(fieldNames))
231 if numFields != uint(len(fieldSorts)) {
232 panic("fieldNames and fieldSorts must have the same length")
235 fieldSyms := make([]C.Z3_symbol, numFields)
236 for i, fname := range fieldNames {
237 fieldSyms[i] = c.MkStringSymbol(fname).ptr
240 sorts := make([]C.Z3_sort, numFields)
241 for i, s := range fieldSorts {
245 var mkTupleDecl C.Z3_func_decl
246 projDecls := make([]C.Z3_func_decl, numFields)
248 tupleSort := C.Z3_mk_tuple_sort(
258 projections := make([]*FuncDecl, numFields)
259 for i := range projDecls {
260 projections[i] = newFuncDecl(c, projDecls[i])
263 return newSort(c, tupleSort), newFuncDecl(c, mkTupleDecl), projections
266// Enumeration sorts (special case of datatypes)
268// MkEnumSort creates an enumeration sort with the given constants.
269func (c *Context) MkEnumSort(name string, enumNames []string) (*Sort, []*FuncDecl, []*FuncDecl) {
270 sym := c.MkStringSymbol(name)
272 numEnums := uint(len(enumNames))
273 enumSyms := make([]C.Z3_symbol, numEnums)
274 for i, ename := range enumNames {
275 enumSyms[i] = c.MkStringSymbol(ename).ptr
278 enumConsts := make([]C.Z3_func_decl, numEnums)
279 enumTesters := make([]C.Z3_func_decl, numEnums)
281 enumSort := C.Z3_mk_enumeration_sort(
290 consts := make([]*FuncDecl, numEnums)
291 for i := range enumConsts {
292 consts[i] = newFuncDecl(c, enumConsts[i])
295 testers := make([]*FuncDecl, numEnums)
296 for i := range enumTesters {
297 testers[i] = newFuncDecl(c, enumTesters[i])
300 return newSort(c, enumSort), consts, testers
303// List sorts (special case of datatypes)
305// MkListSort creates a list sort with the given element sort.
306func (c *Context) MkListSort(name string, elemSort *Sort) (*Sort, *FuncDecl, *FuncDecl, *FuncDecl, *FuncDecl, *FuncDecl, *FuncDecl) {
307 sym := c.MkStringSymbol(name)
309 var nilDecl, consDecl, isNilDecl, isConsDecl, headDecl, tailDecl C.Z3_func_decl
311 listSort := C.Z3_mk_list_sort(
323 return newSort(c, listSort),
324 newFuncDecl(c, nilDecl),
325 newFuncDecl(c, consDecl),
326 newFuncDecl(c, isNilDecl),
327 newFuncDecl(c, isConsDecl),
328 newFuncDecl(c, headDecl),
329 newFuncDecl(c, tailDecl)