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