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