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