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