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