1use crate::prelude::*;
2
3fn chain_link_infix_latex(prop: &str) -> Option<&'static str> {
4 if prop == EQUAL {
5 Some("=")
6 } else if prop == NOT_EQUAL {
7 Some(r"\neq")
8 } else if prop == LESS {
9 Some("<")
10 } else if prop == GREATER {
11 Some(">")
12 } else if prop == LESS_EQUAL {
13 Some(r"\leq")
14 } else if prop == GREATER_EQUAL {
15 Some(r"\geq")
16 } else if prop == IN {
17 Some(r"\in")
18 } else {
19 None
20 }
21}
22
23fn latex_escape_underscore(s: &str) -> String {
24 s.replace('_', r"\_")
25}
26
27fn latex_local_ident(name: &str) -> String {
28 format!(r"\mathit{{{}}}", latex_escape_underscore(name))
29}
30
31fn latex_texttt_escape(s: &str) -> String {
32 let mut out = String::new();
33 for ch in s.chars() {
34 match ch {
35 '_' | '%' | '#' | '&' | '$' => {
36 out.push('\\');
37 out.push(ch);
38 }
39 '{' => out.push_str(r"\{"),
40 '}' => out.push_str(r"\}"),
41 '\\' => out.push_str(r"\textbackslash{}"),
42 '^' => out.push_str(r"\textasciicircum{}"),
43 '~' => out.push_str(r"\textasciitilde{}"),
44 _ => out.push(ch),
45 }
46 }
47 out
48}
49
50fn fn_set_clause_latex(clause: &FnSetClause) -> String {
51 let mut slots: Vec<String> = Vec::new();
52 for g in &clause.params_def_with_set {
53 let set = fn_param_group_type_to_latex(g);
54 for p in &g.params {
55 slots.push(format!(r"{} \in {}", latex_local_ident(p), set));
56 }
57 }
58 let dom = clause
59 .dom_facts
60 .iter()
61 .map(|f| f.to_latex_string())
62 .collect::<Vec<_>>()
63 .join(r", ");
64 let ret = clause.ret_set.to_latex_string();
65 if dom.is_empty() {
66 format!(
67 r"\mathrm{{fn}}\left({}\right)\to {}",
68 slots.join(r", "),
69 ret
70 )
71 } else {
72 format!(
73 r"\mathrm{{fn}}\left({} \,\middle|\, {}\right)\to {}",
74 slots.join(r", "),
75 dom,
76 ret
77 )
78 }
79}
80
81fn fn_param_group_type_to_latex(g: &ParamGroupWithSet) -> String {
82 g.set_obj().to_latex_string()
83}
84
85impl AndChainAtomicFact {
86 pub fn to_latex_string(&self) -> String {
87 match self {
88 AndChainAtomicFact::AtomicFact(x) => x.to_latex_string(),
89 AndChainAtomicFact::AndFact(x) => x.to_latex_string(),
90 AndChainAtomicFact::ChainFact(x) => x.to_latex_string(),
91 }
92 }
93}
94
95impl OrAndChainAtomicFact {
96 pub fn to_latex_string(&self) -> String {
97 match self {
98 OrAndChainAtomicFact::AtomicFact(x) => x.to_latex_string(),
99 OrAndChainAtomicFact::AndFact(x) => x.to_latex_string(),
100 OrAndChainAtomicFact::ChainFact(x) => x.to_latex_string(),
101 OrAndChainAtomicFact::OrFact(x) => x.to_latex_string(),
102 }
103 }
104}
105
106impl AndFact {
107 pub fn to_latex_string(&self) -> String {
108 self.facts
109 .iter()
110 .map(|a| a.to_latex_string())
111 .collect::<Vec<_>>()
112 .join(r" \land ")
113 }
114}
115
116impl ChainFact {
117 pub fn to_latex_string(&self) -> String {
118 if self.objs.is_empty() {
119 return String::new();
120 }
121 let mut s = self.objs[0].to_latex_string();
122 for (i, obj) in self.objs[1..].iter().enumerate() {
123 let pname = self.prop_names[i].to_string();
124 let rhs = obj.to_latex_string();
125 if let Some(op) = chain_link_infix_latex(&pname) {
126 s.push(' ');
127 s.push_str(op);
128 s.push(' ');
129 s.push_str(&rhs);
130 } else if is_comparison_str(&pname) {
131 s.push(' ');
132 s.push_str(&pname);
133 s.push(' ');
134 s.push_str(&rhs);
135 } else {
136 s.push_str(&format!(r" \mathrel{{\mathrm{{{}}}}} {}", pname, rhs));
137 }
138 }
139 s
140 }
141}
142
143impl Abs {
144 pub fn to_latex_string(&self) -> String {
145 format!(r"\left| {} \right|", self.arg.to_latex_string())
146 }
147}
148
149impl Sqrt {
150 pub fn to_latex_string(&self) -> String {
151 format!(r"\sqrt{{{}}}", self.arg.to_latex_string())
152 }
153}
154
155impl Add {
156 pub fn to_latex_string(&self) -> String {
157 format!(
158 "{} + {}",
159 self.left.to_latex_string(),
160 self.right.to_latex_string()
161 )
162 }
163}
164
165impl ByCasesStmt {
166 pub fn to_latex_string(&self) -> String {
167 let goal = self
168 .then_facts
169 .iter()
170 .map(|f| f.to_latex_string())
171 .collect::<Vec<_>>()
172 .join(r" \land ");
173 let mut rows: Vec<String> = Vec::new();
174 rows.push(format!(r"\text{{Proof by cases. Goal:}} & {}", goal));
175 for (i, ((case, proof), imposs)) in self
176 .cases
177 .iter()
178 .zip(self.proofs.iter())
179 .zip(self.impossible_facts.iter())
180 .enumerate()
181 {
182 rows.push(format!(
183 r"\textbf{{\text{{Case {}.}}}} & {}",
184 i + 1,
185 case.to_latex_string()
186 ));
187 for st in proof {
188 rows.push(format!(r"& \quad {}", st.to_latex_string()));
189 }
190 if let Some(atom) = imposs {
191 rows.push(format!(
192 r"\textbf{{\text{{Impossible.}}}} & {}",
193 atom.to_latex_string()
194 ));
195 }
196 }
197 format!(
198 "\\begin{{aligned}}\n{}\n\\end{{aligned}}",
199 rows.join(" \\\\\n")
200 )
201 }
202}
203
204impl ByContraStmt {
205 pub fn to_latex_string(&self) -> String {
206 let goal = self.to_prove.to_latex_string();
207 let mut rows = vec![format!(
208 r"\text{{Proof by contradiction. Goal:}} & {}",
209 goal
210 )];
211 for st in &self.proof {
212 rows.push(format!(r"& \quad {}", st.to_latex_string()));
213 }
214 rows.push(format!(
215 r"\textbf{{\text{{Contradiction.}}}} & {}",
216 self.impossible_fact.to_latex_string()
217 ));
218 format!(
219 "\\begin{{aligned}}\n{}\n\\end{{aligned}}",
220 rows.join(" \\\\\n")
221 )
222 }
223}
224
225impl ByClosedRangeAsCasesStmt {
226 pub fn to_latex_string(&self) -> String {
227 let a = self.closed_range.start.to_latex_string();
228 let b = self.closed_range.end.to_latex_string();
229 let x = self.element.to_latex_string();
230 let row1 = format!(
231 r"&\text{{\textbf{{By closed range as cases}} on }} [\![ {0},{1}]\!]\text{{.}}",
232 a, b
233 );
234 let row2 = format!(
235 r"&\text{{Equivalently }} {0} \in \{{{1},\, {1}+1,\, \ldots,\, {2}\}}\text{{ (segment {1}\ldots {2}).}}",
236 x, a, b
237 );
238 let row3 = format!(
239 r"&\text{{So }} {0}={1}\lor {0}={1}+1\lor\cdots\lor {0}={2}\text{{.}}",
240 x, a, b
241 );
242 format!("\\begin{{aligned}}\n{row1} \\\\\n{row2} \\\\\n{row3} \n\\end{{aligned}}")
243 }
244}
245
246impl ByEnumerateFiniteSetStmt {
247 pub fn to_latex_string(&self) -> String {
248 let mut rows = vec![format!(
249 r"\text{{Proof by exhaustive enumeration (finite cases).}} & {}",
250 self.forall_fact.to_latex_string()
251 )];
252 for st in &self.proof {
253 rows.push(format!(r"& \quad {}", st.to_latex_string()));
254 }
255 format!(
256 "\\begin{{aligned}}\n{}\n\\end{{aligned}}",
257 rows.join(" \\\\\n")
258 )
259 }
260}
261
262impl ByExtensionStmt {
263 pub fn to_latex_string(&self) -> String {
264 let l = self.left.to_latex_string();
265 let r = self.right.to_latex_string();
266 let mut rows = vec![format!(
267 r"\text{{\textbf{{By extensionality}}:}} & {}={} \Longleftrightarrow \bigl({}\subseteq {}\land {}\subseteq {}\bigr)\text{{.}}",
268 l, r, l, r, r, l
269 )];
270 for st in &self.proof {
271 rows.push(format!(r"& \quad {}", st.to_latex_string()));
272 }
273 format!(
274 "\\begin{{aligned}}\n{}\n\\end{{aligned}}",
275 rows.join(" \\\\\n")
276 )
277 }
278}
279
280impl ByFnSetAsSetStmt {
281 pub fn to_latex_string(&self) -> String {
282 format!(
283 "\\begin{{aligned}}\n\\text{{\\textbf{{By fn set as set}}:}} & {} \\in {}\\\\\n& \\quad \\text{{Unfold this membership via the set-theoretic definition of the function space; obtain the corresponding facts.}}\n\\end{{aligned}}",
284 self.func.to_latex_string(),
285 self.fn_set.to_latex_string()
286 )
287 }
288}
289
290impl ByFnAsSetStmt {
291 pub fn to_latex_string(&self) -> String {
292 format!(
293 "\\begin{{aligned}}\n\\text{{\\textbf{{By fn as set}}:}} & \\text{{Use the graph / function definition of }} {}\\text{{.}}\n\\end{{aligned}}",
294 self.function.to_latex_string()
295 )
296 }
297}
298
299impl ByForStmt {
300 pub fn to_latex_string(&self) -> String {
301 let mut rows = vec![format!(
302 r"\text{{\textbf{{by for}}:}} & {}",
303 self.forall_fact.to_latex_string()
304 )];
305 for st in &self.proof {
306 rows.push(format!(r"& \quad {}", st.to_latex_string()));
307 }
308 format!(
309 "\\begin{{aligned}}\n{}\n\\end{{aligned}}",
310 rows.join(" \\\\\n")
311 )
312 }
313}
314
315impl ByTransitivePropStmt {
316 pub fn to_latex_string(&self) -> String {
317 let mut rows = vec![format!(
318 r"\text{{\textbf{{by transitive_prop}}:}} & {}",
319 self.forall_fact.to_latex_string()
320 )];
321 for st in &self.proof {
322 rows.push(format!(r"& \quad {}", st.to_latex_string()));
323 }
324 format!(
325 "\\begin{{aligned}}\n{}\n\\end{{aligned}}",
326 rows.join(" \\\\\n")
327 )
328 }
329}
330
331impl BySymmetricPropStmt {
332 pub fn to_latex_string(&self) -> String {
333 let mut rows = vec![format!(
334 r"\text{{\textbf{{by symmetric_prop}}:}} & {}",
335 self.forall_fact.to_latex_string()
336 )];
337 for st in &self.proof {
338 rows.push(format!(r"& \quad {}", st.to_latex_string()));
339 }
340 format!(
341 "\\begin{{aligned}}\n{}\n\\end{{aligned}}",
342 rows.join(" \\\\\n")
343 )
344 }
345}
346
347impl ByReflexivePropStmt {
348 pub fn to_latex_string(&self) -> String {
349 let mut rows = vec![format!(
350 r"\text{{\textbf{{by reflexive_prop}}:}} & {}",
351 self.forall_fact.to_latex_string()
352 )];
353 for st in &self.proof {
354 rows.push(format!(r"& \quad {}", st.to_latex_string()));
355 }
356 format!(
357 "\\begin{{aligned}}\n{}\n\\end{{aligned}}",
358 rows.join(" \\\\\n")
359 )
360 }
361}
362
363impl ByAntisymmetricPropStmt {
364 pub fn to_latex_string(&self) -> String {
365 let mut rows = vec![format!(
366 r"\text{{\textbf{{by antisymmetric_prop}}:}} & {}",
367 self.forall_fact.to_latex_string()
368 )];
369 for st in &self.proof {
370 rows.push(format!(r"& \quad {}", st.to_latex_string()));
371 }
372 format!(
373 "\\begin{{aligned}}\n{}\n\\end{{aligned}}",
374 rows.join(" \\\\\n")
375 )
376 }
377}
378
379impl ByInducStmt {
380 pub fn to_latex_string(&self) -> String {
381 let goals = self
382 .to_prove
383 .iter()
384 .map(|f| f.to_latex_string())
385 .collect::<Vec<_>>()
386 .join(r" \land ");
387 let induc_label = if self.strong {
388 r"\text{\textbf{strong induc} on }"
389 } else {
390 r"\text{\textbf{by induc} on }"
391 };
392 let mut rows = vec![format!(
393 r"{} {} \text{{ from }} {} \texttt{{:}} & {}",
394 induc_label,
395 latex_local_ident(&self.param),
396 self.induc_from.to_latex_string(),
397 goals
398 )];
399 rows.push(r"\text{prove:} &".to_string());
400 for st in &self.proof {
401 rows.push(format!(r"& \quad {}", st.to_latex_string()));
402 }
403 format!(
404 "\\begin{{aligned}}\n{}\n\\end{{aligned}}",
405 rows.join(" \\\\\n")
406 )
407 }
408}
409
410impl ByTupleAsSetStmt {
411 pub fn to_latex_string(&self) -> String {
412 format!(
413 "\\begin{{aligned}}\n\\text{{\\textbf{{By tuple as set}}:}} & \\text{{Use the set-theoretic ordered-pair / tuple encoding for }} {}\\text{{; obtain the corresponding set-theoretic facts.}}\n\\end{{aligned}}",
414 self.obj.to_latex_string()
415 )
416 }
417}
418
419impl Cap {
420 pub fn to_latex_string(&self) -> String {
421 format!(
422 r"\operatorname{{{}}}\left( {}\right)",
423 CAP,
424 self.left.to_latex_string()
425 )
426 }
427}
428
429impl Cart {
430 pub fn to_latex_string(&self) -> String {
431 let inner = self
432 .args
433 .iter()
434 .map(|o| o.to_latex_string())
435 .collect::<Vec<_>>()
436 .join(", ");
437 format!(r"\operatorname{{{}}}\left( {}\right)", CART, inner)
438 }
439}
440
441impl CartDim {
442 pub fn to_latex_string(&self) -> String {
443 format!(
444 r"\operatorname{{{}}}\left( {}\right)",
445 CART_DIM,
446 self.set.to_latex_string()
447 )
448 }
449}
450
451impl ClaimStmt {
452 pub fn to_latex_string(&self) -> String {
453 let mut rows = vec![
454 format!(
455 r"\text{{\textbf{{claim}}:}} & {}",
456 self.fact.to_latex_string()
457 ),
458 r"\text{\textbf{prove}:} &".to_string(),
459 ];
460 for st in &self.proof {
461 rows.push(format!(r"& \quad {}", st.to_latex_string()));
462 }
463 format!(
464 "\\begin{{aligned}}\n{}\n\\end{{aligned}}",
465 rows.join(" \\\\\n")
466 )
467 }
468}
469
470impl ClosedRange {
471 pub fn to_latex_string(&self) -> String {
472 format!(
473 r"\operatorname{{{}}}\left( {}, {} \right)",
474 CLOSED_RANGE,
475 self.start.to_latex_string(),
476 self.end.to_latex_string()
477 )
478 }
479}
480
481impl Count {
482 pub fn to_latex_string(&self) -> String {
483 format!(
484 r"\operatorname{{{}}}\left( {}\right)",
485 COUNT,
486 self.set.to_latex_string()
487 )
488 }
489}
490
491impl Sum {
492 pub fn to_latex_string(&self) -> String {
493 format!(
494 r"\operatorname{{{}}}\left( {}, {}, {} \right)",
495 SUM,
496 self.start.to_latex_string(),
497 self.end.to_latex_string(),
498 self.func.to_latex_string()
499 )
500 }
501}
502
503impl Product {
504 pub fn to_latex_string(&self) -> String {
505 format!(
506 r"\operatorname{{{}}}\left( {}, {}, {} \right)",
507 PRODUCT,
508 self.start.to_latex_string(),
509 self.end.to_latex_string(),
510 self.func.to_latex_string()
511 )
512 }
513}
514
515impl Cup {
516 pub fn to_latex_string(&self) -> String {
517 format!(
518 r"\operatorname{{{}}}\left( {}\right)",
519 CUP,
520 self.left.to_latex_string()
521 )
522 }
523}
524
525impl Choose {
526 pub fn to_latex_string(&self) -> String {
527 format!(
528 r"\operatorname{{{}}}\left( {}\right)",
529 CHOOSE,
530 self.set.to_latex_string()
531 )
532 }
533}
534
535impl DefAbstractPropStmt {
536 pub fn to_latex_string(&self) -> String {
537 let ps = self
538 .params
539 .iter()
540 .map(|p| latex_local_ident(p))
541 .collect::<Vec<_>>()
542 .join(", ");
543 format!(
544 r"\operatorname{{{}}}\, {}\left\{{ {} \right\}}",
545 ABSTRACT_PROP,
546 latex_local_ident(&self.name),
547 ps
548 )
549 }
550}
551
552impl DefAlgoStmt {
553 pub fn to_latex_string(&self) -> String {
554 let ps = self
555 .params
556 .iter()
557 .map(|p| latex_local_ident(p))
558 .collect::<Vec<_>>()
559 .join(", ");
560 let mut rows = vec![format!(
561 r"\operatorname{{{}}}\, {}\left( {}\right) \texttt{{:}}",
562 ALGO,
563 latex_local_ident(&self.name),
564 ps
565 )];
566 for c in &self.cases {
567 rows.push(format!(
568 r"& \quad \mathrm{{case}}\ {} \texttt{{:}}\ {}",
569 c.condition.to_latex_string(),
570 c.return_stmt.value.to_latex_string()
571 ));
572 }
573 if let Some(dr) = &self.default_return {
574 rows.push(format!(
575 r"& \quad \mathrm{{default}}\ \texttt{{:}}\ {}",
576 dr.value.to_latex_string()
577 ));
578 }
579 format!(
580 "\\begin{{aligned}}\n{}\n\\end{{aligned}}",
581 rows.join(" \\\\\n")
582 )
583 }
584}
585
586impl DefLetStmt {
587 pub fn to_latex_string(&self) -> String {
588 match self.facts.len() {
589 0 => format!(
590 r"\operatorname{{{}}}\, {}",
591 LET,
592 self.param_def.to_latex_string()
593 ),
594 _ => {
595 let mut rows = vec![format!(
596 r"\operatorname{{{}}}\, {}",
597 LET,
598 self.param_def.to_latex_string()
599 )];
600 for fact in &self.facts {
601 rows.push(format!(r"& \quad {}", fact.to_latex_string()));
602 }
603 format!(
604 "\\begin{{aligned}}\n{}\n\\end{{aligned}}",
605 rows.join(" \\\\\n")
606 )
607 }
608 }
609 }
610}
611
612impl DefPropStmt {
613 pub fn to_latex_string(&self) -> String {
614 match self.iff_facts.len() {
615 0 => format!(
616 r"\operatorname{{{}}}\, {}\left\{{ {} \right\}}",
617 PROP,
618 latex_local_ident(&self.name),
619 self.params_def_with_type.to_latex_string()
620 ),
621 _ => {
622 let mut rows = vec![format!(
623 r"\operatorname{{{}}}\, {}\left\{{ {} \right\}} \texttt{{:}}",
624 PROP,
625 latex_local_ident(&self.name),
626 self.params_def_with_type.to_latex_string()
627 )];
628 for fact in &self.iff_facts {
629 rows.push(format!(r"& \quad {}", fact.to_latex_string()));
630 }
631 format!(
632 "\\begin{{aligned}}\n{}\n\\end{{aligned}}",
633 rows.join(" \\\\\n")
634 )
635 }
636 }
637 }
638}
639
640impl Div {
641 pub fn to_latex_string(&self) -> String {
642 format!(
643 r"\frac{{{}}}{{{}}}",
644 self.left.to_latex_string(),
645 self.right.to_latex_string()
646 )
647 }
648}
649
650impl DoNothingStmt {
651 pub fn to_latex_string(&self) -> String {
652 format!(r"\mathrm{{{}}}", DO_NOTHING)
653 }
654}
655
656impl ClearStmt {
657 pub fn to_latex_string(&self) -> String {
658 format!(r"\mathrm{{{}}}", CLEAR)
659 }
660}
661
662impl EqualFact {
663 pub fn to_latex_string(&self) -> String {
664 format!(
665 "{} = {}",
666 self.left.to_latex_string(),
667 self.right.to_latex_string()
668 )
669 }
670}
671
672impl EvalStmt {
673 pub fn to_latex_string(&self) -> String {
674 format!(
675 r"\operatorname{{{}}}\, {}",
676 EVAL,
677 self.obj_to_eval.to_latex_string()
678 )
679 }
680}
681
682impl EvalByStmt {
683 pub fn to_latex_string(&self) -> String {
684 format!(
685 r"\operatorname{{{}}}\, {} \operatorname{{{}}} {}",
686 EVAL,
687 self.lhs.to_latex_string(),
688 FROM,
689 self.rhs.to_latex_string()
690 )
691 }
692}
693
694impl ExistFactEnum {
695 pub fn to_latex_string(&self) -> String {
696 let head = if self.is_not_exist() {
697 r"\nexists"
698 } else if self.is_exist_unique() {
699 r"\exists!"
700 } else {
701 r"\exists"
702 };
703 let params = self.params_def_with_type().to_latex_string();
704 let facts = self
705 .facts()
706 .iter()
707 .map(|f| f.to_latex_string())
708 .collect::<Vec<_>>()
709 .join(r", ");
710 format!(
711 r"{}\, \left( {}\right)\, \mathrm{{st}}\, \left\{{ {} \right\}}",
712 head, params, facts
713 )
714 }
715}
716
717impl ExistBodyFact {
718 pub fn to_latex_string(&self) -> String {
719 match self {
720 ExistBodyFact::AtomicFact(x) => x.to_latex_string(),
721 ExistBodyFact::AndFact(x) => x.to_latex_string(),
722 ExistBodyFact::ChainFact(x) => x.to_latex_string(),
723 ExistBodyFact::OrFact(x) => x.to_latex_string(),
724 ExistBodyFact::InlineForall(x) => x.to_latex_string(),
725 }
726 }
727}
728
729impl ExistOrAndChainAtomicFact {
730 pub fn to_latex_string(&self) -> String {
731 match self {
732 ExistOrAndChainAtomicFact::AtomicFact(x) => x.to_latex_string(),
733 ExistOrAndChainAtomicFact::AndFact(x) => x.to_latex_string(),
734 ExistOrAndChainAtomicFact::ChainFact(x) => x.to_latex_string(),
735 ExistOrAndChainAtomicFact::OrFact(x) => x.to_latex_string(),
736 ExistOrAndChainAtomicFact::ExistFact(x) => x.to_latex_string(),
737 }
738 }
739}
740
741impl FiniteSeqListObj {
742 pub fn to_latex_string(&self) -> String {
743 let inner = self
744 .objs
745 .iter()
746 .map(|o| o.to_latex_string())
747 .collect::<Vec<_>>()
748 .join(", ");
749 format!(r"\left[ {} \right]", inner)
750 }
751}
752
753impl FiniteSeqSet {
754 pub fn to_latex_string(&self) -> String {
755 format!(
756 r"\operatorname{{{}}}\left( {}, {} \right)",
757 FINITE_SEQ,
758 self.set.to_latex_string(),
759 self.n.to_latex_string()
760 )
761 }
762}
763
764impl FnObj {
765 pub fn to_latex_string(&self) -> String {
766 let head = match self.head.as_ref() {
767 FnObjHead::Identifier(i) => i.to_latex_string(),
768 FnObjHead::IdentifierWithMod(i) => i.to_latex_string(),
769 FnObjHead::Forall(p) => latex_local_ident(&p.name),
770 FnObjHead::DefHeader(p) => latex_local_ident(&p.name),
771 FnObjHead::Exist(p) => latex_local_ident(&p.name),
772 FnObjHead::SetBuilder(p) => latex_local_ident(&p.name),
773 FnObjHead::FnSet(p) => latex_local_ident(&p.name),
774 FnObjHead::AnonymousFnLiteral(a) => a.to_latex_string(),
775 FnObjHead::FiniteSeqListObj(v) => v.to_latex_string(),
776 FnObjHead::Induc(p) => latex_local_ident(&p.name),
777 FnObjHead::DefAlgo(p) => latex_local_ident(&p.name),
778 FnObjHead::InstantiatedTemplateObj(t) => latex_texttt_escape(&t.to_string()),
779 };
780 let mut s = head;
781 for group in self.body.iter() {
782 let inner = group
783 .iter()
784 .map(|o| o.to_latex_string())
785 .collect::<Vec<_>>()
786 .join(", ");
787 s.push_str(&format!(r"\left( {} \right)", inner));
788 }
789 s
790 }
791}
792
793impl AnonymousFn {
794 pub fn to_latex_string(&self) -> String {
795 let mut slots: Vec<String> = Vec::new();
796 for g in &self.body.params_def_with_set {
797 let set = fn_param_group_type_to_latex(g);
798 for p in &g.params {
799 slots.push(format!(r"{} \in {}", latex_local_ident(p), set));
800 }
801 }
802 let dom = self
803 .body
804 .dom_facts
805 .iter()
806 .map(|f| f.to_latex_string())
807 .collect::<Vec<_>>()
808 .join(r", ");
809 let ret = self.body.ret_set.to_latex_string();
810 let body = self.equal_to.to_latex_string();
811 let sig = if dom.is_empty() {
812 format!(r"\left({}\right)", slots.join(r", "))
813 } else {
814 format!(r"\left({} \,\middle|\, {}\right)", slots.join(r", "), dom)
815 };
816 format!(
817 r"'\, {} \to {} \mapsto \left\{{ {}\right\}}",
818 sig, ret, body
819 )
820 }
821}
822
823impl FnSet {
824 pub fn to_latex_string(&self) -> String {
825 let mut slots: Vec<String> = Vec::new();
826 for g in &self.body.params_def_with_set {
827 let set = fn_param_group_type_to_latex(g);
828 for p in &g.params {
829 slots.push(format!(r"{} \in {}", latex_local_ident(p), set));
830 }
831 }
832 let dom = self
833 .body
834 .dom_facts
835 .iter()
836 .map(|f| f.to_latex_string())
837 .collect::<Vec<_>>()
838 .join(r", ");
839 let ret = self.body.ret_set.to_latex_string();
840 if dom.is_empty() {
841 format!(
842 r"\mathrm{{fn}}\left({}\right)\to {}",
843 slots.join(r", "),
844 ret
845 )
846 } else {
847 format!(
848 r"\mathrm{{fn}}\left({} \,\middle|\, {}\right)\to {}",
849 slots.join(r", "),
850 dom,
851 ret
852 )
853 }
854 }
855}
856
857impl ForallFact {
858 pub fn to_latex_string(&self) -> String {
859 let params = self.params_def_with_type.to_latex_string();
860 let then = self
861 .then_facts
862 .iter()
863 .map(|f| f.to_latex_string())
864 .collect::<Vec<_>>()
865 .join(r" \land ");
866 if self.dom_facts.is_empty() {
867 format!(r"\forall \left( {}\right),\, {}", params, then)
868 } else {
869 let dom = self
870 .dom_facts
871 .iter()
872 .map(|f| f.to_latex_string())
873 .collect::<Vec<_>>()
874 .join(r" \land ");
875 format!(
876 r"\forall \left( {}\right),\ \left( {}\right) \Rightarrow \left( {}\right)",
877 params, dom, then
878 )
879 }
880 }
881}
882
883impl ForallFactWithIff {
884 pub fn to_latex_string(&self) -> String {
885 let iff = self
886 .iff_facts
887 .iter()
888 .map(|f| f.to_latex_string())
889 .collect::<Vec<_>>()
890 .join(r" \land ");
891 format!(
892 r"{}\, \Longleftrightarrow\, \left( {}\right)",
893 self.forall_fact.to_latex_string(),
894 iff
895 )
896 }
897}
898
899impl NotForallFact {
900 pub fn to_latex_string(&self) -> String {
901 format!(
902 r"\neg\, \left( {}\right)",
903 self.forall_fact.to_latex_string()
904 )
905 }
906}
907
908impl GreaterEqualFact {
909 pub fn to_latex_string(&self) -> String {
910 format!(
911 r"{} \geq {}",
912 self.left.to_latex_string(),
913 self.right.to_latex_string()
914 )
915 }
916}
917
918impl GreaterFact {
919 pub fn to_latex_string(&self) -> String {
920 format!(
921 "{} > {}",
922 self.left.to_latex_string(),
923 self.right.to_latex_string()
924 )
925 }
926}
927
928impl HaveByExistStmt {
929 pub fn to_latex_string(&self) -> String {
930 let names = self
931 .equal_tos
932 .iter()
933 .map(|s| latex_local_ident(s))
934 .collect::<Vec<_>>()
935 .join(", ");
936 format!(
937 r"\mathrm{{have}}\ \mathrm{{by}}\ {} : {}",
938 self.exist_fact_in_have_obj_st.to_latex_string(),
939 names
940 )
941 }
942}
943
944impl HaveFnByInducStmt {
945 pub fn to_latex_string(&self) -> String {
946 let mut rows: Vec<String> = Vec::new();
947 rows.push(format!(
948 r"\mathrm{{have}}\ \mathrm{{fn}}\ {}\ {} \quad \mathrm{{by}}\ \mathrm{{decreasing}}\ {} \ \mathrm{{from}}\ {}",
949 latex_local_ident(&self.name),
950 fn_set_clause_latex(&self.fn_set_clause),
951 self.measure.to_latex_string(),
952 self.lower_bound.to_latex_string(),
953 ));
954 Self::push_case_rows(&mut rows, &self.cases, 1);
955 format!(
956 "\\begin{{aligned}}\n{}\n\\end{{aligned}}",
957 rows.join(" \\\\\n")
958 )
959 }
960
961 fn push_case_rows(rows: &mut Vec<String>, cases: &[HaveFnByInducCase], indent: usize) {
962 let pad = r"\quad ".repeat(indent);
963 for c in cases {
964 match &c.body {
965 HaveFnByInducCaseBody::EqualTo(eq) => rows.push(format!(
966 r"& {} \mathrm{{case}}\ {} : {}",
967 pad,
968 c.case_fact.to_latex_string(),
969 eq.to_latex_string()
970 )),
971 HaveFnByInducCaseBody::NestedCases(nested) => {
972 rows.push(format!(
973 r"& {} \mathrm{{case}}\ {} \texttt{{:}}",
974 pad,
975 c.case_fact.to_latex_string()
976 ));
977 Self::push_case_rows(rows, nested, indent + 1);
978 }
979 }
980 }
981 }
982}
983
984impl HaveFnEqualCaseByCaseStmt {
985 pub fn to_latex_string(&self) -> String {
986 let head = format!(
987 r"\mathrm{{have}}\ \mathrm{{fn}}\ {}\ \mathrm{{by}}\ \mathrm{{cases}}\texttt{{:}}",
988 latex_local_ident(&self.name)
989 );
990 let clause = fn_set_clause_latex(&self.fn_set_clause);
991 let mut rows = vec![format!(r"{} & {}", head, clause)];
992 for (i, case) in self.cases.iter().enumerate() {
993 rows.push(format!(
994 r"& \quad \mathrm{{case}}\ {} \texttt{{:}}\ {}",
995 case.to_latex_string(),
996 self.equal_tos[i].to_latex_string()
997 ));
998 }
999 format!(
1000 "\\begin{{aligned}}\n{}\n\\end{{aligned}}",
1001 rows.join(" \\\\\n")
1002 )
1003 }
1004}
1005
1006impl HaveFnEqualStmt {
1007 pub fn to_latex_string(&self) -> String {
1008 let fn_set_clause = FnSetClause::new(
1009 self.equal_to_anonymous_fn.body.params_def_with_set.clone(),
1010 self.equal_to_anonymous_fn.body.dom_facts.clone(),
1011 (*self.equal_to_anonymous_fn.body.ret_set).clone(),
1012 )
1013 .expect("anonymous function signature was already validated");
1014 format!(
1015 r"\mathrm{{have}}\ \mathrm{{fn}}\ {}\ {} {}",
1016 latex_local_ident(&self.name),
1017 fn_set_clause_latex(&fn_set_clause),
1018 self.equal_to_anonymous_fn.equal_to.to_latex_string()
1019 )
1020 }
1021}
1022
1023impl HaveFnByForallExistUniqueStmt {
1024 pub fn to_latex_string(&self) -> String {
1025 format!(
1026 r"\mathrm{{have}}\ \mathrm{{fn}}\ {}\ \mathrm{{as}}\ \mathrm{{set}}:\ {}",
1027 latex_local_ident(&self.fn_name),
1028 self.forall.to_latex_string()
1029 )
1030 }
1031}
1032
1033impl HaveObjEqualStmt {
1034 pub fn to_latex_string(&self) -> String {
1035 let rhs = self
1036 .objs_equal_to
1037 .iter()
1038 .map(|o| o.to_latex_string())
1039 .collect::<Vec<_>>()
1040 .join(", ");
1041 format!(
1042 r"\mathrm{{have}}\ {} = {}",
1043 self.param_def.to_latex_string(),
1044 rhs
1045 )
1046 }
1047}
1048
1049impl HaveObjInNonemptySetOrParamTypeStmt {
1050 pub fn to_latex_string(&self) -> String {
1051 format!(r"\mathrm{{have}}\ {}", self.param_def.to_latex_string())
1052 }
1053}
1054
1055impl Identifier {
1056 pub fn to_latex_string(&self) -> String {
1057 latex_local_ident(&self.name)
1058 }
1059}
1060
1061impl IdentifierWithMod {
1062 pub fn to_latex_string(&self) -> String {
1063 format!(
1064 r"{}\mathbin{{\mathrm{{::}}}}{}",
1065 latex_local_ident(&self.mod_name),
1066 latex_local_ident(&self.name)
1067 )
1068 }
1069}
1070
1071impl AtomicName {
1072 pub fn to_latex_string(&self) -> String {
1073 match self {
1074 AtomicName::WithoutMod(s) => latex_local_ident(s),
1075 AtomicName::WithMod(m, n) => format!(
1076 r"{}\mathbin{{\mathrm{{::}}}}{}",
1077 latex_local_ident(m),
1078 latex_local_ident(n)
1079 ),
1080 }
1081 }
1082}
1083
1084impl InFact {
1085 pub fn to_latex_string(&self) -> String {
1086 format!(
1087 r"{} \in {}",
1088 self.element.to_latex_string(),
1089 self.set.to_latex_string()
1090 )
1091 }
1092}
1093
1094impl Intersect {
1095 pub fn to_latex_string(&self) -> String {
1096 format!(
1097 r"{} \cap {}",
1098 self.left.to_latex_string(),
1099 self.right.to_latex_string()
1100 )
1101 }
1102}
1103
1104impl IsCartFact {
1105 pub fn to_latex_string(&self) -> String {
1106 format!(
1107 r"\$ \mathrm{{{}}}\left( {}\right)",
1108 IS_CART,
1109 self.set.to_latex_string()
1110 )
1111 }
1112}
1113
1114impl IsFiniteSetFact {
1115 pub fn to_latex_string(&self) -> String {
1116 format!(
1117 r"\$ \mathrm{{{}}}\left( {}\right)",
1118 IS_FINITE_SET,
1119 self.set.to_latex_string()
1120 )
1121 }
1122}
1123
1124impl IsNonemptySetFact {
1125 pub fn to_latex_string(&self) -> String {
1126 format!(
1127 r"\$ \mathrm{{{}}}\left( {}\right)",
1128 IS_NONEMPTY_SET,
1129 self.set.to_latex_string()
1130 )
1131 }
1132}
1133
1134impl IsSetFact {
1135 pub fn to_latex_string(&self) -> String {
1136 format!(
1137 r"\$ \mathrm{{{}}}\left( {}\right)",
1138 IS_SET,
1139 self.set.to_latex_string()
1140 )
1141 }
1142}
1143
1144impl IsTupleFact {
1145 pub fn to_latex_string(&self) -> String {
1146 format!(
1147 r"\$ \mathrm{{{}}}\left( {}\right)",
1148 IS_TUPLE,
1149 self.set.to_latex_string()
1150 )
1151 }
1152}
1153
1154impl KnowStmt {
1155 pub fn to_latex_string(&self) -> String {
1156 if self.facts.len() == 1 {
1157 format!(
1158 r"\operatorname{{{}}} {}",
1159 KNOW,
1160 self.facts[0].to_latex_string()
1161 )
1162 } else {
1163 let rows = self
1164 .facts
1165 .iter()
1166 .map(|fact| format!("& {}", fact.to_latex_string()))
1167 .collect::<Vec<_>>()
1168 .join(" \\\\\n");
1169 format!(
1170 r"\operatorname{{{}}}\colon \begin{{aligned}}{}\end{{aligned}}",
1171 KNOW, rows
1172 )
1173 }
1174 }
1175}
1176
1177impl LessEqualFact {
1178 pub fn to_latex_string(&self) -> String {
1179 format!(
1180 r"{} \leq {}",
1181 self.left.to_latex_string(),
1182 self.right.to_latex_string()
1183 )
1184 }
1185}
1186
1187impl LessFact {
1188 pub fn to_latex_string(&self) -> String {
1189 format!(
1190 "{} < {}",
1191 self.left.to_latex_string(),
1192 self.right.to_latex_string()
1193 )
1194 }
1195}
1196
1197impl ListSet {
1198 pub fn to_latex_string(&self) -> String {
1199 let inner = self
1200 .list
1201 .iter()
1202 .map(|o| o.to_latex_string())
1203 .collect::<Vec<_>>()
1204 .join(", ");
1205 format!(r"\left\{{ {} \right\}}", inner)
1206 }
1207}
1208
1209impl Log {
1210 pub fn to_latex_string(&self) -> String {
1211 format!(
1212 r"\log_{{{}}} \left( {} \right)",
1213 self.base.to_latex_string(),
1214 self.arg.to_latex_string()
1215 )
1216 }
1217}
1218
1219impl MatrixAdd {
1220 pub fn to_latex_string(&self) -> String {
1221 format!(
1222 r"{} \mathbin{{\mathrm{{{}}}}} {}",
1223 self.left.to_latex_string(),
1224 latex_escape_underscore(MATRIX_ADD),
1225 self.right.to_latex_string()
1226 )
1227 }
1228}
1229
1230impl MatrixListObj {
1231 pub fn to_latex_string(&self) -> String {
1232 let rows = self
1233 .rows
1234 .iter()
1235 .map(|row| {
1236 let inner = row
1237 .iter()
1238 .map(|o| o.to_latex_string())
1239 .collect::<Vec<_>>()
1240 .join(", ");
1241 format!(r"\left( {} \right)", inner)
1242 })
1243 .collect::<Vec<_>>()
1244 .join(", ");
1245 format!(r"\left[ {} \right]", rows)
1246 }
1247}
1248
1249impl MatrixMul {
1250 pub fn to_latex_string(&self) -> String {
1251 format!(
1252 r"{} \mathbin{{\mathrm{{{}}}}} {}",
1253 self.left.to_latex_string(),
1254 latex_escape_underscore(MATRIX_MUL),
1255 self.right.to_latex_string()
1256 )
1257 }
1258}
1259
1260impl MatrixPow {
1261 pub fn to_latex_string(&self) -> String {
1262 format!(
1263 r"{} \mathbin{{\mathrm{{{}}}}} {}",
1264 self.base.to_latex_string(),
1265 latex_escape_underscore(MATRIX_POW),
1266 self.exponent.to_latex_string()
1267 )
1268 }
1269}
1270
1271impl MatrixScalarMul {
1272 pub fn to_latex_string(&self) -> String {
1273 format!(
1274 r"{} \mathbin{{\mathrm{{{}}}}} {}",
1275 self.scalar.to_latex_string(),
1276 latex_escape_underscore(MATRIX_SCALAR_MUL),
1277 self.matrix.to_latex_string()
1278 )
1279 }
1280}
1281
1282impl MatrixSet {
1283 pub fn to_latex_string(&self) -> String {
1284 format!(
1285 r"\operatorname{{{}}}\left( {}, {}, {} \right)",
1286 MATRIX,
1287 self.set.to_latex_string(),
1288 self.row_len.to_latex_string(),
1289 self.col_len.to_latex_string()
1290 )
1291 }
1292}
1293
1294impl MatrixSub {
1295 pub fn to_latex_string(&self) -> String {
1296 format!(
1297 r"{} \mathbin{{\mathrm{{{}}}}} {}",
1298 self.left.to_latex_string(),
1299 latex_escape_underscore(MATRIX_SUB),
1300 self.right.to_latex_string()
1301 )
1302 }
1303}
1304
1305impl Max {
1306 pub fn to_latex_string(&self) -> String {
1307 format!(
1308 r"\max \left( {}, {} \right)",
1309 self.left.to_latex_string(),
1310 self.right.to_latex_string()
1311 )
1312 }
1313}
1314
1315impl Min {
1316 pub fn to_latex_string(&self) -> String {
1317 format!(
1318 r"\min \left( {}, {} \right)",
1319 self.left.to_latex_string(),
1320 self.right.to_latex_string()
1321 )
1322 }
1323}
1324
1325impl Mod {
1326 pub fn to_latex_string(&self) -> String {
1327 format!(
1328 r"\left( {} \mathbin{{\mathrm{{mod}}}} {} \right)",
1329 self.left.to_latex_string(),
1330 self.right.to_latex_string()
1331 )
1332 }
1333}
1334
1335impl Mul {
1336 pub fn to_latex_string(&self) -> String {
1337 format!(
1338 r"{0} \cdot {1}",
1339 self.left.to_latex_string(),
1340 self.right.to_latex_string()
1341 )
1342 }
1343}
1344
1345impl NormalAtomicFact {
1346 pub fn to_latex_string(&self) -> String {
1347 let pred = self.predicate.to_latex_string();
1348 let args = self
1349 .body
1350 .iter()
1351 .map(|o| o.to_latex_string())
1352 .collect::<Vec<_>>()
1353 .join(", ");
1354 format!(r"\$ {}\left( {}\right)", pred, args)
1355 }
1356}
1357
1358impl NotEqualFact {
1359 pub fn to_latex_string(&self) -> String {
1360 format!(
1361 r"{} \neq {}",
1362 self.left.to_latex_string(),
1363 self.right.to_latex_string()
1364 )
1365 }
1366}
1367
1368impl NotGreaterEqualFact {
1369 pub fn to_latex_string(&self) -> String {
1370 format!(
1371 r"{} \ngeq {}",
1372 self.left.to_latex_string(),
1373 self.right.to_latex_string()
1374 )
1375 }
1376}
1377
1378impl NotGreaterFact {
1379 pub fn to_latex_string(&self) -> String {
1380 format!(
1381 r"{} \ngtr {}",
1382 self.left.to_latex_string(),
1383 self.right.to_latex_string()
1384 )
1385 }
1386}
1387
1388impl NotInFact {
1389 pub fn to_latex_string(&self) -> String {
1390 format!(
1391 r"{} \notin {}",
1392 self.element.to_latex_string(),
1393 self.set.to_latex_string()
1394 )
1395 }
1396}
1397
1398impl NotIsCartFact {
1399 pub fn to_latex_string(&self) -> String {
1400 format!(
1401 r"\neg \left( \$ \mathrm{{{}}}\left( {}\right) \right)",
1402 IS_CART,
1403 self.set.to_latex_string()
1404 )
1405 }
1406}
1407
1408impl NotIsFiniteSetFact {
1409 pub fn to_latex_string(&self) -> String {
1410 format!(
1411 r"\neg \left( \$ \mathrm{{{}}}\left( {}\right) \right)",
1412 IS_FINITE_SET,
1413 self.set.to_latex_string()
1414 )
1415 }
1416}
1417
1418impl NotIsNonemptySetFact {
1419 pub fn to_latex_string(&self) -> String {
1420 format!(
1421 r"\neg \left( \$ \mathrm{{{}}}\left( {}\right) \right)",
1422 IS_NONEMPTY_SET,
1423 self.set.to_latex_string()
1424 )
1425 }
1426}
1427
1428impl NotIsSetFact {
1429 pub fn to_latex_string(&self) -> String {
1430 format!(
1431 r"\neg \left( \$ \mathrm{{{}}}\left( {}\right) \right)",
1432 IS_SET,
1433 self.set.to_latex_string()
1434 )
1435 }
1436}
1437
1438impl NotIsTupleFact {
1439 pub fn to_latex_string(&self) -> String {
1440 format!(
1441 r"\neg \left( \$ \mathrm{{{}}}\left( {}\right) \right)",
1442 IS_TUPLE,
1443 self.set.to_latex_string()
1444 )
1445 }
1446}
1447
1448impl NotLessEqualFact {
1449 pub fn to_latex_string(&self) -> String {
1450 format!(
1451 r"{} \nleq {}",
1452 self.left.to_latex_string(),
1453 self.right.to_latex_string()
1454 )
1455 }
1456}
1457
1458impl NotLessFact {
1459 pub fn to_latex_string(&self) -> String {
1460 format!(
1461 r"{} \nless {}",
1462 self.left.to_latex_string(),
1463 self.right.to_latex_string()
1464 )
1465 }
1466}
1467
1468impl NotNormalAtomicFact {
1469 pub fn to_latex_string(&self) -> String {
1470 let pred = self.predicate.to_latex_string();
1471 let args = self
1472 .body
1473 .iter()
1474 .map(|o| o.to_latex_string())
1475 .collect::<Vec<_>>()
1476 .join(", ");
1477 format!(r"\neg \left( \$ {}\left( {}\right) \right)", pred, args)
1478 }
1479}
1480
1481impl NotRestrictFact {
1482 pub fn to_latex_string(&self) -> String {
1483 format!(
1484 r"\neg \left( {} \mathrel{{\$}} \mathrm{{{}}}\, {} \right)",
1485 self.obj.to_latex_string(),
1486 RESTRICT_FN_IN,
1487 self.obj_cannot_restrict_to_fn_set.to_latex_string()
1488 )
1489 }
1490}
1491
1492impl NotSubsetFact {
1493 pub fn to_latex_string(&self) -> String {
1494 format!(
1495 r"\neg \left( {} \subseteq {} \right)",
1496 self.left.to_latex_string(),
1497 self.right.to_latex_string()
1498 )
1499 }
1500}
1501
1502impl NotSupersetFact {
1503 pub fn to_latex_string(&self) -> String {
1504 format!(
1505 r"\neg \left( {} \supseteq {} \right)",
1506 self.left.to_latex_string(),
1507 self.right.to_latex_string()
1508 )
1509 }
1510}
1511
1512impl Number {
1513 pub fn to_latex_string(&self) -> String {
1514 self.normalized_value.clone()
1515 }
1516}
1517
1518impl ObjAtIndex {
1519 pub fn to_latex_string(&self) -> String {
1520 format!(
1521 r"{}\left[ {} \right]",
1522 self.obj.to_latex_string(),
1523 self.index.to_latex_string()
1524 )
1525 }
1526}
1527
1528impl OrFact {
1529 pub fn to_latex_string(&self) -> String {
1530 self.facts
1531 .iter()
1532 .map(|f| f.to_latex_string())
1533 .collect::<Vec<_>>()
1534 .join(r" \lor ")
1535 }
1536}
1537
1538impl ParamDefWithType {
1539 pub fn to_latex_string(&self) -> String {
1540 self.groups
1541 .iter()
1542 .map(|g| g.to_latex_string())
1543 .collect::<Vec<_>>()
1544 .join(", ")
1545 }
1546}
1547
1548impl ParamGroupWithParamType {
1549 pub fn to_latex_string(&self) -> String {
1550 let names = self
1551 .params
1552 .iter()
1553 .map(|p| latex_local_ident(p))
1554 .collect::<Vec<_>>()
1555 .join(", ");
1556 format!(r"{}, {}", names, self.param_type.to_latex_string())
1557 }
1558}
1559
1560impl ParamType {
1561 pub fn to_latex_string(&self) -> String {
1562 match self {
1563 ParamType::Set(_) => format!(r"\mathrm{{{}}}", SET),
1564 ParamType::NonemptySet(_) => format!(r"\mathrm{{{}}}", NONEMPTY_SET),
1565 ParamType::FiniteSet(_) => format!(r"\mathrm{{{}}}", FINITE_SET),
1566 ParamType::Obj(o) => o.to_latex_string(),
1567 }
1568 }
1569}
1570
1571impl Pow {
1572 pub fn to_latex_string(&self) -> String {
1573 format!(
1574 "{{{}}}^{{{}}}",
1575 self.base.to_latex_string(),
1576 self.exponent.to_latex_string()
1577 )
1578 }
1579}
1580
1581impl PowerSet {
1582 pub fn to_latex_string(&self) -> String {
1583 format!(r"\mathcal{{P}}\left( {}\right)", self.set.to_latex_string())
1584 }
1585}
1586
1587impl Proj {
1588 pub fn to_latex_string(&self) -> String {
1589 format!(
1590 r"\operatorname{{{}}}\left( {}, {} \right)",
1591 PROJ,
1592 self.set.to_latex_string(),
1593 self.dim.to_latex_string()
1594 )
1595 }
1596}
1597
1598impl ProveStmt {
1599 pub fn to_latex_string(&self) -> String {
1600 if self.proof.is_empty() {
1601 return r"\text{\texttt{(empty proof)}}".to_string();
1602 }
1603 let rows: Vec<String> = self
1604 .proof
1605 .iter()
1606 .map(|st| format!(r"& \quad {}", st.to_latex_string()))
1607 .collect();
1608 format!(
1609 "\\begin{{aligned}}\n{}\n\\end{{aligned}}",
1610 rows.join(" \\\\\n")
1611 )
1612 }
1613}
1614
1615impl Range {
1616 pub fn to_latex_string(&self) -> String {
1617 format!(
1618 r"\operatorname{{{}}}\left( {}, {} \right)",
1619 RANGE,
1620 self.start.to_latex_string(),
1621 self.end.to_latex_string()
1622 )
1623 }
1624}
1625
1626impl RestrictFact {
1627 pub fn to_latex_string(&self) -> String {
1628 format!(
1629 r"{} \mathrel{{\$}} \mathrm{{{}}}\, {}",
1630 self.obj.to_latex_string(),
1631 RESTRICT_FN_IN,
1632 self.obj_can_restrict_to_fn_set.to_latex_string()
1633 )
1634 }
1635}
1636
1637impl RunFileStmt {
1638 pub fn to_latex_string(&self) -> String {
1639 format!(
1640 r"\operatorname{{{}}}\ \texttt{{{}}}",
1641 RUN_FILE,
1642 latex_texttt_escape(&self.file_path)
1643 )
1644 }
1645}
1646
1647impl RunFileInStd {
1648 pub fn to_latex_string(&self) -> String {
1649 format!(
1650 r"\operatorname{{{}}}\ \texttt{{{}}}",
1651 RUN_FILE,
1652 latex_texttt_escape(&self.file_path)
1653 )
1654 }
1655}
1656
1657impl SeqSet {
1658 pub fn to_latex_string(&self) -> String {
1659 format!(
1660 r"\operatorname{{{}}}\left( {}\right)",
1661 SEQ,
1662 self.set.to_latex_string()
1663 )
1664 }
1665}
1666
1667impl SetBuilder {
1668 pub fn to_latex_string(&self) -> String {
1669 let cond = self
1670 .facts
1671 .iter()
1672 .map(|f| f.to_latex_string())
1673 .collect::<Vec<_>>()
1674 .join(r" \land ");
1675 format!(
1676 r"\left\{{ {} \in {} \,\middle|\, {} \right\}}",
1677 latex_local_ident(&self.param),
1678 self.param_set.to_latex_string(),
1679 cond
1680 )
1681 }
1682}
1683
1684impl SetDiff {
1685 pub fn to_latex_string(&self) -> String {
1686 format!(
1687 r"\operatorname{{{}}}\left( {}, {} \right)",
1688 SET_DIFF,
1689 self.left.to_latex_string(),
1690 self.right.to_latex_string()
1691 )
1692 }
1693}
1694
1695impl SetMinus {
1696 pub fn to_latex_string(&self) -> String {
1697 format!(
1698 r"{} \setminus {}",
1699 self.left.to_latex_string(),
1700 self.right.to_latex_string()
1701 )
1702 }
1703}
1704
1705impl Sub {
1706 pub fn to_latex_string(&self) -> String {
1707 format!(
1708 "{} - {}",
1709 self.left.to_latex_string(),
1710 self.right.to_latex_string()
1711 )
1712 }
1713}
1714
1715impl SubsetFact {
1716 pub fn to_latex_string(&self) -> String {
1717 format!(
1718 r"{} \subseteq {}",
1719 self.left.to_latex_string(),
1720 self.right.to_latex_string()
1721 )
1722 }
1723}
1724
1725impl SupersetFact {
1726 pub fn to_latex_string(&self) -> String {
1727 format!(
1728 r"{} \supseteq {}",
1729 self.left.to_latex_string(),
1730 self.right.to_latex_string()
1731 )
1732 }
1733}
1734
1735impl Tuple {
1736 pub fn to_latex_string(&self) -> String {
1737 let inner = self
1738 .args
1739 .iter()
1740 .map(|o| o.to_latex_string())
1741 .collect::<Vec<_>>()
1742 .join(", ");
1743 format!(r"\left( {} \right)", inner)
1744 }
1745}
1746
1747impl TupleDim {
1748 pub fn to_latex_string(&self) -> String {
1749 format!(
1750 r"\operatorname{{{}}}\left( {}\right)",
1751 TUPLE_DIM,
1752 self.arg.to_latex_string()
1753 )
1754 }
1755}
1756
1757impl Union {
1758 pub fn to_latex_string(&self) -> String {
1759 format!(
1760 r"{} \cup {}",
1761 self.left.to_latex_string(),
1762 self.right.to_latex_string()
1763 )
1764 }
1765}
1766
1767impl WitnessExistFact {
1768 pub fn to_latex_string(&self) -> String {
1769 let names = self
1770 .equal_tos
1771 .iter()
1772 .map(|o| o.to_latex_string())
1773 .collect::<Vec<_>>()
1774 .join(", ");
1775 let facts = self
1776 .exist_fact_in_witness
1777 .facts()
1778 .iter()
1779 .map(|f| f.to_latex_string())
1780 .collect::<Vec<_>>()
1781 .join(", ");
1782 let head = format!(
1783 r"\mathrm{{witness}}\ {} : {} \mathrm{{st}} \left\{{ {}\right\}}",
1784 names,
1785 self.exist_fact_in_witness
1786 .params_def_with_type()
1787 .to_latex_string(),
1788 facts
1789 );
1790 if self.proof.is_empty() {
1791 head
1792 } else {
1793 let mut rows = vec![format!(r"{} &", head)];
1794 for st in &self.proof {
1795 rows.push(format!(r"& \quad {}", st.to_latex_string()));
1796 }
1797 format!(
1798 "\\begin{{aligned}}\n{}\n\\end{{aligned}}",
1799 rows.join(" \\\\\n")
1800 )
1801 }
1802 }
1803}
1804
1805impl WitnessNonemptySet {
1806 pub fn to_latex_string(&self) -> String {
1807 let head = format!(
1808 r"\mathrm{{witness}}\ {} {}",
1809 self.obj.to_latex_string(),
1810 self.set.to_latex_string()
1811 );
1812 if self.proof.is_empty() {
1813 head
1814 } else {
1815 let mut rows = vec![format!(r"{} &", head)];
1816 for st in &self.proof {
1817 rows.push(format!(r"& \quad {}", st.to_latex_string()));
1818 }
1819 format!(
1820 "\\begin{{aligned}}\n{}\n\\end{{aligned}}",
1821 rows.join(" \\\\\n")
1822 )
1823 }
1824 }
1825}
1826
1827impl ImportGlobalModuleStmt {
1828 pub fn to_latex_string(&self) -> String {
1829 match &self.as_mod_name {
1830 Some(m) => format!(
1831 r"\operatorname{{{}}}\ {}\ \mathrm{{as}}\ {}",
1832 IMPORT,
1833 latex_local_ident(&self.mod_name),
1834 latex_local_ident(m)
1835 ),
1836 None => format!(
1837 r"\operatorname{{{}}}\ {}",
1838 IMPORT,
1839 latex_local_ident(&self.mod_name)
1840 ),
1841 }
1842 }
1843}
1844
1845impl ImportRelativePathStmt {
1846 pub fn to_latex_string(&self) -> String {
1847 let path = latex_texttt_escape(&self.path);
1848 match &self.as_mod_name {
1849 Some(m) => format!(
1850 r"\operatorname{{{}}}\ \texttt{{{}}}\ \mathrm{{as}}\ {}",
1851 IMPORT,
1852 path,
1853 latex_local_ident(m)
1854 ),
1855 None => format!(r"\operatorname{{{}}}\ \texttt{{{}}}", IMPORT, path),
1856 }
1857 }
1858}
1859
1860impl ImportStmt {
1861 pub fn to_latex_string(&self) -> String {
1862 match self {
1863 ImportStmt::ImportRelativePath(s) => s.to_latex_string(),
1864 ImportStmt::ImportGlobalModule(s) => s.to_latex_string(),
1865 }
1866 }
1867}
1868
1869impl StandardSet {
1870 pub fn to_latex_string(&self) -> String {
1871 match self {
1872 StandardSet::N => r"\mathbb{N}".to_string(),
1873 StandardSet::NPos => r"\mathbb{N}_{>0}".to_string(),
1874 StandardSet::Z => r"\mathbb{Z}".to_string(),
1875 StandardSet::ZNeg => r"\mathbb{Z}_{<0}".to_string(),
1876 StandardSet::ZNz => r"\mathbb{Z}\setminus\{0\}".to_string(),
1877 StandardSet::Q => r"\mathbb{Q}".to_string(),
1878 StandardSet::QPos => r"\mathbb{Q}_{>0}".to_string(),
1879 StandardSet::QNeg => r"\mathbb{Q}_{<0}".to_string(),
1880 StandardSet::QNz => r"\mathbb{Q}\setminus\{0\}".to_string(),
1881 StandardSet::R => r"\mathbb{R}".to_string(),
1882 StandardSet::RPos => r"\mathbb{R}_{>0}".to_string(),
1883 StandardSet::RNeg => r"\mathbb{R}_{<0}".to_string(),
1884 StandardSet::RNz => r"\mathbb{R}\setminus\{0\}".to_string(),
1885 }
1886 }
1887}
1888
1889impl Fact {
1890 pub fn to_latex_string(&self) -> String {
1891 match self {
1892 Fact::AtomicFact(x) => x.to_latex_string(),
1893 Fact::ExistFact(x) => x.to_latex_string(),
1894 Fact::OrFact(x) => x.to_latex_string(),
1895 Fact::AndFact(x) => x.to_latex_string(),
1896 Fact::ChainFact(x) => x.to_latex_string(),
1897 Fact::ForallFact(x) => x.to_latex_string(),
1898 Fact::ForallFactWithIff(x) => x.to_latex_string(),
1899 Fact::NotForall(x) => x.to_latex_string(),
1900 }
1901 }
1902}
1903
1904impl AtomicFact {
1905 pub fn to_latex_string(&self) -> String {
1906 match self {
1907 AtomicFact::NormalAtomicFact(x) => x.to_latex_string(),
1908 AtomicFact::EqualFact(x) => x.to_latex_string(),
1909 AtomicFact::LessFact(x) => x.to_latex_string(),
1910 AtomicFact::GreaterFact(x) => x.to_latex_string(),
1911 AtomicFact::LessEqualFact(x) => x.to_latex_string(),
1912 AtomicFact::GreaterEqualFact(x) => x.to_latex_string(),
1913 AtomicFact::IsSetFact(x) => x.to_latex_string(),
1914 AtomicFact::IsNonemptySetFact(x) => x.to_latex_string(),
1915 AtomicFact::IsFiniteSetFact(x) => x.to_latex_string(),
1916 AtomicFact::InFact(x) => x.to_latex_string(),
1917 AtomicFact::IsCartFact(x) => x.to_latex_string(),
1918 AtomicFact::IsTupleFact(x) => x.to_latex_string(),
1919 AtomicFact::SubsetFact(x) => x.to_latex_string(),
1920 AtomicFact::SupersetFact(x) => x.to_latex_string(),
1921 AtomicFact::RestrictFact(x) => x.to_latex_string(),
1922 AtomicFact::NotRestrictFact(x) => x.to_latex_string(),
1923 AtomicFact::NotNormalAtomicFact(x) => x.to_latex_string(),
1924 AtomicFact::NotEqualFact(x) => x.to_latex_string(),
1925 AtomicFact::NotLessFact(x) => x.to_latex_string(),
1926 AtomicFact::NotGreaterFact(x) => x.to_latex_string(),
1927 AtomicFact::NotLessEqualFact(x) => x.to_latex_string(),
1928 AtomicFact::NotGreaterEqualFact(x) => x.to_latex_string(),
1929 AtomicFact::NotIsSetFact(x) => x.to_latex_string(),
1930 AtomicFact::NotIsNonemptySetFact(x) => x.to_latex_string(),
1931 AtomicFact::NotIsFiniteSetFact(x) => x.to_latex_string(),
1932 AtomicFact::NotInFact(x) => x.to_latex_string(),
1933 AtomicFact::NotIsCartFact(x) => x.to_latex_string(),
1934 AtomicFact::NotIsTupleFact(x) => x.to_latex_string(),
1935 AtomicFact::NotSubsetFact(x) => x.to_latex_string(),
1936 AtomicFact::NotSupersetFact(x) => x.to_latex_string(),
1937 AtomicFact::FnEqualInFact(f) => format!(
1938 r"\mathsf{{fn\_eq\_in}}({},{},{})",
1939 f.left.to_latex_string(),
1940 f.right.to_latex_string(),
1941 f.set.to_latex_string(),
1942 ),
1943 AtomicFact::FnEqualFact(f) => format!(
1944 r"\mathsf{{fn\_eq}}({},{})",
1945 f.left.to_latex_string(),
1946 f.right.to_latex_string(),
1947 ),
1948 }
1949 }
1950}
1951
1952impl Obj {
1953 pub fn to_latex_string(&self) -> String {
1954 match self {
1955 Obj::Atom(AtomObj::Identifier(x)) => x.to_latex_string(),
1956 Obj::Atom(AtomObj::IdentifierWithMod(x)) => x.to_latex_string(),
1957 Obj::FnObj(x) => x.to_latex_string(),
1958 Obj::Number(x) => x.to_latex_string(),
1959 Obj::Add(x) => x.to_latex_string(),
1960 Obj::Sub(x) => x.to_latex_string(),
1961 Obj::Mul(x) => x.to_latex_string(),
1962 Obj::Div(x) => x.to_latex_string(),
1963 Obj::Mod(x) => x.to_latex_string(),
1964 Obj::Pow(x) => x.to_latex_string(),
1965 Obj::Abs(x) => x.to_latex_string(),
1966 Obj::Sqrt(x) => x.to_latex_string(),
1967 Obj::Log(x) => x.to_latex_string(),
1968 Obj::Max(x) => x.to_latex_string(),
1969 Obj::Min(x) => x.to_latex_string(),
1970 Obj::Union(x) => x.to_latex_string(),
1971 Obj::Intersect(x) => x.to_latex_string(),
1972 Obj::SetMinus(x) => x.to_latex_string(),
1973 Obj::SetDiff(x) => x.to_latex_string(),
1974 Obj::Cup(x) => x.to_latex_string(),
1975 Obj::Cap(x) => x.to_latex_string(),
1976 Obj::PowerSet(x) => x.to_latex_string(),
1977 Obj::ListSet(x) => x.to_latex_string(),
1978 Obj::SetBuilder(x) => x.to_latex_string(),
1979 Obj::FnSet(x) => x.to_latex_string(),
1980 Obj::AnonymousFn(x) => x.to_latex_string(),
1981 Obj::Cart(x) => x.to_latex_string(),
1982 Obj::CartDim(x) => x.to_latex_string(),
1983 Obj::Proj(x) => x.to_latex_string(),
1984 Obj::TupleDim(x) => x.to_latex_string(),
1985 Obj::Tuple(x) => x.to_latex_string(),
1986 Obj::Count(x) => x.to_latex_string(),
1987 Obj::Sum(x) => x.to_latex_string(),
1988 Obj::Product(x) => x.to_latex_string(),
1989 Obj::Range(x) => x.to_latex_string(),
1990 Obj::ClosedRange(x) => x.to_latex_string(),
1991 Obj::FiniteSeqSet(x) => x.to_latex_string(),
1992 Obj::SeqSet(x) => x.to_latex_string(),
1993 Obj::FiniteSeqListObj(x) => x.to_latex_string(),
1994 Obj::Choose(x) => x.to_latex_string(),
1995 Obj::ObjAtIndex(x) => x.to_latex_string(),
1996 Obj::StandardSet(x) => x.to_latex_string(),
1997 Obj::StructObj(x) => latex_texttt_escape(&x.to_string()),
1998 Obj::ObjAsStructInstanceWithFieldAccess(x) => latex_texttt_escape(&x.to_string()),
1999 Obj::InstantiatedTemplateObj(x) => latex_texttt_escape(&x.to_string()),
2000 Obj::Atom(AtomObj::Forall(x)) => latex_local_ident(&x.name),
2001 Obj::Atom(AtomObj::Def(x)) => latex_local_ident(&x.name),
2002 Obj::Atom(AtomObj::Exist(x)) => latex_local_ident(&x.name),
2003 Obj::Atom(AtomObj::SetBuilder(x)) => latex_local_ident(&x.name),
2004 Obj::Atom(AtomObj::FnSet(x)) => latex_local_ident(&x.name),
2005 Obj::Atom(AtomObj::Induc(x)) => latex_local_ident(&x.name),
2006 Obj::Atom(AtomObj::DefAlgo(x)) => latex_local_ident(&x.name),
2007 Obj::Atom(AtomObj::DefStructField(x)) => latex_local_ident(&x.name),
2008 Obj::MatrixSet(x) => x.to_latex_string(),
2009 Obj::MatrixListObj(x) => x.to_latex_string(),
2010 Obj::MatrixAdd(x) => x.to_latex_string(),
2011 Obj::MatrixSub(x) => x.to_latex_string(),
2012 Obj::MatrixMul(x) => x.to_latex_string(),
2013 Obj::MatrixScalarMul(x) => x.to_latex_string(),
2014 Obj::MatrixPow(x) => x.to_latex_string(),
2015 }
2016 }
2017}
2018
2019impl Stmt {
2020 pub fn to_latex_string(&self) -> String {
2021 match self {
2022 Stmt::Fact(x) => x.to_latex_string(),
2023 Stmt::DefLetStmt(x) => x.to_latex_string(),
2024 Stmt::DefPropStmt(x) => x.to_latex_string(),
2025 Stmt::DefAbstractPropStmt(x) => x.to_latex_string(),
2026 Stmt::HaveObjInNonemptySetStmt(x) => x.to_latex_string(),
2027 Stmt::HaveObjEqualStmt(x) => x.to_latex_string(),
2028 Stmt::HaveByExistStmt(x) => x.to_latex_string(),
2029 Stmt::HaveFnEqualStmt(x) => x.to_latex_string(),
2030 Stmt::HaveFnEqualCaseByCaseStmt(x) => x.to_latex_string(),
2031 Stmt::HaveFnByInducStmt(x) => x.to_latex_string(),
2032 Stmt::HaveFnByForallExistUniqueStmt(x) => x.to_latex_string(),
2033 Stmt::DefAlgoStmt(x) => x.to_latex_string(),
2034 Stmt::ClaimStmt(x) => x.to_latex_string(),
2035 Stmt::KnowStmt(x) => x.to_latex_string(),
2036 Stmt::ProveStmt(x) => x.to_latex_string(),
2037 Stmt::ImportStmt(x) => x.to_latex_string(),
2038 Stmt::DoNothingStmt(x) => x.to_latex_string(),
2039 Stmt::ClearStmt(x) => x.to_latex_string(),
2040 Stmt::RunFileStmt(x) => x.to_latex_string(),
2041 Stmt::RunFileInStd(x) => x.to_latex_string(),
2042 Stmt::EvalStmt(x) => x.to_latex_string(),
2043 Stmt::EvalByStmt(x) => x.to_latex_string(),
2044 Stmt::WitnessExistFact(x) => x.to_latex_string(),
2045 Stmt::WitnessNonemptySet(x) => x.to_latex_string(),
2046 Stmt::ByCasesStmt(x) => x.to_latex_string(),
2047 Stmt::ByContraStmt(x) => x.to_latex_string(),
2048 Stmt::ByEnumerateFiniteSetStmt(x) => x.to_latex_string(),
2049 Stmt::ByInducStmt(x) => x.to_latex_string(),
2050 Stmt::ByForStmt(x) => x.to_latex_string(),
2051 Stmt::ByExtensionStmt(x) => x.to_latex_string(),
2052 Stmt::ByFnAsSetStmt(x) => x.to_latex_string(),
2053 Stmt::ByTupleAsSetStmt(x) => x.to_latex_string(),
2054 Stmt::ByFnSetAsSetStmt(x) => x.to_latex_string(),
2055 Stmt::ByClosedRangeAsCasesStmt(x) => x.to_latex_string(),
2056 Stmt::ByTransitivePropStmt(x) => x.to_latex_string(),
2057 Stmt::BySymmetricPropStmt(x) => x.to_latex_string(),
2058 Stmt::ByReflexivePropStmt(x) => x.to_latex_string(),
2059 Stmt::ByAntisymmetricPropStmt(x) => x.to_latex_string(),
2060 Stmt::DefStructStmt(x) => latex_texttt_escape(&x.to_string()),
2061 Stmt::DefTemplateStmt(x) => latex_texttt_escape(&x.to_string()),
2062 }
2063 }
2064}