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