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