Skip to content

Commit 22dad5e

Browse files
committed
Merge #651: add conditional formatting for Terminal
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
2 parents dcbef52 + 395aab8 commit 22dad5e

File tree

2 files changed

+148
-153
lines changed

2 files changed

+148
-153
lines changed

src/miniscript/astelem.rs

+140-145
Original file line numberDiff line numberDiff line change
@@ -42,197 +42,89 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Terminal<Pk, Ctx> {
4242
_ => None,
4343
}
4444
}
45-
}
4645

47-
impl<Pk: MiniscriptKey, Ctx: ScriptContext> fmt::Debug for Terminal<Pk, Ctx> {
48-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
49-
f.write_str("[")?;
50-
if let Ok(type_map) = types::Type::type_check(self) {
51-
f.write_str(match type_map.corr.base {
52-
types::Base::B => "B",
53-
types::Base::K => "K",
54-
types::Base::V => "V",
55-
types::Base::W => "W",
56-
})?;
57-
fmt::Write::write_char(f, '/')?;
58-
f.write_str(match type_map.corr.input {
59-
types::Input::Zero => "z",
60-
types::Input::One => "o",
61-
types::Input::OneNonZero => "on",
62-
types::Input::Any => "",
63-
types::Input::AnyNonZero => "n",
64-
})?;
65-
if type_map.corr.dissatisfiable {
66-
fmt::Write::write_char(f, 'd')?;
67-
}
68-
if type_map.corr.unit {
69-
fmt::Write::write_char(f, 'u')?;
70-
}
71-
f.write_str(match type_map.mall.dissat {
72-
types::Dissat::None => "f",
73-
types::Dissat::Unique => "e",
74-
types::Dissat::Unknown => "",
75-
})?;
76-
if type_map.mall.safe {
77-
fmt::Write::write_char(f, 's')?;
78-
}
79-
if type_map.mall.non_malleable {
80-
fmt::Write::write_char(f, 'm')?;
81-
}
82-
} else {
83-
f.write_str("TYPECHECK FAILED")?;
84-
}
85-
f.write_str("]")?;
86-
if let Some((ch, sub)) = self.wrap_char() {
87-
fmt::Write::write_char(f, ch)?;
88-
if sub.node.wrap_char().is_none() {
89-
fmt::Write::write_char(f, ':')?;
90-
}
91-
write!(f, "{:?}", sub)
92-
} else {
93-
match *self {
94-
Terminal::PkK(ref pk) => write!(f, "pk_k({:?})", pk),
95-
Terminal::PkH(ref pk) => write!(f, "pk_h({:?})", pk),
96-
Terminal::RawPkH(ref pkh) => write!(f, "expr_raw_pk_h({:?})", pkh),
97-
Terminal::After(t) => write!(f, "after({})", t),
98-
Terminal::Older(t) => write!(f, "older({})", t),
99-
Terminal::Sha256(ref h) => write!(f, "sha256({})", h),
100-
Terminal::Hash256(ref h) => write!(f, "hash256({})", h),
101-
Terminal::Ripemd160(ref h) => write!(f, "ripemd160({})", h),
102-
Terminal::Hash160(ref h) => write!(f, "hash160({})", h),
103-
Terminal::True => f.write_str("1"),
104-
Terminal::False => f.write_str("0"),
105-
Terminal::AndV(ref l, ref r) => write!(f, "and_v({:?},{:?})", l, r),
106-
Terminal::AndB(ref l, ref r) => write!(f, "and_b({:?},{:?})", l, r),
107-
Terminal::AndOr(ref a, ref b, ref c) => {
108-
if c.node == Terminal::False {
109-
write!(f, "and_n({:?},{:?})", a, b)
110-
} else {
111-
write!(f, "andor({:?},{:?},{:?})", a, b, c)
112-
}
113-
}
114-
Terminal::OrB(ref l, ref r) => write!(f, "or_b({:?},{:?})", l, r),
115-
Terminal::OrD(ref l, ref r) => write!(f, "or_d({:?},{:?})", l, r),
116-
Terminal::OrC(ref l, ref r) => write!(f, "or_c({:?},{:?})", l, r),
117-
Terminal::OrI(ref l, ref r) => write!(f, "or_i({:?},{:?})", l, r),
118-
Terminal::Thresh(k, ref subs) => {
119-
write!(f, "thresh({}", k)?;
120-
for s in subs {
121-
write!(f, ",{:?}", s)?;
122-
}
123-
f.write_str(")")
124-
}
125-
Terminal::Multi(k, ref keys) => {
126-
write!(f, "multi({}", k)?;
127-
for k in keys {
128-
write!(f, ",{:?}", k)?;
129-
}
130-
f.write_str(")")
131-
}
132-
Terminal::MultiA(k, ref keys) => {
133-
write!(f, "multi_a({}", k)?;
134-
for k in keys {
135-
write!(f, ",{}", k)?;
136-
}
137-
f.write_str(")")
138-
}
139-
_ => unreachable!(),
140-
}
141-
}
142-
}
143-
}
144-
145-
impl<Pk: MiniscriptKey, Ctx: ScriptContext> fmt::Display for Terminal<Pk, Ctx> {
146-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
46+
fn conditional_fmt(&self, f: &mut fmt::Formatter, is_debug: bool) -> fmt::Result {
14747
match *self {
148-
Terminal::PkK(ref pk) => write!(f, "pk_k({})", pk),
149-
Terminal::PkH(ref pk) => write!(f, "pk_h({})", pk),
150-
Terminal::RawPkH(ref pkh) => write!(f, "expr_raw_pk_h({})", pkh),
151-
Terminal::After(t) => write!(f, "after({})", t),
152-
Terminal::Older(t) => write!(f, "older({})", t),
153-
Terminal::Sha256(ref h) => write!(f, "sha256({})", h),
154-
Terminal::Hash256(ref h) => write!(f, "hash256({})", h),
155-
Terminal::Ripemd160(ref h) => write!(f, "ripemd160({})", h),
156-
Terminal::Hash160(ref h) => write!(f, "hash160({})", h),
48+
Terminal::PkK(ref pk) => fmt_1(f, "pk_k(", pk, is_debug),
49+
Terminal::PkH(ref pk) => fmt_1(f, "pk_h(", pk, is_debug),
50+
Terminal::RawPkH(ref pkh) => fmt_1(f, "expr_raw_pk_h(", pkh, is_debug),
51+
Terminal::After(ref t) => fmt_1(f, "after(", t, is_debug),
52+
Terminal::Older(ref t) => fmt_1(f, "older(", t, is_debug),
53+
Terminal::Sha256(ref h) => fmt_1(f, "sha256(", h, is_debug),
54+
Terminal::Hash256(ref h) => fmt_1(f, "hash256(", h, is_debug),
55+
Terminal::Ripemd160(ref h) => fmt_1(f, "ripemd160(", h, is_debug),
56+
Terminal::Hash160(ref h) => fmt_1(f, "hash160(", h, is_debug),
15757
Terminal::True => f.write_str("1"),
15858
Terminal::False => f.write_str("0"),
15959
Terminal::AndV(ref l, ref r) if r.node != Terminal::True => {
160-
write!(f, "and_v({},{})", l, r)
60+
fmt_2(f, "and_v(", l, r, is_debug)
16161
}
162-
Terminal::AndB(ref l, ref r) => write!(f, "and_b({},{})", l, r),
62+
Terminal::AndB(ref l, ref r) => fmt_2(f, "and_b(", l, r, is_debug),
16363
Terminal::AndOr(ref a, ref b, ref c) => {
16464
if c.node == Terminal::False {
165-
write!(f, "and_n({},{})", a, b)
65+
fmt_2(f, "and_b(", a, b, is_debug)
16666
} else {
167-
write!(f, "andor({},{},{})", a, b, c)
67+
f.write_str("andor(")?;
68+
conditional_fmt(f, a, is_debug)?;
69+
f.write_str(",")?;
70+
conditional_fmt(f, b, is_debug)?;
71+
f.write_str(",")?;
72+
conditional_fmt(f, c, is_debug)?;
73+
f.write_str(")")
16874
}
16975
}
170-
Terminal::OrB(ref l, ref r) => write!(f, "or_b({},{})", l, r),
171-
Terminal::OrD(ref l, ref r) => write!(f, "or_d({},{})", l, r),
172-
Terminal::OrC(ref l, ref r) => write!(f, "or_c({},{})", l, r),
76+
Terminal::OrB(ref l, ref r) => fmt_2(f, "or_b(", l, r, is_debug),
77+
Terminal::OrD(ref l, ref r) => fmt_2(f, "or_d(", l, r, is_debug),
78+
Terminal::OrC(ref l, ref r) => fmt_2(f, "or_c(", l, r, is_debug),
17379
Terminal::OrI(ref l, ref r)
17480
if l.node != Terminal::False && r.node != Terminal::False =>
17581
{
176-
write!(f, "or_i({},{})", l, r)
177-
}
178-
Terminal::Thresh(k, ref subs) => {
179-
write!(f, "thresh({}", k)?;
180-
for s in subs {
181-
write!(f, ",{}", s)?;
182-
}
183-
f.write_str(")")
184-
}
185-
Terminal::Multi(k, ref keys) => {
186-
write!(f, "multi({}", k)?;
187-
for k in keys {
188-
write!(f, ",{}", k)?;
189-
}
190-
f.write_str(")")
191-
}
192-
Terminal::MultiA(k, ref keys) => {
193-
write!(f, "multi_a({}", k)?;
194-
for k in keys {
195-
write!(f, ",{}", k)?;
196-
}
197-
f.write_str(")")
82+
fmt_2(f, "or_i(", l, r, is_debug)
19883
}
84+
Terminal::Thresh(k, ref subs) => fmt_n(f, "thresh(", k, subs, is_debug),
85+
Terminal::Multi(k, ref keys) => fmt_n(f, "multi(", k, keys, is_debug),
86+
Terminal::MultiA(k, ref keys) => fmt_n(f, "multi_a(", k, keys, is_debug),
19987
// wrappers
20088
_ => {
20189
if let Some((ch, sub)) = self.wrap_char() {
20290
if ch == 'c' {
20391
if let Terminal::PkK(ref pk) = sub.node {
20492
// alias: pk(K) = c:pk_k(K)
205-
return write!(f, "pk({})", pk);
93+
return fmt_1(f, "pk(", pk, is_debug);
20694
} else if let Terminal::RawPkH(ref pkh) = sub.node {
20795
// `RawPkH` is currently unsupported in the descriptor spec
20896
// alias: pkh(K) = c:pk_h(K)
20997
// We temporarily display there using raw_pkh, but these descriptors
21098
// are not defined in the spec yet. These are prefixed with `expr`
21199
// in the descriptor string.
212100
// We do not support parsing these descriptors yet.
213-
return write!(f, "expr_raw_pkh({})", pkh);
101+
return fmt_1(f, "expr_raw_pkh(", pkh, is_debug);
214102
} else if let Terminal::PkH(ref pk) = sub.node {
215103
// alias: pkh(K) = c:pk_h(K)
216-
return write!(f, "pkh({})", pk);
104+
return fmt_1(f, "pkh(", pk, is_debug);
217105
}
218106
}
219107

220108
fmt::Write::write_char(f, ch)?;
221109
match sub.node.wrap_char() {
222110
None => {
223-
fmt::Write::write_char(f, ':')?;
111+
f.write_str(":")?;
224112
}
225113
// Add a ':' wrapper if there are other wrappers apart from c:pk_k()
226114
// tvc:pk_k() -> tv:pk()
227115
Some(('c', ms)) => match ms.node {
228116
Terminal::PkK(_) | Terminal::PkH(_) | Terminal::RawPkH(_) => {
229-
fmt::Write::write_char(f, ':')?
117+
f.write_str(":")?;
230118
}
231119
_ => {}
232120
},
233121
_ => {}
234122
};
235-
write!(f, "{}", sub)
123+
if is_debug {
124+
write!(f, "{:?}", sub)
125+
} else {
126+
write!(f, "{}", sub)
127+
}
236128
} else {
237129
unreachable!();
238130
}
@@ -241,6 +133,109 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> fmt::Display for Terminal<Pk, Ctx> {
241133
}
242134
}
243135

136+
fn fmt_1<D: fmt::Debug + fmt::Display>(
137+
f: &mut fmt::Formatter,
138+
name: &str,
139+
a: &D,
140+
is_debug: bool,
141+
) -> fmt::Result {
142+
f.write_str(&name)?;
143+
conditional_fmt(f, a, is_debug)?;
144+
f.write_str(")")
145+
}
146+
fn fmt_2<D: fmt::Debug + fmt::Display>(
147+
f: &mut fmt::Formatter,
148+
name: &str,
149+
a: &D,
150+
b: &D,
151+
is_debug: bool,
152+
) -> fmt::Result {
153+
f.write_str(&name)?;
154+
conditional_fmt(f, a, is_debug)?;
155+
f.write_str(",")?;
156+
conditional_fmt(f, b, is_debug)?;
157+
f.write_str(")")
158+
}
159+
fn fmt_n<D: fmt::Debug + fmt::Display>(
160+
f: &mut fmt::Formatter,
161+
name: &str,
162+
first: usize,
163+
list: &[D],
164+
is_debug: bool,
165+
) -> fmt::Result {
166+
f.write_str(&name)?;
167+
write!(f, "{}", first)?;
168+
for el in list {
169+
f.write_str(",")?;
170+
conditional_fmt(f, el, is_debug)?;
171+
}
172+
f.write_str(")")
173+
}
174+
fn conditional_fmt<D: fmt::Debug + fmt::Display>(
175+
f: &mut fmt::Formatter,
176+
data: &D,
177+
is_debug: bool,
178+
) -> fmt::Result {
179+
if is_debug {
180+
fmt::Debug::fmt(data, f)
181+
} else {
182+
fmt::Display::fmt(data, f)
183+
}
184+
}
185+
186+
impl<Pk: MiniscriptKey, Ctx: ScriptContext> fmt::Debug for Terminal<Pk, Ctx> {
187+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
188+
fn fmt_type_map(f: &mut fmt::Formatter<'_>, type_map: types::Type) -> fmt::Result {
189+
f.write_str(match type_map.corr.base {
190+
types::Base::B => "B",
191+
types::Base::K => "K",
192+
types::Base::V => "V",
193+
types::Base::W => "W",
194+
})?;
195+
f.write_str("/")?;
196+
f.write_str(match type_map.corr.input {
197+
types::Input::Zero => "z",
198+
types::Input::One => "o",
199+
types::Input::OneNonZero => "on",
200+
types::Input::Any => "",
201+
types::Input::AnyNonZero => "n",
202+
})?;
203+
if type_map.corr.dissatisfiable {
204+
f.write_str("d")?;
205+
}
206+
if type_map.corr.unit {
207+
f.write_str("u")?;
208+
}
209+
f.write_str(match type_map.mall.dissat {
210+
types::Dissat::None => "f",
211+
types::Dissat::Unique => "e",
212+
types::Dissat::Unknown => "",
213+
})?;
214+
if type_map.mall.safe {
215+
f.write_str("s")?;
216+
}
217+
if type_map.mall.non_malleable {
218+
f.write_str("m")?;
219+
}
220+
Ok(())
221+
}
222+
223+
f.write_str("[")?;
224+
if let Ok(type_map) = types::Type::type_check(self) {
225+
fmt_type_map(f, type_map)?;
226+
} else {
227+
f.write_str("TYPECHECK FAILED")?;
228+
}
229+
f.write_str("]")?;
230+
231+
self.conditional_fmt(f, true)
232+
}
233+
}
234+
235+
impl<Pk: MiniscriptKey, Ctx: ScriptContext> fmt::Display for Terminal<Pk, Ctx> {
236+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.conditional_fmt(f, false) }
237+
}
238+
244239
impl<Pk: FromStrKey, Ctx: ScriptContext> crate::expression::FromTree for Arc<Terminal<Pk, Ctx>> {
245240
fn from_tree(top: &expression::Tree) -> Result<Arc<Terminal<Pk, Ctx>>, Error> {
246241
Ok(Arc::new(expression::FromTree::from_tree(top)?))

0 commit comments

Comments
 (0)