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