Skip to content

Commit

Permalink
Merge #651: add conditional formatting for Terminal
Browse files Browse the repository at this point in the history
395aab8 unify debug/display impl for Terminal (Riccardo Casatta)
752acb3 apply immediate dispatch in generic fn (Riccardo Casatta)
426c34d add conditional formatting for Terminal (Riccardo Casatta)

Pull request description:

  fmt functions produce big binaries.

  <details>
    <summary>cargo bloat --release --example big --all-features -n 1000000 --full-fn | grep astelem | grep fmt</summary>
     0.0%   0.1%  2.8KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h75ba3ce6da61d374
   0.0%   0.1%  2.8KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h6786aa26184b9ff6
   0.0%   0.1%  2.8KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h03f9c2155559a440
   0.0%   0.1%  2.8KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h00e63af9b88389b4
   0.0%   0.1%  2.8KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::hb60190c99fd48d17
   0.0%   0.1%  2.8KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::ha9001c527b4cc4d6
   0.0%   0.1%  2.8KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::ha726829fe4f3bf2b
   0.0%   0.1%  2.8KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h95a7eadaa261d645
   0.0%   0.1%  2.8KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h819e09dcb99bbc52
   0.0%   0.1%  2.8KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h6ef89d30f9f4cb57
   0.0%   0.1%  2.8KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h693edb5e35f9fc08
   0.0%   0.1%  2.8KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h27891ccf9609c782
   0.0%   0.1%  2.7KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::he0a63893fe76f527
   0.0%   0.1%  2.7KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h86eba44cb7298c4f
   0.0%   0.1%  2.7KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h37a4628264df8c3b
   0.0%   0.1%  2.7KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h2f3a9d297ec35dea
   0.0%   0.1%  2.7KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h879ad74922a70f16
   0.0%   0.1%  2.7KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h7dc2d9bc27c88fab
   0.0%   0.1%  2.7KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h7578352fd420fc88
   0.0%   0.1%  2.7KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h1809b9931776159e
   0.0%   0.1%  2.7KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::hf7760e0f27d70db4
   0.0%   0.1%  2.7KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h9adfe0d7e2bfdd42
   0.0%   0.1%  2.7KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h61cdb06e2a061932
   0.0%   0.1%  2.7KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h44e1ab5daacde0df
   0.0%   0.1%  2.7KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h2646ddd57694241b
   0.0%   0.1%  2.7KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::he31fd2e9b12960f9
   0.0%   0.1%  2.7KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::hbefb77c4050bd5c9
   0.0%   0.1%  2.7KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::hb4deb7ef951af7af
   0.0%   0.1%  2.7KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h80ee1108b955f2b4
   0.0%   0.1%  2.6KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::hc779f37cb81f761a
   0.0%   0.1%  2.6KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::hc4ac4a9b598fbdfb
   0.0%   0.1%  2.6KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h5cca31d73f30c3c7
   0.0%   0.1%  2.6KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h4588410e445d16c6
   0.0%   0.1%  2.6KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::heb60f683c9e55e36
   0.0%   0.1%  2.6KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::hbe7939a797fcce35
   0.0%   0.1%  2.6KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::ha536af3ff4313ed1
   0.0%   0.1%  2.6KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h8969ddab726dea7f
   0.0%   0.1%  2.6KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h7fca0d80a428dd24
   0.0%   0.1%  2.6KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h6b4909db760a4721
   0.0%   0.1%  2.6KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h5ed643a399966d49
   0.0%   0.1%  2.6KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h1ed7d512c859a5a9
   0.0%   0.1%  2.6KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::hfd9775e798913648
   0.0%   0.1%  2.6KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::hf87563509ea7253d
   0.0%   0.1%  2.6KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::hb8b75c9c988d95c3
   0.0%   0.1%  2.6KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h87b650968eb119ba
   0.0%   0.1%  2.6KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h9986ae4314d85479
   0.0%   0.1%  2.6KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h74343d637646e38a
   0.0%   0.1%  2.6KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h680da8fa0ec0142c
   0.0%   0.1%  2.6KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h6197658ba03f1fdf
   0.0%   0.1%  2.6KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h961e1a4b75732a11
   0.0%   0.1%  2.6KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h57b3cd148371177a
   0.0%   0.1%  2.6KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h13d43f019a96d314
   0.0%   0.1%  2.6KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h008ca416c1ebc0d7
   0.0%   0.1%  2.5KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h82a27926db80dc37
   0.0%   0.1%  2.5KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::hc12b3098c3979175
   0.0%   0.1%  2.5KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h76e624d7abc545ba
   0.0%   0.1%  2.5KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h24511846d004e114
   0.0%   0.1%  2.5KiB       miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h0d96e9d943f04d7d

  </details>

  Since Debug and Display implementations are ~equal except the Debug or Display representation of its child, this introduce conditional fmt trading performance for code size. Since performance shouldn't be that important in string conversion seems an interesting trade-off.

  This is a PoC since the final impl of `conditional_fmt` is a little tedious, would like a concept ack before proceding

ACKs for top commit:
  apoelstra:
    ACK 395aab8

Tree-SHA512: 71fbdc55b11d5f5452c810da3934f087ed7d8a26156bfc6e174d29cbf1590dc85e32142dd12c477a2fbe86393429aa55a5b4d7dedbd96f216d083e1614fc1dac
  • Loading branch information
apoelstra committed Mar 7, 2024
2 parents dcbef52 + 395aab8 commit 22dad5e
Show file tree
Hide file tree
Showing 2 changed files with 148 additions and 153 deletions.
285 changes: 140 additions & 145 deletions src/miniscript/astelem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,197 +42,89 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Terminal<Pk, Ctx> {
_ => None,
}
}
}

impl<Pk: MiniscriptKey, Ctx: ScriptContext> fmt::Debug for Terminal<Pk, Ctx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("[")?;
if let Ok(type_map) = types::Type::type_check(self) {
f.write_str(match type_map.corr.base {
types::Base::B => "B",
types::Base::K => "K",
types::Base::V => "V",
types::Base::W => "W",
})?;
fmt::Write::write_char(f, '/')?;
f.write_str(match type_map.corr.input {
types::Input::Zero => "z",
types::Input::One => "o",
types::Input::OneNonZero => "on",
types::Input::Any => "",
types::Input::AnyNonZero => "n",
})?;
if type_map.corr.dissatisfiable {
fmt::Write::write_char(f, 'd')?;
}
if type_map.corr.unit {
fmt::Write::write_char(f, 'u')?;
}
f.write_str(match type_map.mall.dissat {
types::Dissat::None => "f",
types::Dissat::Unique => "e",
types::Dissat::Unknown => "",
})?;
if type_map.mall.safe {
fmt::Write::write_char(f, 's')?;
}
if type_map.mall.non_malleable {
fmt::Write::write_char(f, 'm')?;
}
} else {
f.write_str("TYPECHECK FAILED")?;
}
f.write_str("]")?;
if let Some((ch, sub)) = self.wrap_char() {
fmt::Write::write_char(f, ch)?;
if sub.node.wrap_char().is_none() {
fmt::Write::write_char(f, ':')?;
}
write!(f, "{:?}", sub)
} else {
match *self {
Terminal::PkK(ref pk) => write!(f, "pk_k({:?})", pk),
Terminal::PkH(ref pk) => write!(f, "pk_h({:?})", pk),
Terminal::RawPkH(ref pkh) => write!(f, "expr_raw_pk_h({:?})", pkh),
Terminal::After(t) => write!(f, "after({})", t),
Terminal::Older(t) => write!(f, "older({})", t),
Terminal::Sha256(ref h) => write!(f, "sha256({})", h),
Terminal::Hash256(ref h) => write!(f, "hash256({})", h),
Terminal::Ripemd160(ref h) => write!(f, "ripemd160({})", h),
Terminal::Hash160(ref h) => write!(f, "hash160({})", h),
Terminal::True => f.write_str("1"),
Terminal::False => f.write_str("0"),
Terminal::AndV(ref l, ref r) => write!(f, "and_v({:?},{:?})", l, r),
Terminal::AndB(ref l, ref r) => write!(f, "and_b({:?},{:?})", l, r),
Terminal::AndOr(ref a, ref b, ref c) => {
if c.node == Terminal::False {
write!(f, "and_n({:?},{:?})", a, b)
} else {
write!(f, "andor({:?},{:?},{:?})", a, b, c)
}
}
Terminal::OrB(ref l, ref r) => write!(f, "or_b({:?},{:?})", l, r),
Terminal::OrD(ref l, ref r) => write!(f, "or_d({:?},{:?})", l, r),
Terminal::OrC(ref l, ref r) => write!(f, "or_c({:?},{:?})", l, r),
Terminal::OrI(ref l, ref r) => write!(f, "or_i({:?},{:?})", l, r),
Terminal::Thresh(k, ref subs) => {
write!(f, "thresh({}", k)?;
for s in subs {
write!(f, ",{:?}", s)?;
}
f.write_str(")")
}
Terminal::Multi(k, ref keys) => {
write!(f, "multi({}", k)?;
for k in keys {
write!(f, ",{:?}", k)?;
}
f.write_str(")")
}
Terminal::MultiA(k, ref keys) => {
write!(f, "multi_a({}", k)?;
for k in keys {
write!(f, ",{}", k)?;
}
f.write_str(")")
}
_ => unreachable!(),
}
}
}
}

impl<Pk: MiniscriptKey, Ctx: ScriptContext> fmt::Display for Terminal<Pk, Ctx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fn conditional_fmt(&self, f: &mut fmt::Formatter, is_debug: bool) -> fmt::Result {
match *self {
Terminal::PkK(ref pk) => write!(f, "pk_k({})", pk),
Terminal::PkH(ref pk) => write!(f, "pk_h({})", pk),
Terminal::RawPkH(ref pkh) => write!(f, "expr_raw_pk_h({})", pkh),
Terminal::After(t) => write!(f, "after({})", t),
Terminal::Older(t) => write!(f, "older({})", t),
Terminal::Sha256(ref h) => write!(f, "sha256({})", h),
Terminal::Hash256(ref h) => write!(f, "hash256({})", h),
Terminal::Ripemd160(ref h) => write!(f, "ripemd160({})", h),
Terminal::Hash160(ref h) => write!(f, "hash160({})", h),
Terminal::PkK(ref pk) => fmt_1(f, "pk_k(", pk, is_debug),
Terminal::PkH(ref pk) => fmt_1(f, "pk_h(", pk, is_debug),
Terminal::RawPkH(ref pkh) => fmt_1(f, "expr_raw_pk_h(", pkh, is_debug),
Terminal::After(ref t) => fmt_1(f, "after(", t, is_debug),
Terminal::Older(ref t) => fmt_1(f, "older(", t, is_debug),
Terminal::Sha256(ref h) => fmt_1(f, "sha256(", h, is_debug),
Terminal::Hash256(ref h) => fmt_1(f, "hash256(", h, is_debug),
Terminal::Ripemd160(ref h) => fmt_1(f, "ripemd160(", h, is_debug),
Terminal::Hash160(ref h) => fmt_1(f, "hash160(", h, is_debug),
Terminal::True => f.write_str("1"),
Terminal::False => f.write_str("0"),
Terminal::AndV(ref l, ref r) if r.node != Terminal::True => {
write!(f, "and_v({},{})", l, r)
fmt_2(f, "and_v(", l, r, is_debug)
}
Terminal::AndB(ref l, ref r) => write!(f, "and_b({},{})", l, r),
Terminal::AndB(ref l, ref r) => fmt_2(f, "and_b(", l, r, is_debug),
Terminal::AndOr(ref a, ref b, ref c) => {
if c.node == Terminal::False {
write!(f, "and_n({},{})", a, b)
fmt_2(f, "and_b(", a, b, is_debug)
} else {
write!(f, "andor({},{},{})", a, b, c)
f.write_str("andor(")?;
conditional_fmt(f, a, is_debug)?;
f.write_str(",")?;
conditional_fmt(f, b, is_debug)?;
f.write_str(",")?;
conditional_fmt(f, c, is_debug)?;
f.write_str(")")
}
}
Terminal::OrB(ref l, ref r) => write!(f, "or_b({},{})", l, r),
Terminal::OrD(ref l, ref r) => write!(f, "or_d({},{})", l, r),
Terminal::OrC(ref l, ref r) => write!(f, "or_c({},{})", l, r),
Terminal::OrB(ref l, ref r) => fmt_2(f, "or_b(", l, r, is_debug),
Terminal::OrD(ref l, ref r) => fmt_2(f, "or_d(", l, r, is_debug),
Terminal::OrC(ref l, ref r) => fmt_2(f, "or_c(", l, r, is_debug),
Terminal::OrI(ref l, ref r)
if l.node != Terminal::False && r.node != Terminal::False =>
{
write!(f, "or_i({},{})", l, r)
}
Terminal::Thresh(k, ref subs) => {
write!(f, "thresh({}", k)?;
for s in subs {
write!(f, ",{}", s)?;
}
f.write_str(")")
}
Terminal::Multi(k, ref keys) => {
write!(f, "multi({}", k)?;
for k in keys {
write!(f, ",{}", k)?;
}
f.write_str(")")
}
Terminal::MultiA(k, ref keys) => {
write!(f, "multi_a({}", k)?;
for k in keys {
write!(f, ",{}", k)?;
}
f.write_str(")")
fmt_2(f, "or_i(", l, r, is_debug)
}
Terminal::Thresh(k, ref subs) => fmt_n(f, "thresh(", k, subs, is_debug),
Terminal::Multi(k, ref keys) => fmt_n(f, "multi(", k, keys, is_debug),
Terminal::MultiA(k, ref keys) => fmt_n(f, "multi_a(", k, keys, is_debug),
// wrappers
_ => {
if let Some((ch, sub)) = self.wrap_char() {
if ch == 'c' {
if let Terminal::PkK(ref pk) = sub.node {
// alias: pk(K) = c:pk_k(K)
return write!(f, "pk({})", pk);
return fmt_1(f, "pk(", pk, is_debug);
} else if let Terminal::RawPkH(ref pkh) = sub.node {
// `RawPkH` is currently unsupported in the descriptor spec
// alias: pkh(K) = c:pk_h(K)
// We temporarily display there using raw_pkh, but these descriptors
// are not defined in the spec yet. These are prefixed with `expr`
// in the descriptor string.
// We do not support parsing these descriptors yet.
return write!(f, "expr_raw_pkh({})", pkh);
return fmt_1(f, "expr_raw_pkh(", pkh, is_debug);
} else if let Terminal::PkH(ref pk) = sub.node {
// alias: pkh(K) = c:pk_h(K)
return write!(f, "pkh({})", pk);
return fmt_1(f, "pkh(", pk, is_debug);
}
}

fmt::Write::write_char(f, ch)?;
match sub.node.wrap_char() {
None => {
fmt::Write::write_char(f, ':')?;
f.write_str(":")?;
}
// Add a ':' wrapper if there are other wrappers apart from c:pk_k()
// tvc:pk_k() -> tv:pk()
Some(('c', ms)) => match ms.node {
Terminal::PkK(_) | Terminal::PkH(_) | Terminal::RawPkH(_) => {
fmt::Write::write_char(f, ':')?
f.write_str(":")?;
}
_ => {}
},
_ => {}
};
write!(f, "{}", sub)
if is_debug {
write!(f, "{:?}", sub)
} else {
write!(f, "{}", sub)
}
} else {
unreachable!();
}
Expand All @@ -241,6 +133,109 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> fmt::Display for Terminal<Pk, Ctx> {
}
}

fn fmt_1<D: fmt::Debug + fmt::Display>(
f: &mut fmt::Formatter,
name: &str,
a: &D,
is_debug: bool,
) -> fmt::Result {
f.write_str(&name)?;
conditional_fmt(f, a, is_debug)?;
f.write_str(")")
}
fn fmt_2<D: fmt::Debug + fmt::Display>(
f: &mut fmt::Formatter,
name: &str,
a: &D,
b: &D,
is_debug: bool,
) -> fmt::Result {
f.write_str(&name)?;
conditional_fmt(f, a, is_debug)?;
f.write_str(",")?;
conditional_fmt(f, b, is_debug)?;
f.write_str(")")
}
fn fmt_n<D: fmt::Debug + fmt::Display>(
f: &mut fmt::Formatter,
name: &str,
first: usize,
list: &[D],
is_debug: bool,
) -> fmt::Result {
f.write_str(&name)?;
write!(f, "{}", first)?;
for el in list {
f.write_str(",")?;
conditional_fmt(f, el, is_debug)?;
}
f.write_str(")")
}
fn conditional_fmt<D: fmt::Debug + fmt::Display>(
f: &mut fmt::Formatter,
data: &D,
is_debug: bool,
) -> fmt::Result {
if is_debug {
fmt::Debug::fmt(data, f)
} else {
fmt::Display::fmt(data, f)
}
}

impl<Pk: MiniscriptKey, Ctx: ScriptContext> fmt::Debug for Terminal<Pk, Ctx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fn fmt_type_map(f: &mut fmt::Formatter<'_>, type_map: types::Type) -> fmt::Result {
f.write_str(match type_map.corr.base {
types::Base::B => "B",
types::Base::K => "K",
types::Base::V => "V",
types::Base::W => "W",
})?;
f.write_str("/")?;
f.write_str(match type_map.corr.input {
types::Input::Zero => "z",
types::Input::One => "o",
types::Input::OneNonZero => "on",
types::Input::Any => "",
types::Input::AnyNonZero => "n",
})?;
if type_map.corr.dissatisfiable {
f.write_str("d")?;
}
if type_map.corr.unit {
f.write_str("u")?;
}
f.write_str(match type_map.mall.dissat {
types::Dissat::None => "f",
types::Dissat::Unique => "e",
types::Dissat::Unknown => "",
})?;
if type_map.mall.safe {
f.write_str("s")?;
}
if type_map.mall.non_malleable {
f.write_str("m")?;
}
Ok(())
}

f.write_str("[")?;
if let Ok(type_map) = types::Type::type_check(self) {
fmt_type_map(f, type_map)?;
} else {
f.write_str("TYPECHECK FAILED")?;
}
f.write_str("]")?;

self.conditional_fmt(f, true)
}
}

impl<Pk: MiniscriptKey, Ctx: ScriptContext> fmt::Display for Terminal<Pk, Ctx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.conditional_fmt(f, false) }
}

impl<Pk: FromStrKey, Ctx: ScriptContext> crate::expression::FromTree for Arc<Terminal<Pk, Ctx>> {
fn from_tree(top: &expression::Tree) -> Result<Arc<Terminal<Pk, Ctx>>, Error> {
Ok(Arc::new(expression::FromTree::from_tree(top)?))
Expand Down
Loading

0 comments on commit 22dad5e

Please sign in to comment.