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