1#![cfg_attr(feature = "nightly", feature(rustc_private))]
5
6#[cfg(feature = "nightly")]
7extern crate rustc_data_structures;
8#[cfg(feature = "nightly")]
9extern crate rustc_macros;
10#[cfg(feature = "nightly")]
11extern crate rustc_serialize;
12#[cfg(feature = "nightly")]
13extern crate rustc_span;
14
15mod constraint;
16#[cfg(feature = "rust-fixpoint")]
17mod constraint_fragments;
18#[cfg(feature = "rust-fixpoint")]
19mod constraint_solving;
20#[cfg(any(feature = "rust-fixpoint", feature = "suggestions"))]
21mod constraint_with_env;
22#[cfg(any(feature = "rust-fixpoint", feature = "suggestions"))]
23mod cstr2smt2;
24mod format;
25#[cfg(any(feature = "rust-fixpoint", feature = "suggestions"))]
26mod graph;
27pub mod parser;
28pub mod sexp;
29pub mod smt_horn;
30
31use std::{
32 collections::{HashMap, hash_map::DefaultHasher},
33 fmt::{self, Debug},
34 hash::{Hash, Hasher},
35 io,
36 str::FromStr,
37};
38#[cfg(not(feature = "rust-fixpoint"))]
39use std::{
40 io::{BufWriter, Write as IOWrite},
41 process::{Command, Stdio},
42};
43
44pub use constraint::{
45 BinOp, BinRel, Bind, Constant, Constraint, DataCtor, DataDecl, DataField, Expr, FlatConstraint,
46 FunSort, Pred, QualParam, Qualifier, Quantifier, Sort, SortCtor, SortDecl, WKVar,
47};
48use derive_where::derive_where;
49#[cfg(feature = "nightly")]
50use rustc_macros::{Decodable, Encodable};
51use serde::{Deserialize, Serialize, de};
52
53pub type Assignments<'a, T> = HashMap<<T as Types>::KVar, Vec<(&'a Qualifier<T>, Vec<usize>)>>;
55
56#[cfg(feature = "rust-fixpoint")]
57use crate::constraint_with_env::ConstraintWithEnv;
58#[cfg(feature = "suggestions")]
59use crate::constraint_with_env::topo_sort_data_declarations;
60
61pub trait Types {
62 type Sort: Identifier + Hash + Clone + Debug + Eq;
63 type KVar: Identifier + Hash + Clone + Debug + Eq;
64 type Var: Identifier + Hash + Clone + Debug + Eq;
65 type String: FixpointFmt + Hash + Clone + Debug + Eq;
66 type Real: FixpointFmt + Hash + Clone + Debug + Eq;
67 type Tag: fmt::Display + FromStr + Hash + Clone + Debug;
68}
69
70pub trait FixpointFmt: Sized {
71 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result;
72
73 fn display(&self) -> impl fmt::Display {
75 struct DisplayAdapter<T>(T);
76 impl<T: FixpointFmt> std::fmt::Display for DisplayAdapter<&T> {
77 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
78 FixpointFmt::fmt(self.0, f)
79 }
80 }
81 DisplayAdapter(self)
82 }
83}
84
85pub trait Identifier: Sized {
86 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result;
87
88 fn display(&self) -> impl fmt::Display {
90 struct DisplayAdapter<T>(T);
91 impl<T: Identifier> fmt::Display for DisplayAdapter<&T> {
92 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
93 Identifier::fmt(self.0, f)
94 }
95 }
96 DisplayAdapter(self)
97 }
98}
99
100impl Identifier for &str {
101 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
102 write!(f, "{self}")
103 }
104}
105
106impl FixpointFmt for u32 {
107 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
108 write!(f, "{self}")
109 }
110}
111
112impl FixpointFmt for String {
113 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
114 write!(f, "\"{self}\"")
115 }
116}
117
118#[macro_export]
119macro_rules! declare_types {
120 ( type Sort = $sort:ty;
121 type KVar = $kvar:ty;
122 type Var = $var:ty;
123 type String = $str:ty;
124 type Real = $real:ty;
125 type Tag = $tag:ty;
126 ) => {
127 pub mod fixpoint_generated {
128 pub struct FixpointTypes;
129 pub type Expr = $crate::Expr<FixpointTypes>;
130 pub type Constraint = $crate::Constraint<FixpointTypes>;
131 pub type FlatConstraint = $crate::FlatConstraint<FixpointTypes>;
132 pub type KVarDecl = $crate::KVarDecl<FixpointTypes>;
133 pub type ConstDecl = $crate::ConstDecl<FixpointTypes>;
134 pub type FunDef = $crate::FunDef<FixpointTypes>;
135 pub type FunSort = $crate::FunSort<FixpointTypes>;
136 pub type FunBody = $crate::FunBody<FixpointTypes>;
137 pub type Task = $crate::Task<FixpointTypes>;
138 pub type Qualifier = $crate::Qualifier<FixpointTypes>;
139 pub type QualParam = $crate::QualParam<FixpointTypes>;
140 pub type Sort = $crate::Sort<FixpointTypes>;
141 pub type SortCtor = $crate::SortCtor<FixpointTypes>;
142 pub type SortDecl = $crate::SortDecl<FixpointTypes>;
143 pub type DataDecl = $crate::DataDecl<FixpointTypes>;
144 pub type DataCtor = $crate::DataCtor<FixpointTypes>;
145 pub type DataField = $crate::DataField<FixpointTypes>;
146 pub type Bind = $crate::Bind<FixpointTypes>;
147 pub type Constant = $crate::Constant<FixpointTypes>;
148 pub type Pred = $crate::Pred<FixpointTypes>;
149 pub use $crate::{BinOp, BinRel, Quantifier, ThyFunc, WKVar};
150 }
151
152 impl $crate::Types for fixpoint_generated::FixpointTypes {
153 type Sort = $sort;
154 type KVar = $kvar;
155 type Var = $var;
156 type String = $str;
157 type Real = $real;
158 type Tag = $tag;
159 }
160 };
161}
162
163#[cfg(feature = "suggestions")]
164pub fn qe_and_simplify<T: Types>(
165 constraint: &FlatConstraint<T>,
166 binder_consts: &Vec<ConstDecl<T>>,
167 global_consts: &Vec<ConstDecl<T>>,
168 datatype_decls: Vec<DataDecl<T>>,
169) -> Result<Expr<T>, cstr2smt2::Z3DecodeError> {
170 let datatype_decls = topo_sort_data_declarations(datatype_decls);
173 cstr2smt2::qe_and_simplify(constraint, binder_consts, global_consts, &datatype_decls)
174}
175
176#[cfg(feature = "suggestions")]
177pub fn check_validity<T: Types>(
178 constraint: &FlatConstraint<T>,
179 binder_consts: &Vec<ConstDecl<T>>,
180 global_consts: &Vec<ConstDecl<T>>,
181 datatype_decls: Vec<DataDecl<T>>,
182) -> bool {
183 let datatype_decls = topo_sort_data_declarations(datatype_decls);
184 cstr2smt2::check_validity(constraint, binder_consts, global_consts, &datatype_decls)
185}
186
187#[derive_where(Hash, Clone, Debug)]
188pub struct ConstDecl<T: Types> {
189 pub name: T::Var,
190 pub sort: Sort<T>,
191 #[derive_where(skip)]
192 pub comment: Option<String>,
193}
194
195#[derive_where(Hash, Debug)]
196pub struct FunDef<T: Types> {
197 pub name: T::Var,
198 pub sort: FunSort<T>,
199 pub body: Option<FunBody<T>>,
200 #[derive_where(skip)]
201 pub comment: Option<String>,
202}
203
204#[derive_where(Hash, Debug)]
205pub struct FunBody<T: Types> {
206 pub args: Vec<T::Var>,
207 pub expr: Expr<T>,
208}
209
210#[derive_where(Hash)]
211pub struct Task<T: Types> {
212 #[derive_where(skip)]
213 pub comments: Vec<String>,
214 pub constants: Vec<ConstDecl<T>>,
215 pub data_decls: Vec<DataDecl<T>>,
216 pub define_funs: Vec<FunDef<T>>,
217 pub kvars: Vec<KVarDecl<T>>,
218 pub constraint: Constraint<T>,
219 pub qualifiers: Vec<Qualifier<T>>,
220 pub scrape_quals: bool,
221 pub solver: SmtSolver,
222}
223
224#[derive(Clone, Copy, Hash)]
225pub enum SmtSolver {
226 Z3,
227 CVC5,
228}
229
230impl fmt::Display for SmtSolver {
231 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
232 match self {
233 SmtSolver::Z3 => write!(f, "z3"),
234 SmtSolver::CVC5 => write!(f, "cvc5"),
235 }
236 }
237}
238
239#[derive(Serialize, Deserialize, Debug, Clone)]
240#[serde(
241 tag = "tag",
242 content = "contents",
243 bound(deserialize = "Tag: FromStr", serialize = "Tag: ToString")
244)]
245pub enum FixpointStatus<Tag> {
246 Safe(Stats),
247 Unsafe(Stats, Vec<Error<Tag>>),
248 Crash(CrashInfo),
249}
250
251#[derive(Serialize, Deserialize, Debug, Clone, Default)]
252#[serde(tag = "tag", content = "contents")]
253pub enum LeanStatus {
254 #[default]
255 Invalid,
256 Valid(u64),
258}
259
260#[derive(Serialize, Deserialize, Debug, Clone)]
261#[serde(bound(deserialize = "Tag: FromStr", serialize = "Tag: ToString"))]
262pub struct VerificationResult<Tag> {
263 pub status: FixpointStatus<Tag>,
264 pub solution: Vec<KVarBind>,
265 #[serde(rename = "nonCutsSolution")]
266 pub non_cuts_solution: Vec<KVarBind>,
267 #[serde(default)]
268 pub lean_status: LeanStatus,
269}
270
271#[derive(Serialize, Deserialize, Debug, Clone)]
272pub struct KVarBind {
273 pub kvar: String,
274 pub val: String,
275}
276
277impl KVarBind {
278 pub fn dump(&self) -> String {
279 format!("{} := {}", self.kvar, self.val)
280 }
281}
282
283impl<Tag> FixpointStatus<Tag> {
284 pub fn is_safe(&self) -> bool {
285 matches!(self, FixpointStatus::Safe(_))
286 }
287
288 pub fn merge(self, other: FixpointStatus<Tag>) -> Self {
289 use FixpointStatus as FR;
290 match (self, other) {
291 (FR::Safe(stats1), FR::Safe(stats2)) => FR::Safe(stats1.merge(&stats2)),
292 (FR::Safe(stats1), FR::Unsafe(stats2, errors)) => {
293 FR::Unsafe(stats1.merge(&stats2), errors)
294 }
295 (FR::Unsafe(stats1, mut errors1), FR::Unsafe(stats2, errors2)) => {
296 errors1.extend(errors2);
297 FR::Unsafe(stats1.merge(&stats2), errors1)
298 }
299 (FR::Unsafe(stats1, errors), FR::Safe(stats2)) => {
300 FR::Unsafe(stats1.merge(&stats2), errors)
301 }
302 (FR::Crash(info1), FR::Crash(info2)) => FR::Crash(info1.merge(info2)),
303 (FR::Crash(info), _) => FR::Crash(info),
304 (_, FR::Crash(info)) => FR::Crash(info),
305 }
306 }
307}
308
309#[derive(Debug, Clone)]
310pub struct Error<Tag> {
311 pub id: i32,
312 pub tag: Tag,
313}
314
315#[derive(Debug, Serialize, Deserialize, Default, Clone)]
316#[serde(rename_all = "camelCase")]
317pub struct Stats {
318 pub num_cstr: i32,
319 pub num_iter: i32,
320 pub num_chck: i32,
321 pub num_vald: i32,
322}
323
324impl Stats {
325 pub fn merge(&self, other: &Stats) -> Self {
326 Stats {
327 num_cstr: self.num_cstr + other.num_cstr,
328 num_iter: self.num_iter + other.num_iter,
329 num_chck: self.num_chck + other.num_chck,
330 num_vald: self.num_vald + other.num_vald,
331 }
332 }
333}
334
335#[derive(Serialize, Deserialize, Debug, Clone)]
336pub struct CrashInfo(Vec<serde_json::Value>);
337
338impl CrashInfo {
339 pub fn merge(self, other: CrashInfo) -> Self {
340 let mut v = self.0;
341 v.extend(other.0);
342 CrashInfo(v)
343 }
344}
345
346#[derive_where(Debug, Clone, Hash)]
347pub struct KVarDecl<T: Types> {
348 pub kvid: T::KVar,
349 pub sorts: Vec<Sort<T>>,
350 #[derive_where(skip)]
351 pub comment: String,
352}
353
354impl<T: Types> Task<T> {
355 pub fn hash_with_default(&self) -> u64 {
356 let mut hasher = DefaultHasher::new();
357 self.hash(&mut hasher);
358 hasher.finish()
359 }
360
361 #[cfg(feature = "rust-fixpoint")]
362 pub fn run(&self) -> io::Result<VerificationResult<T::Tag>> {
363 let mut cstr_with_env = ConstraintWithEnv::new(
364 self.data_decls.clone(),
365 self.kvars.clone(),
366 self.qualifiers.clone(),
367 self.constants.clone(),
368 self.constraint.clone(),
369 );
370 Ok(VerificationResult {
371 status: cstr_with_env.is_satisfiable(),
372 solution: vec![],
373 non_cuts_solution: vec![],
374 lean_status: LeanStatus::default(),
375 })
376 }
377
378 #[cfg(not(feature = "rust-fixpoint"))]
379 pub fn run(&self) -> io::Result<VerificationResult<T::Tag>> {
380 let mut child = Command::new("fixpoint")
381 .arg("-q")
382 .arg("--stdin")
383 .arg("--sorted-solution")
384 .arg("--json")
385 .arg("--allowho")
386 .arg("--allowhoqs")
387 .arg(format!("--solver={}", self.solver))
388 .stdin(Stdio::piped())
389 .stdout(Stdio::piped())
390 .stderr(Stdio::piped())
391 .spawn()?;
392 let mut stdin = None;
393 std::mem::swap(&mut stdin, &mut child.stdin);
394 {
395 let mut w = BufWriter::new(stdin.unwrap());
396 writeln!(w, "{}", format::CompactTask(self))?;
398 }
399 let out = child.wait_with_output()?;
400
401 serde_json::from_slice(&out.stdout).map_err(|err| {
402 if !out.stderr.is_empty() {
405 let stderr = std::str::from_utf8(&out.stderr)
406 .unwrap_or("fixpoint exited with a non-zero return code");
407 io::Error::other(stderr)
408 } else {
409 err.into()
410 }
411 })
412 }
413}
414
415impl<T: Types> KVarDecl<T> {
416 pub fn new(kvid: T::KVar, sorts: Vec<Sort<T>>, comment: String) -> Self {
417 Self { kvid, sorts, comment }
418 }
419}
420
421#[derive(Serialize, Deserialize)]
422struct ErrorInner(i32, String);
423
424impl<Tag: ToString> Serialize for Error<Tag> {
425 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
426 where
427 S: serde::Serializer,
428 {
429 ErrorInner(self.id, self.tag.to_string()).serialize(serializer)
430 }
431}
432
433impl<'de, Tag: FromStr> Deserialize<'de> for Error<Tag> {
434 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
435 where
436 D: serde::Deserializer<'de>,
437 {
438 let ErrorInner(id, tag) = Deserialize::deserialize(deserializer)?;
439 let tag = tag
440 .parse()
441 .map_err(|_| de::Error::invalid_value(de::Unexpected::Str(&tag), &"valid tag"))?;
442 Ok(Error { id, tag })
443 }
444}
445
446#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
447#[cfg_attr(feature = "nightly", derive(Encodable, Decodable))]
448pub enum ThyFunc {
449 StrLen,
451 StrConcat,
452 StrPrefixOf,
453 StrSuffixOf,
454 StrContains,
455
456 BvZeroExtend(u8),
458 BvSignExtend(u8),
459 IntToBv8,
460 Bv8ToInt,
461 IntToBv32,
462 Bv32ToInt,
463 IntToBv64,
464 Bv64ToInt,
465 IntToBv128,
466 Bv128ToInt,
467 BvUle,
468 BvSle,
469 BvUge,
470 BvSge,
471 BvUdiv,
472 BvSdiv,
473 BvSrem,
474 BvUrem,
475 BvLshr,
476 BvAshr,
477 BvAnd,
478 BvOr,
479 BvXor,
480 BvNot,
481 BvAdd,
482 BvNeg,
483 BvSub,
484 BvMul,
485 BvShl,
486 BvUgt,
487 BvSgt,
488 BvUlt,
489 BvSlt,
490
491 SetEmpty,
494 SetSng,
496 SetCup,
498 SetCap,
500 SetDif,
502 SetSub,
504 SetMem,
506
507 MapDefault,
510 MapSelect,
512 MapStore,
514}
515
516impl ThyFunc {
517 pub const ALL: [ThyFunc; 46] = [
518 ThyFunc::StrLen,
519 ThyFunc::StrConcat,
520 ThyFunc::StrPrefixOf,
521 ThyFunc::StrSuffixOf,
522 ThyFunc::StrContains,
523 ThyFunc::IntToBv8,
524 ThyFunc::Bv8ToInt,
525 ThyFunc::IntToBv32,
526 ThyFunc::Bv32ToInt,
527 ThyFunc::IntToBv64,
528 ThyFunc::Bv64ToInt,
529 ThyFunc::IntToBv128,
530 ThyFunc::Bv128ToInt,
531 ThyFunc::BvAdd,
532 ThyFunc::BvNeg,
533 ThyFunc::BvSub,
534 ThyFunc::BvShl,
535 ThyFunc::BvLshr,
536 ThyFunc::BvAshr,
537 ThyFunc::BvMul,
538 ThyFunc::BvUdiv,
539 ThyFunc::BvSdiv,
540 ThyFunc::BvUrem,
541 ThyFunc::BvSrem,
542 ThyFunc::BvAnd,
543 ThyFunc::BvOr,
544 ThyFunc::BvXor,
545 ThyFunc::BvNot,
546 ThyFunc::BvUle,
547 ThyFunc::BvSle,
548 ThyFunc::BvUge,
549 ThyFunc::BvSge,
550 ThyFunc::BvUgt,
551 ThyFunc::BvSgt,
552 ThyFunc::BvUlt,
553 ThyFunc::BvSlt,
554 ThyFunc::SetEmpty,
555 ThyFunc::SetSng,
556 ThyFunc::SetCup,
557 ThyFunc::SetMem,
558 ThyFunc::SetCap,
559 ThyFunc::SetDif,
560 ThyFunc::SetSub,
561 ThyFunc::MapDefault,
562 ThyFunc::MapSelect,
563 ThyFunc::MapStore,
564 ];
565}
566
567impl fmt::Display for ThyFunc {
568 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
569 match self {
570 ThyFunc::StrLen => write!(f, "strLen"),
571 ThyFunc::StrConcat => write!(f, "strConcat"),
572 ThyFunc::StrPrefixOf => write!(f, "strPrefixOf"),
573 ThyFunc::StrSuffixOf => write!(f, "strSuffixOf"),
574 ThyFunc::StrContains => write!(f, "strContains"),
575 ThyFunc::BvZeroExtend(size) => {
576 write!(f, "app (_ zero_extend {size})")
578 }
579 ThyFunc::BvSignExtend(size) => write!(f, "app (_ sign_extend {size})"),
580 ThyFunc::IntToBv32 => write!(f, "int_to_bv32"),
581 ThyFunc::Bv32ToInt => write!(f, "bv32_to_int"),
582 ThyFunc::IntToBv8 => write!(f, "int_to_bv8"),
583 ThyFunc::Bv8ToInt => write!(f, "bv8_to_int"),
584 ThyFunc::IntToBv64 => write!(f, "int_to_bv64"),
585 ThyFunc::Bv64ToInt => write!(f, "bv64_to_int"),
586 ThyFunc::IntToBv128 => write!(f, "int_to_bv128"),
587 ThyFunc::Bv128ToInt => write!(f, "bv128_to_int"),
588 ThyFunc::BvUle => write!(f, "bvule"),
589 ThyFunc::BvSle => write!(f, "bvsle"),
590 ThyFunc::BvUge => write!(f, "bvuge"),
591 ThyFunc::BvSge => write!(f, "bvsge"),
592 ThyFunc::BvUdiv => write!(f, "bvudiv"),
593 ThyFunc::BvSdiv => write!(f, "bvsdiv"),
594 ThyFunc::BvUrem => write!(f, "bvurem"),
595 ThyFunc::BvSrem => write!(f, "bvsrem"),
596 ThyFunc::BvLshr => write!(f, "bvlshr"),
597 ThyFunc::BvAshr => write!(f, "bvashr"),
598 ThyFunc::BvAnd => write!(f, "bvand"),
599 ThyFunc::BvOr => write!(f, "bvor"),
600 ThyFunc::BvXor => write!(f, "bvxor"),
601 ThyFunc::BvNot => write!(f, "bvnot"),
602 ThyFunc::BvAdd => write!(f, "bvadd"),
603 ThyFunc::BvNeg => write!(f, "bvneg"),
604 ThyFunc::BvSub => write!(f, "bvsub"),
605 ThyFunc::BvMul => write!(f, "bvmul"),
606 ThyFunc::BvShl => write!(f, "bvshl"),
607 ThyFunc::BvUgt => write!(f, "bvugt"),
608 ThyFunc::BvSgt => write!(f, "bvsgt"),
609 ThyFunc::BvUlt => write!(f, "bvult"),
610 ThyFunc::BvSlt => write!(f, "bvslt"),
611 ThyFunc::SetEmpty => write!(f, "Set_empty"),
612 ThyFunc::SetSng => write!(f, "Set_sng"),
613 ThyFunc::SetCup => write!(f, "Set_cup"),
614 ThyFunc::SetCap => write!(f, "Set_cap"),
615 ThyFunc::SetDif => write!(f, "Set_dif"),
616 ThyFunc::SetMem => write!(f, "Set_mem"),
617 ThyFunc::SetSub => write!(f, "Set_sub"),
618 ThyFunc::MapDefault => write!(f, "Map_default"),
619 ThyFunc::MapSelect => write!(f, "Map_select"),
620 ThyFunc::MapStore => write!(f, "Map_store"),
621 }
622 }
623}
624
625impl FromStr for ThyFunc {
626 type Err = String;
627 fn from_str(s: &str) -> Result<Self, Self::Err> {
628 match s {
629 "strLen" => Ok(ThyFunc::StrLen),
630 "int_to_bv32" => Ok(ThyFunc::IntToBv32),
631 "bv32_to_int" => Ok(ThyFunc::Bv32ToInt),
632 "int_to_bv8" => Ok(ThyFunc::IntToBv8),
633 "bv8_to_int" => Ok(ThyFunc::Bv8ToInt),
634 "int_to_bv64" => Ok(ThyFunc::IntToBv64),
635 "bv64_to_int" => Ok(ThyFunc::Bv64ToInt),
636 "int_to_bv128" => Ok(ThyFunc::IntToBv128),
637 "bv128_to_int" => Ok(ThyFunc::Bv128ToInt),
638 "bvule" => Ok(ThyFunc::BvUle),
639 "bvsle" => Ok(ThyFunc::BvSle),
640 "bvuge" => Ok(ThyFunc::BvUge),
641 "bvsge" => Ok(ThyFunc::BvSge),
642 "bvudiv" => Ok(ThyFunc::BvUdiv),
643 "bvsdiv" => Ok(ThyFunc::BvSdiv),
644 "bvurem" => Ok(ThyFunc::BvUrem),
645 "bvsrem" => Ok(ThyFunc::BvSrem),
646 "bvlshr" => Ok(ThyFunc::BvLshr),
647 "bvashr" => Ok(ThyFunc::BvAshr),
648 "bvand" => Ok(ThyFunc::BvAnd),
649 "bvor" => Ok(ThyFunc::BvOr),
650 "bvxor" => Ok(ThyFunc::BvXor),
651 "bvnot" => Ok(ThyFunc::BvNot),
652 "bvadd" => Ok(ThyFunc::BvAdd),
653 "bvneg" => Ok(ThyFunc::BvNeg),
654 "bvsub" => Ok(ThyFunc::BvSub),
655 "bvmul" => Ok(ThyFunc::BvMul),
656 "bvshl" => Ok(ThyFunc::BvShl),
657 "bvugt" => Ok(ThyFunc::BvUgt),
658 "bvsgt" => Ok(ThyFunc::BvSgt),
659 "bvult" => Ok(ThyFunc::BvUlt),
660 "bvslt" => Ok(ThyFunc::BvSlt),
661 "Set_empty" => Ok(ThyFunc::SetEmpty),
662 "Set_sng" => Ok(ThyFunc::SetSng),
663 "Set_cup" => Ok(ThyFunc::SetCup),
664 "Set_mem" => Ok(ThyFunc::SetMem),
665 "Map_default" => Ok(ThyFunc::MapDefault),
666 "Map_select" => Ok(ThyFunc::MapSelect),
667 "Map_store" => Ok(ThyFunc::MapStore),
668 _ => Err(format!("Unexpected ThyFunc {}", s)),
673 }
674 }
675}