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