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