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