Skip to main content

oxilean_std/parsec/
functions.rs

1//! Auto-generated module
2//!
3//! 🤖 Generated with [SplitRS](https://github.com/cool-japan/splitrs)
4#![allow(clippy::items_after_test_module)]
5
6use oxilean_kernel::{BinderInfo, Declaration, Environment, Expr, Level, Name};
7
8use super::types::{ContextFreeGrammar, PegExpr};
9
10/// Prop: `Sort 0`.
11#[allow(dead_code)]
12pub fn prop() -> Expr {
13    Expr::Sort(Level::zero())
14}
15/// Type 1: `Sort 1`.
16#[allow(dead_code)]
17pub(super) fn type1() -> Expr {
18    Expr::Sort(Level::succ(Level::zero()))
19}
20/// Type 2: `Sort 2`.
21#[allow(dead_code)]
22pub fn type2() -> Expr {
23    Expr::Sort(Level::succ(Level::succ(Level::zero())))
24}
25/// Nat type constant.
26#[allow(dead_code)]
27pub fn nat_ty() -> Expr {
28    Expr::Const(Name::str("Nat"), vec![])
29}
30/// Int type constant.
31#[allow(dead_code)]
32pub fn int_ty() -> Expr {
33    Expr::Const(Name::str("Int"), vec![])
34}
35/// Bool type constant.
36#[allow(dead_code)]
37pub fn bool_ty() -> Expr {
38    Expr::Const(Name::str("Bool"), vec![])
39}
40/// Char type constant.
41#[allow(dead_code)]
42pub fn char_ty() -> Expr {
43    Expr::Const(Name::str("Char"), vec![])
44}
45/// String type constant.
46#[allow(dead_code)]
47pub fn string_ty() -> Expr {
48    Expr::Const(Name::str("String"), vec![])
49}
50/// Unit type constant.
51#[allow(dead_code)]
52pub fn unit_ty() -> Expr {
53    Expr::Const(Name::str("Unit"), vec![])
54}
55/// `String.Pos` type constant.
56#[allow(dead_code)]
57pub fn string_pos_ty() -> Expr {
58    Expr::Const(Name::str("String.Pos"), vec![])
59}
60/// `List` applied to a type argument.
61#[allow(dead_code)]
62pub fn list_of(elem_ty: Expr) -> Expr {
63    app(Expr::Const(Name::str("List"), vec![]), elem_ty)
64}
65/// `Option` applied to a type argument.
66#[allow(dead_code)]
67pub fn option_of(elem_ty: Expr) -> Expr {
68    app(Expr::Const(Name::str("Option"), vec![]), elem_ty)
69}
70/// `Inhabited` applied to a type argument.
71#[allow(dead_code)]
72pub fn inhabited_of(ty: Expr) -> Expr {
73    app(Expr::Const(Name::str("Inhabited"), vec![]), ty)
74}
75/// Build a non-dependent arrow `A -> B`.
76#[allow(dead_code)]
77pub fn arrow(a: Expr, b: Expr) -> Expr {
78    Expr::Pi(
79        BinderInfo::Default,
80        Name::str("_"),
81        Box::new(a),
82        Box::new(b),
83    )
84}
85/// Function application `f a`.
86#[allow(dead_code)]
87pub fn app(f: Expr, a: Expr) -> Expr {
88    Expr::App(Box::new(f), Box::new(a))
89}
90/// Function application `f a b`.
91#[allow(dead_code)]
92pub fn app2(f: Expr, a: Expr, b: Expr) -> Expr {
93    app(app(f, a), b)
94}
95/// Function application `f a b c`.
96#[allow(dead_code)]
97pub fn app3(f: Expr, a: Expr, b: Expr, c: Expr) -> Expr {
98    app(app2(f, a, b), c)
99}
100/// Function application `f a b c d`.
101#[allow(dead_code)]
102pub fn app4(f: Expr, a: Expr, b: Expr, c: Expr, d: Expr) -> Expr {
103    app(app3(f, a, b, c), d)
104}
105/// An implicit Pi binder.
106#[allow(dead_code)]
107pub fn implicit_pi(name: &str, ty: Expr, body: Expr) -> Expr {
108    Expr::Pi(
109        BinderInfo::Implicit,
110        Name::str(name),
111        Box::new(ty),
112        Box::new(body),
113    )
114}
115/// A default (explicit) Pi binder.
116#[allow(dead_code)]
117pub fn default_pi(name: &str, ty: Expr, body: Expr) -> Expr {
118    Expr::Pi(
119        BinderInfo::Default,
120        Name::str(name),
121        Box::new(ty),
122        Box::new(body),
123    )
124}
125/// An instance-implicit Pi binder.
126#[allow(dead_code)]
127pub fn inst_pi(name: &str, ty: Expr, body: Expr) -> Expr {
128    Expr::Pi(
129        BinderInfo::InstImplicit,
130        Name::str(name),
131        Box::new(ty),
132        Box::new(body),
133    )
134}
135/// Build `Eq @{} ty a b`.
136#[allow(dead_code)]
137pub fn eq_expr(ty: Expr, a: Expr, b: Expr) -> Expr {
138    app3(Expr::Const(Name::str("Eq"), vec![]), ty, a, b)
139}
140/// `ParseResult ε α` applied to two type arguments.
141#[allow(dead_code)]
142pub fn parse_result_of(err_ty: Expr, val_ty: Expr) -> Expr {
143    app2(
144        Expr::Const(Name::str("ParseResult"), vec![]),
145        err_ty,
146        val_ty,
147    )
148}
149/// `Parsec ε α` applied to two type arguments.
150#[allow(dead_code)]
151pub fn parsec_of(err_ty: Expr, val_ty: Expr) -> Expr {
152    app2(Expr::Const(Name::str("Parsec"), vec![]), err_ty, val_ty)
153}
154/// Shorthand to add an axiom to env.
155#[allow(dead_code)]
156pub fn add_axiom(
157    env: &mut Environment,
158    name: &str,
159    univ_params: Vec<Name>,
160    ty: Expr,
161) -> Result<(), String> {
162    env.add(Declaration::Axiom {
163        name: Name::str(name),
164        univ_params,
165        ty,
166    })
167    .map_err(|e| e.to_string())
168}
169/// Build the Parsec parser combinator library in the environment.
170///
171/// Assumes that `String`, `Char`, `Nat`, `Int`, `Bool`, `Unit`, `List`,
172/// `Option`, `Inhabited`, and `Eq` are already declared in `env` or
173/// referenced by name.
174pub fn build_parsec_env(env: &mut Environment) -> Result<(), String> {
175    add_axiom(env, "String.Pos", vec![], type1())?;
176    let parse_result_ty = default_pi("ε", type1(), default_pi("α", type1(), type1()));
177    add_axiom(env, "ParseResult", vec![], parse_result_ty)?;
178    let success_ty = implicit_pi(
179        "ε",
180        type1(),
181        implicit_pi(
182            "α",
183            type1(),
184            default_pi(
185                "pos",
186                string_pos_ty(),
187                default_pi(
188                    "val",
189                    Expr::BVar(1),
190                    parse_result_of(Expr::BVar(3), Expr::BVar(2)),
191                ),
192            ),
193        ),
194    );
195    add_axiom(env, "ParseResult.success", vec![], success_ty)?;
196    let error_ty = implicit_pi(
197        "ε",
198        type1(),
199        implicit_pi(
200            "α",
201            type1(),
202            default_pi(
203                "pos",
204                string_pos_ty(),
205                default_pi(
206                    "err",
207                    Expr::BVar(2),
208                    parse_result_of(Expr::BVar(3), Expr::BVar(2)),
209                ),
210            ),
211        ),
212    );
213    add_axiom(env, "ParseResult.error", vec![], error_ty)?;
214    let parsec_ty = default_pi("ε", type1(), default_pi("α", type1(), type1()));
215    add_axiom(env, "Parsec", vec![], parsec_ty)?;
216    let run_ty = implicit_pi(
217        "ε",
218        type1(),
219        implicit_pi(
220            "α",
221            type1(),
222            default_pi(
223                "p",
224                parsec_of(Expr::BVar(1), Expr::BVar(0)),
225                default_pi(
226                    "s",
227                    string_ty(),
228                    parse_result_of(Expr::BVar(3), Expr::BVar(2)),
229                ),
230            ),
231        ),
232    );
233    add_axiom(env, "Parsec.run", vec![], run_ty)?;
234    let pure_ty = implicit_pi(
235        "ε",
236        type1(),
237        implicit_pi(
238            "α",
239            type1(),
240            default_pi("a", Expr::BVar(0), parsec_of(Expr::BVar(2), Expr::BVar(1))),
241        ),
242    );
243    add_axiom(env, "Parsec.pure", vec![], pure_ty)?;
244    let fail_ty = implicit_pi(
245        "ε",
246        type1(),
247        implicit_pi(
248            "α",
249            type1(),
250            default_pi("e", Expr::BVar(1), parsec_of(Expr::BVar(2), Expr::BVar(1))),
251        ),
252    );
253    add_axiom(env, "Parsec.fail", vec![], fail_ty)?;
254    let bind_ty = implicit_pi(
255        "ε",
256        type1(),
257        implicit_pi(
258            "α",
259            type1(),
260            implicit_pi(
261                "β",
262                type1(),
263                default_pi(
264                    "p",
265                    parsec_of(Expr::BVar(2), Expr::BVar(1)),
266                    default_pi(
267                        "f",
268                        arrow(Expr::BVar(2), parsec_of(Expr::BVar(4), Expr::BVar(2))),
269                        parsec_of(Expr::BVar(4), Expr::BVar(2)),
270                    ),
271                ),
272            ),
273        ),
274    );
275    add_axiom(env, "Parsec.bind", vec![], bind_ty)?;
276    let map_ty = implicit_pi(
277        "ε",
278        type1(),
279        implicit_pi(
280            "α",
281            type1(),
282            implicit_pi(
283                "β",
284                type1(),
285                default_pi(
286                    "f",
287                    arrow(Expr::BVar(1), Expr::BVar(1)),
288                    default_pi(
289                        "p",
290                        parsec_of(Expr::BVar(3), Expr::BVar(2)),
291                        parsec_of(Expr::BVar(4), Expr::BVar(2)),
292                    ),
293                ),
294            ),
295        ),
296    );
297    add_axiom(env, "Parsec.map", vec![], map_ty)?;
298    let seq_ty = implicit_pi(
299        "ε",
300        type1(),
301        implicit_pi(
302            "α",
303            type1(),
304            implicit_pi(
305                "β",
306                type1(),
307                default_pi(
308                    "pf",
309                    parsec_of(Expr::BVar(2), arrow(Expr::BVar(1), Expr::BVar(1))),
310                    default_pi(
311                        "pa",
312                        parsec_of(Expr::BVar(3), Expr::BVar(2)),
313                        parsec_of(Expr::BVar(4), Expr::BVar(2)),
314                    ),
315                ),
316            ),
317        ),
318    );
319    add_axiom(env, "Parsec.seq", vec![], seq_ty)?;
320    let or_else_ty = implicit_pi(
321        "ε",
322        type1(),
323        implicit_pi(
324            "α",
325            type1(),
326            default_pi(
327                "p1",
328                parsec_of(Expr::BVar(1), Expr::BVar(0)),
329                default_pi(
330                    "p2",
331                    parsec_of(Expr::BVar(2), Expr::BVar(1)),
332                    parsec_of(Expr::BVar(3), Expr::BVar(2)),
333                ),
334            ),
335        ),
336    );
337    add_axiom(env, "Parsec.orElse", vec![], or_else_ty)?;
338    let any_ty = implicit_pi(
339        "ε",
340        type1(),
341        inst_pi(
342            "_inst",
343            inhabited_of(Expr::BVar(0)),
344            parsec_of(Expr::BVar(1), char_ty()),
345        ),
346    );
347    add_axiom(env, "Parsec.any", vec![], any_ty)?;
348    let satisfy_ty = implicit_pi(
349        "ε",
350        type1(),
351        inst_pi(
352            "_inst",
353            inhabited_of(Expr::BVar(0)),
354            default_pi(
355                "pred",
356                arrow(char_ty(), bool_ty()),
357                parsec_of(Expr::BVar(2), char_ty()),
358            ),
359        ),
360    );
361    add_axiom(env, "Parsec.satisfy", vec![], satisfy_ty)?;
362    let char_parser_ty = implicit_pi(
363        "ε",
364        type1(),
365        inst_pi(
366            "_inst",
367            inhabited_of(Expr::BVar(0)),
368            default_pi("c", char_ty(), parsec_of(Expr::BVar(2), char_ty())),
369        ),
370    );
371    add_axiom(env, "Parsec.char", vec![], char_parser_ty)?;
372    let digit_ty = implicit_pi(
373        "ε",
374        type1(),
375        inst_pi(
376            "_inst",
377            inhabited_of(Expr::BVar(0)),
378            parsec_of(Expr::BVar(1), char_ty()),
379        ),
380    );
381    add_axiom(env, "Parsec.digit", vec![], digit_ty)?;
382    let alpha_ty = implicit_pi(
383        "ε",
384        type1(),
385        inst_pi(
386            "_inst",
387            inhabited_of(Expr::BVar(0)),
388            parsec_of(Expr::BVar(1), char_ty()),
389        ),
390    );
391    add_axiom(env, "Parsec.alpha", vec![], alpha_ty)?;
392    let alpha_num_ty = implicit_pi(
393        "ε",
394        type1(),
395        inst_pi(
396            "_inst",
397            inhabited_of(Expr::BVar(0)),
398            parsec_of(Expr::BVar(1), char_ty()),
399        ),
400    );
401    add_axiom(env, "Parsec.alphaNum", vec![], alpha_num_ty)?;
402    let ws_ty = implicit_pi(
403        "ε",
404        type1(),
405        inst_pi(
406            "_inst",
407            inhabited_of(Expr::BVar(0)),
408            parsec_of(Expr::BVar(1), unit_ty()),
409        ),
410    );
411    add_axiom(env, "Parsec.ws", vec![], ws_ty)?;
412    let string_parser_ty = implicit_pi(
413        "ε",
414        type1(),
415        inst_pi(
416            "_inst",
417            inhabited_of(Expr::BVar(0)),
418            default_pi("s", string_ty(), parsec_of(Expr::BVar(2), string_ty())),
419        ),
420    );
421    add_axiom(env, "Parsec.string", vec![], string_parser_ty)?;
422    let eof_ty = implicit_pi(
423        "ε",
424        type1(),
425        inst_pi(
426            "_inst",
427            inhabited_of(Expr::BVar(0)),
428            parsec_of(Expr::BVar(1), unit_ty()),
429        ),
430    );
431    add_axiom(env, "Parsec.eof", vec![], eof_ty)?;
432    let many_ty = implicit_pi(
433        "ε",
434        type1(),
435        implicit_pi(
436            "α",
437            type1(),
438            default_pi(
439                "p",
440                parsec_of(Expr::BVar(1), Expr::BVar(0)),
441                parsec_of(Expr::BVar(2), list_of(Expr::BVar(1))),
442            ),
443        ),
444    );
445    add_axiom(env, "Parsec.many", vec![], many_ty)?;
446    let many1_ty = implicit_pi(
447        "ε",
448        type1(),
449        implicit_pi(
450            "α",
451            type1(),
452            default_pi(
453                "p",
454                parsec_of(Expr::BVar(1), Expr::BVar(0)),
455                parsec_of(Expr::BVar(2), list_of(Expr::BVar(1))),
456            ),
457        ),
458    );
459    add_axiom(env, "Parsec.many1", vec![], many1_ty)?;
460    let optional_ty = implicit_pi(
461        "ε",
462        type1(),
463        implicit_pi(
464            "α",
465            type1(),
466            default_pi(
467                "p",
468                parsec_of(Expr::BVar(1), Expr::BVar(0)),
469                parsec_of(Expr::BVar(2), option_of(Expr::BVar(1))),
470            ),
471        ),
472    );
473    add_axiom(env, "Parsec.optional", vec![], optional_ty)?;
474    let sep_by_ty = implicit_pi(
475        "ε",
476        type1(),
477        implicit_pi(
478            "α",
479            type1(),
480            implicit_pi(
481                "β",
482                type1(),
483                default_pi(
484                    "p",
485                    parsec_of(Expr::BVar(2), Expr::BVar(1)),
486                    default_pi(
487                        "sep",
488                        parsec_of(Expr::BVar(3), Expr::BVar(1)),
489                        parsec_of(Expr::BVar(4), list_of(Expr::BVar(3))),
490                    ),
491                ),
492            ),
493        ),
494    );
495    add_axiom(env, "Parsec.sepBy", vec![], sep_by_ty)?;
496    let sep_by1_ty = implicit_pi(
497        "ε",
498        type1(),
499        implicit_pi(
500            "α",
501            type1(),
502            implicit_pi(
503                "β",
504                type1(),
505                default_pi(
506                    "p",
507                    parsec_of(Expr::BVar(2), Expr::BVar(1)),
508                    default_pi(
509                        "sep",
510                        parsec_of(Expr::BVar(3), Expr::BVar(1)),
511                        parsec_of(Expr::BVar(4), list_of(Expr::BVar(3))),
512                    ),
513                ),
514            ),
515        ),
516    );
517    add_axiom(env, "Parsec.sepBy1", vec![], sep_by1_ty)?;
518    let between_ty = implicit_pi(
519        "ε",
520        type1(),
521        implicit_pi(
522            "α",
523            type1(),
524            implicit_pi(
525                "β",
526                type1(),
527                implicit_pi(
528                    "γ",
529                    type1(),
530                    default_pi(
531                        "open",
532                        parsec_of(Expr::BVar(3), Expr::BVar(2)),
533                        default_pi(
534                            "close",
535                            parsec_of(Expr::BVar(4), Expr::BVar(2)),
536                            default_pi(
537                                "p",
538                                parsec_of(Expr::BVar(5), Expr::BVar(2)),
539                                parsec_of(Expr::BVar(6), Expr::BVar(3)),
540                            ),
541                        ),
542                    ),
543                ),
544            ),
545        ),
546    );
547    add_axiom(env, "Parsec.between", vec![], between_ty)?;
548    let not_followed_by_ty = implicit_pi(
549        "ε",
550        type1(),
551        implicit_pi(
552            "α",
553            type1(),
554            default_pi(
555                "p",
556                parsec_of(Expr::BVar(1), Expr::BVar(0)),
557                parsec_of(Expr::BVar(2), unit_ty()),
558            ),
559        ),
560    );
561    add_axiom(env, "Parsec.notFollowedBy", vec![], not_followed_by_ty)?;
562    let lookahead_ty = implicit_pi(
563        "ε",
564        type1(),
565        implicit_pi(
566            "α",
567            type1(),
568            default_pi(
569                "p",
570                parsec_of(Expr::BVar(1), Expr::BVar(0)),
571                parsec_of(Expr::BVar(2), Expr::BVar(1)),
572            ),
573        ),
574    );
575    add_axiom(env, "Parsec.lookahead", vec![], lookahead_ty)?;
576    let chainl_ty = implicit_pi(
577        "ε",
578        type1(),
579        implicit_pi(
580            "α",
581            type1(),
582            default_pi(
583                "p",
584                parsec_of(Expr::BVar(1), Expr::BVar(0)),
585                default_pi(
586                    "op",
587                    parsec_of(
588                        Expr::BVar(2),
589                        arrow(Expr::BVar(1), arrow(Expr::BVar(2), Expr::BVar(3))),
590                    ),
591                    default_pi(
592                        "def",
593                        Expr::BVar(2),
594                        parsec_of(Expr::BVar(4), Expr::BVar(3)),
595                    ),
596                ),
597            ),
598        ),
599    );
600    add_axiom(env, "Parsec.chainl", vec![], chainl_ty)?;
601    let chainr_ty = implicit_pi(
602        "ε",
603        type1(),
604        implicit_pi(
605            "α",
606            type1(),
607            default_pi(
608                "p",
609                parsec_of(Expr::BVar(1), Expr::BVar(0)),
610                default_pi(
611                    "op",
612                    parsec_of(
613                        Expr::BVar(2),
614                        arrow(Expr::BVar(1), arrow(Expr::BVar(2), Expr::BVar(3))),
615                    ),
616                    default_pi(
617                        "def",
618                        Expr::BVar(2),
619                        parsec_of(Expr::BVar(4), Expr::BVar(3)),
620                    ),
621                ),
622            ),
623        ),
624    );
625    add_axiom(env, "Parsec.chainr", vec![], chainr_ty)?;
626    let nat_parser_ty = implicit_pi(
627        "ε",
628        type1(),
629        inst_pi(
630            "_inst",
631            inhabited_of(Expr::BVar(0)),
632            parsec_of(Expr::BVar(1), nat_ty()),
633        ),
634    );
635    add_axiom(env, "Parsec.nat", vec![], nat_parser_ty)?;
636    let int_parser_ty = implicit_pi(
637        "ε",
638        type1(),
639        inst_pi(
640            "_inst",
641            inhabited_of(Expr::BVar(0)),
642            parsec_of(Expr::BVar(1), int_ty()),
643        ),
644    );
645    add_axiom(env, "Parsec.int", vec![], int_parser_ty)?;
646    let hex_digit_ty = implicit_pi(
647        "ε",
648        type1(),
649        inst_pi(
650            "_inst",
651            inhabited_of(Expr::BVar(0)),
652            parsec_of(Expr::BVar(1), char_ty()),
653        ),
654    );
655    add_axiom(env, "Parsec.hexDigit", vec![], hex_digit_ty)?;
656    let hex_nat_ty = implicit_pi(
657        "ε",
658        type1(),
659        inst_pi(
660            "_inst",
661            inhabited_of(Expr::BVar(0)),
662            parsec_of(Expr::BVar(1), nat_ty()),
663        ),
664    );
665    add_axiom(env, "Parsec.hexNat", vec![], hex_nat_ty)?;
666    let token_ty = implicit_pi(
667        "ε",
668        type1(),
669        implicit_pi(
670            "α",
671            type1(),
672            inst_pi(
673                "_inst",
674                inhabited_of(Expr::BVar(1)),
675                default_pi(
676                    "p",
677                    parsec_of(Expr::BVar(2), Expr::BVar(1)),
678                    parsec_of(Expr::BVar(3), Expr::BVar(2)),
679                ),
680            ),
681        ),
682    );
683    add_axiom(env, "Parsec.token", vec![], token_ty)?;
684    let symbol_ty = implicit_pi(
685        "ε",
686        type1(),
687        inst_pi(
688            "_inst",
689            inhabited_of(Expr::BVar(0)),
690            default_pi("s", string_ty(), parsec_of(Expr::BVar(2), string_ty())),
691        ),
692    );
693    add_axiom(env, "Parsec.symbol", vec![], symbol_ty)?;
694    let pure_bind_ty = implicit_pi(
695        "ε",
696        type1(),
697        implicit_pi(
698            "α",
699            type1(),
700            implicit_pi(
701                "β",
702                type1(),
703                default_pi(
704                    "a",
705                    Expr::BVar(1),
706                    default_pi(
707                        "f",
708                        arrow(Expr::BVar(2), parsec_of(Expr::BVar(4), Expr::BVar(2))),
709                        eq_expr(
710                            parsec_of(Expr::BVar(4), Expr::BVar(2)),
711                            app2(
712                                Expr::Const(Name::str("Parsec.bind"), vec![]),
713                                app(Expr::Const(Name::str("Parsec.pure"), vec![]), Expr::BVar(1)),
714                                Expr::BVar(0),
715                            ),
716                            app(Expr::BVar(0), Expr::BVar(1)),
717                        ),
718                    ),
719                ),
720            ),
721        ),
722    );
723    add_axiom(env, "Parsec.pure_bind", vec![], pure_bind_ty)?;
724    let bind_pure_ty = implicit_pi(
725        "ε",
726        type1(),
727        implicit_pi(
728            "α",
729            type1(),
730            default_pi(
731                "p",
732                parsec_of(Expr::BVar(1), Expr::BVar(0)),
733                eq_expr(
734                    parsec_of(Expr::BVar(2), Expr::BVar(1)),
735                    app2(
736                        Expr::Const(Name::str("Parsec.bind"), vec![]),
737                        Expr::BVar(0),
738                        Expr::Const(Name::str("Parsec.pure"), vec![]),
739                    ),
740                    Expr::BVar(0),
741                ),
742            ),
743        ),
744    );
745    add_axiom(env, "Parsec.bind_pure", vec![], bind_pure_ty)?;
746    let bind_assoc_ty = implicit_pi(
747        "ε",
748        type1(),
749        implicit_pi(
750            "α",
751            type1(),
752            implicit_pi(
753                "β",
754                type1(),
755                implicit_pi(
756                    "γ",
757                    type1(),
758                    default_pi(
759                        "p",
760                        parsec_of(Expr::BVar(3), Expr::BVar(2)),
761                        default_pi(
762                            "f",
763                            arrow(Expr::BVar(3), parsec_of(Expr::BVar(5), Expr::BVar(3))),
764                            default_pi(
765                                "g",
766                                arrow(Expr::BVar(3), parsec_of(Expr::BVar(6), Expr::BVar(3))),
767                                eq_expr(
768                                    parsec_of(Expr::BVar(6), Expr::BVar(3)),
769                                    app2(
770                                        Expr::Const(Name::str("Parsec.bind"), vec![]),
771                                        app2(
772                                            Expr::Const(Name::str("Parsec.bind"), vec![]),
773                                            Expr::BVar(2),
774                                            Expr::BVar(1),
775                                        ),
776                                        Expr::BVar(0),
777                                    ),
778                                    app2(
779                                        Expr::Const(Name::str("Parsec.bind"), vec![]),
780                                        Expr::BVar(2),
781                                        Expr::Const(Name::str("Parsec.bind_assoc.rhs"), vec![]),
782                                    ),
783                                ),
784                            ),
785                        ),
786                    ),
787                ),
788            ),
789        ),
790    );
791    add_axiom(env, "Parsec.bind_assoc", vec![], bind_assoc_ty)?;
792    let map_pure_ty = implicit_pi(
793        "ε",
794        type1(),
795        implicit_pi(
796            "α",
797            type1(),
798            implicit_pi(
799                "β",
800                type1(),
801                default_pi(
802                    "f",
803                    arrow(Expr::BVar(1), Expr::BVar(1)),
804                    default_pi(
805                        "a",
806                        Expr::BVar(2),
807                        eq_expr(
808                            parsec_of(Expr::BVar(4), Expr::BVar(2)),
809                            app2(
810                                Expr::Const(Name::str("Parsec.map"), vec![]),
811                                Expr::BVar(1),
812                                app(Expr::Const(Name::str("Parsec.pure"), vec![]), Expr::BVar(0)),
813                            ),
814                            app(
815                                Expr::Const(Name::str("Parsec.pure"), vec![]),
816                                app(Expr::BVar(1), Expr::BVar(0)),
817                            ),
818                        ),
819                    ),
820                ),
821            ),
822        ),
823    );
824    add_axiom(env, "Parsec.map_pure", vec![], map_pure_ty)?;
825    let map_bind_ty = implicit_pi(
826        "ε",
827        type1(),
828        implicit_pi(
829            "α",
830            type1(),
831            implicit_pi(
832                "β",
833                type1(),
834                implicit_pi(
835                    "γ",
836                    type1(),
837                    default_pi(
838                        "f",
839                        arrow(Expr::BVar(1), Expr::BVar(1)),
840                        default_pi(
841                            "p",
842                            parsec_of(Expr::BVar(4), Expr::BVar(3)),
843                            default_pi(
844                                "g",
845                                arrow(Expr::BVar(4), parsec_of(Expr::BVar(6), Expr::BVar(4))),
846                                eq_expr(
847                                    parsec_of(Expr::BVar(6), Expr::BVar(3)),
848                                    app2(
849                                        Expr::Const(Name::str("Parsec.map"), vec![]),
850                                        Expr::BVar(2),
851                                        app2(
852                                            Expr::Const(Name::str("Parsec.bind"), vec![]),
853                                            Expr::BVar(1),
854                                            Expr::BVar(0),
855                                        ),
856                                    ),
857                                    app2(
858                                        Expr::Const(Name::str("Parsec.bind"), vec![]),
859                                        Expr::BVar(1),
860                                        Expr::Const(Name::str("Parsec.map_bind.rhs"), vec![]),
861                                    ),
862                                ),
863                            ),
864                        ),
865                    ),
866                ),
867            ),
868        ),
869    );
870    add_axiom(env, "Parsec.map_bind", vec![], map_bind_ty)?;
871    let or_else_pure_left_ty = implicit_pi(
872        "ε",
873        type1(),
874        implicit_pi(
875            "α",
876            type1(),
877            default_pi(
878                "a",
879                Expr::BVar(0),
880                default_pi(
881                    "p",
882                    parsec_of(Expr::BVar(2), Expr::BVar(1)),
883                    eq_expr(
884                        parsec_of(Expr::BVar(3), Expr::BVar(2)),
885                        app2(
886                            Expr::Const(Name::str("Parsec.orElse"), vec![]),
887                            app(Expr::Const(Name::str("Parsec.pure"), vec![]), Expr::BVar(1)),
888                            Expr::BVar(0),
889                        ),
890                        app(Expr::Const(Name::str("Parsec.pure"), vec![]), Expr::BVar(1)),
891                    ),
892                ),
893            ),
894        ),
895    );
896    add_axiom(env, "Parsec.orElse_pure_left", vec![], or_else_pure_left_ty)?;
897    let or_else_fail_left_ty = implicit_pi(
898        "ε",
899        type1(),
900        implicit_pi(
901            "α",
902            type1(),
903            default_pi(
904                "e",
905                Expr::BVar(1),
906                default_pi(
907                    "p",
908                    parsec_of(Expr::BVar(2), Expr::BVar(1)),
909                    eq_expr(
910                        parsec_of(Expr::BVar(3), Expr::BVar(2)),
911                        app2(
912                            Expr::Const(Name::str("Parsec.orElse"), vec![]),
913                            app(Expr::Const(Name::str("Parsec.fail"), vec![]), Expr::BVar(1)),
914                            Expr::BVar(0),
915                        ),
916                        Expr::BVar(0),
917                    ),
918                ),
919            ),
920        ),
921    );
922    add_axiom(env, "Parsec.orElse_fail_left", vec![], or_else_fail_left_ty)?;
923    Ok(())
924}
925/// Build `ParseResult ε α` from error and value type expressions.
926#[allow(dead_code)]
927pub fn mk_parse_result(err_ty: Expr, val_ty: Expr) -> Expr {
928    parse_result_of(err_ty, val_ty)
929}
930/// Build `Parsec ε α` from error and value type expressions.
931#[allow(dead_code)]
932pub fn mk_parsec(err_ty: Expr, val_ty: Expr) -> Expr {
933    parsec_of(err_ty, val_ty)
934}
935/// Build `Parsec.pure a`.
936#[allow(dead_code)]
937pub fn mk_parsec_pure(val: Expr) -> Expr {
938    app(Expr::Const(Name::str("Parsec.pure"), vec![]), val)
939}
940/// Build `Parsec.bind p f`.
941#[allow(dead_code)]
942pub fn mk_parsec_bind(p: Expr, f: Expr) -> Expr {
943    app2(Expr::Const(Name::str("Parsec.bind"), vec![]), p, f)
944}
945/// Build `Parsec.map f p`.
946#[allow(dead_code)]
947pub fn mk_parsec_map(f: Expr, p: Expr) -> Expr {
948    app2(Expr::Const(Name::str("Parsec.map"), vec![]), f, p)
949}
950/// Build `Parsec.many p`.
951#[allow(dead_code)]
952pub fn mk_parsec_many(p: Expr) -> Expr {
953    app(Expr::Const(Name::str("Parsec.many"), vec![]), p)
954}
955/// Build `Parsec.char c`.
956#[allow(dead_code)]
957pub fn mk_parsec_char(c: Expr) -> Expr {
958    app(Expr::Const(Name::str("Parsec.char"), vec![]), c)
959}
960/// Build `Parsec.seq pf pa`.
961#[allow(dead_code)]
962pub fn mk_parsec_seq(pf: Expr, pa: Expr) -> Expr {
963    app2(Expr::Const(Name::str("Parsec.seq"), vec![]), pf, pa)
964}
965/// Build `Parsec.orElse p1 p2`.
966#[allow(dead_code)]
967pub fn mk_parsec_or_else(p1: Expr, p2: Expr) -> Expr {
968    app2(Expr::Const(Name::str("Parsec.orElse"), vec![]), p1, p2)
969}
970/// Build `Parsec.many1 p`.
971#[allow(dead_code)]
972pub fn mk_parsec_many1(p: Expr) -> Expr {
973    app(Expr::Const(Name::str("Parsec.many1"), vec![]), p)
974}
975/// Build `Parsec.optional p`.
976#[allow(dead_code)]
977pub fn mk_parsec_optional(p: Expr) -> Expr {
978    app(Expr::Const(Name::str("Parsec.optional"), vec![]), p)
979}
980/// Build `Parsec.sepBy p sep`.
981#[allow(dead_code)]
982pub fn mk_parsec_sep_by(p: Expr, sep: Expr) -> Expr {
983    app2(Expr::Const(Name::str("Parsec.sepBy"), vec![]), p, sep)
984}
985/// Build `Parsec.between open close p`.
986#[allow(dead_code)]
987pub fn mk_parsec_between(open: Expr, close: Expr, p: Expr) -> Expr {
988    app3(
989        Expr::Const(Name::str("Parsec.between"), vec![]),
990        open,
991        close,
992        p,
993    )
994}
995/// Build `Parsec.token p`.
996#[allow(dead_code)]
997pub fn mk_parsec_token(p: Expr) -> Expr {
998    app(Expr::Const(Name::str("Parsec.token"), vec![]), p)
999}
1000/// Build `Parsec.symbol s`.
1001#[allow(dead_code)]
1002pub fn mk_parsec_symbol(s: Expr) -> Expr {
1003    app(Expr::Const(Name::str("Parsec.symbol"), vec![]), s)
1004}
1005/// Build `Parsec.run p s`.
1006#[allow(dead_code)]
1007pub fn mk_parsec_run(p: Expr, s: Expr) -> Expr {
1008    app2(Expr::Const(Name::str("Parsec.run"), vec![]), p, s)
1009}
1010/// Build `Parsec.fail e`.
1011#[allow(dead_code)]
1012pub fn mk_parsec_fail(e: Expr) -> Expr {
1013    app(Expr::Const(Name::str("Parsec.fail"), vec![]), e)
1014}
1015/// Build `Parsec.string s`.
1016#[allow(dead_code)]
1017pub fn mk_parsec_string(s: Expr) -> Expr {
1018    app(Expr::Const(Name::str("Parsec.string"), vec![]), s)
1019}
1020/// Build `Parsec.satisfy pred`.
1021#[allow(dead_code)]
1022pub fn mk_parsec_satisfy(pred: Expr) -> Expr {
1023    app(Expr::Const(Name::str("Parsec.satisfy"), vec![]), pred)
1024}
1025/// Build `Parsec.lookahead p`.
1026#[allow(dead_code)]
1027pub fn mk_parsec_lookahead(p: Expr) -> Expr {
1028    app(Expr::Const(Name::str("Parsec.lookahead"), vec![]), p)
1029}
1030/// Build `Parsec.notFollowedBy p`.
1031#[allow(dead_code)]
1032pub fn mk_parsec_not_followed_by(p: Expr) -> Expr {
1033    app(Expr::Const(Name::str("Parsec.notFollowedBy"), vec![]), p)
1034}
1035/// Build `Parsec.chainl p op def`.
1036#[allow(dead_code)]
1037pub fn mk_parsec_chainl(p: Expr, op: Expr, def: Expr) -> Expr {
1038    app3(Expr::Const(Name::str("Parsec.chainl"), vec![]), p, op, def)
1039}
1040/// Build `Parsec.chainr p op def`.
1041#[allow(dead_code)]
1042pub fn mk_parsec_chainr(p: Expr, op: Expr, def: Expr) -> Expr {
1043    app3(Expr::Const(Name::str("Parsec.chainr"), vec![]), p, op, def)
1044}
1045#[cfg(test)]
1046mod tests {
1047    use super::*;
1048    fn make_env() -> Environment {
1049        let mut env = Environment::new();
1050        build_parsec_env(&mut env).expect("build_parsec_env should succeed");
1051        env
1052    }
1053    #[test]
1054    fn test_build_parsec_env_succeeds() {
1055        let mut env = Environment::new();
1056        assert!(build_parsec_env(&mut env).is_ok());
1057    }
1058    #[test]
1059    fn test_parse_result_exists() {
1060        let env = make_env();
1061        assert!(env.get(&Name::str("ParseResult")).is_some());
1062    }
1063    #[test]
1064    fn test_parse_result_success_exists() {
1065        let env = make_env();
1066        assert!(env.get(&Name::str("ParseResult.success")).is_some());
1067    }
1068    #[test]
1069    fn test_parse_result_error_exists() {
1070        let env = make_env();
1071        assert!(env.get(&Name::str("ParseResult.error")).is_some());
1072    }
1073    #[test]
1074    fn test_parsec_type_exists() {
1075        let env = make_env();
1076        assert!(env.get(&Name::str("Parsec")).is_some());
1077    }
1078    #[test]
1079    fn test_parsec_run_exists() {
1080        let env = make_env();
1081        assert!(env.get(&Name::str("Parsec.run")).is_some());
1082    }
1083    #[test]
1084    fn test_parsec_pure_type_is_pi() {
1085        let env = make_env();
1086        let decl = env
1087            .get(&Name::str("Parsec.pure"))
1088            .expect("declaration 'Parsec.pure' should exist in env");
1089        assert!(decl.ty().is_pi());
1090    }
1091    #[test]
1092    fn test_parsec_fail_type_is_pi() {
1093        let env = make_env();
1094        let decl = env
1095            .get(&Name::str("Parsec.fail"))
1096            .expect("declaration 'Parsec.fail' should exist in env");
1097        assert!(decl.ty().is_pi());
1098    }
1099    #[test]
1100    fn test_parsec_bind_type_is_pi() {
1101        let env = make_env();
1102        let decl = env
1103            .get(&Name::str("Parsec.bind"))
1104            .expect("declaration 'Parsec.bind' should exist in env");
1105        assert!(decl.ty().is_pi());
1106    }
1107    #[test]
1108    fn test_parsec_map_type_is_pi() {
1109        let env = make_env();
1110        let decl = env
1111            .get(&Name::str("Parsec.map"))
1112            .expect("declaration 'Parsec.map' should exist in env");
1113        assert!(decl.ty().is_pi());
1114    }
1115    #[test]
1116    fn test_parsec_seq_type_is_pi() {
1117        let env = make_env();
1118        let decl = env
1119            .get(&Name::str("Parsec.seq"))
1120            .expect("declaration 'Parsec.seq' should exist in env");
1121        assert!(decl.ty().is_pi());
1122    }
1123    #[test]
1124    fn test_parsec_or_else_type_is_pi() {
1125        let env = make_env();
1126        let decl = env
1127            .get(&Name::str("Parsec.orElse"))
1128            .expect("declaration 'Parsec.orElse' should exist in env");
1129        assert!(decl.ty().is_pi());
1130    }
1131    #[test]
1132    fn test_parsec_any_exists() {
1133        let env = make_env();
1134        assert!(env.get(&Name::str("Parsec.any")).is_some());
1135    }
1136    #[test]
1137    fn test_parsec_satisfy_exists() {
1138        let env = make_env();
1139        assert!(env.get(&Name::str("Parsec.satisfy")).is_some());
1140    }
1141    #[test]
1142    fn test_parsec_char_exists() {
1143        let env = make_env();
1144        assert!(env.get(&Name::str("Parsec.char")).is_some());
1145    }
1146    #[test]
1147    fn test_parsec_digit_exists() {
1148        let env = make_env();
1149        assert!(env.get(&Name::str("Parsec.digit")).is_some());
1150    }
1151    #[test]
1152    fn test_parsec_alpha_exists() {
1153        let env = make_env();
1154        assert!(env.get(&Name::str("Parsec.alpha")).is_some());
1155    }
1156    #[test]
1157    fn test_parsec_alpha_num_exists() {
1158        let env = make_env();
1159        assert!(env.get(&Name::str("Parsec.alphaNum")).is_some());
1160    }
1161    #[test]
1162    fn test_parsec_ws_exists() {
1163        let env = make_env();
1164        assert!(env.get(&Name::str("Parsec.ws")).is_some());
1165    }
1166    #[test]
1167    fn test_parsec_string_exists() {
1168        let env = make_env();
1169        assert!(env.get(&Name::str("Parsec.string")).is_some());
1170    }
1171    #[test]
1172    fn test_parsec_eof_exists() {
1173        let env = make_env();
1174        assert!(env.get(&Name::str("Parsec.eof")).is_some());
1175    }
1176    #[test]
1177    fn test_parsec_many_exists() {
1178        let env = make_env();
1179        assert!(env.get(&Name::str("Parsec.many")).is_some());
1180    }
1181    #[test]
1182    fn test_parsec_many1_exists() {
1183        let env = make_env();
1184        assert!(env.get(&Name::str("Parsec.many1")).is_some());
1185    }
1186    #[test]
1187    fn test_parsec_optional_exists() {
1188        let env = make_env();
1189        assert!(env.get(&Name::str("Parsec.optional")).is_some());
1190    }
1191    #[test]
1192    fn test_parsec_sep_by_exists() {
1193        let env = make_env();
1194        assert!(env.get(&Name::str("Parsec.sepBy")).is_some());
1195    }
1196    #[test]
1197    fn test_parsec_sep_by1_exists() {
1198        let env = make_env();
1199        assert!(env.get(&Name::str("Parsec.sepBy1")).is_some());
1200    }
1201    #[test]
1202    fn test_parsec_between_exists() {
1203        let env = make_env();
1204        assert!(env.get(&Name::str("Parsec.between")).is_some());
1205    }
1206    #[test]
1207    fn test_parsec_not_followed_by_exists() {
1208        let env = make_env();
1209        assert!(env.get(&Name::str("Parsec.notFollowedBy")).is_some());
1210    }
1211    #[test]
1212    fn test_parsec_lookahead_exists() {
1213        let env = make_env();
1214        assert!(env.get(&Name::str("Parsec.lookahead")).is_some());
1215    }
1216    #[test]
1217    fn test_parsec_chainl_exists() {
1218        let env = make_env();
1219        assert!(env.get(&Name::str("Parsec.chainl")).is_some());
1220    }
1221    #[test]
1222    fn test_parsec_chainr_exists() {
1223        let env = make_env();
1224        assert!(env.get(&Name::str("Parsec.chainr")).is_some());
1225    }
1226    #[test]
1227    fn test_parsec_nat_exists() {
1228        let env = make_env();
1229        assert!(env.get(&Name::str("Parsec.nat")).is_some());
1230    }
1231    #[test]
1232    fn test_parsec_int_exists() {
1233        let env = make_env();
1234        assert!(env.get(&Name::str("Parsec.int")).is_some());
1235    }
1236    #[test]
1237    fn test_parsec_hex_digit_exists() {
1238        let env = make_env();
1239        assert!(env.get(&Name::str("Parsec.hexDigit")).is_some());
1240    }
1241    #[test]
1242    fn test_parsec_hex_nat_exists() {
1243        let env = make_env();
1244        assert!(env.get(&Name::str("Parsec.hexNat")).is_some());
1245    }
1246    #[test]
1247    fn test_parsec_token_exists() {
1248        let env = make_env();
1249        assert!(env.get(&Name::str("Parsec.token")).is_some());
1250    }
1251    #[test]
1252    fn test_parsec_symbol_exists() {
1253        let env = make_env();
1254        assert!(env.get(&Name::str("Parsec.symbol")).is_some());
1255    }
1256    #[test]
1257    fn test_parsec_pure_bind_exists() {
1258        let env = make_env();
1259        assert!(env.get(&Name::str("Parsec.pure_bind")).is_some());
1260    }
1261    #[test]
1262    fn test_parsec_bind_pure_exists() {
1263        let env = make_env();
1264        assert!(env.get(&Name::str("Parsec.bind_pure")).is_some());
1265    }
1266    #[test]
1267    fn test_parsec_bind_assoc_exists() {
1268        let env = make_env();
1269        assert!(env.get(&Name::str("Parsec.bind_assoc")).is_some());
1270    }
1271    #[test]
1272    fn test_parsec_map_pure_exists() {
1273        let env = make_env();
1274        assert!(env.get(&Name::str("Parsec.map_pure")).is_some());
1275    }
1276    #[test]
1277    fn test_parsec_map_bind_exists() {
1278        let env = make_env();
1279        assert!(env.get(&Name::str("Parsec.map_bind")).is_some());
1280    }
1281    #[test]
1282    fn test_parsec_or_else_pure_left_exists() {
1283        let env = make_env();
1284        assert!(env.get(&Name::str("Parsec.orElse_pure_left")).is_some());
1285    }
1286    #[test]
1287    fn test_parsec_or_else_fail_left_exists() {
1288        let env = make_env();
1289        assert!(env.get(&Name::str("Parsec.orElse_fail_left")).is_some());
1290    }
1291    #[test]
1292    fn test_mk_parse_result() {
1293        let r = mk_parse_result(string_ty(), nat_ty());
1294        assert!(matches!(r, Expr::App(_, _)));
1295    }
1296    #[test]
1297    fn test_mk_parsec() {
1298        let p = mk_parsec(string_ty(), nat_ty());
1299        assert!(matches!(p, Expr::App(_, _)));
1300    }
1301    #[test]
1302    fn test_mk_parsec_pure() {
1303        let p = mk_parsec_pure(Expr::Const(Name::str("x"), vec![]));
1304        assert!(matches!(p, Expr::App(_, _)));
1305    }
1306    #[test]
1307    fn test_mk_parsec_bind() {
1308        let p = mk_parsec_bind(
1309            Expr::Const(Name::str("p"), vec![]),
1310            Expr::Const(Name::str("f"), vec![]),
1311        );
1312        assert!(matches!(p, Expr::App(_, _)));
1313    }
1314    #[test]
1315    fn test_mk_parsec_map() {
1316        let m = mk_parsec_map(
1317            Expr::Const(Name::str("f"), vec![]),
1318            Expr::Const(Name::str("p"), vec![]),
1319        );
1320        assert!(matches!(m, Expr::App(_, _)));
1321    }
1322    #[test]
1323    fn test_mk_parsec_many() {
1324        let m = mk_parsec_many(Expr::Const(Name::str("p"), vec![]));
1325        assert!(matches!(m, Expr::App(_, _)));
1326    }
1327    #[test]
1328    fn test_mk_parsec_char() {
1329        let c = mk_parsec_char(Expr::Const(Name::str("c"), vec![]));
1330        assert!(matches!(c, Expr::App(_, _)));
1331    }
1332    #[test]
1333    fn test_all_declarations_are_axioms() {
1334        let env = make_env();
1335        for name in [
1336            "ParseResult",
1337            "ParseResult.success",
1338            "ParseResult.error",
1339            "Parsec",
1340            "Parsec.run",
1341            "Parsec.pure",
1342            "Parsec.fail",
1343            "Parsec.bind",
1344            "Parsec.map",
1345            "Parsec.seq",
1346            "Parsec.orElse",
1347            "Parsec.any",
1348            "Parsec.satisfy",
1349            "Parsec.char",
1350            "Parsec.digit",
1351            "Parsec.alpha",
1352            "Parsec.alphaNum",
1353            "Parsec.ws",
1354            "Parsec.string",
1355            "Parsec.eof",
1356            "Parsec.many",
1357            "Parsec.many1",
1358            "Parsec.optional",
1359            "Parsec.sepBy",
1360            "Parsec.sepBy1",
1361            "Parsec.between",
1362            "Parsec.notFollowedBy",
1363            "Parsec.lookahead",
1364            "Parsec.chainl",
1365            "Parsec.chainr",
1366            "Parsec.nat",
1367            "Parsec.int",
1368            "Parsec.hexDigit",
1369            "Parsec.hexNat",
1370            "Parsec.token",
1371            "Parsec.symbol",
1372        ] {
1373            let decl = env.get(&Name::str(name)).expect("operation should succeed");
1374            assert!(
1375                matches!(decl, Declaration::Axiom { .. }),
1376                "{} should be an axiom",
1377                name
1378            );
1379        }
1380    }
1381    #[test]
1382    fn test_env_declaration_count() {
1383        let env = make_env();
1384        assert!(env.len() >= 40);
1385    }
1386    #[test]
1387    fn test_mk_parsec_seq_is_app() {
1388        let s = mk_parsec_seq(
1389            Expr::Const(Name::str("pf"), vec![]),
1390            Expr::Const(Name::str("pa"), vec![]),
1391        );
1392        assert!(matches!(s, Expr::App(_, _)));
1393    }
1394    #[test]
1395    fn test_mk_parsec_or_else_is_app() {
1396        let o = mk_parsec_or_else(
1397            Expr::Const(Name::str("p1"), vec![]),
1398            Expr::Const(Name::str("p2"), vec![]),
1399        );
1400        assert!(matches!(o, Expr::App(_, _)));
1401    }
1402    #[test]
1403    fn test_mk_parsec_run_is_app() {
1404        let r = mk_parsec_run(
1405            Expr::Const(Name::str("p"), vec![]),
1406            Expr::Const(Name::str("s"), vec![]),
1407        );
1408        assert!(matches!(r, Expr::App(_, _)));
1409    }
1410    #[test]
1411    fn test_mk_parsec_between_is_app() {
1412        let b = mk_parsec_between(
1413            Expr::Const(Name::str("open"), vec![]),
1414            Expr::Const(Name::str("close"), vec![]),
1415            Expr::Const(Name::str("p"), vec![]),
1416        );
1417        assert!(matches!(b, Expr::App(_, _)));
1418    }
1419    #[test]
1420    fn test_mk_parsec_chainl_is_app() {
1421        let c = mk_parsec_chainl(
1422            Expr::Const(Name::str("p"), vec![]),
1423            Expr::Const(Name::str("op"), vec![]),
1424            Expr::Const(Name::str("def"), vec![]),
1425        );
1426        assert!(matches!(c, Expr::App(_, _)));
1427    }
1428    #[test]
1429    fn test_mk_parsec_fail_is_app() {
1430        let f = mk_parsec_fail(Expr::Const(Name::str("e"), vec![]));
1431        assert!(matches!(f, Expr::App(_, _)));
1432    }
1433    #[test]
1434    fn test_mk_parsec_string_is_app() {
1435        let s = mk_parsec_string(Expr::Const(Name::str("s"), vec![]));
1436        assert!(matches!(s, Expr::App(_, _)));
1437    }
1438    #[test]
1439    fn test_mk_parsec_satisfy_is_app() {
1440        let s = mk_parsec_satisfy(Expr::Const(Name::str("pred"), vec![]));
1441        assert!(matches!(s, Expr::App(_, _)));
1442    }
1443    #[test]
1444    fn test_mk_parsec_lookahead_is_app() {
1445        let l = mk_parsec_lookahead(Expr::Const(Name::str("p"), vec![]));
1446        assert!(matches!(l, Expr::App(_, _)));
1447    }
1448}
1449/// ContextFreeGrammar: (N, Σ, P, S) — context-free grammar
1450#[allow(dead_code)]
1451pub fn prs_ext_cfg_ty() -> Expr {
1452    type1()
1453}
1454/// CfgNonterminal: a nonterminal symbol
1455#[allow(dead_code)]
1456pub fn prs_ext_cfg_nonterminal_ty() -> Expr {
1457    type1()
1458}
1459/// CfgTerminal: a terminal symbol
1460#[allow(dead_code)]
1461pub fn prs_ext_cfg_terminal_ty() -> Expr {
1462    type1()
1463}
1464/// CfgProduction: A → α, a production rule
1465#[allow(dead_code)]
1466pub fn prs_ext_cfg_production_ty() -> Expr {
1467    type1()
1468}
1469/// CfgDerivation: A ⇒* w — derivation in zero or more steps
1470#[allow(dead_code)]
1471pub fn prs_ext_cfg_derivation_ty() -> Expr {
1472    arrow(
1473        Expr::Const(Name::str("CfgNonterminal"), vec![]),
1474        arrow(
1475            list_of(Expr::Const(Name::str("CfgTerminal"), vec![])),
1476            prop(),
1477        ),
1478    )
1479}
1480/// CfgLanguage: L(G) = {w ∈ Σ* | S ⇒* w}
1481#[allow(dead_code)]
1482pub fn prs_ext_cfg_language_ty() -> Expr {
1483    arrow(
1484        Expr::Const(Name::str("ContextFreeGrammar"), vec![]),
1485        arrow(
1486            list_of(Expr::Const(Name::str("CfgTerminal"), vec![])),
1487            prop(),
1488        ),
1489    )
1490}
1491/// FirstSet: FIRST(A) = {a ∈ Σ | A ⇒* aα} ∪ (ε if A ⇒* ε)
1492#[allow(dead_code)]
1493pub fn prs_ext_first_set_ty() -> Expr {
1494    arrow(
1495        Expr::Const(Name::str("CfgNonterminal"), vec![]),
1496        list_of(option_of(Expr::Const(Name::str("CfgTerminal"), vec![]))),
1497    )
1498}
1499/// FollowSet: FOLLOW(A) = {a ∈ Σ ∪ {$} | S ⇒* αAaβ}
1500#[allow(dead_code)]
1501pub fn prs_ext_follow_set_ty() -> Expr {
1502    arrow(
1503        Expr::Const(Name::str("CfgNonterminal"), vec![]),
1504        list_of(option_of(Expr::Const(Name::str("CfgTerminal"), vec![]))),
1505    )
1506}
1507/// FirstSetCorrectness: a ∈ FIRST(A) ↔ A ⇒* aα for some α
1508#[allow(dead_code)]
1509pub fn prs_ext_first_set_correct_ty() -> Expr {
1510    arrow(
1511        Expr::Const(Name::str("ContextFreeGrammar"), vec![]),
1512        arrow(Expr::Const(Name::str("CfgNonterminal"), vec![]), prop()),
1513    )
1514}
1515/// FollowSetCorrectness: a ∈ FOLLOW(A) ↔ S ⇒* αAaβ for some α,β
1516#[allow(dead_code)]
1517pub fn prs_ext_follow_set_correct_ty() -> Expr {
1518    arrow(
1519        Expr::Const(Name::str("ContextFreeGrammar"), vec![]),
1520        arrow(Expr::Const(Name::str("CfgNonterminal"), vec![]), prop()),
1521    )
1522}
1523/// LlkGrammar: a grammar that is LL(k) — left-to-right, leftmost derivation, k tokens lookahead
1524#[allow(dead_code)]
1525pub fn prs_ext_llk_grammar_ty() -> Expr {
1526    arrow(
1527        nat_ty(),
1528        arrow(Expr::Const(Name::str("ContextFreeGrammar"), vec![]), prop()),
1529    )
1530}
1531/// LlkParsingTable: the LL(k) parsing table M[A, w] → production
1532#[allow(dead_code)]
1533pub fn prs_ext_llk_table_ty() -> Expr {
1534    arrow(
1535        Expr::Const(Name::str("ContextFreeGrammar"), vec![]),
1536        arrow(nat_ty(), Expr::Const(Name::str("LlkTable"), vec![])),
1537    )
1538}
1539/// LlkCorrectness: LL(k) parser accepts w ↔ w ∈ L(G)
1540#[allow(dead_code)]
1541pub fn prs_ext_llk_correct_ty() -> Expr {
1542    arrow(
1543        Expr::Const(Name::str("ContextFreeGrammar"), vec![]),
1544        arrow(
1545            list_of(Expr::Const(Name::str("CfgTerminal"), vec![])),
1546            prop(),
1547        ),
1548    )
1549}
1550/// LlkDeterminism: LL(k) grammars admit deterministic top-down parsing
1551#[allow(dead_code)]
1552pub fn prs_ext_llk_determinism_ty() -> Expr {
1553    arrow(
1554        Expr::Const(Name::str("ContextFreeGrammar"), vec![]),
1555        arrow(nat_ty(), prop()),
1556    )
1557}
1558/// EarleyItem: (A → α • β, i) — a dotted rule at position i
1559#[allow(dead_code)]
1560pub fn prs_ext_earley_item_ty() -> Expr {
1561    type1()
1562}
1563/// EarleyChart: array of Earley item sets S_0, ..., S_n
1564#[allow(dead_code)]
1565pub fn prs_ext_earley_chart_ty() -> Expr {
1566    type1()
1567}
1568/// EarleyCompleteness: Earley parser recognizes all context-free languages
1569#[allow(dead_code)]
1570pub fn prs_ext_earley_completeness_ty() -> Expr {
1571    arrow(
1572        Expr::Const(Name::str("ContextFreeGrammar"), vec![]),
1573        arrow(
1574            list_of(Expr::Const(Name::str("CfgTerminal"), vec![])),
1575            prop(),
1576        ),
1577    )
1578}
1579/// EarleySoundness: Earley parser accepts w ↔ w ∈ L(G)
1580#[allow(dead_code)]
1581pub fn prs_ext_earley_soundness_ty() -> Expr {
1582    arrow(Expr::Const(Name::str("ContextFreeGrammar"), vec![]), prop())
1583}
1584/// CykAlgorithm: CYK recognizes context-free languages in O(n³ |G|)
1585#[allow(dead_code)]
1586pub fn prs_ext_cyk_ty() -> Expr {
1587    arrow(
1588        Expr::Const(Name::str("ContextFreeGrammar"), vec![]),
1589        arrow(
1590            list_of(Expr::Const(Name::str("CfgTerminal"), vec![])),
1591            bool_ty(),
1592        ),
1593    )
1594}
1595/// CykCorrectness: CYK returns true ↔ w ∈ L(G)
1596#[allow(dead_code)]
1597pub fn prs_ext_cyk_correct_ty() -> Expr {
1598    arrow(
1599        Expr::Const(Name::str("ContextFreeGrammar"), vec![]),
1600        arrow(
1601            list_of(Expr::Const(Name::str("CfgTerminal"), vec![])),
1602            prop(),
1603        ),
1604    )
1605}
1606/// ChomskyNormalForm: every CFG can be converted to CNF
1607#[allow(dead_code)]
1608pub fn prs_ext_cnf_ty() -> Expr {
1609    arrow(
1610        Expr::Const(Name::str("ContextFreeGrammar"), vec![]),
1611        Expr::Const(Name::str("ContextFreeGrammar"), vec![]),
1612    )
1613}
1614/// CnfEquivalence: CNF(G) generates the same language as G (minus ε)
1615#[allow(dead_code)]
1616pub fn prs_ext_cnf_equiv_ty() -> Expr {
1617    arrow(Expr::Const(Name::str("ContextFreeGrammar"), vec![]), prop())
1618}
1619/// PegExpr: a parsing expression (ordered choice, sequence, Kleene*, etc.)
1620#[allow(dead_code)]
1621pub fn prs_ext_peg_expr_ty() -> Expr {
1622    type1()
1623}
1624/// PegResult: result of applying a PEG expression to a string
1625#[allow(dead_code)]
1626pub fn prs_ext_peg_result_ty() -> Expr {
1627    type1()
1628}
1629/// PegSemantics: ⟦e⟧(x) — denotational semantics of PEG expression e on input x
1630#[allow(dead_code)]
1631pub fn prs_ext_peg_semantics_ty() -> Expr {
1632    arrow(
1633        Expr::Const(Name::str("PegExpr"), vec![]),
1634        arrow(string_ty(), Expr::Const(Name::str("PegResult"), vec![])),
1635    )
1636}
1637/// PegOrderedChoice: e1 / e2 — try e1, if it fails try e2
1638#[allow(dead_code)]
1639pub fn prs_ext_peg_ordered_choice_ty() -> Expr {
1640    arrow(
1641        Expr::Const(Name::str("PegExpr"), vec![]),
1642        arrow(
1643            Expr::Const(Name::str("PegExpr"), vec![]),
1644            Expr::Const(Name::str("PegExpr"), vec![]),
1645        ),
1646    )
1647}
1648/// PegStar: e* — zero or more matches of e (greedy)
1649#[allow(dead_code)]
1650pub fn prs_ext_peg_star_ty() -> Expr {
1651    arrow(
1652        Expr::Const(Name::str("PegExpr"), vec![]),
1653        Expr::Const(Name::str("PegExpr"), vec![]),
1654    )
1655}
1656/// PegNot: !e — negative lookahead
1657#[allow(dead_code)]
1658pub fn prs_ext_peg_not_ty() -> Expr {
1659    arrow(
1660        Expr::Const(Name::str("PegExpr"), vec![]),
1661        Expr::Const(Name::str("PegExpr"), vec![]),
1662    )
1663}
1664/// PegDeterminism: PEG parsing is deterministic (no ambiguity by definition)
1665#[allow(dead_code)]
1666pub fn prs_ext_peg_determinism_ty() -> Expr {
1667    arrow(Expr::Const(Name::str("PegExpr"), vec![]), prop())
1668}
1669/// PackratMemo: memoization table for packrat parsing
1670#[allow(dead_code)]
1671pub fn prs_ext_packrat_memo_ty() -> Expr {
1672    type1()
1673}
1674/// PackratParsing: memoized recursive descent for PEGs in linear time
1675#[allow(dead_code)]
1676pub fn prs_ext_packrat_ty() -> Expr {
1677    arrow(
1678        Expr::Const(Name::str("PegExpr"), vec![]),
1679        arrow(
1680            string_ty(),
1681            arrow(
1682                Expr::Const(Name::str("PackratMemo"), vec![]),
1683                option_of(nat_ty()),
1684            ),
1685        ),
1686    )
1687}
1688/// PackratCorrectness: packrat produces the same result as naive PEG matching
1689#[allow(dead_code)]
1690pub fn prs_ext_packrat_correct_ty() -> Expr {
1691    arrow(
1692        Expr::Const(Name::str("PegExpr"), vec![]),
1693        arrow(string_ty(), prop()),
1694    )
1695}
1696/// PackratComplexity: packrat parsing is O(n) in input length
1697#[allow(dead_code)]
1698pub fn prs_ext_packrat_linear_ty() -> Expr {
1699    arrow(
1700        Expr::Const(Name::str("PegExpr"), vec![]),
1701        arrow(nat_ty(), prop()),
1702    )
1703}
1704/// LeftFactoring: transform G to remove common prefixes
1705#[allow(dead_code)]
1706pub fn prs_ext_left_factoring_ty() -> Expr {
1707    arrow(
1708        Expr::Const(Name::str("ContextFreeGrammar"), vec![]),
1709        Expr::Const(Name::str("ContextFreeGrammar"), vec![]),
1710    )
1711}
1712/// LeftRecursionElimination: remove left recursion from a CFG
1713#[allow(dead_code)]
1714pub fn prs_ext_left_rec_elim_ty() -> Expr {
1715    arrow(
1716        Expr::Const(Name::str("ContextFreeGrammar"), vec![]),
1717        Expr::Const(Name::str("ContextFreeGrammar"), vec![]),
1718    )
1719}
1720/// GreibachNormalForm: every CFG can be put in GNF (productions start with terminals)
1721#[allow(dead_code)]
1722pub fn prs_ext_gnf_ty() -> Expr {
1723    arrow(
1724        Expr::Const(Name::str("ContextFreeGrammar"), vec![]),
1725        Expr::Const(Name::str("ContextFreeGrammar"), vec![]),
1726    )
1727}
1728/// GreibachEquivalence: GNF(G) has the same language as G
1729#[allow(dead_code)]
1730pub fn prs_ext_gnf_equiv_ty() -> Expr {
1731    arrow(Expr::Const(Name::str("ContextFreeGrammar"), vec![]), prop())
1732}
1733/// ParserSemanticsDenotation: ⟦p⟧ : String → List (α × String)
1734#[allow(dead_code)]
1735pub fn prs_ext_parser_denotation_ty() -> Expr {
1736    arrow(string_ty(), list_of(type1()))
1737}
1738/// ParserFunctorLaw: map id p = p
1739#[allow(dead_code)]
1740pub fn prs_ext_functor_law_id_ty() -> Expr {
1741    arrow(parsec_of(type1(), type1()), prop())
1742}
1743/// ParserFunctorCompose: map (f ∘ g) p = map f (map g p)
1744#[allow(dead_code)]
1745pub fn prs_ext_functor_compose_ty() -> Expr {
1746    arrow(
1747        parsec_of(type1(), type1()),
1748        arrow(type1(), arrow(type1(), prop())),
1749    )
1750}
1751/// ParserApplicativeLaw: pure f <*> pure x = pure (f x)
1752#[allow(dead_code)]
1753pub fn prs_ext_applicative_law_ty() -> Expr {
1754    arrow(parsec_of(type1(), type1()), prop())
1755}
1756/// ParserAlternativeLaw: fail <|> p = p and p <|> fail = p
1757#[allow(dead_code)]
1758pub fn prs_ext_alternative_law_ty() -> Expr {
1759    arrow(parsec_of(type1(), type1()), prop())
1760}
1761/// ParserMonadLeftId: pure a >>= f = f a
1762#[allow(dead_code)]
1763pub fn prs_ext_monad_left_id_ty() -> Expr {
1764    arrow(
1765        type1(),
1766        arrow(arrow(type1(), parsec_of(type1(), type1())), prop()),
1767    )
1768}
1769/// ParserMonadRightId: p >>= pure = p
1770#[allow(dead_code)]
1771pub fn prs_ext_monad_right_id_ty() -> Expr {
1772    arrow(parsec_of(type1(), type1()), prop())
1773}
1774/// ParserMonadAssoc: (p >>= f) >>= g = p >>= (λa. f a >>= g)
1775#[allow(dead_code)]
1776pub fn prs_ext_monad_assoc_ty() -> Expr {
1777    arrow(
1778        parsec_of(type1(), type1()),
1779        arrow(
1780            arrow(type1(), parsec_of(type1(), type1())),
1781            arrow(arrow(type1(), parsec_of(type1(), type1())), prop()),
1782        ),
1783    )
1784}
1785/// ErrorRecovery: a parser with error recovery capabilities
1786#[allow(dead_code)]
1787pub fn prs_ext_error_recovery_ty() -> Expr {
1788    arrow(
1789        parsec_of(string_ty(), type1()),
1790        parsec_of(string_ty(), type1()),
1791    )
1792}
1793/// SynchronizationSet: set of tokens used for error recovery
1794#[allow(dead_code)]
1795pub fn prs_ext_sync_set_ty() -> Expr {
1796    list_of(char_ty())
1797}
1798/// PrettyPrint: pretty printer as an inverse of parsing
1799#[allow(dead_code)]
1800pub fn prs_ext_pretty_print_ty() -> Expr {
1801    arrow(type1(), string_ty())
1802}
1803/// PrettyPrintRoundtrip: parse (pretty_print x) = Some x
1804#[allow(dead_code)]
1805pub fn prs_ext_pretty_roundtrip_ty() -> Expr {
1806    arrow(type1(), prop())
1807}
1808/// IncrementalParsing: update parse result given a text edit
1809#[allow(dead_code)]
1810pub fn prs_ext_incremental_parse_ty() -> Expr {
1811    arrow(
1812        parsec_of(string_ty(), type1()),
1813        arrow(
1814            string_ty(),
1815            arrow(nat_ty(), parsec_of(string_ty(), type1())),
1816        ),
1817    )
1818}
1819/// TotalParser: a parser guaranteed to terminate on all inputs
1820#[allow(dead_code)]
1821pub fn prs_ext_total_parser_ty() -> Expr {
1822    arrow(parsec_of(string_ty(), type1()), prop())
1823}
1824/// WellFoundedInput: every recursive call is on strictly shorter input
1825#[allow(dead_code)]
1826pub fn prs_ext_well_founded_input_ty() -> Expr {
1827    arrow(parsec_of(string_ty(), type1()), prop())
1828}
1829/// TerminationProof: well-founded recursion ensures total parser terminates
1830#[allow(dead_code)]
1831pub fn prs_ext_termination_proof_ty() -> Expr {
1832    arrow(parsec_of(string_ty(), type1()), arrow(string_ty(), prop()))
1833}
1834/// Derivative: ∂_c L — Brzozowski derivative of language L w.r.t. character c
1835#[allow(dead_code)]
1836pub fn prs_ext_derivative_ty() -> Expr {
1837    arrow(
1838        parsec_of(string_ty(), type1()),
1839        arrow(char_ty(), parsec_of(string_ty(), type1())),
1840    )
1841}
1842/// DerivativeSemantics: ⟦∂_c p⟧(s) = ⟦p⟧(cs)
1843#[allow(dead_code)]
1844pub fn prs_ext_deriv_semantics_ty() -> Expr {
1845    arrow(parsec_of(string_ty(), type1()), arrow(char_ty(), prop()))
1846}
1847/// DerivativeCompaction: compact representation of Brzozowski derivatives
1848#[allow(dead_code)]
1849pub fn prs_ext_deriv_compact_ty() -> Expr {
1850    arrow(
1851        parsec_of(string_ty(), type1()),
1852        parsec_of(string_ty(), type1()),
1853    )
1854}