pyvcg 1.0.9__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyvcg/__init__.py +0 -0
- pyvcg/driver/__init__.py +0 -0
- pyvcg/driver/cvc5_api.py +537 -0
- pyvcg/driver/cvc5_smtlib.py +422 -0
- pyvcg/driver/file_smtlib.py +357 -0
- pyvcg/graph.py +171 -0
- pyvcg/smt.py +1480 -0
- pyvcg/vcg.py +69 -0
- pyvcg/version.py +31 -0
- pyvcg-1.0.9.dist-info/LICENSE +674 -0
- pyvcg-1.0.9.dist-info/METADATA +98 -0
- pyvcg-1.0.9.dist-info/RECORD +14 -0
- pyvcg-1.0.9.dist-info/WHEEL +5 -0
- pyvcg-1.0.9.dist-info/top_level.txt +1 -0
pyvcg/__init__.py
ADDED
|
File without changes
|
pyvcg/driver/__init__.py
ADDED
|
File without changes
|
pyvcg/driver/cvc5_api.py
ADDED
|
@@ -0,0 +1,537 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
##############################################################################
|
|
3
|
+
## ##
|
|
4
|
+
## Verification Condition Generator ##
|
|
5
|
+
## ##
|
|
6
|
+
## Copyright (C) 2023-2025, Florian Schanda ##
|
|
7
|
+
## ##
|
|
8
|
+
## This file is part of PyVCG. ##
|
|
9
|
+
## ##
|
|
10
|
+
## PyVCG is free software: you can redistribute it and/or modify it ##
|
|
11
|
+
## under the terms of the GNU General Public License as published by ##
|
|
12
|
+
## the Free Software Foundation, either version 3 of the License, or ##
|
|
13
|
+
## (at your option) any later version. ##
|
|
14
|
+
## ##
|
|
15
|
+
## PyVCG is distributed in the hope that it will be useful, but ##
|
|
16
|
+
## WITHOUT ANY WARRANTY; without even the implied warranty of ##
|
|
17
|
+
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ##
|
|
18
|
+
## General Public License for more details. ##
|
|
19
|
+
## ##
|
|
20
|
+
## You should have received a copy of the GNU General Public License ##
|
|
21
|
+
## along with PyVCG. If not, see <http://www.gnu.org/licenses/>. ##
|
|
22
|
+
## ##
|
|
23
|
+
##############################################################################
|
|
24
|
+
|
|
25
|
+
import cvc5
|
|
26
|
+
|
|
27
|
+
from pyvcg import smt
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class CVC5_Solver(smt.VC_Solver):
|
|
31
|
+
def __init__(self):
|
|
32
|
+
self.solver = cvc5.Solver()
|
|
33
|
+
self.result = None
|
|
34
|
+
self.values = {}
|
|
35
|
+
|
|
36
|
+
self.const_mapping = {}
|
|
37
|
+
self.var_mapping = {}
|
|
38
|
+
self.enum_mapping = {}
|
|
39
|
+
self.literal_mapping = {}
|
|
40
|
+
self.function_mapping = {}
|
|
41
|
+
self.sort_mapping = {}
|
|
42
|
+
self.record_mapping = {}
|
|
43
|
+
self.user_functions = {}
|
|
44
|
+
|
|
45
|
+
self.relevant_values = []
|
|
46
|
+
|
|
47
|
+
def term_to_python(self, sort, term):
|
|
48
|
+
assert isinstance(sort, smt.Sort)
|
|
49
|
+
assert isinstance(term, cvc5.Term)
|
|
50
|
+
|
|
51
|
+
if isinstance(sort, smt.Enumeration):
|
|
52
|
+
rv = str(term)
|
|
53
|
+
if rv.startswith("|"):
|
|
54
|
+
rv = rv[1:-1]
|
|
55
|
+
return rv
|
|
56
|
+
elif isinstance(sort, smt.Record):
|
|
57
|
+
assert term.getKind() == cvc5.Kind.APPLY_CONSTRUCTOR
|
|
58
|
+
cons_name = term[0].getSymbol()
|
|
59
|
+
assert isinstance(cons_name, str)
|
|
60
|
+
assert cons_name.endswith("__cons") or cons_name.endswith("__null")
|
|
61
|
+
if cons_name.endswith("__null"):
|
|
62
|
+
assert sort.is_recursive
|
|
63
|
+
return None
|
|
64
|
+
else:
|
|
65
|
+
rv = {}
|
|
66
|
+
for idx, name in enumerate(sort.components, 1):
|
|
67
|
+
rv[name] = self.term_to_python(sort.components[name],
|
|
68
|
+
term[idx])
|
|
69
|
+
return rv
|
|
70
|
+
elif sort.name == "Bool":
|
|
71
|
+
return term.getBooleanValue()
|
|
72
|
+
elif sort.name == "Int":
|
|
73
|
+
return term.getIntegerValue()
|
|
74
|
+
elif sort.name == "Real":
|
|
75
|
+
if term.isRealValue():
|
|
76
|
+
return term.getRealValue()
|
|
77
|
+
else: # pragma: no cover
|
|
78
|
+
return None
|
|
79
|
+
elif sort.name == "String":
|
|
80
|
+
return term.getStringValue()
|
|
81
|
+
elif sort.name == "Seq":
|
|
82
|
+
return [self.term_to_python(sort.element_sort(), t)
|
|
83
|
+
for t in term.getSequenceValue()]
|
|
84
|
+
else:
|
|
85
|
+
assert False, (term.getKind(), term.__class__.__name__)
|
|
86
|
+
|
|
87
|
+
def set_solver_option(self, name, value):
|
|
88
|
+
assert isinstance(name, str)
|
|
89
|
+
assert isinstance(value, (bool, int, str))
|
|
90
|
+
if isinstance(value, bool):
|
|
91
|
+
self.solver.setOption(name, str(value).lower())
|
|
92
|
+
else:
|
|
93
|
+
self.solver.setOption(name, str(value))
|
|
94
|
+
|
|
95
|
+
def solve(self):
|
|
96
|
+
result = self.solver.checkSat()
|
|
97
|
+
if result.isSat():
|
|
98
|
+
self.result = "sat"
|
|
99
|
+
elif result.isUnsat():
|
|
100
|
+
self.result = "unsat"
|
|
101
|
+
return
|
|
102
|
+
else: # pragma: no cover
|
|
103
|
+
self.result = "unknown"
|
|
104
|
+
|
|
105
|
+
for constant in self.relevant_values:
|
|
106
|
+
value = self.solver.getValue(self.const_mapping[constant])
|
|
107
|
+
self.values[constant.name] = self.term_to_python(constant.sort,
|
|
108
|
+
value)
|
|
109
|
+
|
|
110
|
+
def get_status(self):
|
|
111
|
+
assert self.result is not None
|
|
112
|
+
return self.result
|
|
113
|
+
|
|
114
|
+
def get_values(self):
|
|
115
|
+
assert self.result is not None
|
|
116
|
+
return self.values
|
|
117
|
+
|
|
118
|
+
def visit_script(self, node, logic, functions):
|
|
119
|
+
assert isinstance(node, smt.Script)
|
|
120
|
+
assert isinstance(logic, str)
|
|
121
|
+
assert isinstance(functions, set)
|
|
122
|
+
assert all(isinstance(function, str)
|
|
123
|
+
for function in functions)
|
|
124
|
+
|
|
125
|
+
self.solver.setOption("produce-models", "true")
|
|
126
|
+
self.solver.setLogic(logic)
|
|
127
|
+
|
|
128
|
+
for function in functions:
|
|
129
|
+
if function == "floor_div":
|
|
130
|
+
lhs = self.solver.mkVar(self.solver.getIntegerSort(),
|
|
131
|
+
"lhs")
|
|
132
|
+
rhs = self.solver.mkVar(self.solver.getIntegerSort(),
|
|
133
|
+
"rhs")
|
|
134
|
+
fun = self.solver.defineFun(
|
|
135
|
+
function,
|
|
136
|
+
[lhs, rhs],
|
|
137
|
+
self.solver.getIntegerSort(),
|
|
138
|
+
self.solver.mkTerm(
|
|
139
|
+
cvc5.Kind.ITE,
|
|
140
|
+
self.solver.mkTerm(cvc5.Kind.LT,
|
|
141
|
+
rhs,
|
|
142
|
+
self.solver.mkInteger(0)),
|
|
143
|
+
self.solver.mkTerm(cvc5.Kind.INTS_DIVISION,
|
|
144
|
+
self.solver.mkTerm(cvc5.Kind.NEG,
|
|
145
|
+
lhs),
|
|
146
|
+
self.solver.mkTerm(cvc5.Kind.NEG,
|
|
147
|
+
rhs)),
|
|
148
|
+
self.solver.mkTerm(cvc5.Kind.INTS_DIVISION,
|
|
149
|
+
lhs,
|
|
150
|
+
rhs)))
|
|
151
|
+
|
|
152
|
+
elif function == "ada_remainder":
|
|
153
|
+
lhs = self.solver.mkVar(self.solver.getIntegerSort(),
|
|
154
|
+
"lhs")
|
|
155
|
+
rhs = self.solver.mkVar(self.solver.getIntegerSort(),
|
|
156
|
+
"rhs")
|
|
157
|
+
fun = self.solver.defineFun(
|
|
158
|
+
function,
|
|
159
|
+
[lhs, rhs],
|
|
160
|
+
self.solver.getIntegerSort(),
|
|
161
|
+
self.solver.mkTerm(
|
|
162
|
+
cvc5.Kind.ITE,
|
|
163
|
+
self.solver.mkTerm(cvc5.Kind.LT,
|
|
164
|
+
lhs,
|
|
165
|
+
self.solver.mkInteger(0)),
|
|
166
|
+
self.solver.mkTerm(
|
|
167
|
+
cvc5.Kind.NEG,
|
|
168
|
+
self.solver.mkTerm(
|
|
169
|
+
cvc5.Kind.INTS_MODULUS,
|
|
170
|
+
self.solver.mkTerm(cvc5.Kind.NEG, lhs),
|
|
171
|
+
rhs)),
|
|
172
|
+
self.solver.mkTerm(cvc5.Kind.INTS_MODULUS,
|
|
173
|
+
lhs,
|
|
174
|
+
rhs)))
|
|
175
|
+
|
|
176
|
+
elif function == "to_int_rna":
|
|
177
|
+
val = self.solver.mkVar(self.solver.getRealSort(),
|
|
178
|
+
"value")
|
|
179
|
+
fun = self.solver.defineFun(
|
|
180
|
+
function,
|
|
181
|
+
[val],
|
|
182
|
+
self.solver.getIntegerSort(),
|
|
183
|
+
self.solver.mkTerm(
|
|
184
|
+
cvc5.Kind.ITE,
|
|
185
|
+
self.solver.mkTerm(cvc5.Kind.GEQ,
|
|
186
|
+
val,
|
|
187
|
+
self.solver.mkReal(0, 1)),
|
|
188
|
+
self.solver.mkTerm(
|
|
189
|
+
cvc5.Kind.TO_INTEGER,
|
|
190
|
+
self.solver.mkTerm(
|
|
191
|
+
cvc5.Kind.ADD,
|
|
192
|
+
val,
|
|
193
|
+
self.solver.mkReal(1, 2))),
|
|
194
|
+
self.solver.mkTerm(
|
|
195
|
+
cvc5.Kind.NEG,
|
|
196
|
+
self.solver.mkTerm(
|
|
197
|
+
cvc5.Kind.TO_INTEGER,
|
|
198
|
+
self.solver.mkTerm(
|
|
199
|
+
cvc5.Kind.SUB,
|
|
200
|
+
self.solver.mkReal(1, 2),
|
|
201
|
+
val)))))
|
|
202
|
+
|
|
203
|
+
else:
|
|
204
|
+
assert False, function
|
|
205
|
+
|
|
206
|
+
self.function_mapping[function] = fun
|
|
207
|
+
|
|
208
|
+
for statement in node.statements:
|
|
209
|
+
statement.walk(self)
|
|
210
|
+
|
|
211
|
+
def visit_constant_declaration(self, node, tr_symbol, tr_value):
|
|
212
|
+
assert isinstance(node, smt.Constant_Declaration)
|
|
213
|
+
assert node.symbol in self.const_mapping
|
|
214
|
+
|
|
215
|
+
if tr_value is not None:
|
|
216
|
+
self.solver.assertFormula(
|
|
217
|
+
self.solver.mkTerm(cvc5.Kind.EQUAL, tr_symbol, tr_value))
|
|
218
|
+
|
|
219
|
+
if node.is_relevant:
|
|
220
|
+
self.relevant_values.append(node.symbol)
|
|
221
|
+
|
|
222
|
+
def visit_function_declaration(self, node, tr_sort, tr_body):
|
|
223
|
+
assert isinstance(node, smt.Function_Declaration)
|
|
224
|
+
|
|
225
|
+
if tr_body is None:
|
|
226
|
+
tr_params = [par.sort.walk(self)
|
|
227
|
+
for par in node.function.parameters]
|
|
228
|
+
fun = self.solver.declareFun(node.function.name,
|
|
229
|
+
tr_params,
|
|
230
|
+
tr_sort)
|
|
231
|
+
|
|
232
|
+
else:
|
|
233
|
+
tr_params = [par.walk(self)
|
|
234
|
+
for par in node.function.parameters]
|
|
235
|
+
fun = self.solver.defineFun(node.function.name,
|
|
236
|
+
tr_params,
|
|
237
|
+
tr_sort,
|
|
238
|
+
tr_body)
|
|
239
|
+
|
|
240
|
+
self.user_functions[node.function] = fun
|
|
241
|
+
|
|
242
|
+
def visit_assertion(self, node, tr_expression):
|
|
243
|
+
assert isinstance(node, smt.Assertion)
|
|
244
|
+
|
|
245
|
+
self.solver.assertFormula(tr_expression)
|
|
246
|
+
|
|
247
|
+
def visit_enumeration_declaration(self, node):
|
|
248
|
+
assert isinstance(node, smt.Enumeration_Declaration)
|
|
249
|
+
|
|
250
|
+
ctors = [self.solver.mkDatatypeConstructorDecl(literal)
|
|
251
|
+
for literal in node.sort.literals]
|
|
252
|
+
|
|
253
|
+
sort = self.solver.declareDatatype(node.sort.name, *ctors)
|
|
254
|
+
self.enum_mapping[node.sort] = sort
|
|
255
|
+
|
|
256
|
+
datatype = sort.getDatatype()
|
|
257
|
+
self.literal_mapping[node.sort] = {
|
|
258
|
+
literal: datatype.getConstructor(literal).getTerm()
|
|
259
|
+
for literal in node.sort.literals
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
def visit_record_declaration(self, node):
|
|
263
|
+
assert isinstance(node, smt.Record_Declaration)
|
|
264
|
+
|
|
265
|
+
ctor = self.solver.mkDatatypeConstructorDecl(node.sort.name +
|
|
266
|
+
"__cons")
|
|
267
|
+
for name, sort in node.sort.components.items():
|
|
268
|
+
if sort is node.sort:
|
|
269
|
+
ctor.addSelectorSelf(name)
|
|
270
|
+
else:
|
|
271
|
+
ctor.addSelector(name, sort.walk(self))
|
|
272
|
+
|
|
273
|
+
if node.sort.is_recursive:
|
|
274
|
+
null_ctor = self.solver.mkDatatypeConstructorDecl(node.sort.name +
|
|
275
|
+
"__null")
|
|
276
|
+
sort = self.solver.declareDatatype(node.sort.name,
|
|
277
|
+
null_ctor,
|
|
278
|
+
ctor)
|
|
279
|
+
else:
|
|
280
|
+
sort = self.solver.declareDatatype(node.sort.name, ctor)
|
|
281
|
+
self.record_mapping[node.sort] = sort
|
|
282
|
+
|
|
283
|
+
def visit_sort(self, node):
|
|
284
|
+
assert isinstance(node, smt.Sort)
|
|
285
|
+
|
|
286
|
+
if node.name == "Bool":
|
|
287
|
+
return self.solver.getBooleanSort()
|
|
288
|
+
elif node.name == "Int":
|
|
289
|
+
return self.solver.getIntegerSort()
|
|
290
|
+
elif node.name == "Real":
|
|
291
|
+
return self.solver.getRealSort()
|
|
292
|
+
elif node.name == "String":
|
|
293
|
+
return self.solver.getStringSort()
|
|
294
|
+
else:
|
|
295
|
+
assert False
|
|
296
|
+
|
|
297
|
+
def visit_parametric_sort(self, node, tr_parameters):
|
|
298
|
+
assert isinstance(node, smt.Parametric_Sort)
|
|
299
|
+
assert isinstance(tr_parameters, list)
|
|
300
|
+
|
|
301
|
+
if node not in self.sort_mapping:
|
|
302
|
+
if node.name == "Seq":
|
|
303
|
+
assert len(tr_parameters) == 1
|
|
304
|
+
self.sort_mapping[node] = \
|
|
305
|
+
self.solver.mkSequenceSort(tr_parameters[0])
|
|
306
|
+
else:
|
|
307
|
+
assert False
|
|
308
|
+
|
|
309
|
+
return self.sort_mapping[node]
|
|
310
|
+
|
|
311
|
+
def visit_function(self, node):
|
|
312
|
+
assert isinstance(node, smt.Function)
|
|
313
|
+
return self.user_functions[node]
|
|
314
|
+
|
|
315
|
+
def visit_enumeration(self, node):
|
|
316
|
+
assert isinstance(node, smt.Enumeration)
|
|
317
|
+
return self.enum_mapping[node]
|
|
318
|
+
|
|
319
|
+
def visit_record(self, node):
|
|
320
|
+
assert isinstance(node, smt.Record)
|
|
321
|
+
return self.record_mapping[node]
|
|
322
|
+
|
|
323
|
+
def visit_boolean_literal(self, node, tr_sort):
|
|
324
|
+
assert isinstance(node, smt.Boolean_Literal)
|
|
325
|
+
return self.solver.mkBoolean(node.value)
|
|
326
|
+
|
|
327
|
+
def visit_integer_literal(self, node, tr_sort):
|
|
328
|
+
assert isinstance(node, smt.Integer_Literal)
|
|
329
|
+
return self.solver.mkInteger(node.value)
|
|
330
|
+
|
|
331
|
+
def visit_real_literal(self, node, tr_sort):
|
|
332
|
+
assert isinstance(node, smt.Real_Literal)
|
|
333
|
+
num, den = node.value.as_integer_ratio()
|
|
334
|
+
return self.solver.mkReal(num, den)
|
|
335
|
+
|
|
336
|
+
def visit_enumeration_literal(self, node, tr_sort):
|
|
337
|
+
assert isinstance(node, smt.Enumeration_Literal)
|
|
338
|
+
cons = self.literal_mapping[node.sort][node.value]
|
|
339
|
+
return self.solver.mkTerm(cvc5.Kind.APPLY_CONSTRUCTOR, cons)
|
|
340
|
+
|
|
341
|
+
def visit_string_literal(self, node, tr_sort):
|
|
342
|
+
assert isinstance(node, smt.String_Literal)
|
|
343
|
+
return self.solver.mkString(node.value)
|
|
344
|
+
|
|
345
|
+
def visit_constant(self, node, tr_sort):
|
|
346
|
+
assert isinstance(node, smt.Constant)
|
|
347
|
+
|
|
348
|
+
if node not in self.const_mapping:
|
|
349
|
+
self.const_mapping[node] = self.solver.mkConst(tr_sort, node.name)
|
|
350
|
+
|
|
351
|
+
return self.const_mapping[node]
|
|
352
|
+
|
|
353
|
+
def visit_bound_variable(self, node, tr_sort):
|
|
354
|
+
assert isinstance(node, smt.Bound_Variable)
|
|
355
|
+
|
|
356
|
+
if node not in self.var_mapping:
|
|
357
|
+
self.var_mapping[node] = self.solver.mkVar(tr_sort, node.name)
|
|
358
|
+
|
|
359
|
+
return self.var_mapping[node]
|
|
360
|
+
|
|
361
|
+
def visit_boolean_negation(self, node, tr_sort, tr_expression):
|
|
362
|
+
assert isinstance(node, smt.Boolean_Negation)
|
|
363
|
+
|
|
364
|
+
return tr_expression.notTerm()
|
|
365
|
+
|
|
366
|
+
def visit_conjunction(self, node, tr_sort, tr_terms):
|
|
367
|
+
assert isinstance(node, smt.Conjunction)
|
|
368
|
+
assert isinstance(tr_terms, list)
|
|
369
|
+
|
|
370
|
+
return self.solver.mkTerm(cvc5.Kind.AND, *tr_terms)
|
|
371
|
+
|
|
372
|
+
def visit_disjunction(self, node, tr_sort, tr_terms):
|
|
373
|
+
assert isinstance(node, smt.Disjunction)
|
|
374
|
+
assert isinstance(tr_terms, list)
|
|
375
|
+
|
|
376
|
+
return self.solver.mkTerm(cvc5.Kind.OR, *tr_terms)
|
|
377
|
+
|
|
378
|
+
def visit_exclusive_disjunction(self, node, tr_sort, tr_lhs, tr_rhs):
|
|
379
|
+
assert isinstance(node, smt.Exclusive_Disjunction)
|
|
380
|
+
|
|
381
|
+
return self.solver.mkTerm(cvc5.Kind.XOR, tr_lhs, tr_rhs)
|
|
382
|
+
|
|
383
|
+
def visit_implication(self, node, tr_sort, tr_lhs, tr_rhs):
|
|
384
|
+
assert isinstance(node, smt.Implication)
|
|
385
|
+
|
|
386
|
+
return self.solver.mkTerm(cvc5.Kind.IMPLIES, tr_lhs, tr_rhs)
|
|
387
|
+
|
|
388
|
+
def visit_comparison(self, node, tr_lhs, tr_rhs):
|
|
389
|
+
assert isinstance(node, smt.Comparison)
|
|
390
|
+
|
|
391
|
+
kind = {"<" : cvc5.Kind.LT,
|
|
392
|
+
"<=" : cvc5.Kind.LEQ,
|
|
393
|
+
">" : cvc5.Kind.GT,
|
|
394
|
+
">=" : cvc5.Kind.GEQ,
|
|
395
|
+
"=" : cvc5.Kind.EQUAL}
|
|
396
|
+
|
|
397
|
+
return self.solver.mkTerm(kind[node.operator], tr_lhs, tr_rhs)
|
|
398
|
+
|
|
399
|
+
def visit_conversion_to_real(self, node, tr_value):
|
|
400
|
+
assert isinstance(node, smt.Conversion_To_Real)
|
|
401
|
+
return self.solver.mkTerm(cvc5.Kind.TO_REAL, tr_value)
|
|
402
|
+
|
|
403
|
+
def visit_conversion_to_integer(self, node, tr_value):
|
|
404
|
+
assert isinstance(node, smt.Conversion_To_Integer)
|
|
405
|
+
if node.rounding == "rtn":
|
|
406
|
+
return self.solver.mkTerm(cvc5.Kind.TO_INTEGER, tr_value)
|
|
407
|
+
else:
|
|
408
|
+
assert node.rounding == "rna"
|
|
409
|
+
return self.solver.mkTerm(cvc5.Kind.APPLY_UF,
|
|
410
|
+
self.function_mapping["to_int_rna"],
|
|
411
|
+
tr_value)
|
|
412
|
+
|
|
413
|
+
def visit_unary_int_arithmetic_op(self, node, tr_operand):
|
|
414
|
+
assert isinstance(node, smt.Unary_Int_Arithmetic_Op)
|
|
415
|
+
|
|
416
|
+
kind = {"-" : cvc5.Kind.NEG,
|
|
417
|
+
"abs" : cvc5.Kind.ABS}
|
|
418
|
+
|
|
419
|
+
return self.solver.mkTerm(kind[node.operator], tr_operand)
|
|
420
|
+
|
|
421
|
+
def visit_unary_real_arithmetic_op(self, node, tr_operand):
|
|
422
|
+
assert isinstance(node, smt.Unary_Real_Arithmetic_Op)
|
|
423
|
+
|
|
424
|
+
kind = {"-" : cvc5.Kind.NEG,
|
|
425
|
+
"abs" : cvc5.Kind.ABS}
|
|
426
|
+
|
|
427
|
+
return self.solver.mkTerm(kind[node.operator], tr_operand)
|
|
428
|
+
|
|
429
|
+
def visit_binary_int_arithmetic_op(self, node, tr_lhs, tr_rhs):
|
|
430
|
+
assert isinstance(node, smt.Binary_Int_Arithmetic_Op)
|
|
431
|
+
|
|
432
|
+
if node.operator in ("floor_div", "ada_remainder"):
|
|
433
|
+
return self.solver.mkTerm(cvc5.Kind.APPLY_UF,
|
|
434
|
+
self.function_mapping[node.operator],
|
|
435
|
+
tr_lhs,
|
|
436
|
+
tr_rhs)
|
|
437
|
+
|
|
438
|
+
kind = {"+" : cvc5.Kind.ADD,
|
|
439
|
+
"-" : cvc5.Kind.SUB,
|
|
440
|
+
"*" : cvc5.Kind.MULT,
|
|
441
|
+
"div" : cvc5.Kind.INTS_DIVISION,
|
|
442
|
+
"mod" : cvc5.Kind.INTS_MODULUS}
|
|
443
|
+
|
|
444
|
+
return self.solver.mkTerm(kind[node.operator], tr_lhs, tr_rhs)
|
|
445
|
+
|
|
446
|
+
def visit_binary_real_arithmetic_op(self, node, tr_lhs, tr_rhs):
|
|
447
|
+
assert isinstance(node, smt.Binary_Real_Arithmetic_Op)
|
|
448
|
+
|
|
449
|
+
kind = {"+" : cvc5.Kind.ADD,
|
|
450
|
+
"-" : cvc5.Kind.SUB,
|
|
451
|
+
"*" : cvc5.Kind.MULT,
|
|
452
|
+
"/" : cvc5.Kind.DIVISION}
|
|
453
|
+
|
|
454
|
+
return self.solver.mkTerm(kind[node.operator], tr_lhs, tr_rhs)
|
|
455
|
+
|
|
456
|
+
def visit_string_length(self, node, tr_string):
|
|
457
|
+
assert isinstance(node, smt.String_Length)
|
|
458
|
+
return self.solver.mkTerm(cvc5.Kind.STRING_LENGTH, tr_string)
|
|
459
|
+
|
|
460
|
+
def visit_string_predicate(self, node, tr_first, tr_second):
|
|
461
|
+
assert isinstance(node, smt.String_Predicate)
|
|
462
|
+
|
|
463
|
+
kind = {"contains" : cvc5.Kind.STRING_CONTAINS,
|
|
464
|
+
"prefixof" : cvc5.Kind.STRING_PREFIX,
|
|
465
|
+
"suffixof" : cvc5.Kind.STRING_SUFFIX}
|
|
466
|
+
|
|
467
|
+
return self.solver.mkTerm(kind[node.operation],
|
|
468
|
+
tr_first,
|
|
469
|
+
tr_second)
|
|
470
|
+
|
|
471
|
+
def visit_string_concatenation(self, node, tr_lhs, tr_rhs):
|
|
472
|
+
assert isinstance(node, smt.String_Concatenation)
|
|
473
|
+
return self.solver.mkTerm(cvc5.Kind.STRING_CONCAT, tr_lhs, tr_rhs)
|
|
474
|
+
|
|
475
|
+
def visit_sequence_length(self, node, tr_sequence):
|
|
476
|
+
assert isinstance(node, smt.Sequence_Length)
|
|
477
|
+
return self.solver.mkTerm(cvc5.Kind.SEQ_LENGTH, tr_sequence)
|
|
478
|
+
|
|
479
|
+
def visit_sequence_index(self, node, tr_sequence, tr_index):
|
|
480
|
+
assert isinstance(node, smt.Sequence_Index)
|
|
481
|
+
return self.solver.mkTerm(cvc5.Kind.SEQ_NTH, tr_sequence, tr_index)
|
|
482
|
+
|
|
483
|
+
def visit_sequence_contains(self, node, tr_sequence, tr_item):
|
|
484
|
+
assert isinstance(node, smt.Sequence_Contains)
|
|
485
|
+
return self.solver.mkTerm(cvc5.Kind.SEQ_CONTAINS,
|
|
486
|
+
tr_sequence,
|
|
487
|
+
self.solver.mkTerm(cvc5.Kind.SEQ_UNIT,
|
|
488
|
+
tr_item))
|
|
489
|
+
|
|
490
|
+
def visit_sequence_concatenation(self, node, tr_lhs, tr_rhs):
|
|
491
|
+
assert isinstance(node, smt.Sequence_Concatenation)
|
|
492
|
+
return self.solver.mkTerm(cvc5.Kind.SEQ_CONCAT, tr_lhs, tr_rhs)
|
|
493
|
+
|
|
494
|
+
def visit_record_access(self, node, tr_record):
|
|
495
|
+
assert isinstance(node, smt.Record_Access)
|
|
496
|
+
assert node.record.sort in self.record_mapping
|
|
497
|
+
s_record_sort = self.record_mapping[node.record.sort]
|
|
498
|
+
s_selector = s_record_sort.getDatatype().getSelector(node.component)
|
|
499
|
+
return self.solver.mkTerm(cvc5.Kind.APPLY_SELECTOR,
|
|
500
|
+
s_selector.getTerm(),
|
|
501
|
+
tr_record)
|
|
502
|
+
|
|
503
|
+
def visit_record_null_check(self, node, tr_record):
|
|
504
|
+
assert isinstance(node, smt.Record_Null_Check)
|
|
505
|
+
s_record_sort = self.record_mapping[node.record.sort]
|
|
506
|
+
s_dt = s_record_sort.getDatatype()
|
|
507
|
+
s_cons = s_dt.getConstructor(node.record.sort.name + "__null")
|
|
508
|
+
return self.solver.mkTerm(
|
|
509
|
+
cvc5.Kind.APPLY_TESTER,
|
|
510
|
+
s_cons.getTesterTerm(),
|
|
511
|
+
tr_record)
|
|
512
|
+
|
|
513
|
+
def visit_function_application(self, node, tr_function, tr_args):
|
|
514
|
+
assert isinstance(node, smt.Function_Application)
|
|
515
|
+
assert isinstance(tr_args, list)
|
|
516
|
+
|
|
517
|
+
return self.solver.mkTerm(cvc5.Kind.APPLY_UF,
|
|
518
|
+
tr_function,
|
|
519
|
+
*tr_args)
|
|
520
|
+
|
|
521
|
+
def visit_conditional(self, node, tr_condition, tr_true, tr_false):
|
|
522
|
+
assert isinstance(node, smt.Conditional)
|
|
523
|
+
return self.solver.mkTerm(cvc5.Kind.ITE,
|
|
524
|
+
tr_condition,
|
|
525
|
+
tr_true,
|
|
526
|
+
tr_false)
|
|
527
|
+
|
|
528
|
+
def visit_quantifier(self, node, tr_variables, tr_body):
|
|
529
|
+
assert isinstance(node, smt.Quantifier)
|
|
530
|
+
|
|
531
|
+
kind = {"forall" : cvc5.Kind.FORALL,
|
|
532
|
+
"exists" : cvc5.Kind.EXISTS}
|
|
533
|
+
|
|
534
|
+
return self.solver.mkTerm(kind[node.kind],
|
|
535
|
+
self.solver.mkTerm(cvc5.Kind.VARIABLE_LIST,
|
|
536
|
+
*tr_variables),
|
|
537
|
+
tr_body)
|