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