1use super::Sig;
2use crate::{
3 expr::{
4 parser, ApplyExpr, BindExpr, BindSig, Doc, Expr, ExprKind, LambdaExpr,
5 ModuleKind, Sandbox, SelectExpr, SigItem, SigKind, StructExpr, StructWithExpr,
6 TypeDefExpr,
7 },
8 typ::Type,
9};
10use compact_str::format_compact;
11use netidx::{path::Path, utils::Either};
12use netidx_value::{parser::VAL_ESC, Value};
13use poolshark::local::LPooled;
14use std::fmt::{self, Formatter, Write};
15
16fn pretty_print_exprs_int<'a, A, F: Fn(&'a A) -> &'a Expr>(
17 buf: &mut PrettyBuf,
18 exprs: &'a [A],
19 open: &str,
20 close: &str,
21 sep: &str,
22 f: F,
23) -> fmt::Result {
24 writeln!(buf, "{}", open)?;
25 buf.with_indent::<fmt::Result, _>(2, |buf| {
26 for i in 0..exprs.len() {
27 f(&exprs[i]).kind.fmt_pretty(buf)?;
28 if i < exprs.len() - 1 {
29 buf.kill_newline();
30 writeln!(buf, "{}", sep)?
31 }
32 }
33 Ok(())
34 })?;
35 writeln!(buf, "{}", close)
36}
37
38fn pretty_print_exprs(
39 buf: &mut PrettyBuf,
40 exprs: &[Expr],
41 open: &str,
42 close: &str,
43 sep: &str,
44) -> fmt::Result {
45 pretty_print_exprs_int(buf, exprs, open, close, sep, |a| a)
46}
47
48#[derive(Debug)]
49pub struct PrettyBuf {
50 pub indent: usize,
51 pub limit: usize,
52 pub buf: LPooled<String>,
53}
54
55impl PrettyBuf {
56 pub fn new(limit: usize) -> Self {
57 Self { indent: 0, limit, buf: LPooled::take() }
58 }
59
60 pub fn len(&self) -> usize {
61 self.buf.len()
62 }
63
64 pub fn newline(&self) -> bool {
65 self.buf.chars().next_back().map(|c| c == '\n').unwrap_or(true)
66 }
67
68 pub fn push_indent(&mut self) {
69 if self.newline() {
70 self.buf.extend((0..self.indent).into_iter().map(|_| ' '));
71 }
72 }
73
74 pub fn with_indent<R, F: FnOnce(&mut Self) -> R>(&mut self, inc: usize, f: F) -> R {
75 self.indent += inc;
76 let r = f(self);
77 self.indent -= inc;
78 r
79 }
80
81 pub fn kill_newline(&mut self) {
82 if let Some('\n') = self.buf.chars().next_back() {
83 self.buf.pop();
84 }
85 }
86}
87
88impl fmt::Write for PrettyBuf {
89 fn write_char(&mut self, c: char) -> fmt::Result {
90 self.push_indent();
91 self.buf.write_char(c)
92 }
93
94 fn write_str(&mut self, s: &str) -> fmt::Result {
95 self.push_indent();
96 self.buf.write_str(s)
97 }
98
99 fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> fmt::Result {
100 self.push_indent();
101 self.buf.write_fmt(args)
102 }
103}
104
105pub trait PrettyDisplay: fmt::Display {
106 fn fmt_pretty_inner(&self, buf: &mut PrettyBuf) -> fmt::Result;
109
110 fn fmt_pretty(&self, buf: &mut PrettyBuf) -> fmt::Result {
114 use fmt::Write;
115 let start = buf.len();
116 writeln!(buf, "{}", self)?;
117 if buf.len() - start <= buf.limit {
121 return Ok(());
122 } else {
123 buf.buf.truncate(start);
124 self.fmt_pretty_inner(buf)
125 }
126 }
127
128 fn to_string_pretty(&self, limit: usize) -> LPooled<String> {
130 let mut buf = PrettyBuf::new(limit);
131 self.fmt_pretty(&mut buf).unwrap();
132 buf.buf
133 }
134}
135
136impl fmt::Display for Doc {
137 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
138 if let Some(doc) = self.0.as_ref() {
139 if doc == "" {
140 writeln!(f, "///")?;
141 } else {
142 for line in doc.lines() {
143 writeln!(f, "///{line}")?;
144 }
145 }
146 }
147 Ok(())
148 }
149}
150
151impl PrettyDisplay for Doc {
152 fn fmt_pretty_inner(&self, buf: &mut PrettyBuf) -> fmt::Result {
153 if let Some(doc) = self.0.as_ref() {
154 if doc == "" {
155 writeln!(buf, "///")?;
156 } else {
157 for line in doc.lines() {
158 writeln!(buf, "///{line}")?;
159 }
160 }
161 }
162 Ok(())
163 }
164}
165
166impl TypeDefExpr {
167 fn write_name_and_params(&self, f: &mut impl fmt::Write) -> fmt::Result {
168 write!(f, "type {}", self.name)?;
169 if !self.params.is_empty() {
170 write!(f, "<")?;
171 for (i, (tv, ct)) in self.params.iter().enumerate() {
172 write!(f, "{tv}")?;
173 if let Some(ct) = ct {
174 write!(f, ": {ct}")?;
175 }
176 if i < self.params.len() - 1 {
177 write!(f, ", ")?;
178 }
179 }
180 write!(f, ">")?;
181 }
182 Ok(())
183 }
184}
185
186impl fmt::Display for TypeDefExpr {
187 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
188 self.write_name_and_params(f)?;
189 write!(f, " = {}", self.typ)
190 }
191}
192
193impl PrettyDisplay for TypeDefExpr {
194 fn fmt_pretty_inner(&self, buf: &mut PrettyBuf) -> fmt::Result {
195 self.write_name_and_params(buf)?;
196 writeln!(buf, " =")?;
197 buf.with_indent(2, |buf| self.typ.fmt_pretty(buf))
198 }
199}
200
201impl fmt::Display for Sandbox {
202 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
203 macro_rules! write_sandbox {
204 ($kind:literal, $l:expr) => {{
205 write!(f, "sandbox {} [ ", $kind)?;
206 for (i, p) in $l.iter().enumerate() {
207 if i < $l.len() - 1 {
208 write!(f, "{}, ", p)?
209 } else {
210 write!(f, "{}", p)?
211 }
212 }
213 write!(f, " ]")
214 }};
215 }
216 match self {
217 Sandbox::Unrestricted => write!(f, "sandbox unrestricted"),
218 Sandbox::Blacklist(l) => write_sandbox!("blacklist", l),
219 Sandbox::Whitelist(l) => write_sandbox!("whitelist", l),
220 }
221 }
222}
223
224impl PrettyDisplay for Sandbox {
225 fn fmt_pretty_inner(&self, buf: &mut PrettyBuf) -> fmt::Result {
226 macro_rules! write_sandbox {
227 ($kind:literal, $l:expr) => {{
228 writeln!(buf, "sandbox {} [ ", $kind)?;
229 buf.with_indent::<fmt::Result, _>(2, |buf| {
230 for (i, p) in $l.iter().enumerate() {
231 if i < $l.len() - 1 {
232 writeln!(buf, "{}, ", p)?
233 } else {
234 writeln!(buf, "{}", p)?
235 }
236 }
237 Ok(())
238 })?;
239 write!(buf, " ]")
240 }};
241 }
242 match self {
243 Sandbox::Blacklist(l) => write_sandbox!("blacklist", l),
244 Sandbox::Whitelist(l) => write_sandbox!("whitelist", l),
245 Sandbox::Unrestricted => writeln!(buf, "sandbox unrestricted"),
246 }
247 }
248}
249
250impl fmt::Display for BindSig {
251 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
252 write!(f, "val {}: {}", self.name, self.typ)
253 }
254}
255
256impl PrettyDisplay for BindSig {
257 fn fmt_pretty_inner(&self, buf: &mut PrettyBuf) -> fmt::Result {
258 write!(buf, "val {}: ", self.name)?;
259 self.typ.fmt_pretty(buf)
260 }
261}
262
263impl fmt::Display for SigItem {
264 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
265 write!(f, "{}", self.doc)?;
266 match &self.kind {
267 SigKind::TypeDef(td) => write!(f, "{td}"),
268 SigKind::Bind(bind) => write!(f, "{bind}"),
269 SigKind::Module(name) => write!(f, "mod {name}"),
270 SigKind::Use(path) => write!(f, "use {path}"),
271 }
272 }
273}
274
275impl PrettyDisplay for SigItem {
276 fn fmt_pretty_inner(&self, buf: &mut PrettyBuf) -> fmt::Result {
277 write!(buf, "{}", self.doc)?;
278 match &self.kind {
279 SigKind::Bind(b) => b.fmt_pretty(buf),
280 SigKind::TypeDef(d) => d.fmt_pretty(buf),
281 SigKind::Module(name) => writeln!(buf, "mod {name}"),
282 SigKind::Use(path) => writeln!(buf, "use {path}"),
283 }
284 }
285}
286
287impl fmt::Display for Sig {
288 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
289 if !self.toplevel {
290 write!(f, "sig {{ ")?;
291 }
292 for (i, si) in self.iter().enumerate() {
293 write!(f, "{si}")?;
294 if i < self.len() - 1 {
295 write!(f, "; ")?
296 }
297 }
298 if !self.toplevel {
299 write!(f, " }}")?
300 }
301 Ok(())
302 }
303}
304
305impl PrettyDisplay for Sig {
306 fn fmt_pretty_inner(&self, buf: &mut PrettyBuf) -> fmt::Result {
307 if !self.toplevel {
308 writeln!(buf, "sig {{")?;
309 }
310 buf.with_indent(2, |buf| {
311 for (i, si) in self.iter().enumerate() {
312 si.fmt_pretty(buf)?;
313 if i < self.len() - 1 {
314 buf.kill_newline();
315 writeln!(buf, ";")?
316 }
317 }
318 Ok(())
319 })?;
320 if !self.toplevel {
321 writeln!(buf, "}}")?
322 }
323 Ok(())
324 }
325}
326
327impl fmt::Display for BindExpr {
328 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
329 let BindExpr { rec, pattern, typ, value } = self;
330 let rec = if *rec { " rec" } else { "" };
331 match typ {
332 None => write!(f, "let{} {pattern} = {value}", rec),
333 Some(typ) => write!(f, "let{} {pattern}: {typ} = {value}", rec),
334 }
335 }
336}
337
338impl PrettyDisplay for BindExpr {
339 fn fmt_pretty_inner(&self, buf: &mut PrettyBuf) -> fmt::Result {
340 let BindExpr { rec, pattern, typ, value } = self;
341 let rec = if *rec { " rec" } else { "" };
342 match typ {
343 None => writeln!(buf, "let{} {pattern} = ", rec)?,
344 Some(typ) => writeln!(buf, "let{} {pattern}: {typ} = ", rec)?,
345 }
346 buf.with_indent(2, |buf| value.fmt_pretty(buf))
347 }
348}
349
350impl fmt::Display for StructWithExpr {
351 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
352 let Self { source, replace } = self;
353 match &source.kind {
354 ExprKind::Ref { .. } => write!(f, "{{ {source} with ")?,
355 _ => write!(f, "{{ ({source}) with ")?,
356 }
357 for (i, (name, e)) in replace.iter().enumerate() {
358 match &e.kind {
359 ExprKind::Ref { name: n }
360 if Path::dirname(&**n).is_none()
361 && Path::basename(&**n) == Some(&**name) =>
362 {
363 write!(f, "{name}")?
364 }
365 _ => write!(f, "{name}: {e}")?,
366 }
367 if i < replace.len() - 1 {
368 write!(f, ", ")?
369 }
370 }
371 write!(f, " }}")
372 }
373}
374
375impl PrettyDisplay for StructWithExpr {
376 fn fmt_pretty_inner(&self, buf: &mut PrettyBuf) -> fmt::Result {
377 let Self { source, replace } = self;
378 match &source.kind {
379 ExprKind::Ref { .. } => writeln!(buf, "{{ {source} with")?,
380 _ => writeln!(buf, "{{ ({source}) with")?,
381 }
382 buf.with_indent::<fmt::Result, _>(2, |buf| {
383 for (i, (name, e)) in replace.iter().enumerate() {
384 match &e.kind {
385 ExprKind::Ref { name: n }
386 if Path::dirname(&**n).is_none()
387 && Path::basename(&**n) == Some(&**name) =>
388 {
389 write!(buf, "{name}")?
390 }
391 e => {
392 write!(buf, "{name}: ")?;
393 buf.with_indent(2, |buf| e.fmt_pretty(buf))?
394 }
395 }
396 if i < replace.len() - 1 {
397 buf.kill_newline();
398 writeln!(buf, ",")?
399 }
400 }
401 Ok(())
402 })?;
403 writeln!(buf, "}}")
404 }
405}
406
407impl fmt::Display for StructExpr {
408 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
409 let Self { args } = self;
410 write!(f, "{{ ")?;
411 for (i, (n, e)) in args.iter().enumerate() {
412 match &e.kind {
413 ExprKind::Ref { name }
414 if Path::dirname(&**name).is_none()
415 && Path::basename(&**name) == Some(&**n) =>
416 {
417 write!(f, "{n}")?
418 }
419 _ => write!(f, "{n}: {e}")?,
420 }
421 if i < args.len() - 1 {
422 write!(f, ", ")?
423 }
424 }
425 write!(f, " }}")
426 }
427}
428
429impl PrettyDisplay for StructExpr {
430 fn fmt_pretty_inner(&self, buf: &mut PrettyBuf) -> fmt::Result {
431 let Self { args } = self;
432 writeln!(buf, "{{")?;
433 buf.with_indent::<fmt::Result, _>(2, |buf| {
434 for (i, (n, e)) in args.iter().enumerate() {
435 match &e.kind {
436 ExprKind::Ref { name }
437 if Path::dirname(&**name).is_none()
438 && Path::basename(&**name) == Some(&**n) =>
439 {
440 write!(buf, "{n}")?
441 }
442 _ => {
443 write!(buf, "{n}: ")?;
444 buf.with_indent(2, |buf| e.fmt_pretty(buf))?;
445 }
446 }
447 if i < args.len() - 1 {
448 buf.kill_newline();
449 writeln!(buf, ", ")?
450 }
451 }
452 Ok(())
453 })?;
454 writeln!(buf, "}}")
455 }
456}
457
458impl fmt::Display for ApplyExpr {
459 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
460 let Self { args, function } = self;
461 match &function.kind {
462 ExprKind::Ref { name: _ } => write!(f, "{function}")?,
463 function => write!(f, "({function})")?,
464 }
465 write!(f, "(")?;
466 for i in 0..args.len() {
467 match &args[i].0 {
468 None => write!(f, "{}", &args[i].1)?,
469 Some(name) => match &args[i].1.kind {
470 ExprKind::Ref { name: n }
471 if Path::dirname(&n.0).is_none()
472 && Path::basename(&n.0) == Some(name.as_str()) =>
473 {
474 write!(f, "#{name}")?
475 }
476 _ => write!(f, "#{name}: {}", &args[i].1)?,
477 },
478 }
479 if i < args.len() - 1 {
480 write!(f, ", ")?
481 }
482 }
483 write!(f, ")")
484 }
485}
486
487impl PrettyDisplay for ApplyExpr {
488 fn fmt_pretty_inner(&self, buf: &mut PrettyBuf) -> fmt::Result {
489 let Self { args, function } = self;
490 match &function.kind {
491 ExprKind::Ref { .. } => function.fmt_pretty(buf)?,
492 e => {
493 write!(buf, "(")?;
494 e.fmt_pretty(buf)?;
495 buf.kill_newline();
496 write!(buf, ")")?;
497 }
498 }
499 buf.kill_newline();
500 writeln!(buf, "(")?;
501 buf.with_indent::<fmt::Result, _>(2, |buf| {
502 for i in 0..args.len() {
503 match &args[i].0 {
504 None => args[i].1.fmt_pretty(buf)?,
505 Some(name) => match &args[i].1.kind {
506 ExprKind::Ref { name: n }
507 if Path::dirname(&n.0).is_none()
508 && Path::basename(&n.0) == Some(name.as_str()) =>
509 {
510 writeln!(buf, "#{name}")?
511 }
512 _ => {
513 write!(buf, "#{name}: ")?;
514 buf.with_indent(2, |buf| args[i].1.fmt_pretty(buf))?
515 }
516 },
517 }
518 if i < args.len() - 1 {
519 buf.kill_newline();
520 writeln!(buf, ",")?
521 }
522 }
523 Ok(())
524 })?;
525 writeln!(buf, ")")
526 }
527}
528
529impl fmt::Display for LambdaExpr {
530 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
531 let LambdaExpr { args, vargs, rtype, constraints, throws, body } = self;
532 for (i, (tvar, typ)) in constraints.iter().enumerate() {
533 write!(f, "{tvar}: {typ}")?;
534 if i < constraints.len() - 1 {
535 write!(f, ", ")?;
536 }
537 }
538 write!(f, "|")?;
539 for (i, a) in args.iter().enumerate() {
540 match &a.labeled {
541 None => {
542 write!(f, "{}", a.pattern)?;
543 if let Some(t) = &a.constraint {
544 write!(f, ": {t}")?
545 }
546 }
547 Some(def) => {
548 write!(f, "#{}", a.pattern)?;
549 if let Some(t) = &a.constraint {
550 write!(f, ": {t}")?
551 }
552 if let Some(def) = def {
553 write!(f, " = {def}")?;
554 }
555 }
556 }
557 if vargs.is_some() || i < args.len() - 1 {
558 write!(f, ", ")?
559 }
560 }
561 if let Some(typ) = vargs {
562 match typ {
563 None => write!(f, "@args")?,
564 Some(typ) => write!(f, "@args: {typ}")?,
565 }
566 }
567 write!(f, "| ")?;
568 if let Some(t) = rtype {
569 match t {
570 Type::Fn(ft) => write!(f, "-> ({ft}) ")?,
571 Type::ByRef(t) => match &**t {
572 Type::Fn(ft) => write!(f, "-> &({ft}) ")?,
573 t => write!(f, "-> &{t} ")?,
574 },
575 t => write!(f, "-> {t} ")?,
576 }
577 }
578 if let Some(t) = throws {
579 write!(f, "throws {t} ")?
580 }
581 match body {
582 Either::Right(builtin) => write!(f, "'{builtin}"),
583 Either::Left(body) => write!(f, "{body}"),
584 }
585 }
586}
587
588impl PrettyDisplay for LambdaExpr {
589 fn fmt_pretty_inner(&self, buf: &mut PrettyBuf) -> fmt::Result {
590 let LambdaExpr { args, vargs, rtype, constraints, throws, body } = self;
591 for (i, (tvar, typ)) in constraints.iter().enumerate() {
592 write!(buf, "{tvar}: {typ}")?;
593 if i < constraints.len() - 1 {
594 write!(buf, ", ")?;
595 }
596 }
597 write!(buf, "|")?;
598 for (i, a) in args.iter().enumerate() {
599 match &a.labeled {
600 None => {
601 write!(buf, "{}", a.pattern)?;
602 if let Some(typ) = &a.constraint {
603 write!(buf, ": {typ}")?;
604 }
605 }
606 Some(def) => {
607 write!(buf, "#{}", a.pattern)?;
608 if let Some(t) = &a.constraint {
609 write!(buf, ": {t}")?
610 }
611 if let Some(def) = def {
612 write!(buf, " = {def}")?;
613 }
614 }
615 }
616 if vargs.is_some() || i < args.len() - 1 {
617 write!(buf, ", ")?
618 }
619 }
620 if let Some(typ) = vargs {
621 write!(buf, "@args")?;
622 if let Some(t) = typ {
623 write!(buf, ": {t}")?
624 }
625 }
626 write!(buf, "| ")?;
627 if let Some(t) = rtype {
628 match t {
629 Type::Fn(ft) => write!(buf, "-> ({ft}) ")?,
630 Type::ByRef(t) => match &**t {
631 Type::Fn(ft) => write!(buf, "-> &({ft}) ")?,
632 t => write!(buf, "-> &{t} ")?,
633 },
634 t => write!(buf, "-> {t} ")?,
635 }
636 }
637 if let Some(t) = throws {
638 write!(buf, "throws {t} ")?
639 }
640 match body {
641 Either::Right(builtin) => {
642 writeln!(buf, "'{builtin}")
643 }
644 Either::Left(body) => match &body.kind {
645 ExprKind::Do { exprs } => pretty_print_exprs(buf, exprs, "{", "}", ";"),
646 _ => body.fmt_pretty(buf),
647 },
648 }
649 }
650}
651
652impl fmt::Display for SelectExpr {
653 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
654 let SelectExpr { arg, arms } = self;
655 write!(f, "select {arg} {{")?;
656 for (i, (pat, rhs)) in arms.iter().enumerate() {
657 if let Some(tp) = &pat.type_predicate {
658 write!(f, "{tp} as ")?;
659 }
660 write!(f, "{} ", pat.structure_predicate)?;
661 if let Some(guard) = &pat.guard {
662 write!(f, "if {guard} ")?;
663 }
664 write!(f, "=> {rhs}")?;
665 if i < arms.len() - 1 {
666 write!(f, ", ")?
667 }
668 }
669 write!(f, "}}")
670 }
671}
672
673impl PrettyDisplay for SelectExpr {
674 fn fmt_pretty_inner(&self, buf: &mut PrettyBuf) -> fmt::Result {
675 let SelectExpr { arg, arms } = self;
676 write!(buf, "select ")?;
677 arg.fmt_pretty(buf)?;
678 buf.kill_newline();
679 writeln!(buf, " {{")?;
680 buf.with_indent(2, |buf| {
681 for (i, (pat, expr)) in arms.iter().enumerate() {
682 if let Some(tp) = &pat.type_predicate {
683 write!(buf, "{tp} as ")?;
684 }
685 write!(buf, "{} ", pat.structure_predicate)?;
686 if let Some(guard) = &pat.guard {
687 write!(buf, "if ")?;
688 buf.with_indent(2, |buf| guard.fmt_pretty(buf))?;
689 buf.kill_newline();
690 write!(buf, " ")?;
691 }
692 write!(buf, "=> ")?;
693 if let ExprKind::Do { exprs } = &expr.kind {
694 let term = if i < arms.len() - 1 { "}," } else { "}" };
695 buf.with_indent(2, |buf| {
696 pretty_print_exprs(buf, exprs, "{", term, ";")
697 })?;
698 } else if i < arms.len() - 1 {
699 buf.with_indent(2, |buf| expr.fmt_pretty(buf))?;
700 buf.kill_newline();
701 writeln!(buf, ",")?
702 } else {
703 buf.with_indent(2, |buf| expr.fmt_pretty(buf))?;
704 }
705 }
706 Ok(())
707 })?;
708 writeln!(buf, "}}")
709 }
710}
711
712impl PrettyDisplay for ExprKind {
713 fn fmt_pretty_inner(&self, buf: &mut PrettyBuf) -> fmt::Result {
714 macro_rules! binop {
715 ($sep:literal, $lhs:expr, $rhs:expr) => {{
716 writeln!(buf, "{} {}", $lhs, $sep)?;
717 $rhs.fmt_pretty(buf)
718 }};
719 }
720 match self {
721 ExprKind::Constant(_)
722 | ExprKind::NoOp
723 | ExprKind::Use { .. }
724 | ExprKind::Ref { .. }
725 | ExprKind::StructRef { .. }
726 | ExprKind::TupleRef { .. }
727 | ExprKind::TypeDef { .. }
728 | ExprKind::ArrayRef { .. }
729 | ExprKind::MapRef { .. }
730 | ExprKind::ArraySlice { .. }
731 | ExprKind::StringInterpolate { .. }
732 | ExprKind::Module {
733 name: _,
734 value: ModuleKind::Unresolved { .. } | ModuleKind::Resolved { .. },
735 } => {
736 writeln!(buf, "{self}")
737 }
738 ExprKind::ExplicitParens(e) => {
739 writeln!(buf, "(")?;
740 buf.with_indent(2, |buf| e.fmt_pretty(buf))?;
741 writeln!(buf, ")")
742 }
743 ExprKind::Do { exprs } => pretty_print_exprs(buf, exprs, "{", "}", ";"),
744 ExprKind::Array { args } => pretty_print_exprs(buf, args, "[", "]", ","),
745 ExprKind::Tuple { args } => pretty_print_exprs(buf, args, "(", ")", ","),
746 ExprKind::Bind(b) => b.fmt_pretty(buf),
747 ExprKind::StructWith(sw) => sw.fmt_pretty(buf),
748 ExprKind::Module {
749 name,
750 value: ModuleKind::Dynamic { sandbox, sig, source },
751 } => {
752 writeln!(buf, "mod {name} dynamic {{")?;
753 buf.with_indent(2, |buf| {
754 sandbox.fmt_pretty(buf)?;
755 buf.kill_newline();
756 writeln!(buf, ";")?;
757 sig.fmt_pretty(buf)?;
758 buf.kill_newline();
759 writeln!(buf, ";")?;
760 write!(buf, "source ")?;
761 buf.with_indent(2, |buf| source.fmt_pretty(buf))?;
762 buf.kill_newline();
763 writeln!(buf, ";")
764 })?;
765 writeln!(buf, "}}")
766 }
767 ExprKind::Connect { name, value, deref } => {
768 let deref = if *deref { "*" } else { "" };
769 writeln!(buf, "{deref}{name} <- ")?;
770 buf.with_indent(2, |buf| value.fmt_pretty(buf))
771 }
772 ExprKind::TypeCast { expr, typ } => {
773 writeln!(buf, "cast<{typ}>(")?;
774 buf.with_indent(2, |buf| expr.fmt_pretty(buf))?;
775 writeln!(buf, ")")
776 }
777 ExprKind::Map { args } => {
778 writeln!(buf, "{{")?;
779 buf.with_indent::<fmt::Result, _>(2, |buf| {
780 for (i, (k, v)) in args.iter().enumerate() {
781 writeln!(buf, "{k} => {v}")?;
782 if i < args.len() - 1 {
783 buf.kill_newline();
784 writeln!(buf, ",")?
785 }
786 }
787 Ok(())
788 })?;
789 writeln!(buf, "}}")
790 }
791 ExprKind::Any { args } => {
792 write!(buf, "any")?;
793 pretty_print_exprs(buf, args, "(", ")", ",")
794 }
795 ExprKind::Variant { tag: _, args } if args.len() == 0 => {
796 write!(buf, "{self}")
797 }
798 ExprKind::Variant { tag, args } => {
799 write!(buf, "`{tag}")?;
800 pretty_print_exprs(buf, args, "(", ")", ",")
801 }
802 ExprKind::Struct(st) => st.fmt_pretty(buf),
803 ExprKind::Qop(e) => {
804 e.fmt_pretty(buf)?;
805 buf.kill_newline();
806 writeln!(buf, "?")
807 }
808 ExprKind::OrNever(e) => {
809 e.fmt_pretty(buf)?;
810 buf.kill_newline();
811 writeln!(buf, "$")
812 }
813 ExprKind::TryCatch(tc) => {
814 writeln!(buf, "try")?;
815 pretty_print_exprs(buf, &tc.exprs, "", "", "; ")?;
816 match &tc.constraint {
817 None => write!(buf, "catch({}) => ", tc.bind)?,
818 Some(t) => write!(buf, "catch({}: {t}) => ", tc.bind)?,
819 }
820 match &tc.handler.kind {
821 ExprKind::Do { exprs } => {
822 pretty_print_exprs(buf, exprs, "{", "}", "; ")
823 }
824 _ => {
825 writeln!(buf, "")?;
826 buf.with_indent(2, |buf| tc.handler.fmt_pretty(buf))
827 }
828 }
829 }
830 ExprKind::Apply(ae) => ae.fmt_pretty(buf),
831 ExprKind::Lambda(l) => l.fmt_pretty(buf),
832 ExprKind::Eq { lhs, rhs } => binop!("==", lhs, rhs),
833 ExprKind::Ne { lhs, rhs } => binop!("!=", lhs, rhs),
834 ExprKind::Lt { lhs, rhs } => binop!("<", lhs, rhs),
835 ExprKind::Gt { lhs, rhs } => binop!(">", lhs, rhs),
836 ExprKind::Lte { lhs, rhs } => binop!("<=", lhs, rhs),
837 ExprKind::Gte { lhs, rhs } => binop!(">=", lhs, rhs),
838 ExprKind::And { lhs, rhs } => binop!("&&", lhs, rhs),
839 ExprKind::Or { lhs, rhs } => binop!("||", lhs, rhs),
840 ExprKind::Add { lhs, rhs } => binop!("+", lhs, rhs),
841 ExprKind::Sub { lhs, rhs } => binop!("-", lhs, rhs),
842 ExprKind::Mul { lhs, rhs } => binop!("*", lhs, rhs),
843 ExprKind::Div { lhs, rhs } => binop!("/", lhs, rhs),
844 ExprKind::Mod { lhs, rhs } => binop!("%", lhs, rhs),
845 ExprKind::Sample { lhs, rhs } => binop!("~", lhs, rhs),
846 ExprKind::Not { expr } => match &expr.kind {
847 ExprKind::Do { exprs } => pretty_print_exprs(buf, exprs, "!{", "}", ";"),
848 _ => {
849 write!(buf, "!")?;
850 expr.fmt_pretty(buf)
851 }
852 },
853 ExprKind::ByRef(e) => {
854 write!(buf, "&")?;
855 e.fmt_pretty(buf)
856 }
857 ExprKind::Deref(e) => {
858 write!(buf, "*")?;
859 buf.with_indent(2, |buf| e.fmt_pretty(buf))
860 }
861 ExprKind::Select(se) => se.fmt_pretty(buf),
862 }
863 }
864}
865
866impl fmt::Display for ExprKind {
867 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
868 fn print_exprs(
869 f: &mut fmt::Formatter,
870 exprs: &[Expr],
871 open: &str,
872 close: &str,
873 sep: &str,
874 ) -> fmt::Result {
875 write!(f, "{open}")?;
876 for i in 0..exprs.len() {
877 write!(f, "{}", &exprs[i])?;
878 if i < exprs.len() - 1 {
879 write!(f, "{sep}")?
880 }
881 }
882 write!(f, "{close}")
883 }
884 match self {
885 ExprKind::Constant(v @ Value::String(_)) => {
886 v.fmt_ext(f, &parser::GRAPHIX_ESC, true)
887 }
888 ExprKind::NoOp => Ok(()),
889 ExprKind::ExplicitParens(e) => write!(f, "({e})"),
890 ExprKind::Constant(v) => v.fmt_ext(f, &VAL_ESC, true),
891 ExprKind::Bind(b) => write!(f, "{b}"),
892 ExprKind::StructWith(sw) => write!(f, "{sw}"),
893 ExprKind::Connect { name, value, deref } => {
894 let deref = if *deref { "*" } else { "" };
895 write!(f, "{deref}{name} <- {value}")
896 }
897 ExprKind::Use { name } => {
898 write!(f, "use {name}")
899 }
900 ExprKind::Ref { name } => {
901 write!(f, "{name}")
902 }
903 ExprKind::StructRef { source, field } => match &source.kind {
904 ExprKind::Ref { .. } => {
905 write!(f, "{source}.{field}")
906 }
907 source => write!(f, "({source}).{field}"),
908 },
909 ExprKind::TupleRef { source, field } => match &source.kind {
910 ExprKind::Ref { .. } => {
911 write!(f, "{source}.{field}")
912 }
913 source => write!(f, "({source}).{field}"),
914 },
915 ExprKind::Module {
916 value:
917 ModuleKind::Resolved { from_interface: true, .. }
918 | ModuleKind::Unresolved { from_interface: true },
919 ..
920 } => Ok(()),
921 ExprKind::Module { name, value } => {
922 write!(f, "mod {name}")?;
923 match value {
924 ModuleKind::Resolved { .. } | ModuleKind::Unresolved { .. } => Ok(()),
925 ModuleKind::Dynamic { sandbox, sig, source } => {
926 write!(f, " dynamic {{ {sandbox};")?;
927 write!(f, " {sig};")?;
928 write!(f, " source {source} }}")
929 }
930 }
931 }
932 ExprKind::TypeCast { expr, typ } => write!(f, "cast<{typ}>({expr})"),
933 ExprKind::TypeDef(td) => write!(f, "{td}"),
934 ExprKind::Do { exprs } => print_exprs(f, &**exprs, "{", "}", "; "),
935 ExprKind::Lambda(l) => write!(f, "{l}"),
936 ExprKind::Array { args } => print_exprs(f, args, "[", "]", ", "),
937 ExprKind::Map { args } => {
938 write!(f, "{{")?;
939 for (i, (k, v)) in args.iter().enumerate() {
940 write!(f, "{k} => {v}")?;
941 if i < args.len() - 1 {
942 write!(f, ", ")?
943 }
944 }
945 write!(f, "}}")
946 }
947 ExprKind::MapRef { source, key } => match &source.kind {
948 ExprKind::Ref { name } => write!(f, "{name}{{{key}}}"),
949 _ => write!(f, "({source}){{{key}}}"),
950 },
951 ExprKind::Any { args } => {
952 write!(f, "any")?;
953 print_exprs(f, args, "(", ")", ", ")
954 }
955 ExprKind::Tuple { args } => print_exprs(f, args, "(", ")", ", "),
956 ExprKind::Variant { tag, args } if args.len() == 0 => {
957 write!(f, "`{tag}")
958 }
959 ExprKind::Variant { tag, args } => {
960 write!(f, "`{tag}")?;
961 print_exprs(f, args, "(", ")", ", ")
962 }
963 ExprKind::Struct(st) => write!(f, "{st}"),
964 ExprKind::Qop(e) => write!(f, "{}?", e),
965 ExprKind::OrNever(e) => write!(f, "{}$", e),
966 ExprKind::TryCatch(tc) => {
967 write!(f, "try ")?;
968 print_exprs(f, &tc.exprs, "", "", "; ")?;
969 match &tc.constraint {
970 None => write!(f, " catch({}) => {}", tc.bind, tc.handler),
971 Some(t) => write!(f, " catch({}: {t}) => {}", tc.bind, tc.handler),
972 }
973 }
974 ExprKind::StringInterpolate { args } => {
975 write!(f, "\"")?;
976 for s in args.iter() {
977 match &s.kind {
978 ExprKind::Constant(Value::String(s)) if s.len() > 0 => {
979 let es = parser::GRAPHIX_ESC.escape(&*s);
980 write!(f, "{es}",)?;
981 }
982 s => {
983 write!(f, "[{s}]")?;
984 }
985 }
986 }
987 write!(f, "\"")
988 }
989 ExprKind::ArrayRef { source, i } => match &source.kind {
990 ExprKind::Ref { .. } => {
991 write!(f, "{}[{}]", source, i)
992 }
993 _ => write!(f, "({})[{}]", &source, &i),
994 },
995 ExprKind::ArraySlice { source, start, end } => {
996 let s = match start.as_ref() {
997 None => "",
998 Some(e) => &format_compact!("{e}"),
999 };
1000 let e = match &end.as_ref() {
1001 None => "",
1002 Some(e) => &format_compact!("{e}"),
1003 };
1004 match &source.kind {
1005 ExprKind::Ref { .. } => {
1006 write!(f, "{}[{}..{}]", source, s, e)
1007 }
1008 _ => write!(f, "({})[{}..{}]", source, s, e),
1009 }
1010 }
1011 ExprKind::Apply(ap) => write!(f, "{ap}"),
1012 ExprKind::Select(se) => write!(f, "{se}"),
1013 ExprKind::Eq { lhs, rhs } => write!(f, "{lhs} == {rhs}"),
1014 ExprKind::Ne { lhs, rhs } => write!(f, "{lhs} != {rhs}"),
1015 ExprKind::Gt { lhs, rhs } => write!(f, "{lhs} > {rhs}"),
1016 ExprKind::Lt { lhs, rhs } => write!(f, "{lhs} < {rhs}"),
1017 ExprKind::Gte { lhs, rhs } => write!(f, "{lhs} >= {rhs}"),
1018 ExprKind::Lte { lhs, rhs } => write!(f, "{lhs} <= {rhs}"),
1019 ExprKind::And { lhs, rhs } => write!(f, "{lhs} && {rhs}"),
1020 ExprKind::Or { lhs, rhs } => write!(f, "{lhs} || {rhs}"),
1021 ExprKind::Add { lhs, rhs } => write!(f, "{lhs} + {rhs}"),
1022 ExprKind::Sub { lhs, rhs } => write!(f, "{lhs} - {rhs}"),
1023 ExprKind::Mul { lhs, rhs } => write!(f, "{lhs} * {rhs}"),
1024 ExprKind::Div { lhs, rhs } => write!(f, "{lhs} / {rhs}"),
1025 ExprKind::Mod { lhs, rhs } => write!(f, "{lhs} % {rhs}"),
1026 ExprKind::Sample { lhs, rhs } => write!(f, "{lhs} ~ {rhs}"),
1027 ExprKind::ByRef(e) => write!(f, "&{e}"),
1028 ExprKind::Deref(e) => write!(f, "*{e}"),
1029 ExprKind::Not { expr } => write!(f, "!{expr}"),
1030 }
1031 }
1032}