use std::io;
pub use crate::{errors::*, prelude::*};
pub type Model<Ident, Type, Value> = Vec<(Ident, Vec<(Ident, Type)>, Type, Value)>;
pub trait Sym2Smt<Info = ()> {
fn sym_to_smt2<Writer>(&self, w: &mut Writer, i: Info) -> SmtRes<()>
where
Writer: io::Write;
}
pub trait Expr2Smt<Info = ()> {
fn expr_to_smt2<Writer>(&self, w: &mut Writer, i: Info) -> SmtRes<()>
where
Writer: io::Write;
fn to_smt_named<Sym>(self, name: Sym) -> NamedExpr<Sym, Self, Info>
where
Sym: Sym2Smt,
Self: Sized,
{
NamedExpr::new(name, self)
}
fn as_smt_named<Sym>(&self, name: Sym) -> NamedExpr<Sym, &Self, Info>
where
Sym: Sym2Smt,
Self: Sized,
{
NamedExpr::new(name, &self)
}
}
pub trait Sort2Smt {
fn sort_to_smt2<Writer>(&self, w: &mut Writer) -> SmtRes<()>
where
Writer: io::Write;
}
pub trait SymAndSort<Info = ()> {
type Sym: Sym2Smt<Info>;
type Sort: Sort2Smt;
fn sym(&self) -> &Self::Sym;
fn sort(&self) -> &Self::Sort;
}
impl<'a, T, Info> SymAndSort<Info> for &'a T
where
T: SymAndSort<Info>,
{
type Sym = <T as SymAndSort<Info>>::Sym;
type Sort = <T as SymAndSort<Info>>::Sort;
fn sym(&self) -> &Self::Sym {
(*self).sym()
}
fn sort(&self) -> &Self::Sort {
(*self).sort()
}
}
impl<Info, Sym, Sort> SymAndSort<Info> for (Sym, Sort)
where
Sym: Sym2Smt<Info>,
Sort: Sort2Smt,
{
type Sym = Sym;
type Sort = Sort;
fn sym(&self) -> &Sym {
&self.0
}
fn sort(&self) -> &Sort {
&self.1
}
}
pub trait FunDef<Info = ()> {
type FunSym: Sym2Smt<Info>;
type SortedSym: SymAndSort<Info>;
type ArgsIter: Iterator<Item = Self::SortedSym>;
type OutSort: Sort2Smt;
type Body: Expr2Smt<Info>;
fn fun_sym(&self) -> &Self::FunSym;
fn args(&self) -> Self::ArgsIter;
fn out_sort(&self) -> &Self::OutSort;
fn body(&self) -> &Self::Body;
}
impl<'a, T, Info> FunDef<Info> for &'a T
where
T: FunDef<Info>,
{
type FunSym = T::FunSym;
type SortedSym = T::SortedSym;
type ArgsIter = T::ArgsIter;
type OutSort = T::OutSort;
type Body = T::Body;
fn fun_sym(&self) -> &Self::FunSym {
(*self).fun_sym()
}
fn args(&self) -> Self::ArgsIter {
(*self).args()
}
fn out_sort(&self) -> &Self::OutSort {
(*self).out_sort()
}
fn body(&self) -> &Self::Body {
(*self).body()
}
}
impl<FunSym, SortedSym, Args, OutSort, Body, Info> FunDef<Info> for (FunSym, Args, OutSort, Body)
where
FunSym: Sym2Smt<Info>,
SortedSym: SymAndSort<Info>,
Args: IntoIterator<Item = SortedSym> + Clone,
OutSort: Sort2Smt,
Body: Expr2Smt<Info>,
{
type FunSym = FunSym;
type SortedSym = SortedSym;
type ArgsIter = Args::IntoIter;
type OutSort = OutSort;
type Body = Body;
fn fun_sym(&self) -> &FunSym {
&self.0
}
fn args(&self) -> Self::ArgsIter {
self.1.clone().into_iter()
}
fn out_sort(&self) -> &OutSort {
&self.2
}
fn body(&self) -> &Body {
&self.3
}
}
pub trait AdtVariantField {
type FieldSym: Sym2Smt;
type FieldSort: Sort2Smt;
fn field_sym(&self) -> &Self::FieldSym;
fn field_sort(&self) -> &Self::FieldSort;
}
impl<'a, T> AdtVariantField for &'a T
where
T: AdtVariantField,
{
type FieldSym = T::FieldSym;
type FieldSort = T::FieldSort;
fn field_sym(&self) -> &Self::FieldSym {
(*self).field_sym()
}
fn field_sort(&self) -> &Self::FieldSort {
(*self).field_sort()
}
}
impl<FieldSym, FieldSort> AdtVariantField for (FieldSym, FieldSort)
where
FieldSym: Sym2Smt,
FieldSort: Sort2Smt,
{
type FieldSym = FieldSym;
type FieldSort = FieldSort;
fn field_sym(&self) -> &FieldSym {
&self.0
}
fn field_sort(&self) -> &FieldSort {
&self.1
}
}
pub trait AdtVariant {
type VariantSym: Sym2Smt;
type Field: AdtVariantField;
type FieldIter: Iterator<Item = Self::Field>;
fn sym(&self) -> &Self::VariantSym;
fn fields(&self) -> Self::FieldIter;
}
impl<'a, T> AdtVariant for &'a T
where
T: AdtVariant,
{
type VariantSym = T::VariantSym;
type Field = T::Field;
type FieldIter = T::FieldIter;
fn sym(&self) -> &Self::VariantSym {
(*self).sym()
}
fn fields(&self) -> Self::FieldIter {
(*self).fields()
}
}
impl<VariantSym, Field, FieldIntoIter> AdtVariant for (VariantSym, FieldIntoIter)
where
VariantSym: Sym2Smt,
Field: AdtVariantField,
FieldIntoIter: IntoIterator<Item = Field> + Clone,
{
type VariantSym = VariantSym;
type Field = Field;
type FieldIter = FieldIntoIter::IntoIter;
fn sym(&self) -> &VariantSym {
&self.0
}
fn fields(&self) -> Self::FieldIter {
self.1.clone().into_iter()
}
}
pub trait AdtDecl {
type AdtSym: Sym2Smt;
type VariantSym: Sym2Smt;
type SortArg: Sym2Smt;
type SortArgsIter: Iterator<Item = Self::SortArg> + ExactSizeIterator;
type Variant: AdtVariant;
type VariantIter: Iterator<Item = Self::Variant>;
fn adt_sym(&self) -> &Self::AdtSym;
fn adt_sort_args(&self) -> Self::SortArgsIter;
fn arity(&self) -> usize {
self.adt_sort_args().len()
}
fn adt_variants(&self) -> Self::VariantIter;
}
impl<AdtSym, ArgsIntoIter, VariantIntoIter> AdtDecl for (AdtSym, ArgsIntoIter, VariantIntoIter)
where
AdtSym: Sym2Smt,
ArgsIntoIter: IntoIterator + Clone,
ArgsIntoIter::IntoIter: ExactSizeIterator,
ArgsIntoIter::Item: Sym2Smt,
VariantIntoIter: IntoIterator + Clone,
VariantIntoIter::Item: AdtVariant,
{
type AdtSym = AdtSym;
type VariantSym = ArgsIntoIter::Item;
type SortArg = ArgsIntoIter::Item;
type SortArgsIter = ArgsIntoIter::IntoIter;
type Variant = VariantIntoIter::Item;
type VariantIter = VariantIntoIter::IntoIter;
fn adt_sym(&self) -> &AdtSym {
&self.0
}
fn adt_sort_args(&self) -> ArgsIntoIter::IntoIter {
self.1.clone().into_iter()
}
fn adt_variants(&self) -> VariantIntoIter::IntoIter {
self.2.clone().into_iter()
}
}
impl<'a, T> AdtDecl for &'a T
where
T: AdtDecl,
{
type AdtSym = T::AdtSym;
type VariantSym = T::VariantSym;
type SortArg = T::SortArg;
type SortArgsIter = T::SortArgsIter;
type Variant = T::Variant;
type VariantIter = T::VariantIter;
fn adt_sym(&self) -> &Self::AdtSym {
(*self).adt_sym()
}
fn adt_sort_args(&self) -> Self::SortArgsIter {
(*self).adt_sort_args()
}
fn adt_variants(&self) -> Self::VariantIter {
(*self).adt_variants()
}
}
#[inline]
pub fn write_str<W: io::Write>(w: &mut W, s: &str) -> SmtRes<()> {
w.write_all(s.as_bytes())?;
Ok(())
}
impl<'a, T, Info> Sym2Smt<Info> for &'a T
where
T: Sym2Smt<Info> + ?Sized,
{
fn sym_to_smt2<Writer>(&self, writer: &mut Writer, info: Info) -> SmtRes<()>
where
Writer: io::Write,
{
(*self).sym_to_smt2(writer, info)
}
}
impl<'a, T, Info> Expr2Smt<Info> for &'a T
where
T: Expr2Smt<Info> + ?Sized,
{
fn expr_to_smt2<Writer>(&self, writer: &mut Writer, info: Info) -> SmtRes<()>
where
Writer: io::Write,
{
(*self).expr_to_smt2(writer, info)
}
}
impl<'a, T> Sort2Smt for &'a T
where
T: Sort2Smt + ?Sized,
{
fn sort_to_smt2<Writer>(&self, writer: &mut Writer) -> SmtRes<()>
where
Writer: io::Write,
{
(*self).sort_to_smt2(writer)
}
}
impl<T> Sym2Smt<T> for str {
fn sym_to_smt2<Writer>(&self, writer: &mut Writer, _: T) -> SmtRes<()>
where
Writer: io::Write,
{
write_str(writer, self)
}
}
impl<T> Expr2Smt<T> for str {
fn expr_to_smt2<Writer>(&self, writer: &mut Writer, _: T) -> SmtRes<()>
where
Writer: io::Write,
{
write_str(writer, self)
}
}
impl Sort2Smt for str {
fn sort_to_smt2<Writer>(&self, writer: &mut Writer) -> SmtRes<()>
where
Writer: io::Write,
{
write_str(writer, self)
}
}
impl<T> Sym2Smt<T> for String {
fn sym_to_smt2<Writer>(&self, writer: &mut Writer, _: T) -> SmtRes<()>
where
Writer: io::Write,
{
write_str(writer, self)
}
}
impl<T> Expr2Smt<T> for String {
fn expr_to_smt2<Writer>(&self, writer: &mut Writer, _: T) -> SmtRes<()>
where
Writer: io::Write,
{
write_str(writer, self)
}
}
impl Sort2Smt for String {
fn sort_to_smt2<Writer>(&self, writer: &mut Writer) -> SmtRes<()>
where
Writer: io::Write,
{
write_str(writer, self)
}
}
pub struct NamedExpr<Sym, Expr, Info> {
sym: Sym,
expr: Expr,
_phantom: std::marker::PhantomData<Info>,
}
impl<Sym, Expr, Info> NamedExpr<Sym, Expr, Info> {
pub fn new(sym: Sym, expr: Expr) -> Self {
Self {
sym,
expr,
_phantom: std::marker::PhantomData,
}
}
}
impl<Sym, Expr, Info> Expr2Smt<Info> for NamedExpr<Sym, Expr, Info>
where
Sym: Sym2Smt<()>,
Expr: Expr2Smt<Info>,
{
fn expr_to_smt2<Writer>(&self, w: &mut Writer, i: Info) -> SmtRes<()>
where
Writer: io::Write,
{
write!(w, "(! ")?;
self.expr.expr_to_smt2(w, i)?;
write!(w, " :named ")?;
self.sym.sym_to_smt2(w, ())?;
write!(w, ")")?;
Ok(())
}
}