in amzn-smt-ir/src/term/convert.rs [94:210]
fn convert<L: Logic>(t: RawTerm) -> Result<Term<L>, InvalidTerm<L>>
where
QualIdentifier: Into<IVar<L::Var>>,
{
#[derive(Debug)]
enum Type {
Op(QualIdentifier, usize),
Let(Vec<ISymbol>),
Quantifier(quantifier::Kind, Vec<(ISymbol, ISort)>),
}
let ident = convert_qual_identifier;
let convert_or_enqueue = |t: RawTerm, pending: &mut Vec<_>| {
use RawTerm::*;
match t {
Constant(c) => Ok(Some(Term::Constant(c.into()))),
QualIdentifier(q) => {
let t = (ICoreOp::parse(ident(q), vec![]).map(Term::CoreOp))
.or_else(|InvalidOp { func, .. }| IOp::parse(func, vec![]).map(Term::OtherOp))
.unwrap_or_else(|InvalidOp { func, .. }| Term::Variable(func.into()));
Ok(Some(t))
}
Application {
qual_identifier: op,
arguments: args,
} => {
pending.push(Either::Left(Type::Op(ident(op), args.len())));
pending.extend(args.into_iter().rev().map(Either::Right));
Ok(None)
}
Let { var_bindings, term } => {
let mut vars = vec![];
let mut ts = vec![];
for (var, t) in var_bindings {
vars.push(var.into());
ts.push(t);
}
pending.push(Either::Left(Type::Let(vars)));
pending.extend(ts.into_iter().rev().map(Either::Right));
pending.push(Either::Right(*term));
Ok(None)
}
Forall { vars, term } => {
let vars = vars
.into_iter()
.map(|(sym, sort)| (sym.into(), Sort::from(sort).into()))
.collect();
pending.push(Either::Left(Type::Quantifier(
quantifier::Kind::Universal,
vars,
)));
pending.push(Either::Right(*term));
Ok(None)
}
Exists { vars, term } => {
let vars = vars
.into_iter()
.map(|(sym, sort)| (sym.into(), Sort::from(sort).into()))
.collect();
pending.push(Either::Left(Type::Quantifier(
quantifier::Kind::Existential,
vars,
)));
pending.push(Either::Right(*term));
Ok(None)
}
Match { .. } => Err(InvalidTerm::Match),
Attributes { term, .. } => {
pending.push(Either::Right(*term));
Ok(None)
}
}
};
let mut pending = vec![];
let mut converted: Vec<Term<L>> = vec![];
if let Some(t) = convert_or_enqueue(t, &mut pending)? {
return Ok(t);
};
while let Some(next) = pending.pop() {
match next {
Either::Left(ty) => match ty {
Type::Op(func, num_args) => {
let args = converted.drain(converted.len() - num_args..);
let args = args.collect::<Vec<_>>();
let op = (ICoreOp::parse(func, args).map(Term::CoreOp))
.or_else(|InvalidOp { func, args }| IOp::parse(func, args).map(Into::into))
.or_else(|InvalidOp { func, args }| {
IUF::parse(func.sym().clone(), args).map(Into::into)
})?;
converted.push(op);
}
Type::Let(vars) => {
let ts = converted.drain(converted.len() - vars.len()..);
let bindings = vars.into_iter().zip(ts).collect();
let term = converted.pop().unwrap();
converted.push(Term::Let(Let { bindings, term }.into()));
}
Type::Quantifier(kind, vars) => {
let t = converted.pop().unwrap();
let q = L::Quantifier::parse(kind, vars, t)?.into();
converted.push(Term::Quantifier(q));
}
},
Either::Right(t) => {
if let Some(t) = convert_or_enqueue(t, &mut pending)? {
converted.push(t);
}
}
}
}
Ok(converted.pop().unwrap())
}