Skip to main content

litex/to_latex/
to_latex_string.rs

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