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