Z3
 
Loading...
Searching...
No Matches
datatype.go
Go to the documentation of this file.
1package z3
2
3/*
4#include "z3.h"
5#include <stdlib.h>
6*/
7import "C"
8import (
9 "runtime"
10 "unsafe"
11)
12
13// Constructor represents a datatype constructor.
14type Constructor struct {
15 ctx *Context
16 ptr C.Z3_constructor
17}
18
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)
26 })
27 return c
28}
29
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))
39
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")
43 }
44
45 var cFieldNames *C.Z3_symbol
46 var cSorts *C.Z3_sort
47 var cSortRefs *C.uint
48
49 if numFields > 0 {
50 fieldSyms := make([]C.Z3_symbol, numFields)
51 for i, fname := range fieldNames {
52 fieldSyms[i] = c.MkStringSymbol(fname).ptr
53 }
54 cFieldNames = &fieldSyms[0]
55
56 sorts := make([]C.Z3_sort, numFields)
57 for i, s := range fieldSorts {
58 if s != nil {
59 sorts[i] = s.ptr
60 }
61 }
62 cSorts = &sorts[0]
63
64 refs := make([]C.uint, numFields)
65 for i, r := range fieldSortRefs {
66 refs[i] = C.uint(r)
67 }
68 cSortRefs = &refs[0]
69 }
70
71 sym := c.MkStringSymbol(name)
72 recSym := c.MkStringSymbol(recognizer)
73
74 return newConstructor(c, C.Z3_mk_constructor(
75 c.ptr,
76 sym.ptr,
77 recSym.ptr,
78 C.uint(numFields),
79 cFieldNames,
80 cSorts,
81 cSortRefs,
82 ))
83}
84
85// ConstructorList represents a list of datatype constructors.
86type ConstructorList struct {
87 ctx *Context
88 ptr C.Z3_constructor_list
89}
90
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)
98 })
99 return cl
100}
101
102// MkConstructorList creates a list of constructors for a datatype.
103func (c *Context) MkConstructorList(constructors []*Constructor) *ConstructorList {
104 numCons := uint(len(constructors))
105 if numCons == 0 {
106 return nil
107 }
108
109 cons := make([]C.Z3_constructor, numCons)
110 for i, constr := range constructors {
111 cons[i] = constr.ptr
112 }
113
114 return newConstructorList(c, C.Z3_mk_constructor_list(c.ptr, C.uint(numCons), &cons[0]))
115}
116
117// MkDatatypeSort creates a datatype sort from a constructor list.
118func (c *Context) MkDatatypeSort(name string, constructors []*Constructor) *Sort {
119 sym := c.MkStringSymbol(name)
120
121 numCons := uint(len(constructors))
122 cons := make([]C.Z3_constructor, numCons)
123 for i, constr := range constructors {
124 cons[i] = constr.ptr
125 }
126
127 return newSort(c, C.Z3_mk_datatype(c.ptr, sym.ptr, C.uint(numCons), &cons[0]))
128}
129
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")
135 }
136
137 syms := make([]C.Z3_symbol, numTypes)
138 for i, name := range names {
139 syms[i] = c.MkStringSymbol(name).ptr
140 }
141
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 {
146 cons[j] = constr.ptr
147 }
148 cLists[i] = C.Z3_mk_constructor_list(c.ptr, C.uint(len(constrs)), &cons[0])
149 }
150
151 resultSorts := make([]C.Z3_sort, numTypes)
152
153 C.Z3_mk_datatypes(c.ptr, C.uint(numTypes), &syms[0], &resultSorts[0], &cLists[0])
154
155 // Clean up constructor lists
156 for i := range cLists {
157 C.Z3_del_constructor_list(c.ptr, cLists[i])
158 }
159
160 sorts := make([]*Sort, numTypes)
161 for i := range resultSorts {
162 sorts[i] = newSort(c, resultSorts[i])
163 }
164
165 return sorts
166}
167
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)))
171}
172
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)))
176}
177
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)))
182}
183
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))
187}
188
189// Tuple sorts (special case of datatypes)
190
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)
194
195 numFields := uint(len(fieldNames))
196 if numFields != uint(len(fieldSorts)) {
197 panic("fieldNames and fieldSorts must have the same length")
198 }
199
200 fieldSyms := make([]C.Z3_symbol, numFields)
201 for i, fname := range fieldNames {
202 fieldSyms[i] = c.MkStringSymbol(fname).ptr
203 }
204
205 sorts := make([]C.Z3_sort, numFields)
206 for i, s := range fieldSorts {
207 sorts[i] = s.ptr
208 }
209
210 var mkTupleDecl C.Z3_func_decl
211 projDecls := make([]C.Z3_func_decl, numFields)
212
213 tupleSort := C.Z3_mk_tuple_sort(
214 c.ptr,
215 sym.ptr,
216 C.uint(numFields),
217 &fieldSyms[0],
218 &sorts[0],
219 &mkTupleDecl,
220 &projDecls[0],
221 )
222
223 projections := make([]*FuncDecl, numFields)
224 for i := range projDecls {
225 projections[i] = newFuncDecl(c, projDecls[i])
226 }
227
228 return newSort(c, tupleSort), newFuncDecl(c, mkTupleDecl), projections
229}
230
231// Enumeration sorts (special case of datatypes)
232
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)
236
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
241 }
242
243 enumConsts := make([]C.Z3_func_decl, numEnums)
244 enumTesters := make([]C.Z3_func_decl, numEnums)
245
246 enumSort := C.Z3_mk_enumeration_sort(
247 c.ptr,
248 sym.ptr,
249 C.uint(numEnums),
250 &enumSyms[0],
251 &enumConsts[0],
252 &enumTesters[0],
253 )
254
255 consts := make([]*FuncDecl, numEnums)
256 for i := range enumConsts {
257 consts[i] = newFuncDecl(c, enumConsts[i])
258 }
259
260 testers := make([]*FuncDecl, numEnums)
261 for i := range enumTesters {
262 testers[i] = newFuncDecl(c, enumTesters[i])
263 }
264
265 return newSort(c, enumSort), consts, testers
266}
267
268// List sorts (special case of datatypes)
269
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)
273
274 var nilDecl, consDecl, isNilDecl, isConsDecl, headDecl, tailDecl C.Z3_func_decl
275
276 listSort := C.Z3_mk_list_sort(
277 c.ptr,
278 sym.ptr,
279 elemSort.ptr,
280 &nilDecl,
281 &isNilDecl,
282 &consDecl,
283 &isConsDecl,
284 &headDecl,
285 &tailDecl,
286 )
287
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)
295}