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