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        let fn_set_clause = FnSetClause::new(
969            self.equal_to_anonymous_fn.body.params_def_with_set.clone(),
970            self.equal_to_anonymous_fn.body.dom_facts.clone(),
971            (*self.equal_to_anonymous_fn.body.ret_set).clone(),
972        );
973        format!(
974            r"\mathrm{{have}}\ \mathrm{{fn}}\ {}\ {} {}",
975            latex_local_ident(&self.name),
976            fn_set_clause_latex(&fn_set_clause),
977            self.equal_to_anonymous_fn.equal_to.to_latex_string()
978        )
979    }
980}
981
982impl HaveFnByForallExistUniqueStmt {
983    pub fn to_latex_string(&self) -> String {
984        format!(
985            r"\mathrm{{have}}\ \mathrm{{fn}}\ {}\ \mathrm{{by}}\ {}",
986            latex_local_ident(&self.fn_name),
987            self.forall.to_latex_string()
988        )
989    }
990}
991
992impl HaveObjEqualStmt {
993    pub fn to_latex_string(&self) -> String {
994        let rhs = self
995            .objs_equal_to
996            .iter()
997            .map(|o| o.to_latex_string())
998            .collect::<Vec<_>>()
999            .join(", ");
1000        format!(
1001            r"\mathrm{{have}}\ {} = {}",
1002            self.param_def.to_latex_string(),
1003            rhs
1004        )
1005    }
1006}
1007
1008impl HaveObjInNonemptySetOrParamTypeStmt {
1009    pub fn to_latex_string(&self) -> String {
1010        format!(r"\mathrm{{have}}\ {}", self.param_def.to_latex_string())
1011    }
1012}
1013
1014impl Identifier {
1015    pub fn to_latex_string(&self) -> String {
1016        latex_local_ident(&self.name)
1017    }
1018}
1019
1020impl IdentifierWithMod {
1021    pub fn to_latex_string(&self) -> String {
1022        format!(
1023            r"{}\mathbin{{\mathrm{{::}}}}{}",
1024            latex_local_ident(&self.mod_name),
1025            latex_local_ident(&self.name)
1026        )
1027    }
1028}
1029
1030impl AtomicName {
1031    pub fn to_latex_string(&self) -> String {
1032        match self {
1033            AtomicName::WithoutMod(s) => latex_local_ident(s),
1034            AtomicName::WithMod(m, n) => format!(
1035                r"{}\mathbin{{\mathrm{{::}}}}{}",
1036                latex_local_ident(m),
1037                latex_local_ident(n)
1038            ),
1039        }
1040    }
1041}
1042
1043impl InFact {
1044    pub fn to_latex_string(&self) -> String {
1045        format!(
1046            r"{} \in {}",
1047            self.element.to_latex_string(),
1048            self.set.to_latex_string()
1049        )
1050    }
1051}
1052
1053impl Intersect {
1054    pub fn to_latex_string(&self) -> String {
1055        format!(
1056            r"{} \cap {}",
1057            self.left.to_latex_string(),
1058            self.right.to_latex_string()
1059        )
1060    }
1061}
1062
1063impl IsCartFact {
1064    pub fn to_latex_string(&self) -> String {
1065        format!(
1066            r"\$ \mathrm{{{}}}\left( {}\right)",
1067            IS_CART,
1068            self.set.to_latex_string()
1069        )
1070    }
1071}
1072
1073impl IsFiniteSetFact {
1074    pub fn to_latex_string(&self) -> String {
1075        format!(
1076            r"\$ \mathrm{{{}}}\left( {}\right)",
1077            IS_FINITE_SET,
1078            self.set.to_latex_string()
1079        )
1080    }
1081}
1082
1083impl IsNonemptySetFact {
1084    pub fn to_latex_string(&self) -> String {
1085        format!(
1086            r"\$ \mathrm{{{}}}\left( {}\right)",
1087            IS_NONEMPTY_SET,
1088            self.set.to_latex_string()
1089        )
1090    }
1091}
1092
1093impl IsSetFact {
1094    pub fn to_latex_string(&self) -> String {
1095        format!(
1096            r"\$ \mathrm{{{}}}\left( {}\right)",
1097            IS_SET,
1098            self.set.to_latex_string()
1099        )
1100    }
1101}
1102
1103impl IsTupleFact {
1104    pub fn to_latex_string(&self) -> String {
1105        format!(
1106            r"\$ \mathrm{{{}}}\left( {}\right)",
1107            IS_TUPLE,
1108            self.set.to_latex_string()
1109        )
1110    }
1111}
1112
1113impl KnowStmt {
1114    pub fn to_latex_string(&self) -> String {
1115        if self.facts.len() == 1 {
1116            format!(
1117                r"\operatorname{{{}}} {}",
1118                KNOW,
1119                self.facts[0].to_latex_string()
1120            )
1121        } else {
1122            let rows = self
1123                .facts
1124                .iter()
1125                .map(|fact| format!("& {}", fact.to_latex_string()))
1126                .collect::<Vec<_>>()
1127                .join(" \\\\\n");
1128            format!(
1129                r"\operatorname{{{}}}\colon \begin{{aligned}}{}\end{{aligned}}",
1130                KNOW, rows
1131            )
1132        }
1133    }
1134}
1135
1136impl LessEqualFact {
1137    pub fn to_latex_string(&self) -> String {
1138        format!(
1139            r"{} \leq {}",
1140            self.left.to_latex_string(),
1141            self.right.to_latex_string()
1142        )
1143    }
1144}
1145
1146impl LessFact {
1147    pub fn to_latex_string(&self) -> String {
1148        format!(
1149            "{} < {}",
1150            self.left.to_latex_string(),
1151            self.right.to_latex_string()
1152        )
1153    }
1154}
1155
1156impl ListSet {
1157    pub fn to_latex_string(&self) -> String {
1158        let inner = self
1159            .list
1160            .iter()
1161            .map(|o| o.to_latex_string())
1162            .collect::<Vec<_>>()
1163            .join(", ");
1164        format!(r"\left\{{ {} \right\}}", inner)
1165    }
1166}
1167
1168impl Log {
1169    pub fn to_latex_string(&self) -> String {
1170        format!(
1171            r"\log_{{{}}} \left( {} \right)",
1172            self.base.to_latex_string(),
1173            self.arg.to_latex_string()
1174        )
1175    }
1176}
1177
1178impl MatrixAdd {
1179    pub fn to_latex_string(&self) -> String {
1180        format!(
1181            r"{} \mathbin{{\mathrm{{{}}}}} {}",
1182            self.left.to_latex_string(),
1183            latex_escape_underscore(MATRIX_ADD),
1184            self.right.to_latex_string()
1185        )
1186    }
1187}
1188
1189impl MatrixListObj {
1190    pub fn to_latex_string(&self) -> String {
1191        let rows = self
1192            .rows
1193            .iter()
1194            .map(|row| {
1195                let inner = row
1196                    .iter()
1197                    .map(|o| o.to_latex_string())
1198                    .collect::<Vec<_>>()
1199                    .join(", ");
1200                format!(r"\left( {} \right)", inner)
1201            })
1202            .collect::<Vec<_>>()
1203            .join(", ");
1204        format!(r"\left[ {} \right]", rows)
1205    }
1206}
1207
1208impl MatrixMul {
1209    pub fn to_latex_string(&self) -> String {
1210        format!(
1211            r"{} \mathbin{{\mathrm{{{}}}}} {}",
1212            self.left.to_latex_string(),
1213            latex_escape_underscore(MATRIX_MUL),
1214            self.right.to_latex_string()
1215        )
1216    }
1217}
1218
1219impl MatrixPow {
1220    pub fn to_latex_string(&self) -> String {
1221        format!(
1222            r"{} \mathbin{{\mathrm{{{}}}}} {}",
1223            self.base.to_latex_string(),
1224            latex_escape_underscore(MATRIX_POW),
1225            self.exponent.to_latex_string()
1226        )
1227    }
1228}
1229
1230impl MatrixScalarMul {
1231    pub fn to_latex_string(&self) -> String {
1232        format!(
1233            r"{} \mathbin{{\mathrm{{{}}}}} {}",
1234            self.scalar.to_latex_string(),
1235            latex_escape_underscore(MATRIX_SCALAR_MUL),
1236            self.matrix.to_latex_string()
1237        )
1238    }
1239}
1240
1241impl MatrixSet {
1242    pub fn to_latex_string(&self) -> String {
1243        format!(
1244            r"\operatorname{{{}}}\left( {}, {}, {} \right)",
1245            MATRIX,
1246            self.set.to_latex_string(),
1247            self.row_len.to_latex_string(),
1248            self.col_len.to_latex_string()
1249        )
1250    }
1251}
1252
1253impl MatrixSub {
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_SUB),
1259            self.right.to_latex_string()
1260        )
1261    }
1262}
1263
1264impl Max {
1265    pub fn to_latex_string(&self) -> String {
1266        format!(
1267            r"\max \left( {}, {} \right)",
1268            self.left.to_latex_string(),
1269            self.right.to_latex_string()
1270        )
1271    }
1272}
1273
1274impl Min {
1275    pub fn to_latex_string(&self) -> String {
1276        format!(
1277            r"\min \left( {}, {} \right)",
1278            self.left.to_latex_string(),
1279            self.right.to_latex_string()
1280        )
1281    }
1282}
1283
1284impl Mod {
1285    pub fn to_latex_string(&self) -> String {
1286        format!(
1287            r"\left( {} \mathbin{{\mathrm{{mod}}}} {} \right)",
1288            self.left.to_latex_string(),
1289            self.right.to_latex_string()
1290        )
1291    }
1292}
1293
1294impl Mul {
1295    pub fn to_latex_string(&self) -> String {
1296        format!(
1297            r"{0} \cdot {1}",
1298            self.left.to_latex_string(),
1299            self.right.to_latex_string()
1300        )
1301    }
1302}
1303
1304impl NormalAtomicFact {
1305    pub fn to_latex_string(&self) -> String {
1306        let pred = self.predicate.to_latex_string();
1307        let args = self
1308            .body
1309            .iter()
1310            .map(|o| o.to_latex_string())
1311            .collect::<Vec<_>>()
1312            .join(", ");
1313        format!(r"\$ {}\left( {}\right)", pred, args)
1314    }
1315}
1316
1317impl NotEqualFact {
1318    pub fn to_latex_string(&self) -> String {
1319        format!(
1320            r"{} \neq {}",
1321            self.left.to_latex_string(),
1322            self.right.to_latex_string()
1323        )
1324    }
1325}
1326
1327impl NotGreaterEqualFact {
1328    pub fn to_latex_string(&self) -> String {
1329        format!(
1330            r"{} \ngeq {}",
1331            self.left.to_latex_string(),
1332            self.right.to_latex_string()
1333        )
1334    }
1335}
1336
1337impl NotGreaterFact {
1338    pub fn to_latex_string(&self) -> String {
1339        format!(
1340            r"{} \ngtr {}",
1341            self.left.to_latex_string(),
1342            self.right.to_latex_string()
1343        )
1344    }
1345}
1346
1347impl NotInFact {
1348    pub fn to_latex_string(&self) -> String {
1349        format!(
1350            r"{} \notin {}",
1351            self.element.to_latex_string(),
1352            self.set.to_latex_string()
1353        )
1354    }
1355}
1356
1357impl NotIsCartFact {
1358    pub fn to_latex_string(&self) -> String {
1359        format!(
1360            r"\neg \left( \$ \mathrm{{{}}}\left( {}\right) \right)",
1361            IS_CART,
1362            self.set.to_latex_string()
1363        )
1364    }
1365}
1366
1367impl NotIsFiniteSetFact {
1368    pub fn to_latex_string(&self) -> String {
1369        format!(
1370            r"\neg \left( \$ \mathrm{{{}}}\left( {}\right) \right)",
1371            IS_FINITE_SET,
1372            self.set.to_latex_string()
1373        )
1374    }
1375}
1376
1377impl NotIsNonemptySetFact {
1378    pub fn to_latex_string(&self) -> String {
1379        format!(
1380            r"\neg \left( \$ \mathrm{{{}}}\left( {}\right) \right)",
1381            IS_NONEMPTY_SET,
1382            self.set.to_latex_string()
1383        )
1384    }
1385}
1386
1387impl NotIsSetFact {
1388    pub fn to_latex_string(&self) -> String {
1389        format!(
1390            r"\neg \left( \$ \mathrm{{{}}}\left( {}\right) \right)",
1391            IS_SET,
1392            self.set.to_latex_string()
1393        )
1394    }
1395}
1396
1397impl NotIsTupleFact {
1398    pub fn to_latex_string(&self) -> String {
1399        format!(
1400            r"\neg \left( \$ \mathrm{{{}}}\left( {}\right) \right)",
1401            IS_TUPLE,
1402            self.set.to_latex_string()
1403        )
1404    }
1405}
1406
1407impl NotLessEqualFact {
1408    pub fn to_latex_string(&self) -> String {
1409        format!(
1410            r"{} \nleq {}",
1411            self.left.to_latex_string(),
1412            self.right.to_latex_string()
1413        )
1414    }
1415}
1416
1417impl NotLessFact {
1418    pub fn to_latex_string(&self) -> String {
1419        format!(
1420            r"{} \nless {}",
1421            self.left.to_latex_string(),
1422            self.right.to_latex_string()
1423        )
1424    }
1425}
1426
1427impl NotNormalAtomicFact {
1428    pub fn to_latex_string(&self) -> String {
1429        let pred = self.predicate.to_latex_string();
1430        let args = self
1431            .body
1432            .iter()
1433            .map(|o| o.to_latex_string())
1434            .collect::<Vec<_>>()
1435            .join(", ");
1436        format!(r"\neg \left( \$ {}\left( {}\right) \right)", pred, args)
1437    }
1438}
1439
1440impl NotRestrictFact {
1441    pub fn to_latex_string(&self) -> String {
1442        format!(
1443            r"\neg \left( {} \mathrel{{\$}} \mathrm{{{}}}\, {} \right)",
1444            self.obj.to_latex_string(),
1445            RESTRICT_FN_IN,
1446            self.obj_cannot_restrict_to_fn_set.to_latex_string()
1447        )
1448    }
1449}
1450
1451impl NotSubsetFact {
1452    pub fn to_latex_string(&self) -> String {
1453        format!(
1454            r"\neg \left( {} \subseteq {} \right)",
1455            self.left.to_latex_string(),
1456            self.right.to_latex_string()
1457        )
1458    }
1459}
1460
1461impl NotSupersetFact {
1462    pub fn to_latex_string(&self) -> String {
1463        format!(
1464            r"\neg \left( {} \supseteq {} \right)",
1465            self.left.to_latex_string(),
1466            self.right.to_latex_string()
1467        )
1468    }
1469}
1470
1471impl Number {
1472    pub fn to_latex_string(&self) -> String {
1473        self.normalized_value.clone()
1474    }
1475}
1476
1477impl ObjAtIndex {
1478    pub fn to_latex_string(&self) -> String {
1479        format!(
1480            r"{}\left[ {} \right]",
1481            self.obj.to_latex_string(),
1482            self.index.to_latex_string()
1483        )
1484    }
1485}
1486
1487impl OrFact {
1488    pub fn to_latex_string(&self) -> String {
1489        self.facts
1490            .iter()
1491            .map(|f| f.to_latex_string())
1492            .collect::<Vec<_>>()
1493            .join(r" \lor ")
1494    }
1495}
1496
1497impl ParamDefWithType {
1498    pub fn to_latex_string(&self) -> String {
1499        self.groups
1500            .iter()
1501            .map(|g| g.to_latex_string())
1502            .collect::<Vec<_>>()
1503            .join(", ")
1504    }
1505}
1506
1507impl ParamGroupWithParamType {
1508    pub fn to_latex_string(&self) -> String {
1509        let names = self
1510            .params
1511            .iter()
1512            .map(|p| latex_local_ident(p))
1513            .collect::<Vec<_>>()
1514            .join(", ");
1515        format!(r"{}, {}", names, self.param_type.to_latex_string())
1516    }
1517}
1518
1519impl ParamType {
1520    pub fn to_latex_string(&self) -> String {
1521        match self {
1522            ParamType::Set(_) => format!(r"\mathrm{{{}}}", SET),
1523            ParamType::NonemptySet(_) => format!(r"\mathrm{{{}}}", NONEMPTY_SET),
1524            ParamType::FiniteSet(_) => format!(r"\mathrm{{{}}}", FINITE_SET),
1525            ParamType::Obj(o) => o.to_latex_string(),
1526        }
1527    }
1528}
1529
1530impl Pow {
1531    pub fn to_latex_string(&self) -> String {
1532        format!(
1533            "{{{}}}^{{{}}}",
1534            self.base.to_latex_string(),
1535            self.exponent.to_latex_string()
1536        )
1537    }
1538}
1539
1540impl PowerSet {
1541    pub fn to_latex_string(&self) -> String {
1542        format!(r"\mathcal{{P}}\left( {}\right)", self.set.to_latex_string())
1543    }
1544}
1545
1546impl Proj {
1547    pub fn to_latex_string(&self) -> String {
1548        format!(
1549            r"\operatorname{{{}}}\left( {}, {} \right)",
1550            PROJ,
1551            self.set.to_latex_string(),
1552            self.dim.to_latex_string()
1553        )
1554    }
1555}
1556
1557impl ProveStmt {
1558    pub fn to_latex_string(&self) -> String {
1559        if self.proof.is_empty() {
1560            return r"\text{\texttt{(empty proof)}}".to_string();
1561        }
1562        let rows: Vec<String> = self
1563            .proof
1564            .iter()
1565            .map(|st| format!(r"& \quad {}", st.to_latex_string()))
1566            .collect();
1567        format!(
1568            "\\begin{{aligned}}\n{}\n\\end{{aligned}}",
1569            rows.join(" \\\\\n")
1570        )
1571    }
1572}
1573
1574impl Range {
1575    pub fn to_latex_string(&self) -> String {
1576        format!(
1577            r"\operatorname{{{}}}\left( {}, {} \right)",
1578            RANGE,
1579            self.start.to_latex_string(),
1580            self.end.to_latex_string()
1581        )
1582    }
1583}
1584
1585impl RestrictFact {
1586    pub fn to_latex_string(&self) -> String {
1587        format!(
1588            r"{} \mathrel{{\$}} \mathrm{{{}}}\, {}",
1589            self.obj.to_latex_string(),
1590            RESTRICT_FN_IN,
1591            self.obj_can_restrict_to_fn_set.to_latex_string()
1592        )
1593    }
1594}
1595
1596impl RunFileStmt {
1597    pub fn to_latex_string(&self) -> String {
1598        format!(
1599            r"\operatorname{{{}}}\ \texttt{{{}}}",
1600            RUN_FILE,
1601            latex_texttt_escape(&self.file_path)
1602        )
1603    }
1604}
1605
1606impl SeqSet {
1607    pub fn to_latex_string(&self) -> String {
1608        format!(
1609            r"\operatorname{{{}}}\left( {}\right)",
1610            SEQ,
1611            self.set.to_latex_string()
1612        )
1613    }
1614}
1615
1616impl SetBuilder {
1617    pub fn to_latex_string(&self) -> String {
1618        let cond = self
1619            .facts
1620            .iter()
1621            .map(|f| f.to_latex_string())
1622            .collect::<Vec<_>>()
1623            .join(r" \land ");
1624        format!(
1625            r"\left\{{ {} \in {} \,\middle|\, {} \right\}}",
1626            latex_local_ident(&self.param),
1627            self.param_set.to_latex_string(),
1628            cond
1629        )
1630    }
1631}
1632
1633impl SetDiff {
1634    pub fn to_latex_string(&self) -> String {
1635        format!(
1636            r"\operatorname{{{}}}\left( {}, {} \right)",
1637            SET_DIFF,
1638            self.left.to_latex_string(),
1639            self.right.to_latex_string()
1640        )
1641    }
1642}
1643
1644impl SetMinus {
1645    pub fn to_latex_string(&self) -> String {
1646        format!(
1647            r"{} \setminus {}",
1648            self.left.to_latex_string(),
1649            self.right.to_latex_string()
1650        )
1651    }
1652}
1653
1654impl Sub {
1655    pub fn to_latex_string(&self) -> String {
1656        format!(
1657            "{} - {}",
1658            self.left.to_latex_string(),
1659            self.right.to_latex_string()
1660        )
1661    }
1662}
1663
1664impl SubsetFact {
1665    pub fn to_latex_string(&self) -> String {
1666        format!(
1667            r"{} \subseteq {}",
1668            self.left.to_latex_string(),
1669            self.right.to_latex_string()
1670        )
1671    }
1672}
1673
1674impl SupersetFact {
1675    pub fn to_latex_string(&self) -> String {
1676        format!(
1677            r"{} \supseteq {}",
1678            self.left.to_latex_string(),
1679            self.right.to_latex_string()
1680        )
1681    }
1682}
1683
1684impl Tuple {
1685    pub fn to_latex_string(&self) -> String {
1686        let inner = self
1687            .args
1688            .iter()
1689            .map(|o| o.to_latex_string())
1690            .collect::<Vec<_>>()
1691            .join(", ");
1692        format!(r"\left( {} \right)", inner)
1693    }
1694}
1695
1696impl TupleDim {
1697    pub fn to_latex_string(&self) -> String {
1698        format!(
1699            r"\operatorname{{{}}}\left( {}\right)",
1700            TUPLE_DIM,
1701            self.arg.to_latex_string()
1702        )
1703    }
1704}
1705
1706impl Union {
1707    pub fn to_latex_string(&self) -> String {
1708        format!(
1709            r"{} \cup {}",
1710            self.left.to_latex_string(),
1711            self.right.to_latex_string()
1712        )
1713    }
1714}
1715
1716impl WitnessExistFact {
1717    pub fn to_latex_string(&self) -> String {
1718        let names = self
1719            .equal_tos
1720            .iter()
1721            .map(|o| o.to_latex_string())
1722            .collect::<Vec<_>>()
1723            .join(", ");
1724        let facts = self
1725            .exist_fact_in_witness
1726            .facts()
1727            .iter()
1728            .map(|f| f.to_latex_string())
1729            .collect::<Vec<_>>()
1730            .join(", ");
1731        let head = format!(
1732            r"\mathrm{{witness}}\ {} : {} \mathrm{{st}} \left\{{ {}\right\}}",
1733            names,
1734            self.exist_fact_in_witness
1735                .params_def_with_type()
1736                .to_latex_string(),
1737            facts
1738        );
1739        if self.proof.is_empty() {
1740            head
1741        } else {
1742            let mut rows = vec![format!(r"{} &", head)];
1743            for st in &self.proof {
1744                rows.push(format!(r"& \quad {}", st.to_latex_string()));
1745            }
1746            format!(
1747                "\\begin{{aligned}}\n{}\n\\end{{aligned}}",
1748                rows.join(" \\\\\n")
1749            )
1750        }
1751    }
1752}
1753
1754impl WitnessNonemptySet {
1755    pub fn to_latex_string(&self) -> String {
1756        let head = format!(
1757            r"\mathrm{{witness}}\ {} {}",
1758            self.obj.to_latex_string(),
1759            self.set.to_latex_string()
1760        );
1761        if self.proof.is_empty() {
1762            head
1763        } else {
1764            let mut rows = vec![format!(r"{} &", head)];
1765            for st in &self.proof {
1766                rows.push(format!(r"& \quad {}", st.to_latex_string()));
1767            }
1768            format!(
1769                "\\begin{{aligned}}\n{}\n\\end{{aligned}}",
1770                rows.join(" \\\\\n")
1771            )
1772        }
1773    }
1774}
1775
1776impl ImportGlobalModuleStmt {
1777    pub fn to_latex_string(&self) -> String {
1778        match &self.as_mod_name {
1779            Some(m) => format!(
1780                r"\operatorname{{{}}}\ {}\ \mathrm{{as}}\ {}",
1781                IMPORT,
1782                latex_local_ident(&self.mod_name),
1783                latex_local_ident(m)
1784            ),
1785            None => format!(
1786                r"\operatorname{{{}}}\ {}",
1787                IMPORT,
1788                latex_local_ident(&self.mod_name)
1789            ),
1790        }
1791    }
1792}
1793
1794impl ImportRelativePathStmt {
1795    pub fn to_latex_string(&self) -> String {
1796        let path = latex_texttt_escape(&self.path);
1797        match &self.as_mod_name {
1798            Some(m) => format!(
1799                r"\operatorname{{{}}}\ \texttt{{{}}}\ \mathrm{{as}}\ {}",
1800                IMPORT,
1801                path,
1802                latex_local_ident(m)
1803            ),
1804            None => format!(r"\operatorname{{{}}}\ \texttt{{{}}}", IMPORT, path),
1805        }
1806    }
1807}
1808
1809impl ImportStmt {
1810    pub fn to_latex_string(&self) -> String {
1811        match self {
1812            ImportStmt::ImportRelativePath(s) => s.to_latex_string(),
1813            ImportStmt::ImportGlobalModule(s) => s.to_latex_string(),
1814        }
1815    }
1816}
1817
1818impl StandardSet {
1819    pub fn to_latex_string(&self) -> String {
1820        match self {
1821            StandardSet::N => r"\mathbb{N}".to_string(),
1822            StandardSet::NPos => r"\mathbb{N}_{>0}".to_string(),
1823            StandardSet::Z => r"\mathbb{Z}".to_string(),
1824            StandardSet::ZNeg => r"\mathbb{Z}_{<0}".to_string(),
1825            StandardSet::ZNz => r"\mathbb{Z}\setminus\{0\}".to_string(),
1826            StandardSet::Q => r"\mathbb{Q}".to_string(),
1827            StandardSet::QPos => r"\mathbb{Q}_{>0}".to_string(),
1828            StandardSet::QNeg => r"\mathbb{Q}_{<0}".to_string(),
1829            StandardSet::QNz => r"\mathbb{Q}\setminus\{0\}".to_string(),
1830            StandardSet::R => r"\mathbb{R}".to_string(),
1831            StandardSet::RPos => r"\mathbb{R}_{>0}".to_string(),
1832            StandardSet::RNeg => r"\mathbb{R}_{<0}".to_string(),
1833            StandardSet::RNz => r"\mathbb{R}\setminus\{0\}".to_string(),
1834        }
1835    }
1836}
1837
1838impl Fact {
1839    pub fn to_latex_string(&self) -> String {
1840        match self {
1841            Fact::AtomicFact(x) => x.to_latex_string(),
1842            Fact::ExistFact(x) => x.to_latex_string(),
1843            Fact::OrFact(x) => x.to_latex_string(),
1844            Fact::AndFact(x) => x.to_latex_string(),
1845            Fact::ChainFact(x) => x.to_latex_string(),
1846            Fact::ForallFact(x) => x.to_latex_string(),
1847            Fact::ForallFactWithIff(x) => x.to_latex_string(),
1848            Fact::NotForall(x) => x.to_latex_string(),
1849        }
1850    }
1851}
1852
1853impl AtomicFact {
1854    pub fn to_latex_string(&self) -> String {
1855        match self {
1856            AtomicFact::NormalAtomicFact(x) => x.to_latex_string(),
1857            AtomicFact::EqualFact(x) => x.to_latex_string(),
1858            AtomicFact::LessFact(x) => x.to_latex_string(),
1859            AtomicFact::GreaterFact(x) => x.to_latex_string(),
1860            AtomicFact::LessEqualFact(x) => x.to_latex_string(),
1861            AtomicFact::GreaterEqualFact(x) => x.to_latex_string(),
1862            AtomicFact::IsSetFact(x) => x.to_latex_string(),
1863            AtomicFact::IsNonemptySetFact(x) => x.to_latex_string(),
1864            AtomicFact::IsFiniteSetFact(x) => x.to_latex_string(),
1865            AtomicFact::InFact(x) => x.to_latex_string(),
1866            AtomicFact::IsCartFact(x) => x.to_latex_string(),
1867            AtomicFact::IsTupleFact(x) => x.to_latex_string(),
1868            AtomicFact::SubsetFact(x) => x.to_latex_string(),
1869            AtomicFact::SupersetFact(x) => x.to_latex_string(),
1870            AtomicFact::RestrictFact(x) => x.to_latex_string(),
1871            AtomicFact::NotRestrictFact(x) => x.to_latex_string(),
1872            AtomicFact::NotNormalAtomicFact(x) => x.to_latex_string(),
1873            AtomicFact::NotEqualFact(x) => x.to_latex_string(),
1874            AtomicFact::NotLessFact(x) => x.to_latex_string(),
1875            AtomicFact::NotGreaterFact(x) => x.to_latex_string(),
1876            AtomicFact::NotLessEqualFact(x) => x.to_latex_string(),
1877            AtomicFact::NotGreaterEqualFact(x) => x.to_latex_string(),
1878            AtomicFact::NotIsSetFact(x) => x.to_latex_string(),
1879            AtomicFact::NotIsNonemptySetFact(x) => x.to_latex_string(),
1880            AtomicFact::NotIsFiniteSetFact(x) => x.to_latex_string(),
1881            AtomicFact::NotInFact(x) => x.to_latex_string(),
1882            AtomicFact::NotIsCartFact(x) => x.to_latex_string(),
1883            AtomicFact::NotIsTupleFact(x) => x.to_latex_string(),
1884            AtomicFact::NotSubsetFact(x) => x.to_latex_string(),
1885            AtomicFact::NotSupersetFact(x) => x.to_latex_string(),
1886            AtomicFact::FnEqualInFact(f) => format!(
1887                r"\mathsf{{fn\_eq\_in}}({},{},{})",
1888                f.left.to_latex_string(),
1889                f.right.to_latex_string(),
1890                f.set.to_latex_string(),
1891            ),
1892            AtomicFact::FnEqualFact(f) => format!(
1893                r"\mathsf{{fn\_eq}}({},{})",
1894                f.left.to_latex_string(),
1895                f.right.to_latex_string(),
1896            ),
1897        }
1898    }
1899}
1900
1901impl Obj {
1902    pub fn to_latex_string(&self) -> String {
1903        match self {
1904            Obj::Atom(AtomObj::Identifier(x)) => x.to_latex_string(),
1905            Obj::Atom(AtomObj::IdentifierWithMod(x)) => x.to_latex_string(),
1906            Obj::FnObj(x) => x.to_latex_string(),
1907            Obj::Number(x) => x.to_latex_string(),
1908            Obj::Add(x) => x.to_latex_string(),
1909            Obj::Sub(x) => x.to_latex_string(),
1910            Obj::Mul(x) => x.to_latex_string(),
1911            Obj::Div(x) => x.to_latex_string(),
1912            Obj::Mod(x) => x.to_latex_string(),
1913            Obj::Pow(x) => x.to_latex_string(),
1914            Obj::Abs(x) => x.to_latex_string(),
1915            Obj::Log(x) => x.to_latex_string(),
1916            Obj::Max(x) => x.to_latex_string(),
1917            Obj::Min(x) => x.to_latex_string(),
1918            Obj::Union(x) => x.to_latex_string(),
1919            Obj::Intersect(x) => x.to_latex_string(),
1920            Obj::SetMinus(x) => x.to_latex_string(),
1921            Obj::SetDiff(x) => x.to_latex_string(),
1922            Obj::Cup(x) => x.to_latex_string(),
1923            Obj::Cap(x) => x.to_latex_string(),
1924            Obj::PowerSet(x) => x.to_latex_string(),
1925            Obj::ListSet(x) => x.to_latex_string(),
1926            Obj::SetBuilder(x) => x.to_latex_string(),
1927            Obj::FnSet(x) => x.to_latex_string(),
1928            Obj::AnonymousFn(x) => x.to_latex_string(),
1929            Obj::Cart(x) => x.to_latex_string(),
1930            Obj::CartDim(x) => x.to_latex_string(),
1931            Obj::Proj(x) => x.to_latex_string(),
1932            Obj::TupleDim(x) => x.to_latex_string(),
1933            Obj::Tuple(x) => x.to_latex_string(),
1934            Obj::Count(x) => x.to_latex_string(),
1935            Obj::Sum(x) => x.to_latex_string(),
1936            Obj::Product(x) => x.to_latex_string(),
1937            Obj::Range(x) => x.to_latex_string(),
1938            Obj::ClosedRange(x) => x.to_latex_string(),
1939            Obj::FiniteSeqSet(x) => x.to_latex_string(),
1940            Obj::SeqSet(x) => x.to_latex_string(),
1941            Obj::FiniteSeqListObj(x) => x.to_latex_string(),
1942            Obj::Choose(x) => x.to_latex_string(),
1943            Obj::ObjAtIndex(x) => x.to_latex_string(),
1944            Obj::StandardSet(x) => x.to_latex_string(),
1945            Obj::FamilyObj(x) => x.to_latex_string(),
1946            Obj::Atom(AtomObj::Forall(x)) => latex_local_ident(&x.name),
1947            Obj::Atom(AtomObj::Def(x)) => latex_local_ident(&x.name),
1948            Obj::Atom(AtomObj::Exist(x)) => latex_local_ident(&x.name),
1949            Obj::Atom(AtomObj::SetBuilder(x)) => latex_local_ident(&x.name),
1950            Obj::Atom(AtomObj::FnSet(x)) => latex_local_ident(&x.name),
1951            Obj::Atom(AtomObj::Induc(x)) => latex_local_ident(&x.name),
1952            Obj::Atom(AtomObj::DefAlgo(x)) => latex_local_ident(&x.name),
1953            Obj::MatrixSet(x) => x.to_latex_string(),
1954            Obj::MatrixListObj(x) => x.to_latex_string(),
1955            Obj::MatrixAdd(x) => x.to_latex_string(),
1956            Obj::MatrixSub(x) => x.to_latex_string(),
1957            Obj::MatrixMul(x) => x.to_latex_string(),
1958            Obj::MatrixScalarMul(x) => x.to_latex_string(),
1959            Obj::MatrixPow(x) => x.to_latex_string(),
1960        }
1961    }
1962}
1963
1964impl Stmt {
1965    pub fn to_latex_string(&self) -> String {
1966        match self {
1967            Stmt::Fact(x) => x.to_latex_string(),
1968            Stmt::DefLetStmt(x) => x.to_latex_string(),
1969            Stmt::DefPropStmt(x) => x.to_latex_string(),
1970            Stmt::DefAbstractPropStmt(x) => x.to_latex_string(),
1971            Stmt::HaveObjInNonemptySetStmt(x) => x.to_latex_string(),
1972            Stmt::HaveObjEqualStmt(x) => x.to_latex_string(),
1973            Stmt::HaveByExistStmt(x) => x.to_latex_string(),
1974            Stmt::HaveFnEqualStmt(x) => x.to_latex_string(),
1975            Stmt::HaveFnEqualCaseByCaseStmt(x) => x.to_latex_string(),
1976            Stmt::HaveFnByInducStmt(x) => x.to_latex_string(),
1977            Stmt::HaveFnByForallExistUniqueStmt(x) => x.to_latex_string(),
1978            Stmt::DefFamilyStmt(x) => x.to_latex_string(),
1979            Stmt::DefAlgoStmt(x) => x.to_latex_string(),
1980            Stmt::ClaimStmt(x) => x.to_latex_string(),
1981            Stmt::KnowStmt(x) => x.to_latex_string(),
1982            Stmt::ProveStmt(x) => x.to_latex_string(),
1983            Stmt::ImportStmt(x) => x.to_latex_string(),
1984            Stmt::DoNothingStmt(x) => x.to_latex_string(),
1985            Stmt::ClearStmt(x) => x.to_latex_string(),
1986            Stmt::RunFileStmt(x) => x.to_latex_string(),
1987            Stmt::EvalStmt(x) => x.to_latex_string(),
1988            Stmt::WitnessExistFact(x) => x.to_latex_string(),
1989            Stmt::WitnessNonemptySet(x) => x.to_latex_string(),
1990            Stmt::ByCasesStmt(x) => x.to_latex_string(),
1991            Stmt::ByContraStmt(x) => x.to_latex_string(),
1992            Stmt::ByEnumerateFiniteSetStmt(x) => x.to_latex_string(),
1993            Stmt::ByInducStmt(x) => x.to_latex_string(),
1994            Stmt::ByForStmt(x) => x.to_latex_string(),
1995            Stmt::ByExtensionStmt(x) => x.to_latex_string(),
1996            Stmt::ByFnStmt(x) => x.to_latex_string(),
1997            Stmt::ByFamilyStmt(x) => x.to_latex_string(),
1998            Stmt::ByTuple(x) => x.to_latex_string(),
1999            Stmt::ByFnSetStmt(x) => x.to_latex_string(),
2000            Stmt::ByEnumerateClosedRangeStmt(x) => x.to_latex_string(),
2001        }
2002    }
2003}