1use std::fmt::{Display, Formatter};
2use std::hash::Hash;
3
4use ordered_float::OrderedFloat;
5
6use super::util::ListDisplay;
7use crate::generic_ast::*;
8use crate::span::Span;
9
10macro_rules! impl_from {
12 ($ctor:ident($t:ty)) => {
13 impl From<Literal> for $t {
14 fn from(literal: Literal) -> Self {
15 match literal {
16 Literal::$ctor(t) => t,
17 #[allow(unreachable_patterns)]
18 _ => panic!("Expected {}, got {literal}", stringify!($ctor)),
19 }
20 }
21 }
22
23 impl From<$t> for Literal {
24 fn from(t: $t) -> Self {
25 Literal::$ctor(t)
26 }
27 }
28 };
29}
30
31pub const INTERNAL_SYMBOL_PREFIX: &str = "@";
32
33impl<Head: Display, Leaf: Display> Display for GenericRule<Head, Leaf>
34where
35 Head: Clone + Display,
36 Leaf: Clone + PartialEq + Eq + Display + Hash,
37{
38 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
39 let indent = " ".repeat(7);
40 write!(f, "(rule (")?;
41 for (i, fact) in self.body.iter().enumerate() {
42 if i > 0 {
43 write!(f, "{indent}")?;
44 }
45
46 if i != self.body.len() - 1 {
47 writeln!(f, "{fact}")?;
48 } else {
49 write!(f, "{fact}")?;
50 }
51 }
52 write!(f, ")\n (")?;
53 for (i, action) in self.head.0.iter().enumerate() {
54 if i > 0 {
55 write!(f, "{indent}")?;
56 }
57 if i != self.head.0.len() - 1 {
58 writeln!(f, "{action}")?;
59 } else {
60 write!(f, "{action}")?;
61 }
62 }
63 let ruleset = if !self.ruleset.is_empty() {
64 format!(":ruleset {}", &self.ruleset)
65 } else {
66 "".into()
67 };
68 let name = if !self.name.is_empty() {
69 format!(":name \"{}\"", &self.name)
70 } else {
71 "".into()
72 };
73 let eval_mode = match self.eval_mode {
74 RuleEvalMode::Seminaive => "",
75 RuleEvalMode::Naive => " :naive",
76 RuleEvalMode::UnsafeSeminaive => " :unsafe-seminaive",
77 };
78 let no_decomp = if self.no_decomp { " :no-decomp" } else { "" };
79 let include_subsumed = if self.include_subsumed {
80 " :internal-include-subsumed"
81 } else {
82 ""
83 };
84 write!(
85 f,
86 ")\n{indent} {ruleset} {name}{eval_mode}{no_decomp}{include_subsumed})"
87 )
88 }
89}
90
91impl_from!(Int(i64));
93impl_from!(Float(OrderedFloat<f64>));
94impl_from!(String(String));
95
96impl<Head: Display, Leaf: Display> Display for GenericFact<Head, Leaf> {
97 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
98 match self {
99 GenericFact::Eq(_, e1, e2) => write!(f, "(= {e1} {e2})"),
100 GenericFact::Fact(expr) => write!(f, "{expr}"),
101 }
102 }
103}
104
105impl<Head: Display, Leaf: Display> Display for GenericAction<Head, Leaf>
107where
108 Head: Clone + Display,
109 Leaf: Clone + PartialEq + Eq + Display + Hash,
110{
111 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
112 match self {
113 GenericAction::Let(_, lhs, rhs) => write!(f, "(let {lhs} {rhs})"),
114 GenericAction::Set(_, lhs, args, rhs) => {
115 if args.is_empty() {
116 write!(f, "(set ({lhs}) {rhs})")
117 } else {
118 write!(
119 f,
120 "(set ({} {}) {})",
121 lhs,
122 args.iter()
123 .map(|a| format!("{a}"))
124 .collect::<Vec<_>>()
125 .join(" "),
126 rhs
127 )
128 }
129 }
130 GenericAction::Union(_, lhs, rhs) => write!(f, "(union {lhs} {rhs})"),
131 GenericAction::Change(_, change, lhs, args) => {
132 let change_str = match change {
133 Change::Delete => "delete",
134 Change::Subsume => "subsume",
135 };
136 if args.is_empty() {
137 write!(f, "({change_str} ({lhs}))")
138 } else {
139 write!(
140 f,
141 "({} ({} {}))",
142 change_str,
143 lhs,
144 args.iter()
145 .map(|a| format!("{a}"))
146 .collect::<Vec<_>>()
147 .join(" ")
148 )
149 }
150 }
151 GenericAction::Panic(_, msg) => write!(f, "(panic \"{msg}\")"),
152 GenericAction::Expr(_, e) => write!(f, "{e}"),
153 }
154 }
155}
156
157impl<Head, Leaf> Display for GenericExpr<Head, Leaf>
158where
159 Head: Display,
160 Leaf: Display,
161{
162 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
163 match self {
164 GenericExpr::Lit(_ann, lit) => write!(f, "{lit}"),
165 GenericExpr::Var(_ann, var) => write!(f, "{var}"),
166 GenericExpr::Call(_ann, op, children) => match children.is_empty() {
167 true => write!(f, "({op})"),
168 false => write!(f, "({} {})", op, ListDisplay(children, " ")),
169 },
170 }
171 }
172}
173
174impl<Head, Leaf> Default for GenericActions<Head, Leaf>
175where
176 Head: Clone + Display,
177 Leaf: Clone + PartialEq + Eq + Display + Hash,
178{
179 fn default() -> Self {
180 Self(vec![])
181 }
182}
183
184impl<Head, Leaf> GenericRule<Head, Leaf>
185where
186 Head: Clone + Display,
187 Leaf: Clone + PartialEq + Eq + Display + Hash,
188{
189 pub fn visit_exprs(
191 self,
192 f: &mut impl FnMut(GenericExpr<Head, Leaf>) -> GenericExpr<Head, Leaf>,
193 ) -> Self {
194 Self {
195 span: self.span,
196 head: self.head.visit_exprs(f),
197 body: self
198 .body
199 .into_iter()
200 .map(|bexpr| bexpr.visit_exprs(f))
201 .collect(),
202 name: self.name.clone(),
203 ruleset: self.ruleset.clone(),
204 eval_mode: self.eval_mode,
205 no_decomp: self.no_decomp,
206 include_subsumed: self.include_subsumed,
207 }
208 }
209
210 pub fn visit_actions(
212 self,
213 f: &mut impl FnMut(GenericAction<Head, Leaf>) -> GenericAction<Head, Leaf>,
214 ) -> Self {
215 Self {
216 span: self.span,
217 head: self.head.visit_actions(f),
218 body: self.body,
219 name: self.name,
220 ruleset: self.ruleset,
221 eval_mode: self.eval_mode,
222 no_decomp: self.no_decomp,
223 include_subsumed: self.include_subsumed,
224 }
225 }
226
227 pub fn map_symbols<Head2, Leaf2>(
229 self,
230 head: &mut impl FnMut(Head) -> Head2,
231 leaf: &mut impl FnMut(Leaf) -> Leaf2,
232 ) -> GenericRule<Head2, Leaf2>
233 where
234 Head2: Clone + Display,
235 Leaf2: Clone + PartialEq + Eq + Display + Hash,
236 {
237 GenericRule {
238 span: self.span,
239 head: self.head.map_symbols(head, leaf),
240 body: self
241 .body
242 .into_iter()
243 .map(|fact| fact.map_symbols(head, leaf))
244 .collect(),
245 name: self.name,
246 ruleset: self.ruleset,
247 eval_mode: self.eval_mode,
248 no_decomp: self.no_decomp,
249 include_subsumed: self.include_subsumed,
250 }
251 }
252
253 pub fn make_unresolved(self) -> GenericRule<String, String> {
255 let mut map_head = |h: Head| h.to_string();
256 let mut map_leaf = |l: Leaf| l.to_string();
257 self.map_symbols(&mut map_head, &mut map_leaf)
258 }
259}
260
261impl<Head, Leaf> GenericActions<Head, Leaf>
262where
263 Head: Clone + Display,
264 Leaf: Clone + PartialEq + Eq + Display + Hash,
265{
266 pub fn len(&self) -> usize {
267 self.0.len()
268 }
269
270 pub fn is_empty(&self) -> bool {
271 self.0.is_empty()
272 }
273
274 pub fn iter(&self) -> impl Iterator<Item = &GenericAction<Head, Leaf>> {
275 self.0.iter()
276 }
277
278 pub fn visit_vars(&self, f: &mut impl FnMut(&Span, &Leaf)) {
279 for action in &self.0 {
280 action.visit_vars(f);
281 }
282 }
283
284 pub fn visit_exprs(
286 self,
287 f: &mut impl FnMut(GenericExpr<Head, Leaf>) -> GenericExpr<Head, Leaf>,
288 ) -> Self {
289 Self(self.0.into_iter().map(|a| a.visit_exprs(f)).collect())
290 }
291
292 pub fn visit_actions(
294 self,
295 f: &mut impl FnMut(GenericAction<Head, Leaf>) -> GenericAction<Head, Leaf>,
296 ) -> Self {
297 Self(self.0.into_iter().map(f).collect())
298 }
299
300 pub fn new(actions: Vec<GenericAction<Head, Leaf>>) -> Self {
301 Self(actions)
302 }
303
304 pub fn singleton(action: GenericAction<Head, Leaf>) -> Self {
305 Self(vec![action])
306 }
307
308 pub fn map_symbols<Head2, Leaf2>(
310 self,
311 head: &mut impl FnMut(Head) -> Head2,
312 leaf: &mut impl FnMut(Leaf) -> Leaf2,
313 ) -> GenericActions<Head2, Leaf2>
314 where
315 Head2: Clone + Display,
316 Leaf2: Clone + PartialEq + Eq + Display + Hash,
317 {
318 GenericActions(
319 self.0
320 .into_iter()
321 .map(|action| action.map_symbols(head, leaf))
322 .collect(),
323 )
324 }
325
326 pub fn make_unresolved(self) -> GenericActions<String, String> {
328 let mut map_head = |h: Head| h.to_string();
329 let mut map_leaf = |l: Leaf| l.to_string();
330 self.map_symbols(&mut map_head, &mut map_leaf)
331 }
332}
333
334impl<Head, Leaf> GenericAction<Head, Leaf>
335where
336 Head: Clone + Display,
337 Leaf: Clone + Eq + Display + Hash,
338{
339 pub fn visit_vars(&self, f: &mut impl FnMut(&Span, &Leaf)) {
340 if let GenericAction::Let(span, lhs, _) = self {
341 f(span, lhs);
342 }
343 let mut visit = |expr: GenericExpr<Head, Leaf>| match expr {
344 GenericExpr::Var(span, var) => {
345 f(&span, &var);
346 GenericExpr::Var(span, var)
347 }
348 other => other,
349 };
350 let _ = self.clone().visit_exprs(&mut visit);
351 }
352
353 pub fn map_exprs(
355 &self,
356 f: &mut impl FnMut(&GenericExpr<Head, Leaf>) -> GenericExpr<Head, Leaf>,
357 ) -> Self {
358 match self {
359 GenericAction::Let(span, lhs, rhs) => {
360 GenericAction::Let(span.clone(), lhs.clone(), f(rhs))
361 }
362 GenericAction::Set(span, lhs, args, rhs) => {
363 let right = f(rhs);
364 GenericAction::Set(
365 span.clone(),
366 lhs.clone(),
367 args.iter().map(f).collect(),
368 right,
369 )
370 }
371 GenericAction::Change(span, change, lhs, args) => GenericAction::Change(
372 span.clone(),
373 *change,
374 lhs.clone(),
375 args.iter().map(f).collect(),
376 ),
377 GenericAction::Union(span, lhs, rhs) => {
378 GenericAction::Union(span.clone(), f(lhs), f(rhs))
379 }
380 GenericAction::Panic(span, msg) => GenericAction::Panic(span.clone(), msg.clone()),
381 GenericAction::Expr(span, e) => GenericAction::Expr(span.clone(), f(e)),
382 }
383 }
384
385 pub fn visit_exprs(
388 self,
389 f: &mut impl FnMut(GenericExpr<Head, Leaf>) -> GenericExpr<Head, Leaf>,
390 ) -> Self {
391 match self {
392 GenericAction::Let(span, lhs, rhs) => {
393 GenericAction::Let(span, lhs.clone(), rhs.visit_exprs(f))
394 }
395 GenericAction::Set(span, lhs, args, rhs) => {
399 let args = args.into_iter().map(|e| e.visit_exprs(f)).collect();
400 GenericAction::Set(span, lhs.clone(), args, rhs.visit_exprs(f))
401 }
402 GenericAction::Change(span, change, lhs, args) => {
403 let args = args.into_iter().map(|e| e.visit_exprs(f)).collect();
404 GenericAction::Change(span, change, lhs.clone(), args)
405 }
406 GenericAction::Union(span, lhs, rhs) => {
407 GenericAction::Union(span, lhs.visit_exprs(f), rhs.visit_exprs(f))
408 }
409 GenericAction::Panic(span, msg) => GenericAction::Panic(span, msg.clone()),
410 GenericAction::Expr(span, e) => GenericAction::Expr(span, e.visit_exprs(f)),
411 }
412 }
413
414 pub fn subst(&self, subst: &mut impl FnMut(&Span, &Leaf) -> GenericExpr<Head, Leaf>) -> Self {
415 self.map_exprs(&mut |e| e.subst_leaf(subst))
416 }
417
418 pub fn map_def_use(self, fvar: &mut impl FnMut(Leaf, bool) -> Leaf) -> Self {
419 macro_rules! fvar_expr {
420 () => {
421 |span, s: _| GenericExpr::Var(span.clone(), fvar(s.clone(), false))
422 };
423 }
424 match self {
425 GenericAction::Let(span, lhs, rhs) => {
426 let lhs = fvar(lhs, true);
427 let rhs = rhs.subst_leaf(&mut fvar_expr!());
428 GenericAction::Let(span, lhs, rhs)
429 }
430 GenericAction::Set(span, lhs, args, rhs) => {
431 let args = args
432 .into_iter()
433 .map(|e| e.subst_leaf(&mut fvar_expr!()))
434 .collect();
435 let rhs = rhs.subst_leaf(&mut fvar_expr!());
436 GenericAction::Set(span, lhs.clone(), args, rhs)
437 }
438 GenericAction::Change(span, change, lhs, args) => {
439 let args = args
440 .into_iter()
441 .map(|e| e.subst_leaf(&mut fvar_expr!()))
442 .collect();
443 GenericAction::Change(span, change, lhs.clone(), args)
444 }
445 GenericAction::Union(span, lhs, rhs) => {
446 let lhs = lhs.subst_leaf(&mut fvar_expr!());
447 let rhs = rhs.subst_leaf(&mut fvar_expr!());
448 GenericAction::Union(span, lhs, rhs)
449 }
450 GenericAction::Panic(span, msg) => GenericAction::Panic(span, msg.clone()),
451 GenericAction::Expr(span, e) => {
452 GenericAction::Expr(span, e.subst_leaf(&mut fvar_expr!()))
453 }
454 }
455 }
456
457 pub fn map_symbols<Head2, Leaf2>(
459 self,
460 head: &mut impl FnMut(Head) -> Head2,
461 leaf: &mut impl FnMut(Leaf) -> Leaf2,
462 ) -> GenericAction<Head2, Leaf2>
463 where
464 Head2: Clone + Display,
465 Leaf2: Clone + Eq + Display + Hash,
466 {
467 match self {
468 GenericAction::Let(span, lhs, rhs) => {
469 GenericAction::Let(span, leaf(lhs), rhs.map_symbols(head, leaf))
470 }
471 GenericAction::Set(span, head_sym, args, rhs) => {
472 let mut mapped_args = Vec::with_capacity(args.len());
473 for arg in args {
474 mapped_args.push(arg.map_symbols(head, leaf));
475 }
476 GenericAction::Set(
477 span,
478 head(head_sym),
479 mapped_args,
480 rhs.map_symbols(head, leaf),
481 )
482 }
483 GenericAction::Change(span, change, head_sym, args) => {
484 let mut mapped_args = Vec::with_capacity(args.len());
485 for arg in args {
486 mapped_args.push(arg.map_symbols(head, leaf));
487 }
488 GenericAction::Change(span, change, head(head_sym), mapped_args)
489 }
490 GenericAction::Union(span, lhs, rhs) => GenericAction::Union(
491 span,
492 lhs.map_symbols(head, leaf),
493 rhs.map_symbols(head, leaf),
494 ),
495 GenericAction::Panic(span, msg) => GenericAction::Panic(span, msg),
496 GenericAction::Expr(span, expr) => {
497 GenericAction::Expr(span, expr.map_symbols(head, leaf))
498 }
499 }
500 }
501
502 pub fn make_unresolved(self) -> GenericAction<String, String> {
505 let mut map_head = |h: Head| h.to_string();
506 let mut map_leaf = |l: Leaf| l.to_string();
507 self.map_symbols(&mut map_head, &mut map_leaf)
508 }
509}
510
511impl<Head, Leaf> GenericFact<Head, Leaf>
512where
513 Head: Clone + Display,
514 Leaf: Clone + PartialEq + Eq + Display + Hash,
515{
516 pub fn visit_vars(&self, f: &mut impl FnMut(&Span, &Leaf)) {
517 let mut visit = |expr: GenericExpr<Head, Leaf>| match expr {
518 GenericExpr::Var(span, var) => {
519 f(&span, &var);
520 GenericExpr::Var(span, var)
521 }
522 other => other,
523 };
524 let _ = self.clone().visit_exprs(&mut visit);
525 }
526
527 pub fn visit_exprs(
528 self,
529 f: &mut impl FnMut(GenericExpr<Head, Leaf>) -> GenericExpr<Head, Leaf>,
530 ) -> GenericFact<Head, Leaf> {
531 match self {
532 GenericFact::Eq(span, e1, e2) => {
533 GenericFact::Eq(span, e1.visit_exprs(f), e2.visit_exprs(f))
534 }
535 GenericFact::Fact(expr) => GenericFact::Fact(expr.visit_exprs(f)),
536 }
537 }
538
539 pub fn map_exprs<Head2, Leaf2>(
540 &self,
541 f: &mut impl FnMut(&GenericExpr<Head, Leaf>) -> GenericExpr<Head2, Leaf2>,
542 ) -> GenericFact<Head2, Leaf2> {
543 match self {
544 GenericFact::Eq(span, e1, e2) => GenericFact::Eq(span.clone(), f(e1), f(e2)),
545 GenericFact::Fact(expr) => GenericFact::Fact(f(expr)),
546 }
547 }
548
549 pub fn subst<Leaf2, Head2>(
550 &self,
551 subst_leaf: &mut impl FnMut(&Span, &Leaf) -> GenericExpr<Head2, Leaf2>,
552 subst_head: &mut impl FnMut(&Head) -> Head2,
553 ) -> GenericFact<Head2, Leaf2> {
554 self.map_exprs(&mut |e| e.subst(subst_leaf, subst_head))
555 }
556}
557
558impl<Head, Leaf> GenericFact<Head, Leaf>
559where
560 Leaf: Clone + PartialEq + Eq + Display + Hash,
561 Head: Clone + Display,
562{
563 pub fn map_symbols<Head2, Leaf2>(
565 self,
566 head: &mut impl FnMut(Head) -> Head2,
567 leaf: &mut impl FnMut(Leaf) -> Leaf2,
568 ) -> GenericFact<Head2, Leaf2>
569 where
570 Head2: Clone + Display,
571 Leaf2: Clone + PartialEq + Eq + Display + Hash,
572 {
573 match self {
574 GenericFact::Eq(span, e1, e2) => {
575 GenericFact::Eq(span, e1.map_symbols(head, leaf), e2.map_symbols(head, leaf))
576 }
577 GenericFact::Fact(expr) => GenericFact::Fact(expr.map_symbols(head, leaf)),
578 }
579 }
580
581 pub fn make_unresolved(self) -> GenericFact<String, String> {
583 let mut map_head = |h: Head| h.to_string();
584 let mut map_leaf = |l: Leaf| l.to_string();
585 self.map_symbols(&mut map_head, &mut map_leaf)
586 }
587}
588
589impl<Head: Clone + Display, Leaf: Hash + Clone + Display + Eq> GenericExpr<Head, Leaf> {
590 pub fn visit_vars(&self, f: &mut impl FnMut(&Span, &Leaf)) {
591 let mut visit = |expr: GenericExpr<Head, Leaf>| match expr {
592 GenericExpr::Var(span, var) => {
593 f(&span, &var);
594 GenericExpr::Var(span, var)
595 }
596 other => other,
597 };
598 let _ = self.clone().visit_exprs(&mut visit);
599 }
600
601 pub fn span(&self) -> Span {
602 match self {
603 GenericExpr::Lit(span, _) => span.clone(),
604 GenericExpr::Var(span, _) => span.clone(),
605 GenericExpr::Call(span, _, _) => span.clone(),
606 }
607 }
608
609 pub fn is_var(&self) -> bool {
610 matches!(self, GenericExpr::Var(_, _))
611 }
612
613 pub fn get_var(&self) -> Option<Leaf> {
614 match self {
615 GenericExpr::Var(_ann, v) => Some(v.clone()),
616 _ => None,
617 }
618 }
619
620 fn children(&self) -> &[Self] {
621 match self {
622 GenericExpr::Var(_, _) | GenericExpr::Lit(_, _) => &[],
623 GenericExpr::Call(_, _, children) => children,
624 }
625 }
626
627 pub fn ast_size(&self) -> usize {
628 let mut size = 0;
629 self.walk(&mut |_e| size += 1, &mut |_| {});
630 size
631 }
632
633 pub fn walk(&self, pre: &mut impl FnMut(&Self), post: &mut impl FnMut(&Self)) {
636 pre(self);
637 self.children()
638 .iter()
639 .for_each(|child| child.walk(pre, post));
640 post(self);
641 }
642
643 pub fn fold<Out>(&self, f: &mut impl FnMut(&Self, Vec<Out>) -> Out) -> Out {
647 let ts = self.children().iter().map(|child| child.fold(f)).collect();
648 f(self, ts)
649 }
650
651 pub fn find<Out>(&self, f: &mut impl FnMut(&Self) -> Option<Out>) -> Option<Out> {
654 if let Some(result) = f(self) {
656 return Some(result);
657 }
658
659 for child in self.children().iter() {
661 if let Some(result) = child.find(f) {
662 return Some(result);
663 }
664 }
665
666 None
667 }
668
669 pub fn visit_exprs(self, f: &mut impl FnMut(Self) -> Self) -> Self {
672 match self {
673 GenericExpr::Lit(..) => f(self),
674 GenericExpr::Var(..) => f(self),
675 GenericExpr::Call(span, op, children) => {
676 let children = children.into_iter().map(|c| c.visit_exprs(f)).collect();
677 f(GenericExpr::Call(span, op.clone(), children))
678 }
679 }
680 }
681
682 pub fn subst<Head2, Leaf2>(
684 &self,
685 subst_leaf: &mut impl FnMut(&Span, &Leaf) -> GenericExpr<Head2, Leaf2>,
686 subst_head: &mut impl FnMut(&Head) -> Head2,
687 ) -> GenericExpr<Head2, Leaf2> {
688 match self {
689 GenericExpr::Lit(span, lit) => GenericExpr::Lit(span.clone(), lit.clone()),
690 GenericExpr::Var(span, v) => subst_leaf(span, v),
691 GenericExpr::Call(span, op, children) => {
692 let children = children
693 .iter()
694 .map(|c| c.subst(subst_leaf, subst_head))
695 .collect();
696 GenericExpr::Call(span.clone(), subst_head(op), children)
697 }
698 }
699 }
700
701 pub fn subst_leaf<Leaf2>(
702 &self,
703 subst_leaf: &mut impl FnMut(&Span, &Leaf) -> GenericExpr<Head, Leaf2>,
704 ) -> GenericExpr<Head, Leaf2> {
705 self.subst(subst_leaf, &mut |x| x.clone())
706 }
707
708 pub fn map_symbols<Head2, Leaf2>(
710 self,
711 head: &mut impl FnMut(Head) -> Head2,
712 leaf: &mut impl FnMut(Leaf) -> Leaf2,
713 ) -> GenericExpr<Head2, Leaf2> {
714 match self {
715 GenericExpr::Lit(span, lit) => GenericExpr::Lit(span, lit),
716 GenericExpr::Var(span, var) => GenericExpr::Var(span, leaf(var)),
717 GenericExpr::Call(span, op, children) => {
718 let mut mapped_children = Vec::with_capacity(children.len());
719 for child in children {
720 mapped_children.push(child.map_symbols(head, leaf));
721 }
722 GenericExpr::Call(span, head(op), mapped_children)
723 }
724 }
725 }
726
727 pub fn make_unresolved(self) -> GenericExpr<String, String> {
729 let mut map_head = |h: Head| h.to_string();
730 let mut map_leaf = |l: Leaf| l.to_string();
731 self.map_symbols(&mut map_head, &mut map_leaf)
732 }
733
734 pub fn vars(&self) -> impl Iterator<Item = Leaf> + '_ {
735 let iterator: Box<dyn Iterator<Item = Leaf>> = match self {
736 GenericExpr::Lit(_ann, _l) => Box::new(std::iter::empty()),
737 GenericExpr::Var(_ann, v) => Box::new(std::iter::once(v.clone())),
738 GenericExpr::Call(_ann, _head, exprs) => Box::new(exprs.iter().flat_map(|e| e.vars())),
739 };
740 iterator
741 }
742}
743
744impl Display for Literal {
745 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
746 match &self {
747 Literal::Int(i) => Display::fmt(i, f),
748 Literal::Float(n) => {
749 let str = n.to_string();
751 if let Ok(_num) = str.parse::<i64>() {
752 write!(f, "{str}.0")
753 } else {
754 write!(f, "{str}")
755 }
756 }
757 Literal::Bool(b) => Display::fmt(b, f),
758 Literal::String(s) => {
763 write!(f, "\"")?;
764 for c in s.chars() {
765 match c {
766 '\\' => write!(f, "\\\\")?,
767 '"' => write!(f, "\\\"")?,
768 c => write!(f, "{c}")?,
769 }
770 }
771 write!(f, "\"")
772 }
773 Literal::Unit => write!(f, "()"),
774 }
775 }
776}
777
778#[cfg(test)]
779mod tests {
780 use super::*;
781
782 #[test]
783 fn display_nullary_call_without_trailing_space() {
784 let expr = GenericExpr::<String, String>::Call(Span::Panic, "foo".into(), vec![]);
785
786 assert_eq!(expr.to_string(), "(foo)");
787 }
788
789 #[test]
790 fn display_nullary_change_without_trailing_space() {
791 let delete = GenericAction::<String, String>::Change(
792 Span::Panic,
793 Change::Delete,
794 "foo".into(),
795 vec![],
796 );
797 let subsume = GenericAction::<String, String>::Change(
798 Span::Panic,
799 Change::Subsume,
800 "foo".into(),
801 vec![],
802 );
803
804 assert_eq!(delete.to_string(), "(delete (foo))");
805 assert_eq!(subsume.to_string(), "(subsume (foo))");
806 }
807
808 #[test]
809 fn display_string_literal_escapes_special_characters() {
810 assert_eq!(Literal::String("plain".into()).to_string(), "\"plain\"");
811 assert_eq!(Literal::String("a\"b".into()).to_string(), "\"a\\\"b\"");
812 assert_eq!(Literal::String("a\\b".into()).to_string(), "\"a\\\\b\"");
813 assert_eq!(Literal::String("a\nb".into()).to_string(), "\"a\nb\"");
815 }
816}