graphix_compiler/expr/parser/
mod.rs

1use crate::{
2    expr::{
3        get_origin, set_origin, Arg, Bind, Expr, ExprId, ExprKind, Lambda, ModPath,
4        ModuleKind, Origin, Pattern, Sandbox, Sig, SigItem, StructurePattern, TryCatch,
5        TypeDef,
6    },
7    typ::{FnArgType, FnType, TVar, Type},
8};
9use anyhow::{bail, Result};
10use arcstr::{literal, ArcStr};
11use combine::{
12    attempt, between, chainl1, choice, eof, look_ahead, many, many1, none_of,
13    not_followed_by, optional,
14    parser::{
15        char::{alpha_num, digit, space, string},
16        combinator::recognize,
17        range::{take_while, take_while1},
18    },
19    position, sep_by, sep_by1, skip_many,
20    stream::{
21        position::{self, SourcePosition},
22        Range,
23    },
24    token, unexpected_any, value, EasyParser, ParseError, Parser, RangeStream,
25};
26use compact_str::CompactString;
27use escaping::Escape;
28use fxhash::FxHashSet;
29use netidx::{
30    path::Path,
31    publisher::{Typ, Value},
32    utils::Either,
33};
34use netidx_value::parser::{
35    escaped_string, int, value as parse_value, VAL_ESC, VAL_MUST_ESC,
36};
37use parking_lot::RwLock;
38use poolshark::local::LPooled;
39use std::sync::LazyLock;
40use triomphe::Arc;
41
42#[cfg(test)]
43mod test;
44
45fn escape_generic(c: char) -> bool {
46    c.is_control()
47}
48
49pub const GRAPHIX_MUST_ESC: [char; 4] = ['"', '\\', '[', ']'];
50pub static GRAPHIX_ESC: LazyLock<Escape> = LazyLock::new(|| {
51    Escape::new(
52        '\\',
53        &['"', '\\', '[', ']', '\n', '\r', '\t', '\0'],
54        &[('\n', "n"), ('\r', "r"), ('\t', "t"), ('\0', "0")],
55        Some(escape_generic),
56    )
57    .unwrap()
58});
59pub const RESERVED: LazyLock<FxHashSet<&str>> = LazyLock::new(|| {
60    FxHashSet::from_iter([
61        "true", "false", "ok", "null", "mod", "let", "select", "pub", "type", "fn",
62        "cast", "if", "i8", "u8", "i16", "u16", "u32", "v32", "i32", "z32", "u64", "v64",
63        "i64", "z64", "f32", "f64", "decimal", "datetime", "duration", "bool", "string",
64        "bytes", "result", "null", "_", "?", "fn", "Array", "Map", "any", "Any", "use",
65        "rec", "catch", "try",
66    ])
67});
68
69fn spaces<I>() -> impl Parser<I, Output = ()>
70where
71    I: RangeStream<Token = char>,
72    I::Error: ParseError<I::Token, I::Range, I::Position>,
73    I::Range: Range,
74{
75    combine::parser::char::spaces().with(skip_many(attempt(
76        string("//")
77            .with(not_followed_by(token('/')))
78            .with(skip_many(none_of(['\n'])))
79            .with(combine::parser::char::spaces()),
80    )))
81}
82
83fn doc_comment<I>() -> impl Parser<I, Output = Option<ArcStr>>
84where
85    I: RangeStream<Token = char>,
86    I::Error: ParseError<I::Token, I::Range, I::Position>,
87    I::Range: Range,
88{
89    combine::parser::char::spaces()
90        .with(many(
91            string("///")
92                .with(many(none_of(['\n'])))
93                .skip(combine::parser::char::spaces()),
94        ))
95        .map(
96            |lines: LPooled<Vec<String>>| {
97                if lines.len() == 0 {
98                    None
99                } else {
100                    Some(ArcStr::from(lines.join("\n")))
101                }
102            },
103        )
104}
105
106fn spstring<'a, I>(s: &'static str) -> impl Parser<I, Output = &'a str>
107where
108    I: RangeStream<Token = char>,
109    I::Error: ParseError<I::Token, I::Range, I::Position>,
110    I::Range: Range,
111{
112    spaces().with(string(s))
113}
114
115fn ident<I>(cap: bool) -> impl Parser<I, Output = ArcStr>
116where
117    I: RangeStream<Token = char>,
118    I::Error: ParseError<I::Token, I::Range, I::Position>,
119    I::Range: Range,
120{
121    recognize((
122        take_while1(move |c: char| c.is_alphabetic() && cap == c.is_uppercase()),
123        take_while(|c: char| c.is_alphanumeric() || c == '_'),
124    ))
125    .map(|s: CompactString| ArcStr::from(s.as_str()))
126}
127
128fn fname<I>() -> impl Parser<I, Output = ArcStr>
129where
130    I: RangeStream<Token = char>,
131    I::Error: ParseError<I::Token, I::Range, I::Position>,
132    I::Range: Range,
133{
134    ident(false).then(|s| {
135        if RESERVED.contains(&s.as_str()) {
136            unexpected_any("can't use keyword as a function or variable name").left()
137        } else {
138            value(s).right()
139        }
140    })
141}
142
143fn spfname<I>() -> impl Parser<I, Output = ArcStr>
144where
145    I: RangeStream<Token = char>,
146    I::Error: ParseError<I::Token, I::Range, I::Position>,
147    I::Range: Range,
148{
149    spaces().with(fname())
150}
151
152fn typname<I>() -> impl Parser<I, Output = ArcStr>
153where
154    I: RangeStream<Token = char>,
155    I::Error: ParseError<I::Token, I::Range, I::Position>,
156    I::Range: Range,
157{
158    ident(true).then(|s| {
159        if RESERVED.contains(&s.as_str()) {
160            unexpected_any("can't use keyword as a type name").left()
161        } else {
162            value(s).right()
163        }
164    })
165}
166
167fn sptypname<I>() -> impl Parser<I, Output = ArcStr>
168where
169    I: RangeStream<Token = char>,
170    I::Error: ParseError<I::Token, I::Range, I::Position>,
171    I::Range: Range,
172{
173    spaces().with(typname())
174}
175
176pub(crate) fn modpath<I>() -> impl Parser<I, Output = ModPath>
177where
178    I: RangeStream<Token = char>,
179    I::Error: ParseError<I::Token, I::Range, I::Position>,
180    I::Range: Range,
181{
182    sep_by1(fname(), string("::"))
183        .map(|mut v: LPooled<Vec<ArcStr>>| ModPath(Path::from_iter(v.drain(..))))
184}
185
186fn spmodpath<I>() -> impl Parser<I, Output = ModPath>
187where
188    I: RangeStream<Token = char>,
189    I::Error: ParseError<I::Token, I::Range, I::Position>,
190    I::Range: Range,
191{
192    spaces().with(modpath())
193}
194
195fn typath<I>() -> impl Parser<I, Output = ModPath>
196where
197    I: RangeStream<Token = char>,
198    I::Error: ParseError<I::Token, I::Range, I::Position>,
199    I::Range: Range,
200{
201    sep_by1(choice((attempt(spfname()), sptypname())), string("::")).then(
202        |mut parts: LPooled<Vec<ArcStr>>| {
203            if parts.len() == 0 {
204                unexpected_any("empty type path").left()
205            } else {
206                match parts.last().unwrap().chars().next() {
207                    None => unexpected_any("empty name").left(),
208                    Some(c) if c.is_lowercase() => {
209                        unexpected_any("type names must be capitalized").left()
210                    }
211                    Some(_) => value(ModPath::from(parts.drain(..))).right(),
212                }
213            }
214        },
215    )
216}
217
218fn sptypath<I>() -> impl Parser<I, Output = ModPath>
219where
220    I: RangeStream<Token = char>,
221    I::Error: ParseError<I::Token, I::Range, I::Position>,
222    I::Range: Range,
223{
224    spaces().with(typath())
225}
226
227fn csep<I>() -> impl Parser<I, Output = char>
228where
229    I: RangeStream<Token = char>,
230    I::Error: ParseError<I::Token, I::Range, I::Position>,
231    I::Range: Range,
232{
233    attempt(spaces().with(token(',')))
234}
235
236fn sptoken<I>(t: char) -> impl Parser<I, Output = char>
237where
238    I: RangeStream<Token = char>,
239    I::Error: ParseError<I::Token, I::Range, I::Position>,
240    I::Range: Range,
241{
242    spaces().with(token(t))
243}
244
245parser! {
246    fn interpolated[I]()(I) -> Expr
247    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
248    {
249        #[derive(Debug, Clone)]
250        enum Intp {
251            Lit(SourcePosition, String),
252            Expr(Expr),
253        }
254        impl Intp {
255            fn to_expr(self) -> Expr {
256                match self {
257                    Intp::Lit(pos, s) => Expr {
258                        id: ExprId::new(),
259                        ori: get_origin(),
260                        pos,
261                        kind: ExprKind::Constant(Value::from(s)),
262                    },
263                    Intp::Expr(s) => s,
264                }
265            }
266        }
267        (
268            position(),
269            between(
270                token('"'),
271                token('"'),
272                many(choice((
273                    attempt(between(token('['), sptoken(']'), expr()).map(Intp::Expr)),
274                    (position(), escaped_string(&GRAPHIX_MUST_ESC, &GRAPHIX_ESC))
275                    .then(|(pos, s)| {
276                        if s.is_empty() {
277                            unexpected_any("empty string").right()
278                        } else {
279                            value(Intp::Lit(pos, s)).left()
280                        }
281                    }),
282                ))),
283            ),
284        )
285            .map(|(pos, mut toks): (_, LPooled<Vec<Intp>>)| {
286                let mut argvec = vec![];
287                toks.drain(..)
288                    .fold(None, |src, tok| -> Option<Expr> {
289                        match (src, tok) {
290                            (None, t @ Intp::Lit(_, _)) => Some(t.to_expr()),
291                            (None, Intp::Expr(s)) => {
292                                argvec.push(s);
293                                Some(
294                                    ExprKind::StringInterpolate {
295                                        args: Arc::from_iter(argvec.clone().into_iter()),
296                                    }
297                                    .to_expr(pos),
298                                )
299                            }
300                            (Some(src @ Expr { kind: ExprKind::Constant(_), .. }), s) => {
301                                argvec.extend([src, s.to_expr()]);
302                                Some(
303                                    ExprKind::StringInterpolate {
304                                        args: Arc::from_iter(argvec.clone().into_iter()),
305                                    }
306                                    .to_expr(pos),
307                                )
308                            }
309                            (
310                                Some(Expr {
311                                    kind: ExprKind::StringInterpolate { args: _ },
312                                    ..
313                                }),
314                                s,
315                            ) => {
316                                argvec.push(s.to_expr());
317                                Some(
318                                    ExprKind::StringInterpolate {
319                                        args: Arc::from_iter(argvec.clone().into_iter()),
320                                    }
321                                    .to_expr(pos),
322                                )
323                            }
324                            (Some(Expr { kind: ExprKind::Bind { .. }, .. }), _)
325                                | (Some(Expr { kind: ExprKind::StructWith { .. }, .. }), _)
326                                | (Some(Expr { kind: ExprKind::Array { .. }, .. }), _)
327                                | (Some(Expr { kind: ExprKind::Map { .. }, .. }), _)
328                                | (Some(Expr { kind: ExprKind::MapRef { .. }, .. }), _)
329                                | (Some(Expr { kind: ExprKind::Any { .. }, .. }), _)
330                                | (Some(Expr { kind: ExprKind::StructRef { .. }, .. }), _)
331                                | (Some(Expr { kind: ExprKind::TupleRef { .. }, .. }), _)
332                                | (Some(Expr { kind: ExprKind::Tuple { .. }, .. }), _)
333                                | (Some(Expr { kind: ExprKind::Variant { .. }, .. }), _)
334                                | (Some(Expr { kind: ExprKind::Struct { .. }, .. }), _)
335                                | (Some(Expr { kind: ExprKind::Qop(_), .. }), _)
336                                | (Some(Expr { kind: ExprKind::OrNever(_), .. }), _)
337                                | (Some(Expr { kind: ExprKind::TryCatch(_), .. }), _)
338                                | (Some(Expr { kind: ExprKind::Do { .. }, .. }), _)
339                                | (Some(Expr { kind: ExprKind::Module { .. }, .. }), _)
340                                | (Some(Expr { kind: ExprKind::Use { .. }, .. }), _)
341                                | (Some(Expr { kind: ExprKind::Connect { .. }, .. }), _)
342                                | (Some(Expr { kind: ExprKind::Ref { .. }, .. }), _)
343                                | (Some(Expr { kind: ExprKind::Eq { .. }, .. }), _)
344                                | (Some(Expr { kind: ExprKind::Ne { .. }, .. }), _)
345                                | (Some(Expr { kind: ExprKind::Lt { .. }, .. }), _)
346                                | (Some(Expr { kind: ExprKind::Gt { .. }, .. }), _)
347                                | (Some(Expr { kind: ExprKind::Gte { .. }, .. }), _)
348                                | (Some(Expr { kind: ExprKind::Lte { .. }, .. }), _)
349                                | (Some(Expr { kind: ExprKind::And { .. }, .. }), _)
350                                | (Some(Expr { kind: ExprKind::Or { .. }, .. }), _)
351                                | (Some(Expr { kind: ExprKind::Not { .. }, .. }), _)
352                                | (Some(Expr { kind: ExprKind::Add { .. }, .. }), _)
353                                | (Some(Expr { kind: ExprKind::Sub { .. }, .. }), _)
354                                | (Some(Expr { kind: ExprKind::Mul { .. }, .. }), _)
355                                | (Some(Expr { kind: ExprKind::Div { .. }, .. }), _)
356                                | (Some(Expr { kind: ExprKind::Mod { .. }, .. }), _)
357                                | (Some(Expr { kind: ExprKind::Select { .. }, .. }), _)
358                                | (Some(Expr { kind: ExprKind::TypeCast { .. }, .. }), _)
359                                | (Some(Expr { kind: ExprKind::TypeDef { .. }, .. }), _)
360                                | (Some(Expr { kind: ExprKind::ArrayRef { .. }, .. }), _)
361                                | (Some(Expr { kind: ExprKind::ArraySlice { .. }, .. }), _)
362                                | (Some(Expr { kind: ExprKind::Apply { .. }, .. }), _)
363                                | (Some(Expr { kind: ExprKind::ByRef(_), .. }), _)
364                                | (Some(Expr { kind: ExprKind::Deref(_), .. }), _)
365                                | (Some(Expr { kind: ExprKind::Sample { .. }, .. }), _)
366                                | (Some(Expr { kind: ExprKind::Lambda { .. }, .. }), _) => {
367                                    unreachable!()
368                                }
369                        }
370                    })
371                    .unwrap_or_else(|| ExprKind::Constant(Value::from("")).to_expr(pos))
372            })
373    }
374}
375
376parser! {
377    fn sig_item[I]()(I) -> SigItem
378    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
379    {
380        choice((
381            attempt(spaces().with(typedef())).map(|e| match e.kind {
382                ExprKind::TypeDef(td) => SigItem::TypeDef(td),
383                _ => unreachable!()
384            }),
385            attempt(spstring("val").with(space()).with((spfname(), sptoken(':').with(typexp()))))
386                .map(|(name, typ)| {
387                    SigItem::Bind(name, typ)
388                }),
389            attempt(spstring("mod").with(space()).with((
390                spfname().skip(sptoken(':')).skip(spstring("sig")),
391                between(sptoken('{'), sptoken('}'),
392                    sep_by1(sig_item(), attempt(sptoken(';'))))
393            ))).map(|(name, mut items): (ArcStr, LPooled<Vec<SigItem>>)| {
394                SigItem::Module(name, Sig(Arc::from_iter(items.drain(..))))
395            })
396        ))
397    }
398}
399
400parser! {
401    fn sandbox[I]()(I) -> Sandbox
402    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
403    {
404        choice((
405            spstring("unrestricted").map(|_| Sandbox::Unrestricted),
406            spstring("blacklist").with(between(
407                sptoken('['), sptoken(']'),
408                sep_by1(spaces().with(modpath()), csep())
409            )).map(|l: Vec<ModPath>| Sandbox::Blacklist(Arc::from(l))),
410            spstring("whitelist").with(between(
411                sptoken('['), sptoken(']'),
412                sep_by1(spaces().with(modpath()), csep())
413            )).map(|l: Vec<ModPath>| Sandbox::Whitelist(Arc::from(l)))
414        ))
415        .skip(sptoken(';'))
416    }
417}
418
419parser! {
420    fn dynamic_module[I]()(I) -> ModuleKind
421    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
422    {
423        space().with(spstring("dynamic")).with(between(
424            sptoken('{'), sptoken('}'),
425            (
426                spstring("sandbox").with(space()).with(sandbox()),
427                spstring("sig").with(between(
428                    sptoken('{'), sptoken('}'),
429                    sep_by1(sig_item(), attempt(sptoken(';')))
430                        .map(|i: Vec<SigItem>| Sig(Arc::from(i)))
431                ))
432                .skip(sptoken(';')),
433                spstring("source").with(space()).with(expr())
434            )
435        )).map(|(sandbox, sig, source)| {
436            ModuleKind::Dynamic { sandbox, sig, source: Arc::new(source) }
437        })
438    }
439}
440
441parser! {
442    fn inline_module[I]()(I) -> ModuleKind
443    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
444    {
445        between(
446            sptoken('{'), sptoken('}'),
447            sep_by(expr(), attempt(sptoken(';')))
448        )
449        .map(|m: Vec<Expr>| ModuleKind::Inline(Arc::from(m)))
450    }
451}
452
453parser! {
454    fn module[I]()(I) -> Expr
455    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
456    {
457        (
458            position(),
459            optional(string("pub").skip(space())).map(|o| o.is_some()),
460            spstring("mod").with(space()).with(spfname()),
461            optional(choice((
462                attempt(inline_module()),
463                attempt(dynamic_module())
464            ))).map(|m| m.unwrap_or(ModuleKind::Unresolved))
465        )
466            .map(|(pos, export, name, value)| {
467                ExprKind::Module { name, export, value }.to_expr(pos)
468            })
469    }
470}
471
472fn use_module<I>() -> impl Parser<I, Output = Expr>
473where
474    I: RangeStream<Token = char, Position = SourcePosition>,
475    I::Error: ParseError<I::Token, I::Range, I::Position>,
476    I::Range: Range,
477{
478    (position(), string("use").with(space()).with(spmodpath()))
479        .map(|(pos, name)| ExprKind::Use { name }.to_expr(pos))
480}
481
482parser! {
483    fn do_block[I]()(I) -> Expr
484    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
485    {
486        (
487            position(),
488            between(token('{'), sptoken('}'), sep_by1(expr(), attempt(sptoken(';')))),
489        )
490            .then(|(pos, args): (_, Vec<Expr>)| {
491                if args.len() < 2 {
492                    unexpected_any("do must contain at least 2 expressions").left()
493                } else {
494                    value(ExprKind::Do { exprs: Arc::from(args) }.to_expr(pos)).right()
495                }
496            })
497    }
498}
499
500parser! {
501    fn array[I]()(I) -> Expr
502    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
503    {
504        (position(), between(token('['), sptoken(']'), sep_by(expr(), csep()))).map(
505            |(pos, mut args): (_, LPooled<Vec<Expr>>)| {
506                ExprKind::Array { args: Arc::from_iter(args.drain(..)) }.to_expr(pos)
507            },
508        )
509    }
510}
511
512parser! {
513    fn apply_pexp[I]()(I) -> Expr
514    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
515    {
516        choice((
517            attempt(spaces().with(qop(reference()))),
518            between(sptoken('('), sptoken(')'), expr()),
519        ))
520    }
521}
522
523parser! {
524    fn ref_pexp[I]()(I) -> Expr
525    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
526    {
527        choice((
528            attempt(spaces().with(qop(reference()))),
529            between(sptoken('('), sptoken(')'), expr()),
530        ))
531    }
532}
533
534parser! {
535    fn structref[I]()(I) -> Expr
536    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
537    {
538        (position(), ref_pexp().skip(sptoken('.')), spfname()).map(|(pos, source, field)| {
539            ExprKind::StructRef { source: Arc::new(source), field }.to_expr(pos)
540        })
541    }
542}
543
544parser! {
545    fn tupleref[I]()(I) -> Expr
546    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
547    {
548        (position(), ref_pexp().skip(sptoken('.')), int::<_, usize>()).map(
549            |(pos, source, field)| {
550                ExprKind::TupleRef { source: Arc::new(source), field }.to_expr(pos)
551            },
552        )
553    }
554}
555
556parser! {
557    fn arrayref[I]()(I) -> Expr
558    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
559    {
560        (
561            position(),
562            ref_pexp(),
563            between(
564                token('['),
565                sptoken(']'),
566                choice((
567                    attempt(
568                        (
569                            position(),
570                            spaces().with(optional(many1(digit()))).skip(spstring("..")),
571                            spaces().with(optional(many1(digit()))),
572                        )
573                            .skip(look_ahead(sptoken(']'))),
574                    )
575                        .map(
576                            |(pos, start, end): (
577                                _,
578                                Option<CompactString>,
579                                Option<CompactString>,
580                            )| {
581                                let start = start.map(|i| Value::U64(i.parse().unwrap()));
582                                let start = start.map(|e| ExprKind::Constant(e).to_expr(pos));
583                                let end = end.map(|i| Value::U64(i.parse().unwrap()));
584                                let end = end.map(|e| ExprKind::Constant(e).to_expr(pos));
585                                Either::Left((start, end))
586                            },
587                        ),
588                    attempt((
589                        optional(attempt(expr())).skip(spstring("..")),
590                        optional(attempt(expr())),
591                    ))
592                        .map(|(start, end)| Either::Left((start, end))),
593                    attempt(expr()).map(|e| Either::Right(e)),
594                )),
595            ),
596        )
597            .map(|(pos, a, args)| match args {
598                Either::Left((start, end)) => ExprKind::ArraySlice {
599                    source: Arc::new(a),
600                    start: start.map(Arc::new),
601                    end: end.map(Arc::new),
602                }
603                .to_expr(pos),
604                Either::Right(i) => {
605                    ExprKind::ArrayRef { source: Arc::new(a), i: Arc::new(i) }.to_expr(pos)
606                }
607            })
608    }
609}
610
611parser! {
612    fn mapref[I]()(I) -> Expr
613    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
614    {
615        (position(), ref_pexp(), between(sptoken('{'), sptoken('}'), expr())).map(|(pos, source, key)| {
616            ExprKind::MapRef { source: Arc::new(source), key: Arc::new(key) }.to_expr(pos)
617        })
618    }
619}
620
621parser! {
622    fn apply[I]()(I) -> Expr
623    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
624    {
625        (
626            position(),
627            apply_pexp(),
628            between(
629                sptoken('('),
630                sptoken(')'),
631                sep_by(
632                    choice((
633                        attempt((sptoken('#').with(fname()).skip(token(':')), expr()))
634                            .map(|(n, e)| (Some(n), e)),
635                        attempt((
636                            position(),
637                            sptoken('#').with(fname()),
638                        ))
639                            .map(|(pos, n)| {
640                                let e = ExprKind::Ref { name: [n.clone()].into() }.to_expr(pos);
641                                (Some(n), e)
642                            }),
643                        expr().map(|e| (None, e)),
644                    )),
645                    csep(),
646                ),
647            ),
648        )
649            .then(|(pos, function, args): (_, Expr, Vec<(Option<ArcStr>, Expr)>)| {
650                let mut anon = false;
651                for (a, _) in &args {
652                    if a.is_some() && anon {
653                        return unexpected_any(
654                            "labeled arguments must come before anonymous arguments",
655                        )
656                            .right();
657                    }
658                    anon |= a.is_none();
659                }
660                value((pos, function, args)).left()
661            })
662            .map(|(pos, function, args): (_, Expr, Vec<(Option<ArcStr>, Expr)>)| {
663                ExprKind::Apply { function: Arc::new(function), args: Arc::from(args) }
664                .to_expr(pos)
665            })
666    }
667}
668
669parser! {
670    fn any[I]()(I) -> Expr
671    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
672    {
673        (
674            position(),
675            string("any").with(between(sptoken('('), sptoken(')'), sep_by(expr(), csep()))),
676        )
677            .map(|(pos, args): (_, Vec<Expr>)| {
678                ExprKind::Any { args: Arc::from(args) }.to_expr(pos)
679            })
680    }
681}
682
683fn typeprim<I>() -> impl Parser<I, Output = Typ>
684where
685    I: RangeStream<Token = char>,
686    I::Error: ParseError<I::Token, I::Range, I::Position>,
687    I::Range: Range,
688{
689    choice((
690        attempt(spstring("i8").map(|_| Typ::I8)),
691        attempt(spstring("u8").map(|_| Typ::U8)),
692        attempt(spstring("i16").map(|_| Typ::I16)),
693        attempt(spstring("u16").map(|_| Typ::U16)),
694        attempt(spstring("u32").map(|_| Typ::U32)),
695        attempt(spstring("v32").map(|_| Typ::V32)),
696        attempt(spstring("i32").map(|_| Typ::I32)),
697        attempt(spstring("z32").map(|_| Typ::Z32)),
698        attempt(spstring("u64").map(|_| Typ::U64)),
699        attempt(spstring("v64").map(|_| Typ::V64)),
700        attempt(spstring("i64").map(|_| Typ::I64)),
701        attempt(spstring("z64").map(|_| Typ::Z64)),
702        attempt(spstring("f32").map(|_| Typ::F32)),
703        attempt(spstring("f64").map(|_| Typ::F64)),
704        attempt(spstring("decimal").map(|_| Typ::Decimal)),
705        attempt(spstring("datetime").map(|_| Typ::DateTime)),
706        attempt(spstring("duration").map(|_| Typ::Duration)),
707        attempt(spstring("bool").map(|_| Typ::Bool)),
708        attempt(spstring("string").map(|_| Typ::String)),
709        attempt(spstring("bytes").map(|_| Typ::Bytes)),
710        attempt(spstring("error").map(|_| Typ::Error)),
711        attempt(spstring("array").map(|_| Typ::Array)),
712        attempt(spstring("null").map(|_| Typ::Null)),
713    ))
714    .skip(not_followed_by(choice((alpha_num(), token('_')))))
715}
716
717parser! {
718    fn fntype[I]()(I) -> FnType
719    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
720    {
721        spstring("fn")
722            .with((
723                optional(attempt(between(
724                    token('<'),
725                    sptoken('>'),
726                    sep_by1((tvar().skip(sptoken(':')), typexp()), csep()),
727                )))
728                    .map(|cs: Option<LPooled<Vec<(TVar, Type)>>>| match cs {
729                        Some(cs) => Arc::new(RwLock::new(cs)),
730                        None => Arc::new(RwLock::new(LPooled::take())),
731                    }),
732                between(
733                    token('('),
734                    sptoken(')'),
735                    sep_by(
736                        choice((
737                            attempt(
738                                (
739                                    spaces()
740                                        .with(optional(token('?')).map(|o| o.is_some()))
741                                        .skip(token('#')),
742                                    fname().skip(token(':')),
743                                    typexp(),
744                                )
745                                    .map(
746                                        |(optional, name, typ)| {
747                                            Either::Left(FnArgType {
748                                                label: Some((name.into(), optional)),
749                                                typ,
750                                            })
751                                        },
752                                    ),
753                            ),
754                            attempt(
755                                typexp()
756                                    .map(|typ| Either::Left(FnArgType { label: None, typ })),
757                            ),
758                            attempt(
759                                spstring("@args:").with(typexp()).map(|e| Either::Right(e)),
760                            ),
761                        )),
762                        csep(),
763                    ),
764                ),
765                spstring("->").with(typexp()),
766                optional(attempt(space().with(spstring("throws")).with(space()).with(typexp())))
767            ))
768            .then(
769                |(constraints, mut args, rtype, throws): (
770                    Arc<RwLock<LPooled<Vec<(TVar, Type)>>>>,
771                    Vec<Either<FnArgType, Type>>,
772                    Type,
773                    Option<Type>
774                )| {
775                    let vargs = match args.pop() {
776                        None => None,
777                        Some(Either::Right(t)) => Some(t),
778                        Some(Either::Left(t)) => {
779                            args.push(Either::Left(t));
780                            None
781                        }
782                    };
783                    if !args.iter().all(|a| a.is_left()) {
784                        return unexpected_any(
785                            "vargs must appear once at the end of the args",
786                        )
787                            .left();
788                    }
789                    let args = Arc::from_iter(args.into_iter().map(|t| match t {
790                        Either::Left(t) => t,
791                        Either::Right(_) => unreachable!(),
792                    }));
793                    let mut anon = false;
794                    for a in args.iter() {
795                        if anon && a.label.is_some() {
796                            return unexpected_any(
797                                "anonymous args must appear after labeled args",
798                            )
799                                .left();
800                        }
801                        anon |= a.label.is_none();
802                    }
803                    let throws = throws.unwrap_or(Type::Bottom);
804                    value(FnType { args, vargs, rtype, constraints, throws }).right()
805                },
806            )
807    }
808}
809
810fn tvar<I>() -> impl Parser<I, Output = TVar>
811where
812    I: RangeStream<Token = char>,
813    I::Error: ParseError<I::Token, I::Range, I::Position>,
814    I::Range: Range,
815{
816    sptoken('\'').with(fname()).map(TVar::empty_named)
817}
818
819parser! {
820    fn typexp[I]()(I) -> Type
821    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
822    {
823        choice((
824            attempt(sptoken('&').with(typexp()).map(|t| Type::ByRef(Arc::new(t)))),
825            attempt(sptoken('_').map(|_| Type::Bottom)),
826            attempt(
827                between(sptoken('['), sptoken(']'), sep_by(typexp(), csep()))
828                    .map(|mut ts: LPooled<Vec<Type>>| Type::flatten_set(ts.drain(..))),
829            ),
830            attempt(between(sptoken('('), sptoken(')'), sep_by1(typexp(), csep())).map(
831                |mut exps: LPooled<Vec<Type>>| {
832                    if exps.len() == 1 {
833                        exps.pop().unwrap()
834                    } else {
835                        Type::Tuple(Arc::from_iter(exps.drain(..)))
836                    }
837                },
838            )),
839            attempt(
840                between(
841                    sptoken('{'),
842                    sptoken('}'),
843                    sep_by1((spfname().skip(sptoken(':')), typexp()), csep()),
844                )
845                    .then(|mut exps: LPooled<Vec<(ArcStr, Type)>>| {
846                        let s = exps.iter().map(|(n, _)| n).collect::<LPooled<FxHashSet<_>>>();
847                        if s.len() < exps.len() {
848                            return unexpected_any("struct field names must be unique").left();
849                        }
850                        drop(s);
851                        exps.sort_by_key(|(n, _)| n.clone());
852                        value(Type::Struct(Arc::from_iter(exps.drain(..)))).right()
853                    }),
854            ),
855            attempt(
856                (
857                    sptoken('`').with(ident(true)),
858                    optional(attempt(between(
859                        token('('),
860                        sptoken(')'),
861                        sep_by1(typexp(), csep()),
862                    ))),
863                )
864                    .map(|(tag, typs): (ArcStr, Option<LPooled<Vec<Type>>>)| {
865                        let mut t = match typs {
866                            None => LPooled::take(),
867                            Some(v) => v,
868                        };
869                        Type::Variant(tag.clone(), Arc::from_iter(t.drain(..)))
870                    }),
871            ),
872            attempt(fntype().map(|f| Type::Fn(Arc::new(f)))),
873            attempt(spstring("Array").with(between(sptoken('<'), sptoken('>'), typexp())))
874                .map(|t| Type::Array(Arc::new(t))),
875            attempt(spstring("Map").with(
876                between(sptoken('<'), sptoken('>'),
877                    (typexp().skip(sptoken(',')), typexp())
878                )))
879                .map(|(k, v)| Type::Map { key: Arc::new(k), value: Arc::new(v) }),
880            attempt(spstring("Error").with(between(sptoken('<'), sptoken('>'), typexp())))
881                .map(|t| Type::Error(Arc::new(t))),
882            attempt((
883                sptypath(),
884                optional(attempt(between(
885                    sptoken('<'),
886                    sptoken('>'),
887                    sep_by1(typexp(), csep()),
888                ))),
889            ))
890                .map(|(n, params): (ModPath, Option<LPooled<Vec<Type>>>)| {
891                    let params = params
892                        .map(|mut a| Arc::from_iter(a.drain(..)))
893                        .unwrap_or_else(|| Arc::from_iter([]));
894                    Type::Ref { scope: ModPath::root(), name: n, params }
895                }),
896            attempt(spstring("Any")).map(|_| Type::Any),
897            attempt(typeprim()).map(|typ| Type::Primitive(typ.into())),
898            attempt(tvar()).map(|tv| Type::TVar(tv)),
899        ))
900    }
901}
902
903parser! {
904    fn lambda_args[I]()(I) -> (LPooled<Vec<Arg>>, Option<Option<Type>>)
905    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
906    {
907        sep_by(
908            (
909                choice((
910                    attempt(spaces().with(structure_pattern())).map(|p| (false, p)),
911                    attempt(spaces().with(token('#').with(fname())))
912                        .map(|b| (true, StructurePattern::Bind(b))),
913                    attempt(spstring("@args"))
914                        .map(|s| (false, StructurePattern::Bind(ArcStr::from(s)))),
915                )),
916                optional(attempt(sptoken(':').with(typexp()))),
917                optional(attempt(sptoken('=').with(expr()))),
918            ),
919            csep(),
920        )
921            .then(|v: Vec<((bool, StructurePattern), Option<Type>, Option<Expr>)>| {
922                let args = v
923                    .into_iter()
924                    .map(|((labeled, pattern), constraint, default)| {
925                        if !labeled && default.is_some() {
926                            bail!("labeled")
927                        } else {
928                            Ok(Arg { labeled: labeled.then_some(default), pattern, constraint })
929                        }
930                    })
931                    .collect::<Result<LPooled<Vec<_>>>>();
932                match args {
933                    Ok(a) => value(a).right(),
934                    Err(_) => {
935                        unexpected_any("only labeled arguments may have a default value").left()
936                    }
937                }
938            })
939        // @args must be last
940            .then(|mut v: LPooled<Vec<Arg>>| {
941                match v.iter().enumerate().find(|(_, a)| match &a.pattern {
942                    StructurePattern::Bind(n) if n == "@args" => true,
943                    _ => false,
944                }) {
945                    None => value((v, None)).left(),
946                    Some((i, _)) => {
947                        if i == v.len() - 1 {
948                            let a = v.pop().unwrap();
949                            value((v, Some(a.constraint))).left()
950                        } else {
951                            unexpected_any("@args must be the last argument").right()
952                        }
953                    }
954                }
955            })
956        // labeled before anonymous args
957            .then(|(v, vargs): (LPooled<Vec<Arg>>, Option<Option<Type>>)| {
958                let mut anon = false;
959                for a in v.iter() {
960                    if a.labeled.is_some() && anon {
961                        return unexpected_any("labeled args must come before anon args").right();
962                    }
963                    anon |= a.labeled.is_none();
964                }
965                value((v, vargs)).left()
966            })
967    }
968}
969
970parser! {
971    fn lambda[I]()(I) -> Expr
972    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
973    {
974        (
975            position(),
976            attempt(sep_by((tvar().skip(sptoken(':')), typexp()), csep()))
977                .map(|mut tvs: LPooled<Vec<(TVar, Type)>>| Arc::from_iter(tvs.drain(..))),
978            between(sptoken('|'), sptoken('|'), lambda_args()),
979            optional(attempt(spstring("->").with(typexp()))),
980            optional(attempt(space().with(spstring("throws").with(space()).with(typexp())))),
981            space().with(choice((
982                attempt(sptoken('\'').with(fname()).skip(not_followed_by(sptoken(':'))))
983                    .map(Either::Right),
984                expr().map(|e| Either::Left(e)),
985            ))),
986        )
987            .map(|(pos, constraints, (mut args, vargs), rtype, throws, body)| {
988                let args = Arc::from_iter(args.drain(..));
989                ExprKind::Lambda(Arc::new(Lambda { args, vargs, rtype, throws, constraints, body }))
990                    .to_expr(pos)
991            })
992    }
993}
994
995parser! {
996    fn letbind[I]()(I) -> Expr
997    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
998    {
999        (
1000            position(),
1001            doc_comment(),
1002            optional(string("pub").skip(space())).map(|o| o.is_some()),
1003            spstring("let")
1004                .with(space())
1005                .with((
1006                    optional(attempt(spstring("rec").with(space()))),
1007                    structure_pattern(),
1008                    optional(attempt(sptoken(':').with(typexp())))
1009                ))
1010                .skip(spstring("=")),
1011            expr(),
1012        )
1013            .map(|(pos, doc, export, (rec, pattern, typ), value)| {
1014                let rec = rec.is_some();
1015                ExprKind::Bind(Arc::new(Bind { rec, doc, export, pattern, typ, value }))
1016                    .to_expr(pos)
1017            })
1018    }
1019}
1020
1021parser! {
1022    fn connect[I]()(I) -> Expr
1023    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1024    {
1025        (position(), optional(token('*')), spmodpath().skip(spstring("<-")), expr()).map(
1026            |(pos, deref, name, e)| {
1027                ExprKind::Connect { name, value: Arc::new(e), deref: deref.is_some() }
1028                .to_expr(pos)
1029            },
1030        )
1031    }
1032}
1033
1034fn literal<I>() -> impl Parser<I, Output = Expr>
1035where
1036    I: RangeStream<Token = char, Position = SourcePosition>,
1037    I::Error: ParseError<I::Token, I::Range, I::Position>,
1038    I::Range: Range,
1039{
1040    (position(), parse_value(&VAL_MUST_ESC, &VAL_ESC).skip(not_followed_by(token('_'))))
1041        .then(|(pos, v)| match v {
1042            Value::String(_) => {
1043                unexpected_any("parse error in string interpolation").left()
1044            }
1045            v => value(ExprKind::Constant(v).to_expr(pos)).right(),
1046        })
1047}
1048
1049fn reference<I>() -> impl Parser<I, Output = Expr>
1050where
1051    I: RangeStream<Token = char, Position = SourcePosition>,
1052    I::Error: ParseError<I::Token, I::Range, I::Position>,
1053    I::Range: Range,
1054{
1055    (position(), modpath()).map(|(pos, name)| ExprKind::Ref { name }.to_expr(pos))
1056}
1057
1058parser! {
1059    fn deref_arith[I]()(I) -> Expr
1060    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1061    {
1062        (position(), token('*').with(arith_term()))
1063            .map(|(pos, expr)| ExprKind::Deref(Arc::new(expr)).to_expr(pos))
1064    }
1065}
1066
1067parser! {
1068    fn qop[I, P](p: P)(I) -> Expr
1069    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range, P: Parser<I, Output = Expr>]
1070    {
1071        enum Op {
1072            Qop,
1073            OrNever,
1074        }
1075        (
1076            position(),
1077            p,
1078            optional(choice((
1079                attempt(sptoken('?')).map(|_| Op::Qop),
1080                attempt(sptoken('$')).map(|_| Op::OrNever)
1081            )))
1082        ).map(|(pos, e, qop)| match qop {
1083            None => e,
1084            Some(Op::Qop) => ExprKind::Qop(Arc::new(e)).to_expr(pos),
1085            Some(Op::OrNever) => ExprKind::OrNever(Arc::new(e)).to_expr(pos)
1086        })
1087    }
1088}
1089
1090parser! {
1091    fn arith_term[I]()(I) -> Expr
1092    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1093    {
1094        choice((
1095            attempt(spaces().with(qop(deref_arith()))),
1096            attempt(spaces().with(raw_string())),
1097            attempt(spaces().with(array())),
1098            attempt(spaces().with(byref_arith())),
1099            attempt(spaces().with(tuple())),
1100            attempt(spaces().with(structure())),
1101            attempt(spaces().with(map())),
1102            attempt(spaces().with(variant())),
1103            attempt(spaces().with(structwith())),
1104            attempt(spaces().with(qop(arrayref()))),
1105            attempt(spaces().with(qop(tupleref()))),
1106            attempt(spaces().with(qop(structref()))),
1107            attempt(spaces().with(qop(mapref()))),
1108            attempt(spaces().with(qop(apply()))),
1109            attempt(spaces().with(qop(do_block()))),
1110            attempt(spaces().with(qop(select()))),
1111            attempt(spaces().with(qop(cast()))),
1112            attempt(spaces().with(qop(any()))),
1113            attempt(spaces().with(interpolated())),
1114            attempt(spaces().with(literal())),
1115            attempt(spaces().with(qop(reference()))),
1116            attempt(
1117                (position(), sptoken('!').with(arith()))
1118                    .map(|(pos, expr)| ExprKind::Not { expr: Arc::new(expr) }.to_expr(pos)),
1119            ),
1120            attempt(between(sptoken('('), sptoken(')'), arith())),
1121        ))
1122            .skip(spaces())
1123    }
1124}
1125
1126parser! {
1127    fn arith[I]()(I) -> Expr
1128    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1129    {
1130        choice((
1131            attempt(chainl1(
1132                arith_term(),
1133                choice((
1134                    attempt(spstring("+")),
1135                    attempt(spstring("-")),
1136                    attempt(spstring("*")),
1137                    attempt(spstring("/")),
1138                    attempt(spstring("%")),
1139                    attempt(spstring("==")),
1140                    attempt(spstring("!=")),
1141                    attempt(spstring(">=")),
1142                    attempt(spstring("<=")),
1143                    attempt(spstring(">")),
1144                    attempt(spstring("<")),
1145                    attempt(spstring("&&")),
1146                    attempt(spstring("||")),
1147                    attempt(spstring("~")),
1148                ))
1149                    .map(|op: &str| match op {
1150                        "+" => |lhs: Expr, rhs: Expr| {
1151                            let pos = lhs.pos;
1152                            ExprKind::Add { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1153                        },
1154                        "-" => |lhs: Expr, rhs: Expr| {
1155                            let pos = lhs.pos;
1156                            ExprKind::Sub { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1157                        },
1158                        "*" => |lhs: Expr, rhs: Expr| {
1159                            let pos = lhs.pos;
1160                            ExprKind::Mul { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1161                        },
1162                        "/" => |lhs: Expr, rhs: Expr| {
1163                            let pos = lhs.pos;
1164                            ExprKind::Div { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1165                        },
1166                        "%" => |lhs: Expr, rhs: Expr| {
1167                            let pos = lhs.pos;
1168                            ExprKind::Mod { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1169                        },
1170                        "==" => |lhs: Expr, rhs: Expr| {
1171                            let pos = lhs.pos;
1172                            ExprKind::Eq { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1173                        },
1174                        "!=" => |lhs: Expr, rhs: Expr| {
1175                            let pos = lhs.pos;
1176                            ExprKind::Ne { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1177                        },
1178                        ">" => |lhs: Expr, rhs: Expr| {
1179                            let pos = lhs.pos;
1180                            ExprKind::Gt { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1181                        },
1182                        "<" => |lhs: Expr, rhs: Expr| {
1183                            let pos = lhs.pos;
1184                            ExprKind::Lt { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1185                        },
1186                        ">=" => |lhs: Expr, rhs: Expr| {
1187                            let pos = lhs.pos;
1188                            ExprKind::Gte { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1189                        },
1190                        "<=" => |lhs: Expr, rhs: Expr| {
1191                            let pos = lhs.pos;
1192                            ExprKind::Lte { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1193                        },
1194                        "&&" => |lhs: Expr, rhs: Expr| {
1195                            let pos = lhs.pos;
1196                            ExprKind::And { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1197                        },
1198                        "||" => |lhs: Expr, rhs: Expr| {
1199                            let pos = lhs.pos;
1200                            ExprKind::Or { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1201                        },
1202                        "~" => |lhs: Expr, rhs: Expr| {
1203                            let pos = lhs.pos;
1204                            ExprKind::Sample { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }
1205                            .to_expr(pos)
1206                        },
1207                        _ => unreachable!(),
1208                    }),
1209            )),
1210            attempt((position(), sptoken('!').with(arith_term())))
1211                .map(|(pos, expr)| ExprKind::Not { expr: Arc::new(expr) }.to_expr(pos)),
1212            attempt(between(sptoken('('), sptoken(')'), arith())),
1213        ))
1214    }
1215}
1216
1217parser! {
1218    fn slice_pattern[I]()(I) -> StructurePattern
1219    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1220    {
1221        macro_rules! all_left {
1222            ($pats:expr) => {{
1223                let mut err = false;
1224                let pats: Arc<[StructurePattern]> =
1225                    Arc::from_iter($pats.drain(..).map(|s| match s {
1226                        Either::Left(s) => s,
1227                        Either::Right(_) => {
1228                            err = true;
1229                            StructurePattern::Ignore
1230                        }
1231                    }));
1232                if err {
1233                    return unexpected_any("invalid pattern").left();
1234                }
1235                pats
1236            }};
1237        }
1238        (
1239            optional(attempt(spfname().skip(sptoken('@')))),
1240            between(
1241                sptoken('['),
1242                sptoken(']'),
1243                sep_by(
1244                    choice((
1245                        attempt(spstring("..")).map(|_| Either::Right(None)),
1246                        attempt(spfname().skip(spstring("..")))
1247                            .map(|n| Either::Right(Some(n))),
1248                        structure_pattern().map(|p| Either::Left(p)),
1249                    )),
1250                    csep(),
1251                ),
1252            ),
1253        )
1254            .then(
1255                |(all, mut pats): (
1256                    Option<ArcStr>,
1257                    LPooled<Vec<Either<StructurePattern, Option<ArcStr>>>>,
1258                )| {
1259                    if pats.len() == 0 {
1260                        value(StructurePattern::Slice { all, binds: Arc::from_iter([]) })
1261                            .right()
1262                    } else if pats.len() == 1 {
1263                        match pats.pop().unwrap() {
1264                            Either::Left(s) => value(StructurePattern::Slice {
1265                                all,
1266                                binds: Arc::from_iter([s]),
1267                            })
1268                                .right(),
1269                            Either::Right(_) => {
1270                                unexpected_any("invalid singular range match").left()
1271                            }
1272                        }
1273                    } else {
1274                        match (&pats[0], &pats[pats.len() - 1]) {
1275                            (Either::Right(_), Either::Right(_)) => {
1276                                unexpected_any("invalid pattern").left()
1277                            }
1278                            (Either::Right(_), Either::Left(_)) => {
1279                                let head = pats.remove(0).right().unwrap();
1280                                let suffix = all_left!(pats);
1281                                value(StructurePattern::SliceSuffix { all, head, suffix })
1282                                    .right()
1283                            }
1284                            (Either::Left(_), Either::Right(_)) => {
1285                                let tail = pats.pop().unwrap().right().unwrap();
1286                                let prefix = all_left!(pats);
1287                                value(StructurePattern::SlicePrefix { all, tail, prefix })
1288                                    .right()
1289                            }
1290                            (Either::Left(_), Either::Left(_)) => {
1291                                value(StructurePattern::Slice { all, binds: all_left!(pats) })
1292                                    .right()
1293                            }
1294                        }
1295                    }
1296                },
1297            )
1298    }
1299}
1300
1301fn raw_string<I>() -> impl Parser<I, Output = Expr>
1302where
1303    I: RangeStream<Token = char, Position = SourcePosition>,
1304    I::Error: ParseError<I::Token, I::Range, I::Position>,
1305    I::Range: Range,
1306{
1307    static MUST_ESC: [char; 2] = ['\\', '\''];
1308    static ESC: LazyLock<Escape> =
1309        LazyLock::new(|| Escape::new('\\', &MUST_ESC, &[], None).unwrap());
1310    (position(), between(string("r\'"), token('\''), escaped_string(&MUST_ESC, &ESC)))
1311        .map(|(pos, s): (_, String)| {
1312            ExprKind::Constant(Value::String(s.into())).to_expr(pos)
1313        })
1314}
1315
1316parser! {
1317    fn tuple_pattern[I]()(I) -> StructurePattern
1318    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1319    {
1320        (
1321            optional(attempt(spfname().skip(sptoken('@')))),
1322            between(sptoken('('), sptoken(')'), sep_by1(structure_pattern(), csep())),
1323        )
1324            .then(|(all, mut binds): (Option<ArcStr>, LPooled<Vec<StructurePattern>>)| {
1325                if binds.len() < 2 {
1326                    unexpected_any("tuples must have at least 2 elements").left()
1327                } else {
1328                    value(StructurePattern::Tuple { all, binds: Arc::from_iter(binds.drain(..)) })
1329                        .right()
1330                }
1331            })
1332    }
1333}
1334
1335parser! {
1336    fn variant_pattern[I]()(I) -> StructurePattern
1337    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1338    {
1339        (
1340            optional(attempt(spfname().skip(sptoken('@')))),
1341            sptoken('`').with(typname()),
1342            optional(attempt(between(
1343                sptoken('('),
1344                sptoken(')'),
1345                sep_by1(structure_pattern(), csep()),
1346            ))),
1347        )
1348            .map(
1349                |(all, tag, binds): (
1350                    Option<ArcStr>,
1351                    ArcStr,
1352                    Option<LPooled<Vec<StructurePattern>>>,
1353                )| {
1354                    let mut binds = match binds {
1355                        None => LPooled::take(),
1356                        Some(a) => a,
1357                    };
1358                    StructurePattern::Variant { all, tag, binds: Arc::from_iter(binds.drain(..)) }
1359                },
1360            )
1361    }
1362}
1363
1364parser! {
1365    fn struct_pattern[I]()(I) -> StructurePattern
1366    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1367    {
1368        (
1369            optional(attempt(spfname().skip(sptoken('@')))),
1370            between(
1371                sptoken('{'),
1372                sptoken('}'),
1373                sep_by1(
1374                    choice((
1375                        attempt((spfname().skip(sptoken(':')), structure_pattern()))
1376                            .map(|(s, p)| (s, p, true)),
1377                        attempt(spfname()).map(|s| {
1378                            let p = StructurePattern::Bind(s.clone());
1379                            (s, p, true)
1380                        }),
1381                        spstring("..")
1382                            .map(|_| (literal!(""), StructurePattern::Ignore, false)),
1383                    )),
1384                    csep(),
1385                ),
1386            ),
1387        )
1388            .then(
1389                |(all, mut binds): (
1390                    Option<ArcStr>,
1391                    LPooled<Vec<(ArcStr, StructurePattern, bool)>>,
1392                )| {
1393                    let mut exhaustive = true;
1394                    binds.retain(|(_, _, ex)| {
1395                        exhaustive &= *ex;
1396                        *ex
1397                    });
1398                    binds.sort_by_key(|(s, _, _)| s.clone());
1399                    let s = binds.iter().map(|(s, _, _)| s).collect::<LPooled<FxHashSet<_>>>();
1400                    if s.len() < binds.len() {
1401                        unexpected_any("struct fields must be unique").left()
1402                    } else {
1403                        drop(s);
1404                        let binds = Arc::from_iter(binds.drain(..).map(|(s, p, _)| (s, p)));
1405                        value(StructurePattern::Struct { all, exhaustive, binds }).right()
1406                    }
1407                },
1408            )
1409    }
1410}
1411
1412parser! {
1413    fn structure_pattern[I]()(I) -> StructurePattern
1414    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1415    {
1416        choice((
1417            attempt(slice_pattern()),
1418            attempt(tuple_pattern()),
1419            attempt(struct_pattern()),
1420            attempt(variant_pattern()),
1421            attempt(parse_value(&VAL_MUST_ESC, &VAL_ESC).skip(not_followed_by(token('_'))))
1422                .map(|v| StructurePattern::Literal(v)),
1423            attempt(sptoken('_')).map(|_| StructurePattern::Ignore),
1424            spfname().map(|name| StructurePattern::Bind(name)),
1425        ))
1426    }
1427}
1428
1429parser! {
1430    fn pattern[I]()(I) -> Pattern
1431    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1432    {
1433        (
1434            optional(attempt(typexp().skip(space().with(spstring("as "))))),
1435            structure_pattern(),
1436            optional(attempt(space().with(spstring("if").with(space()).with(expr())))),
1437        )
1438            .map(
1439                |(type_predicate, structure_predicate, guard): (
1440                    Option<Type>,
1441                    StructurePattern,
1442                    Option<Expr>,
1443                )| { Pattern { type_predicate, structure_predicate, guard } },
1444            )
1445    }
1446}
1447
1448parser! {
1449    fn select[I]()(I) -> Expr
1450    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1451    {
1452        (
1453            position(),
1454            string("select").with(space()).with((
1455                expr(),
1456                between(
1457                    sptoken('{'),
1458                    sptoken('}'),
1459                    sep_by1((pattern(), spstring("=>").with(expr())), csep()),
1460                ),
1461            )),
1462        )
1463            .map(|(pos, (arg, arms)): (_, (Expr, Vec<(Pattern, Expr)>))| {
1464                ExprKind::Select { arg: Arc::new(arg), arms: Arc::from(arms) }.to_expr(pos)
1465            })
1466    }
1467}
1468
1469parser! {
1470    fn cast[I]()(I) -> Expr
1471    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1472    {
1473        (
1474            position(),
1475            string("cast").with(between(token('<'), sptoken('>'), typexp())),
1476            between(sptoken('('), sptoken(')'), expr()),
1477        )
1478            .map(|(pos, typ, e)| ExprKind::TypeCast { expr: Arc::new(e), typ }.to_expr(pos))
1479    }
1480}
1481
1482parser! {
1483    fn typedef[I]()(I) -> Expr
1484    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1485    {
1486        (
1487            position(),
1488            string("type").with(sptypname()),
1489            optional(attempt(between(
1490                sptoken('<'),
1491                sptoken('>'),
1492                sep_by1((tvar(), optional(attempt(sptoken(':').with(typexp())))), csep()),
1493            ))),
1494            sptoken('=').with(typexp()),
1495        )
1496            .map(|(pos, name, params, typ)| {
1497                let params = params
1498                    .map(|mut ps: LPooled<Vec<(TVar, Option<Type>)>>| {
1499                        Arc::from_iter(ps.drain(..))
1500                    })
1501                    .unwrap_or_else(|| Arc::<[(TVar, Option<Type>)]>::from(Vec::new()));
1502                ExprKind::TypeDef(TypeDef { name, params, typ }).to_expr(pos)
1503            })
1504    }
1505}
1506
1507parser! {
1508    fn tuple[I]()(I) -> Expr
1509    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1510    {
1511        (position(), between(token('('), sptoken(')'), sep_by1(expr(), csep()))).then(
1512            |(pos, mut exprs): (_, LPooled<Vec<Expr>>)| {
1513                if exprs.len() < 2 {
1514                    unexpected_any("tuples must have at least 2 elements").left()
1515                } else {
1516                    value(ExprKind::Tuple { args: Arc::from_iter(exprs.drain(..)) }.to_expr(pos))
1517                        .right()
1518                }
1519            },
1520        )
1521    }
1522}
1523
1524parser! {
1525    fn structure[I]()(I) -> Expr
1526    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1527    {
1528        (
1529            position(),
1530            between(
1531                token('{'),
1532                sptoken('}'),
1533                sep_by1((spfname(), optional(attempt(sptoken(':')).with(expr()))), csep()),
1534            ),
1535        )
1536            .then(|(pos, mut exprs): (_, LPooled<Vec<(ArcStr, Option<Expr>)>>)| {
1537                let s = exprs.iter().map(|(n, _)| n).collect::<LPooled<FxHashSet<_>>>();
1538                if s.len() < exprs.len() {
1539                    return unexpected_any("struct fields must be unique").left();
1540                }
1541                drop(s);
1542                exprs.sort_by_key(|(n, _)| n.clone());
1543                let args = exprs.drain(..).map(|(n, e)| match e {
1544                    Some(e) => (n, e),
1545                    None => {
1546                        let e = ExprKind::Ref { name: [n.clone()].into() }.to_expr(pos);
1547                        (n, e)
1548                    }
1549                });
1550                value(ExprKind::Struct { args: Arc::from_iter(args) }.to_expr(pos)).right()
1551            })
1552    }
1553}
1554
1555parser! {
1556    fn map[I]()(I) -> Expr
1557    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1558    {
1559        (
1560            position(),
1561            between(
1562                token('{'),
1563                sptoken('}'),
1564                sep_by((expr(), spstring("=>").with(expr())), csep()),
1565            ),
1566        )
1567            .map(|(pos, mut args): (_, LPooled<Vec<(Expr, Expr)>>)| {
1568                ExprKind::Map { args: Arc::from_iter(args.drain(..)) }.to_expr(pos)
1569            })
1570    }
1571}
1572
1573parser! {
1574    fn variant[I]()(I) -> Expr
1575    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1576    {
1577        (
1578            position(),
1579            token('`').with(ident(true)),
1580            optional(attempt(between(token('('), sptoken(')'), sep_by1(expr(), csep())))),
1581        )
1582            .map(|(pos, tag, args): (_, ArcStr, Option<LPooled<Vec<Expr>>>)| {
1583                let mut args = match args {
1584                    None => LPooled::take(),
1585                    Some(a) => a,
1586                };
1587                ExprKind::Variant { tag, args: Arc::from_iter(args.drain(..)) }.to_expr(pos)
1588            })
1589    }
1590}
1591
1592parser! {
1593    fn structwith[I]()(I) -> Expr
1594    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1595    {
1596        (
1597            position(),
1598            between(
1599                token('{'),
1600                sptoken('}'),
1601                (
1602                    ref_pexp().skip(space()).skip(spstring("with")).skip(space()),
1603                    sep_by1((spfname(), optional(attempt(sptoken(':').with(expr())))), csep()),
1604                ),
1605            ),
1606        )
1607            .then(
1608                |(pos, (source, mut exprs)): (_, (Expr, LPooled<Vec<(ArcStr, Option<Expr>)>>))| {
1609                    let s = exprs.iter().map(|(n, _)| n).collect::<LPooled<FxHashSet<_>>>();
1610                    if s.len() < exprs.len() {
1611                        return unexpected_any("struct fields must be unique").left();
1612                    }
1613                    drop(s);
1614                    exprs.sort_by_key(|(n, _)| n.clone());
1615                    let exprs = exprs.drain(..).map(|(name, e)| match e {
1616                        Some(e) => (name, e),
1617                        None => {
1618                            let e = ExprKind::Ref { name: ModPath::from([name.clone()]) }.to_expr(pos);
1619                            (name, e)
1620                        }
1621                    });
1622                    let e = ExprKind::StructWith {
1623                        source: Arc::new(source),
1624                        replace: Arc::from_iter(exprs),
1625                    }
1626                    .to_expr(pos);
1627                    value(e).right()
1628                },
1629            )
1630    }
1631}
1632
1633parser! {
1634    fn try_catch[I]()(I) -> Expr
1635    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1636    {
1637        (
1638            position().skip(string("try")).skip(space()),
1639            sep_by1(expr(), attempt(sptoken(';'))),
1640            spstring("catch").with(
1641                between(
1642                    sptoken('('),
1643                    sptoken(')'),
1644                    (spfname(), optional(attempt(sptoken(':').with(typexp()))))
1645                )
1646            ),
1647            spstring("=>").with(expr())
1648        )
1649            .map(|(pos, mut exprs, (bind, constraint), handler):
1650                  (_, LPooled<Vec<Expr>>, _, _)|
1651            {
1652                ExprKind::TryCatch(Arc::new(TryCatch {
1653                    bind,
1654                    constraint,
1655                    exprs: Arc::from_iter(exprs.drain(..)),
1656                    handler: Arc::new(handler)
1657                })).to_expr(pos)
1658            })
1659    }
1660}
1661
1662parser! {
1663    fn byref[I]()(I) -> Expr
1664    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1665    {
1666        (position(), token('&').with(expr()))
1667            .map(|(pos, expr)| ExprKind::ByRef(Arc::new(expr)).to_expr(pos))
1668    }
1669}
1670
1671parser! {
1672    fn byref_arith[I]()(I) -> Expr
1673    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1674    {
1675        (position(), token('&').with(arith_term()))
1676            .map(|(pos, expr)| ExprKind::ByRef(Arc::new(expr)).to_expr(pos))
1677    }
1678}
1679
1680parser! {
1681    fn deref[I]()(I) -> Expr
1682    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1683    {
1684        (position(), token('*').with(expr()))
1685            .map(|(pos, expr)| ExprKind::Deref(Arc::new(expr)).to_expr(pos))
1686    }
1687}
1688
1689parser! {
1690    fn expr[I]()(I) -> Expr
1691    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1692    {
1693        choice((
1694            attempt(choice((
1695                attempt(spaces().with(try_catch())),
1696                attempt(spaces().with(module())),
1697                attempt(spaces().with(use_module())),
1698                attempt(spaces().with(typedef())),
1699                attempt(spaces().with(raw_string())),
1700                attempt(spaces().with(array())),
1701                attempt(spaces().with(byref())),
1702                attempt(spaces().with(connect())),
1703                attempt(spaces().with(arith())),
1704                attempt(spaces().with(qop(mapref()))),
1705                attempt(spaces().with(qop(arrayref()))),
1706                attempt(spaces().with(qop(tupleref()))),
1707                attempt(spaces().with(qop(structref()))),
1708                attempt(spaces().with(qop(deref()))),
1709                attempt(spaces().with(qop(apply()))),
1710                attempt(spaces().with(tuple())),
1711                attempt(spaces().with(between(token('('), sptoken(')'), expr()))),
1712            ))),
1713            attempt(spaces().with(structure())),
1714            attempt(spaces().with(map())),
1715            attempt(spaces().with(variant())),
1716            attempt(spaces().with(structwith())),
1717            attempt(spaces().with(qop(do_block()))),
1718            attempt(spaces().with(lambda())),
1719            attempt(spaces().with(letbind())),
1720            attempt(spaces().with(qop(select()))),
1721            attempt(spaces().with(qop(cast()))),
1722            attempt(spaces().with(qop(any()))),
1723            attempt(spaces().with(interpolated())),
1724            attempt(spaces().with(literal())),
1725            attempt(spaces().with(qop(reference())))
1726        ))
1727    }
1728}
1729
1730/// Parse one or more expressions
1731///
1732/// followed by (optional) whitespace and then eof. At least one
1733/// expression is required otherwise this function will fail.
1734pub fn parse(ori: Origin) -> anyhow::Result<Arc<[Expr]>> {
1735    let ori = Arc::new(ori);
1736    set_origin(ori.clone());
1737    let mut r: LPooled<Vec<Option<Expr>>> = sep_by1(
1738        choice((expr().map(Some), look_ahead(spaces().with(eof())).map(|_| None))),
1739        attempt(sptoken(';')),
1740    )
1741    .skip(spaces())
1742    .skip(eof())
1743    .easy_parse(position::Stream::new(&*ori.text))
1744    .map(|(r, _)| r)
1745    .map_err(|e| anyhow::anyhow!(format!("{}", e)))?;
1746    Ok(Arc::from_iter(r.drain(..).filter_map(|e| e)))
1747}
1748
1749/// Parse one and only one expression.
1750pub fn parse_one(s: &str) -> anyhow::Result<Expr> {
1751    expr()
1752        .skip(spaces())
1753        .skip(eof())
1754        .easy_parse(position::Stream::new(&*s))
1755        .map(|(r, _)| r)
1756        .map_err(|e| anyhow::anyhow!(format!("{e}")))
1757}
1758
1759pub fn test_parse_mapref(s: &str) -> anyhow::Result<Expr> {
1760    mapref()
1761        .skip(spaces())
1762        .skip(eof())
1763        .easy_parse(position::Stream::new(&*s))
1764        .map(|(r, _)| r)
1765        .map_err(|e| anyhow::anyhow!(format!("{e}")))
1766}
1767
1768/// Parse one fntype expression
1769pub fn parse_fn_type(s: &str) -> anyhow::Result<FnType> {
1770    fntype()
1771        .skip(spaces())
1772        .skip(eof())
1773        .easy_parse(position::Stream::new(s))
1774        .map(|(r, _)| r)
1775        .map_err(|e| anyhow::anyhow!(format!("{e}")))
1776}
1777
1778/// Parse one type expression
1779pub fn parse_type(s: &str) -> anyhow::Result<Type> {
1780    typexp()
1781        .skip(spaces())
1782        .skip(eof())
1783        .easy_parse(position::Stream::new(s))
1784        .map(|(r, _)| r)
1785        .map_err(|e| anyhow::anyhow!(format!("{e}")))
1786}
1787
1788pub(super) fn parse_modpath(s: &str) -> anyhow::Result<ModPath> {
1789    modpath()
1790        .skip(spaces())
1791        .skip(eof())
1792        .easy_parse(position::Stream::new(s))
1793        .map(|(r, _)| r)
1794        .map_err(|e| anyhow::anyhow!(format!("{e}")))
1795}