1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
|
###############################################################################
# Top contributors (to current version):
# Daniel Larraz
#
# This file is part of the cvc5 project.
#
# Copyright (c) 2009-2025 by the authors listed in the file AUTHORS
# in the top-level source directory and their institutional affiliations.
# All rights reserved. See the file COPYING in the top-level source
# directory for licensing information.
# #############################################################################
#
# "Ouroborous" test: does cvc5 read its own output?
#
# The "Ouroborous" test, named after the serpent that swallows its
# own tail, ensures that cvc5 can parse some input, output it again
# (in any of its languages) and then parse it again. The result of
# the first parse must be equal to the result of the second parse;
# both strings and expressions are compared for equality.
#
# To add a new test, simply add a call to run_test_string() under
# run_test(), below. If you don't specify an input language,
# LANG_SMTLIB_V2 is used. If your example depends on symbolic constants,
# you'll need to declare them in the "declarations" global, just
# below, in SMT-LIBv2 form (but they're good for all languages).
##
import cvc5
def parse(instr: str, input_language: str, output_language: str) -> str:
assert input_language == "smt2"
assert output_language == "smt2"
declarations = """(set-logic ALL)
(declare-sort U 0)
(declare-fun f (U) U)
(declare-fun x () U)
(declare-fun y () U)
(assert (= (f x) x))
(declare-fun a () (Array U (Array U U)))
"""
tm = cvc5.TermManager()
solver = cvc5.Solver(tm)
solver.setOption("input-language", input_language)
solver.setOption("output-language", output_language)
sm = cvc5.SymbolManager(tm)
parser = cvc5.InputParser(solver, sm)
# Parse declarations to bind symbols
parser.setStringInput(cvc5.InputLanguage.SMT_LIB_2_6, declarations, "internal-buffer")
while True:
cmd = parser.nextCommand()
if cmd.isNull():
break
# Invoke the command, which may bind symbols
cmd.invoke(solver, sm)
assert parser.done() # parser should be done
parser.setStringInput(cvc5.InputLanguage.SMT_LIB_2_6, instr, "internal-buffer")
term = parser.nextTerm()
s = str(term)
assert parser.nextTerm().isNull() # next expr should be null
return s
def translate(instr: str, input_language: str, output_language: str) -> str:
print("="*50)
print(f"translating from {input_language} to {output_language} this string:")
print(instr)
outstr = parse(instr, input_language, output_language)
print("got this:")
print(outstr)
print(f"reparsing as {output_language}")
poutstr = parse(outstr, output_language, output_language)
assert outstr == poutstr
print(f"got same expressions {outstr} and {poutstr}")
print("="*50)
return outstr
def run_test_string(instr: str, instr_language: str):
print(f"\nstarting with: {instr}\n in language {instr_language}")
smt2str = translate(instr, instr_language, "smt2")
print(f"in SMT2 : {smt2str}")
outstr = translate(smt2str, "smt2", "smt2")
print(f"to SMT2 : {outstr}\n")
assert outstr == smt2str
def run_test():
run_test_string("(= (f (f y)) x)", "smt2")
run_test_string("(= ((_ extract 2 1) (bvnot (bvadd #b000 #b011))) #b10)", "smt2")
run_test_string("((_ extract 2 0) (bvnot (bvadd (bvmul #b001 #b011) #b011)))", "smt2")
run_test()
|