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