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