1use core::fmt;
2use std::fmt::Display;
3
4use super::*;
5
6pub struct FloatDisplay(pub f64);
7impl fmt::Display for FloatDisplay {
8 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9 write!(f, "{:.7e}", self.0)
10 }
11}
12
13pub struct TableFloatDisplay(pub f64);
14impl fmt::Display for TableFloatDisplay {
15 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
16 if self.0.is_sign_positive() {
17 write!(f, " {: <13.7e}", self.0)
18 } else {
19 write!(f, "{: <14.7e}", self.0)
20 }
21 }
22}
23
24pub struct OptionDispaly<'a, T, F: Fn(&T, &mut fmt::Formatter<'_>) -> fmt::Result>(
25 pub &'a Option<T>,
26 pub F,
27);
28impl<T, F: Fn(&T, &mut fmt::Formatter<'_>) -> fmt::Result> Display for OptionDispaly<'_, T, F> {
29 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
30 if let Some(t) = self.0 {
31 self.1(t, f)
32 } else {
33 Ok(())
34 }
35 }
36}
37
38pub fn display_wrap<
39 W: fmt::Write,
40 T,
41 I: Iterator<Item = T>,
42 SEP: fmt::Display,
43 F: FnMut(T, &mut W) -> fmt::Result,
44>(
45 f: &mut W,
46 iter: I,
47 mut fmt_one: F,
48 line_sep: SEP,
49 item_sep: char,
50 wrap_size: usize,
51) -> fmt::Result {
52 use itertools::Itertools as _;
53 for mut ts in iter.into_iter().chunks(wrap_size).into_iter() {
54 write!(f, "\n{line_sep}")?;
55 if let Some(first) = ts.next() {
56 fmt_one(first, f)?;
57 for t in ts {
58 write!(f, "{}", item_sep)?;
59 fmt_one(t, f)?;
60 }
61 }
62 }
63 Ok(())
64}
65
66pub fn display_inline<
67 W: fmt::Write,
68 T,
69 I: Iterator<Item = T>,
70 F: FnMut(T, &mut W) -> fmt::Result,
71>(
72 f: &mut W,
73 iter: I,
74 mut fmt_one: F,
75 sep: char,
76 skip_first_sep: bool,
77) -> fmt::Result {
78 let mut iter = iter.into_iter();
79 if skip_first_sep {
80 if let Some(first) = iter.next() {
81 fmt_one(first, f)?;
82 }
83 }
84 for t in iter {
85 write!(f, "{sep}")?;
86 fmt_one(t, f)?;
87 }
88 Ok(())
89}
90
91pub fn display_multiline<
92 W: fmt::Write,
93 T,
94 I: Iterator<Item = T>,
95 F: FnMut(T, &mut W) -> fmt::Result,
96>(
97 f: &mut W,
98 iter: I,
99 mut fmt_one: F,
100) -> fmt::Result {
101 for t in iter.into_iter() {
102 writeln!(f)?;
103 fmt_one(t, f)?;
104 }
105 Ok(())
106}
107
108impl fmt::Display for ast::Value<'_> {
109 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
110 match self {
111 Self::Num(float) => write!(f, "{}", FloatDisplay(*float)),
112 Self::Expr(expr) => write!(f, "'{expr}'"),
113 }
114 }
115}
116impl fmt::Display for ast::KeyValue<'_> {
117 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
118 write!(f, "{}={}", self.k, self.v)
119 }
120}
121
122impl fmt::Display for ast::Token<'_> {
123 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
124 match self {
125 Self::KV(key_value) => write!(f, "{key_value}"),
126 Self::Value(v) => write!(f, "{v}"),
127 Self::V(name) => write!(f, "V({name})"),
128 Self::I(name) => write!(f, "I({name})"),
129 }
130 }
131}
132
133impl fmt::Display for ast::ModelType<'_> {
134 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
135 match self {
136 Self::AMP => write!(f, "AMP"),
137 Self::C => write!(f, "C"),
138 Self::CORE => write!(f, "CORE"),
139 Self::D => write!(f, "D"),
140 Self::L => write!(f, "L"),
141 Self::NJF => write!(f, "NJF"),
142 Self::NMOS => write!(f, "NMOS"),
143 Self::NPN => write!(f, "NPN"),
144 Self::OPT => write!(f, "OPT"),
145 Self::PJF => write!(f, "PJF"),
146 Self::PMOS => write!(f, "PMOS"),
147 Self::PNP => write!(f, "PNP"),
148 Self::R => write!(f, "R"),
149 Self::U => write!(f, "U"),
150 Self::W => write!(f, "W"),
151 Self::S => write!(f, "S"),
152 Self::Unknown(span) => write!(f, "{span}"),
153 }
154 }
155}
156impl fmt::Display for ast::DataFiles<'_> {
157 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
158 display_multiline(f, self.files.iter(), |file, f| {
159 write!(f, "+ FILE='{}'", file.file)?;
160 display_inline(
161 f,
162 file.pname_col_num.iter(),
163 |pname_col_num, f| write!(f, "{}={}", pname_col_num.pname, pname_col_num.col_num),
164 ' ',
165 false,
166 )
167 })?;
168 write!(
169 f,
170 "{}",
171 OptionDispaly(&self.out, |out, f| write!(f, "\n+ OUT='{out}'")),
172 )
173 }
174}
175
176impl fmt::Display for ast::Data<'_> {
177 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
178 write!(f, ".DATA {}", self.name)?;
179 match &self.values {
180 ast::DataValues::InlineExpr { params, values } => {
181 write!(f, "\n+",)?;
182 display_inline(f, params.iter(), Display::fmt, ' ', false)?;
183 write!(f, " DATAFORM")?;
184 display_wrap(f, values.iter(), Display::fmt, "+ ", ' ', params.len())?;
185 }
186 ast::DataValues::InlineNum { params, values } => {
187 write!(f, "\n+",)?;
188 display_inline(f, params.iter(), Display::fmt, ' ', false)?;
189 display_wrap(
190 f,
191 values.iter(),
192 |float: &f64, f: &mut fmt::Formatter<'_>| write!(f, "{}", FloatDisplay(*float)),
193 "+ ",
194 ' ',
195 params.len(),
196 )?;
197 }
198 ast::DataValues::MER(data_files) => write!(f, " MER{data_files}")?,
199 ast::DataValues::LAM(data_files) => write!(f, " LAM{data_files}")?,
200 }
201 write!(f, "\n.ENDDATA")
202 }
203}
204
205impl fmt::Display for instance::Instance<'_> {
206 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
207 write!(f, "{} {}", self.name, self.ctx)
208 }
209}
210
211impl fmt::Display for instance::InstanceCtx<'_> {
212 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
213 match self {
214 instance::InstanceCtx::Resistor(resistor) => write!(f, "{resistor}"),
215 instance::InstanceCtx::Capacitor(capacitor) => write!(f, "{capacitor}"),
216 instance::InstanceCtx::Inductor(inductor) => write!(f, "{inductor}"),
217 instance::InstanceCtx::Voltage(voltage) => write!(f, "{voltage}"),
218 instance::InstanceCtx::Current(current) => write!(f, "{current}"),
219 instance::InstanceCtx::MOSFET(mosfet) => write!(f, "{mosfet}"),
220 instance::InstanceCtx::BJT(bjt) => write!(f, "{bjt}"),
221 instance::InstanceCtx::Diode(diode) => write!(f, "{diode}"),
222 instance::InstanceCtx::Subckt(subckt) => write!(f, "{subckt}"),
223 instance::InstanceCtx::Unknown {
224 r#type: _,
225 nodes,
226 params,
227 } => {
228 display_inline(f, nodes.iter(), Display::fmt, ' ', true)?;
229 display_inline(f, params.iter(), Display::fmt, ' ', false)
230 }
231 }
232 }
233}
234
235impl fmt::Display for instance::Subckt<'_> {
236 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
237 display_inline(f, self.nodes.iter(), Display::fmt, ' ', true)?;
238 write!(f, " {}", self.cktname)?;
239 display_inline(f, self.params.iter(), Display::fmt, ' ', false)
240 }
241}
242
243impl fmt::Display for instance::Voltage<'_> {
244 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
245 write!(f, "{} {} {}", self.n1, self.n2, self.source,)
246 }
247}
248
249impl fmt::Display for instance::Current<'_> {
250 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
251 write!(f, "{} {} {}", self.n1, self.n2, self.source,)
252 }
253}
254
255impl fmt::Display for instance::VoltageSource<'_> {
256 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
257 match self {
258 instance::VoltageSource::Params(params) => {
259 display_inline(f, params.iter(), Display::fmt, ' ', false)
260 }
261 instance::VoltageSource::Value(value) => write!(f, "{value}"),
262 instance::VoltageSource::PWL(pwl) => write!(f, "{pwl}"),
263 }
264 }
265}
266
267impl fmt::Display for instance::CurrentSource<'_> {
268 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
269 match self {
270 instance::CurrentSource::Params(params) => {
271 display_inline(f, params.iter(), Display::fmt, ' ', false)
272 }
273 instance::CurrentSource::Value(value) => write!(f, "{value}"),
274 instance::CurrentSource::PWL(pwl) => write!(f, "{pwl}"),
275 }
276 }
277}
278
279impl fmt::Display for instance::TimeValuePoint<'_> {
280 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
281 write!(f, "{} {}", self.time, self.value,)
282 }
283}
284
285impl fmt::Display for instance::PWL<'_> {
286 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
287 write!(f, "PWL(",)?;
288 display_wrap(f, self.points.iter(), Display::fmt, "+ ", ' ', 1)?;
289 write!(f, ")",)
290 }
291}
292
293impl fmt::Display for instance::Resistor<'_> {
294 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
295 write!(f, "{} {} {}", self.n1, self.n2, self.value,)
296 }
297}
298impl fmt::Display for instance::Capacitor<'_> {
299 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
300 write!(f, "{} {} {}", self.n1, self.n2, self.value,)
301 }
302}
303impl fmt::Display for instance::Inductor<'_> {
304 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
305 write!(f, "{} {} {}", self.n1, self.n2, self.value,)
306 }
307}
308
309impl fmt::Display for instance::MOSFET<'_> {
310 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
311 write!(
312 f,
313 "{} {} {}{} {}",
314 self.nd,
315 self.ng,
316 self.ns,
317 OptionDispaly(&self.nb, |nb, f| write!(f, " {nb}")),
318 self.mname,
319 )?;
320 display_inline(f, self.params.iter(), Display::fmt, ' ', false)
321 }
322}
323
324impl fmt::Display for instance::BJT<'_> {
325 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
326 write!(
327 f,
328 "{} {} {}{} {}",
329 self.nc,
330 self.nb,
331 self.ne,
332 OptionDispaly(&self.ns, |ns, f| write!(f, " {ns}")),
333 self.mname,
334 )?;
335 display_inline(f, self.params.iter(), Display::fmt, ' ', false)
336 }
337}
338
339impl fmt::Display for instance::Diode<'_> {
340 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
341 write!(f, "{} {} {}", self.nplus, self.nminus, self.mname,)?;
342 display_inline(f, self.params.iter(), Display::fmt, ' ', false)
343 }
344}
345
346impl fmt::Display for ast::Model<'_> {
347 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
348 write!(f, ".MODEL {} {}", self.name, self.model_type,)?;
349 display_wrap(f, self.params.iter(), Display::fmt, "+ ", ' ', 4)
350 }
351}
352
353impl fmt::Display for Subckt<'_> {
354 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
355 write!(f, ".SUBCKT {}", self.name,)?;
356 display_inline(f, self.ports.iter(), Display::fmt, ' ', false)?;
357 display_inline(f, self.params.iter(), Display::fmt, ' ', false)?;
358 write!(f, "{}\n.ENDS {}", self.ast, self.name)
359 }
360}
361
362impl fmt::Display for ast::Unknwon<'_> {
363 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
364 write!(f, ".{}", self.cmd)?;
365 display_inline(f, self.tokens.iter(), Display::fmt, ' ', false)
366 }
367}
368impl fmt::Display for ast::General<'_> {
369 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
370 write!(f, ".{}", self.cmd)?;
371 display_inline(f, self.tokens.iter(), Display::fmt, ' ', false)
372 }
373}
374
375impl fmt::Display for AST<'_> {
376 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
377 if !self.option.is_empty() {
378 write!(f, ".OPTION ",)?;
379 display_wrap(
380 f,
381 self.option.iter(),
382 |option: &(Cow<'_, str>, Option<ast::Value<'_>>), f: &mut fmt::Formatter<'_>| {
383 if let Some(v) = &option.1 {
384 write!(f, "{}={v}", option.0)
385 } else {
386 write!(f, "{}", option.0)
387 }
388 },
389 "+ ",
390 ' ',
391 4,
392 )?;
393 }
394 if !self.param.is_empty() {
395 write!(f, "\n.PARAM ",)?;
396 display_wrap(f, self.param.iter(), Display::fmt, "+ ", ' ', 4)?;
397 }
398 display_multiline(f, self.model.iter(), Display::fmt)?;
399 display_multiline(f, self.subckt.values(), Display::fmt)?;
400 display_multiline(f, self.instance.iter(), Display::fmt)?;
401 display_multiline(
402 f,
403 self.init_condition.iter(),
404 |ic: &(Cow<'_, str>, ast::Value<'_>, Option<Cow<'_, str>>),
405 f: &mut fmt::Formatter<'_>| {
406 write!(f, ".IC V({})={}", ic.0, ic.1)?;
407 if let Some(subckt) = &ic.2 {
408 write!(f, " suckt={subckt}")
409 } else {
410 Ok(())
411 }
412 },
413 )?;
414 display_multiline(
415 f,
416 self.nodeset.iter(),
417 |ic: &(Cow<'_, str>, ast::Value<'_>, Option<Cow<'_, str>>),
418 f: &mut fmt::Formatter<'_>| {
419 write!(f, ".NODESET {}={}", ic.0, ic.1)?;
420 if let Some(subckt) = &ic.2 {
421 write!(f, " suckt={subckt}")
422 } else {
423 Ok(())
424 }
425 },
426 )?;
427 display_multiline(f, self.data.iter(), Display::fmt)?;
428 display_multiline(f, self.general.iter(), Display::fmt)?;
429 display_multiline(f, self.unknwon.iter(), Display::fmt)?;
430 Ok(())
431 }
432}
433
434impl fmt::Display for ast::GeneralCmd {
435 fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
436 todo!()
437 }
438}