use std::collections::BTreeMap;
use sva_ast::{Arg, Expr};
use crate::instantiate::{Bound, Cx, Instances, Node};
impl Instances {
pub(crate) fn display_name(&self, file: &str, binds: &[(String, Bound)]) -> String {
if binds.is_empty() {
return file.to_string();
}
let args: Vec<String> = binds
.iter()
.map(|(k, v)| {
let v = v.thunk();
format!("{k}={}", self.render(v.expr, self.cx(v.scope)))
})
.collect();
format!("{file}({})", args.join(", "))
}
pub fn render(&self, e: &Expr, cx: Cx) -> String {
sva_ast::render_expr(&self.copy(e, cx))
}
pub fn exprs(&self) -> BTreeMap<String, Expr> {
self.nodes
.keys()
.map(|path| {
let (e, cx) = self.at(path).expect("a key of the map it indexes");
(path.clone(), self.copy(e, cx))
})
.collect()
}
fn copy(&self, e: &Expr, cx: Cx) -> Expr {
if let Some(r) = self.follow(e, cx, |e2, cx2| self.copy(e2, cx2)) {
return r;
}
match self.node(e, cx) {
Node::Lit(l) => Expr::Lit(l.clone()),
Node::Name(name) => Expr::Var(name.to_string()),
Node::Bin(op, l, r) => {
Expr::Bin(op, Box::new(self.copy(l, cx)), Box::new(self.copy(r, cx)))
}
Node::Call { name, args, span } => Expr::Call {
name: name.to_string(),
args: args
.iter()
.map(|a| match a {
Arg::Pos(x) => Arg::Pos(self.copy(x, cx)),
Arg::Named(k, x) => Arg::Named(k.clone(), self.copy(x, cx)),
})
.collect(),
span,
},
Node::Read {
path,
arg,
address,
span,
} => Expr::Ref {
address,
path: path.to_string(),
arg: Box::new(self.copy(arg, cx)),
binds: Vec::new(),
span,
},
Node::Own { arg, address, span } => Expr::SelfRef {
arg: Box::new(self.copy(arg, cx)),
address,
span,
},
Node::Signal {
name,
of,
arg,
span,
} => {
let arg = Box::new(self.copy(arg, cx));
match self.copy(of.expr, self.signal(of, cx)) {
Expr::Ref {
path,
arg: now,
binds,
address: sva_ast::Address::Time,
..
} if binds.is_empty() && *now == Expr::Var("t".to_string()) => Expr::Ref {
path,
arg,
binds,
address: sva_ast::Address::Index,
span,
},
_ => Expr::Indexed {
name: name.to_string(),
arg,
span,
},
}
}
}
}
}