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, StructurePattern,
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 module[I]()(I) -> Expr
355    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
356    {
357        (
358            position(),
359            optional(string("pub").skip(space())).map(|o| o.is_some()),
360            spstring("mod").with(space()).with(spfname()),
361            optional(attempt(between(sptoken('{'), sptoken('}'), sep_by(expr(), attempt(sptoken(';'))))))
362                .map(|m: Option<Vec<Expr>>| match m {
363                    Some(m) => ModuleKind::Inline(Arc::from(m)),
364                    None => ModuleKind::Unresolved
365                }),
366        )
367            .map(|(pos, export, name, value)| {
368                ExprKind::Module { name, export, value }.to_expr(pos)
369            })
370    }
371}
372
373fn use_module<I>() -> impl Parser<I, Output = Expr>
374where
375    I: RangeStream<Token = char, Position = SourcePosition>,
376    I::Error: ParseError<I::Token, I::Range, I::Position>,
377    I::Range: Range,
378{
379    (position(), string("use").with(space()).with(spmodpath()))
380        .map(|(pos, name)| ExprKind::Use { name }.to_expr(pos))
381}
382
383parser! {
384    fn do_block[I]()(I) -> Expr
385    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
386    {
387        (
388            position(),
389            between(token('{'), sptoken('}'), sep_by1(expr(), attempt(sptoken(';')))),
390        )
391            .then(|(pos, args): (_, Vec<Expr>)| {
392                if args.len() < 2 {
393                    unexpected_any("do must contain at least 2 expressions").left()
394                } else {
395                    value(ExprKind::Do { exprs: Arc::from(args) }.to_expr(pos)).right()
396                }
397            })
398    }
399}
400
401parser! {
402    fn array[I]()(I) -> Expr
403    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
404    {
405        (position(), between(token('['), sptoken(']'), sep_by(expr(), csep()))).map(
406            |(pos, args): (_, SmallVec<[Expr; 4]>)| {
407                ExprKind::Array { args: Arc::from_iter(args.into_iter()) }.to_expr(pos)
408            },
409        )
410    }
411}
412
413parser! {
414    fn apply_pexp[I]()(I) -> Expr
415    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
416    {
417        choice((
418            attempt(spaces().with(qop(reference()))),
419            between(sptoken('('), sptoken(')'), expr()),
420        ))
421    }
422}
423
424parser! {
425    fn ref_pexp[I]()(I) -> Expr
426    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
427    {
428        choice((
429            attempt(spaces().with(qop(reference()))),
430            between(sptoken('('), sptoken(')'), expr()),
431        ))
432    }
433}
434
435parser! {
436    fn structref[I]()(I) -> Expr
437    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
438    {
439        (position(), ref_pexp().skip(sptoken('.')), spfname()).map(|(pos, source, field)| {
440            ExprKind::StructRef { source: Arc::new(source), field }.to_expr(pos)
441        })
442    }
443}
444
445parser! {
446    fn tupleref[I]()(I) -> Expr
447    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
448    {
449        (position(), ref_pexp().skip(sptoken('.')), int::<_, usize>()).map(
450            |(pos, source, field)| {
451                ExprKind::TupleRef { source: Arc::new(source), field }.to_expr(pos)
452            },
453        )
454    }
455}
456
457parser! {
458    fn arrayref[I]()(I) -> Expr
459    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
460    {
461        (
462            position(),
463            ref_pexp(),
464            between(
465                token('['),
466                sptoken(']'),
467                choice((
468                    attempt(
469                        (
470                            position(),
471                            spaces().with(optional(many1(digit()))).skip(spstring("..")),
472                            spaces().with(optional(many1(digit()))),
473                        )
474                            .skip(look_ahead(sptoken(']'))),
475                    )
476                        .map(
477                            |(pos, start, end): (
478                                _,
479                                Option<CompactString>,
480                                Option<CompactString>,
481                            )| {
482                                let start = start.map(|i| Value::U64(i.parse().unwrap()));
483                                let start = start.map(|e| ExprKind::Constant(e).to_expr(pos));
484                                let end = end.map(|i| Value::U64(i.parse().unwrap()));
485                                let end = end.map(|e| ExprKind::Constant(e).to_expr(pos));
486                                Either::Left((start, end))
487                            },
488                        ),
489                    attempt((
490                        optional(attempt(expr())).skip(spstring("..")),
491                        optional(attempt(expr())),
492                    ))
493                        .map(|(start, end)| Either::Left((start, end))),
494                    attempt(expr()).map(|e| Either::Right(e)),
495                )),
496            ),
497        )
498            .map(|(pos, a, args)| match args {
499                Either::Left((start, end)) => ExprKind::ArraySlice {
500                    source: Arc::new(a),
501                    start: start.map(Arc::new),
502                    end: end.map(Arc::new),
503                }
504                .to_expr(pos),
505                Either::Right(i) => {
506                    ExprKind::ArrayRef { source: Arc::new(a), i: Arc::new(i) }.to_expr(pos)
507                }
508            })
509    }
510}
511
512parser! {
513    fn apply[I]()(I) -> Expr
514    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
515    {
516        (
517            position(),
518            apply_pexp(),
519            between(
520                sptoken('('),
521                sptoken(')'),
522                sep_by(
523                    choice((
524                        attempt((sptoken('#').with(fname()).skip(token(':')), expr()))
525                            .map(|(n, e)| (Some(n), e)),
526                        attempt((
527                            position(),
528                            sptoken('#').with(fname()),
529                        ))
530                            .map(|(pos, n)| {
531                                let e = ExprKind::Ref { name: [n.clone()].into() }.to_expr(pos);
532                                (Some(n), e)
533                            }),
534                        expr().map(|e| (None, e)),
535                    )),
536                    csep(),
537                ),
538            ),
539        )
540            .then(|(pos, function, args): (_, Expr, Vec<(Option<ArcStr>, Expr)>)| {
541                let mut anon = false;
542                for (a, _) in &args {
543                    if a.is_some() && anon {
544                        return unexpected_any(
545                            "labeled arguments must come before anonymous arguments",
546                        )
547                            .right();
548                    }
549                    anon |= a.is_none();
550                }
551                value((pos, function, args)).left()
552            })
553            .map(|(pos, function, args): (_, Expr, Vec<(Option<ArcStr>, Expr)>)| {
554                ExprKind::Apply { function: Arc::new(function), args: Arc::from(args) }
555                .to_expr(pos)
556            })
557    }
558}
559
560parser! {
561    fn any[I]()(I) -> Expr
562    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
563    {
564        (
565            position(),
566            string("any").with(between(sptoken('('), sptoken(')'), sep_by(expr(), csep()))),
567        )
568            .map(|(pos, args): (_, Vec<Expr>)| {
569                ExprKind::Any { args: Arc::from(args) }.to_expr(pos)
570            })
571    }
572}
573
574fn typeprim<I>() -> impl Parser<I, Output = Typ>
575where
576    I: RangeStream<Token = char>,
577    I::Error: ParseError<I::Token, I::Range, I::Position>,
578    I::Range: Range,
579{
580    choice((
581        attempt(spstring("u32").map(|_| Typ::U32)),
582        attempt(spstring("v32").map(|_| Typ::V32)),
583        attempt(spstring("i32").map(|_| Typ::I32)),
584        attempt(spstring("z32").map(|_| Typ::Z32)),
585        attempt(spstring("u64").map(|_| Typ::U64)),
586        attempt(spstring("v64").map(|_| Typ::V64)),
587        attempt(spstring("i64").map(|_| Typ::I64)),
588        attempt(spstring("z64").map(|_| Typ::Z64)),
589        attempt(spstring("f32").map(|_| Typ::F32)),
590        attempt(spstring("f64").map(|_| Typ::F64)),
591        attempt(spstring("decimal").map(|_| Typ::Decimal)),
592        attempt(spstring("datetime").map(|_| Typ::DateTime)),
593        attempt(spstring("duration").map(|_| Typ::Duration)),
594        attempt(spstring("bool").map(|_| Typ::Bool)),
595        attempt(spstring("string").map(|_| Typ::String)),
596        attempt(spstring("bytes").map(|_| Typ::Bytes)),
597        attempt(spstring("error").map(|_| Typ::Error)),
598        attempt(spstring("array").map(|_| Typ::Array)),
599        attempt(spstring("null").map(|_| Typ::Null)),
600    ))
601    .skip(not_followed_by(choice((alpha_num(), token('_')))))
602}
603
604parser! {
605    fn fntype[I]()(I) -> FnType
606    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
607    {
608        spstring("fn")
609            .with((
610                optional(attempt(between(
611                    token('<'),
612                    sptoken('>'),
613                    sep_by1((tvar().skip(sptoken(':')), typexp()), csep()),
614                )))
615                    .map(|cs: Option<SmallVec<[(TVar, Type); 4]>>| match cs {
616                        Some(cs) => Arc::new(RwLock::new(cs.into_iter().collect())),
617                        None => Arc::new(RwLock::new(vec![])),
618                    }),
619                between(
620                    token('('),
621                    sptoken(')'),
622                    sep_by(
623                        choice((
624                            attempt(
625                                (
626                                    spaces()
627                                        .with(optional(token('?')).map(|o| o.is_some()))
628                                        .skip(token('#')),
629                                    fname().skip(token(':')),
630                                    typexp(),
631                                )
632                                    .map(
633                                        |(optional, name, typ)| {
634                                            Either::Left(FnArgType {
635                                                label: Some((name.into(), optional)),
636                                                typ,
637                                            })
638                                        },
639                                    ),
640                            ),
641                            attempt(
642                                typexp()
643                                    .map(|typ| Either::Left(FnArgType { label: None, typ })),
644                            ),
645                            attempt(
646                                spstring("@args:").with(typexp()).map(|e| Either::Right(e)),
647                            ),
648                        )),
649                        csep(),
650                    ),
651                ),
652                spstring("->").with(typexp()),
653            ))
654            .then(
655                |(constraints, mut args, rtype): (
656                    Arc<RwLock<Vec<(TVar, Type)>>>,
657                    Vec<Either<FnArgType, Type>>,
658                    Type,
659                )| {
660                    let vargs = match args.pop() {
661                        None => None,
662                        Some(Either::Right(t)) => Some(t),
663                        Some(Either::Left(t)) => {
664                            args.push(Either::Left(t));
665                            None
666                        }
667                    };
668                    if !args.iter().all(|a| a.is_left()) {
669                        return unexpected_any(
670                            "vargs must appear once at the end of the args",
671                        )
672                            .left();
673                    }
674                    let args = Arc::from_iter(args.into_iter().map(|t| match t {
675                        Either::Left(t) => t,
676                        Either::Right(_) => unreachable!(),
677                    }));
678                    let mut anon = false;
679                    for a in args.iter() {
680                        if anon && a.label.is_some() {
681                            return unexpected_any(
682                                "anonymous args must appear after labeled args",
683                            )
684                                .left();
685                        }
686                        anon |= a.label.is_none();
687                    }
688                    value(FnType { args, vargs, rtype, constraints }).right()
689                },
690            )
691    }
692}
693
694fn tvar<I>() -> impl Parser<I, Output = TVar>
695where
696    I: RangeStream<Token = char>,
697    I::Error: ParseError<I::Token, I::Range, I::Position>,
698    I::Range: Range,
699{
700    sptoken('\'').with(fname()).map(TVar::empty_named)
701}
702
703parser! {
704    fn typexp[I]()(I) -> Type
705    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
706    {
707        choice((
708            attempt(sptoken('&').with(typexp()).map(|t| Type::ByRef(Arc::new(t)))),
709            attempt(sptoken('_').map(|_| Type::Bottom)),
710            attempt(
711                between(sptoken('['), sptoken(']'), sep_by(typexp(), csep()))
712                    .map(|ts: SmallVec<[Type; 16]>| Type::flatten_set(ts)),
713            ),
714            attempt(between(sptoken('('), sptoken(')'), sep_by1(typexp(), csep())).then(
715                |exps: SmallVec<[Type; 16]>| {
716                    if exps.len() < 2 {
717                        unexpected_any("tuples must have at least 2 elements").left()
718                    } else {
719                        value(Type::Tuple(Arc::from_iter(exps))).right()
720                    }
721                },
722            )),
723            attempt(
724                between(
725                    sptoken('{'),
726                    sptoken('}'),
727                    sep_by1((spfname().skip(sptoken(':')), typexp()), csep()),
728                )
729                    .then(|mut exps: SmallVec<[(ArcStr, Type); 16]>| {
730                        let s = exps.iter().map(|(n, _)| n).collect::<FxHashSet<_>>();
731                        if s.len() < exps.len() {
732                            return unexpected_any("struct field names must be unique").left();
733                        }
734                        exps.sort_by_key(|(n, _)| n.clone());
735                        value(Type::Struct(Arc::from_iter(exps))).right()
736                    }),
737            ),
738            attempt(
739                (
740                    sptoken('`').with(typname()),
741                    optional(attempt(between(
742                        token('('),
743                        sptoken(')'),
744                        sep_by1(typexp(), csep()),
745                    ))),
746                )
747                    .map(|(tag, typs): (ArcStr, Option<SmallVec<[Type; 5]>>)| {
748                        let t = match typs {
749                            None => smallvec![],
750                            Some(v) => v,
751                        };
752                        Type::Variant(tag.clone(), Arc::from_iter(t))
753                    }),
754            ),
755            attempt(fntype().map(|f| Type::Fn(Arc::new(f)))),
756            attempt(spstring("Array").with(between(sptoken('<'), sptoken('>'), typexp())))
757                .map(|t| Type::Array(Arc::new(t))),
758            attempt((
759                sptypath(),
760                optional(attempt(between(
761                    sptoken('<'),
762                    sptoken('>'),
763                    sep_by1(typexp(), csep()),
764                ))),
765            ))
766                .map(|(n, params): (ModPath, Option<SmallVec<[Type; 8]>>)| {
767                    let params = params
768                        .map(|a| Arc::from_iter(a.into_iter()))
769                        .unwrap_or_else(|| Arc::from_iter([]));
770                    Type::Ref { scope: ModPath::root(), name: n, params }
771                }),
772            attempt(spstring("Any")).map(|_| Type::Any),
773            attempt(typeprim()).map(|typ| Type::Primitive(typ.into())),
774            attempt(tvar()).map(|tv| Type::TVar(tv)),
775        ))
776    }
777}
778
779parser! {
780    fn lambda_args[I]()(I) -> (Vec<Arg>, Option<Option<Type>>)
781    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
782    {
783        sep_by(
784            (
785                choice((
786                    attempt(spaces().with(structure_pattern())).map(|p| (false, p)),
787                    attempt(spaces().with(token('#').with(fname())))
788                        .map(|b| (true, StructurePattern::Bind(b))),
789                    attempt(spstring("@args"))
790                        .map(|s| (false, StructurePattern::Bind(ArcStr::from(s)))),
791                )),
792                optional(attempt(sptoken(':').with(typexp()))),
793                optional(attempt(sptoken('=').with(expr()))),
794            ),
795            csep(),
796        )
797            .then(|v: Vec<((bool, StructurePattern), Option<Type>, Option<Expr>)>| {
798                let args = v
799                    .into_iter()
800                    .map(|((labeled, pattern), constraint, default)| {
801                        if !labeled && default.is_some() {
802                            bail!("labeled")
803                        } else {
804                            Ok(Arg { labeled: labeled.then_some(default), pattern, constraint })
805                        }
806                    })
807                    .collect::<Result<Vec<_>>>();
808                match args {
809                    Ok(a) => value(a).right(),
810                    Err(_) => {
811                        unexpected_any("only labeled arguments may have a default value").left()
812                    }
813                }
814            })
815        // @args must be last
816            .then(|mut v: Vec<Arg>| {
817                match v.iter().enumerate().find(|(_, a)| match &a.pattern {
818                    StructurePattern::Bind(n) if n == "@args" => true,
819                    _ => false,
820                }) {
821                    None => value((v, None)).left(),
822                    Some((i, _)) => {
823                        if i == v.len() - 1 {
824                            let a = v.pop().unwrap();
825                            value((v, Some(a.constraint))).left()
826                        } else {
827                            unexpected_any("@args must be the last argument").right()
828                        }
829                    }
830                }
831            })
832        // labeled before anonymous args
833            .then(|(v, vargs): (Vec<Arg>, Option<Option<Type>>)| {
834                let mut anon = false;
835                for a in &v {
836                    if a.labeled.is_some() && anon {
837                        return unexpected_any("labeled args must come before anon args").right();
838                    }
839                    anon |= a.labeled.is_none();
840                }
841                value((v, vargs)).left()
842            })
843    }
844}
845
846parser! {
847    fn lambda[I]()(I) -> Expr
848    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
849    {
850        (
851            position(),
852            attempt(sep_by((tvar().skip(sptoken(':')), typexp()), csep()))
853                .map(|tvs: SmallVec<[(TVar, Type); 4]>| Arc::from_iter(tvs)),
854            between(sptoken('|'), sptoken('|'), lambda_args()),
855            optional(attempt(spstring("->").with(typexp()).skip(space()))),
856            choice((
857                attempt(sptoken('\'').with(fname()).skip(not_followed_by(sptoken(':'))))
858                    .map(Either::Right),
859                expr().map(|e| Either::Left(e)),
860            )),
861        )
862            .map(|(pos, constraints, (args, vargs), rtype, body)| {
863                let args = Arc::from_iter(args);
864                ExprKind::Lambda(Arc::new(Lambda { args, vargs, rtype, constraints, body }))
865                    .to_expr(pos)
866            })
867    }
868}
869
870parser! {
871    fn letbind[I]()(I) -> Expr
872    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
873    {
874        (
875            position(),
876            doc_comment(),
877            optional(string("pub").skip(space())).map(|o| o.is_some()),
878            spstring("let")
879                .with(space())
880                .with((structure_pattern(), optional(attempt(sptoken(':').with(typexp())))))
881                .skip(spstring("=")),
882            expr(),
883        )
884            .map(|(pos, doc, export, (pattern, typ), value)| {
885                ExprKind::Bind(Arc::new(Bind { doc, export, pattern, typ, value }))
886                    .to_expr(pos)
887            })
888    }
889}
890
891parser! {
892    fn connect[I]()(I) -> Expr
893    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
894    {
895        (position(), optional(token('*')), spmodpath().skip(spstring("<-")), expr()).map(
896            |(pos, deref, name, e)| {
897                ExprKind::Connect { name, value: Arc::new(e), deref: deref.is_some() }
898                .to_expr(pos)
899            },
900        )
901    }
902}
903
904fn literal<I>() -> impl Parser<I, Output = Expr>
905where
906    I: RangeStream<Token = char, Position = SourcePosition>,
907    I::Error: ParseError<I::Token, I::Range, I::Position>,
908    I::Range: Range,
909{
910    (position(), parse_value(&GRAPHIX_ESC).skip(not_followed_by(token('_'))))
911        .map(|(pos, v)| ExprKind::Constant(v).to_expr(pos))
912}
913
914fn reference<I>() -> impl Parser<I, Output = Expr>
915where
916    I: RangeStream<Token = char, Position = SourcePosition>,
917    I::Error: ParseError<I::Token, I::Range, I::Position>,
918    I::Range: Range,
919{
920    (position(), modpath()).map(|(pos, name)| ExprKind::Ref { name }.to_expr(pos))
921}
922
923parser! {
924    fn deref_arith[I]()(I) -> Expr
925    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
926    {
927        (position(), token('*').with(arith_term()))
928            .map(|(pos, expr)| ExprKind::Deref(Arc::new(expr)).to_expr(pos))
929    }
930}
931
932parser! {
933    fn qop[I, P](p: P)(I) -> Expr
934    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range, P: Parser<I, Output = Expr>]
935    {
936        (position(), p, optional(attempt(sptoken('?')))).map(|(pos, e, qop)| match qop {
937            None => e,
938            Some(_) => ExprKind::Qop(Arc::new(e)).to_expr(pos),
939        })
940    }
941}
942
943parser! {
944    fn arith_term[I]()(I) -> Expr
945    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
946    {
947        choice((
948            attempt(spaces().with(qop(deref_arith()))),
949            attempt(spaces().with(raw_string())),
950            attempt(spaces().with(array())),
951            attempt(spaces().with(byref_arith())),
952            attempt(spaces().with(tuple())),
953            attempt(spaces().with(structure())),
954            attempt(spaces().with(variant())),
955            attempt(spaces().with(qop(apply()))),
956            attempt(spaces().with(structwith())),
957            attempt(spaces().with(qop(arrayref()))),
958            attempt(spaces().with(qop(tupleref()))),
959            attempt(spaces().with(qop(structref()))),
960            attempt(spaces().with(qop(do_block()))),
961            attempt(spaces().with(qop(select()))),
962            attempt(spaces().with(qop(cast()))),
963            attempt(spaces().with(qop(any()))),
964            attempt(spaces().with(interpolated())),
965            attempt(spaces().with(literal())),
966            attempt(spaces().with(qop(reference()))),
967            attempt(
968                (position(), sptoken('!').with(arith()))
969                    .map(|(pos, expr)| ExprKind::Not { expr: Arc::new(expr) }.to_expr(pos)),
970            ),
971            attempt(between(sptoken('('), sptoken(')'), arith())),
972        ))
973            .skip(spaces())
974    }
975}
976
977parser! {
978    fn arith[I]()(I) -> Expr
979    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
980    {
981        choice((
982            attempt(chainl1(
983                arith_term(),
984                choice((
985                    attempt(spstring("+")),
986                    attempt(spstring("-")),
987                    attempt(spstring("*")),
988                    attempt(spstring("/")),
989                    attempt(spstring("%")),
990                    attempt(spstring("==")),
991                    attempt(spstring("!=")),
992                    attempt(spstring(">=")),
993                    attempt(spstring("<=")),
994                    attempt(spstring(">")),
995                    attempt(spstring("<")),
996                    attempt(spstring("&&")),
997                    attempt(spstring("||")),
998                    attempt(spstring("~")),
999                ))
1000                    .map(|op: &str| match op {
1001                        "+" => |lhs: Expr, rhs: Expr| {
1002                            let pos = lhs.pos;
1003                            ExprKind::Add { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1004                        },
1005                        "-" => |lhs: Expr, rhs: Expr| {
1006                            let pos = lhs.pos;
1007                            ExprKind::Sub { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1008                        },
1009                        "*" => |lhs: Expr, rhs: Expr| {
1010                            let pos = lhs.pos;
1011                            ExprKind::Mul { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1012                        },
1013                        "/" => |lhs: Expr, rhs: Expr| {
1014                            let pos = lhs.pos;
1015                            ExprKind::Div { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1016                        },
1017                        "%" => |lhs: Expr, rhs: Expr| {
1018                            let pos = lhs.pos;
1019                            ExprKind::Mod { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1020                        },
1021                        "==" => |lhs: Expr, rhs: Expr| {
1022                            let pos = lhs.pos;
1023                            ExprKind::Eq { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1024                        },
1025                        "!=" => |lhs: Expr, rhs: Expr| {
1026                            let pos = lhs.pos;
1027                            ExprKind::Ne { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1028                        },
1029                        ">" => |lhs: Expr, rhs: Expr| {
1030                            let pos = lhs.pos;
1031                            ExprKind::Gt { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1032                        },
1033                        "<" => |lhs: Expr, rhs: Expr| {
1034                            let pos = lhs.pos;
1035                            ExprKind::Lt { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1036                        },
1037                        ">=" => |lhs: Expr, rhs: Expr| {
1038                            let pos = lhs.pos;
1039                            ExprKind::Gte { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1040                        },
1041                        "<=" => |lhs: Expr, rhs: Expr| {
1042                            let pos = lhs.pos;
1043                            ExprKind::Lte { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1044                        },
1045                        "&&" => |lhs: Expr, rhs: Expr| {
1046                            let pos = lhs.pos;
1047                            ExprKind::And { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1048                        },
1049                        "||" => |lhs: Expr, rhs: Expr| {
1050                            let pos = lhs.pos;
1051                            ExprKind::Or { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1052                        },
1053                        "~" => |lhs: Expr, rhs: Expr| {
1054                            let pos = lhs.pos;
1055                            ExprKind::Sample { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }
1056                            .to_expr(pos)
1057                        },
1058                        _ => unreachable!(),
1059                    }),
1060            )),
1061            attempt((position(), sptoken('!').with(arith_term())))
1062                .map(|(pos, expr)| ExprKind::Not { expr: Arc::new(expr) }.to_expr(pos)),
1063            attempt(between(sptoken('('), sptoken(')'), arith())),
1064        ))
1065    }
1066}
1067
1068parser! {
1069    fn slice_pattern[I]()(I) -> StructurePattern
1070    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1071    {
1072        macro_rules! all_left {
1073            ($pats:expr) => {{
1074                let mut err = false;
1075                let pats: Arc<[StructurePattern]> =
1076                    Arc::from_iter($pats.into_iter().map(|s| match s {
1077                        Either::Left(s) => s,
1078                        Either::Right(_) => {
1079                            err = true;
1080                            StructurePattern::Ignore
1081                        }
1082                    }));
1083                if err {
1084                    return unexpected_any("invalid pattern").left();
1085                }
1086                pats
1087            }};
1088        }
1089        (
1090            optional(attempt(spfname().skip(sptoken('@')))),
1091            between(
1092                sptoken('['),
1093                sptoken(']'),
1094                sep_by(
1095                    choice((
1096                        attempt(spstring("..")).map(|_| Either::Right(None)),
1097                        attempt(spfname().skip(spstring("..")))
1098                            .map(|n| Either::Right(Some(n))),
1099                        structure_pattern().map(|p| Either::Left(p)),
1100                    )),
1101                    csep(),
1102                ),
1103            ),
1104        )
1105            .then(
1106                |(all, mut pats): (
1107                    Option<ArcStr>,
1108                    SmallVec<[Either<StructurePattern, Option<ArcStr>>; 8]>,
1109                )| {
1110                    if pats.len() == 0 {
1111                        value(StructurePattern::Slice { all, binds: Arc::from_iter([]) })
1112                            .right()
1113                    } else if pats.len() == 1 {
1114                        match pats.pop().unwrap() {
1115                            Either::Left(s) => value(StructurePattern::Slice {
1116                                all,
1117                                binds: Arc::from_iter([s]),
1118                            })
1119                                .right(),
1120                            Either::Right(_) => {
1121                                unexpected_any("invalid singular range match").left()
1122                            }
1123                        }
1124                    } else {
1125                        match (&pats[0], &pats[pats.len() - 1]) {
1126                            (Either::Right(_), Either::Right(_)) => {
1127                                unexpected_any("invalid pattern").left()
1128                            }
1129                            (Either::Right(_), Either::Left(_)) => {
1130                                let head = pats.remove(0).right().unwrap();
1131                                let suffix = all_left!(pats);
1132                                value(StructurePattern::SliceSuffix { all, head, suffix })
1133                                    .right()
1134                            }
1135                            (Either::Left(_), Either::Right(_)) => {
1136                                let tail = pats.pop().unwrap().right().unwrap();
1137                                let prefix = all_left!(pats);
1138                                value(StructurePattern::SlicePrefix { all, tail, prefix })
1139                                    .right()
1140                            }
1141                            (Either::Left(_), Either::Left(_)) => {
1142                                value(StructurePattern::Slice { all, binds: all_left!(pats) })
1143                                    .right()
1144                            }
1145                        }
1146                    }
1147                },
1148            )
1149    }
1150}
1151
1152fn raw_string<I>() -> impl Parser<I, Output = Expr>
1153where
1154    I: RangeStream<Token = char, Position = SourcePosition>,
1155    I::Error: ParseError<I::Token, I::Range, I::Position>,
1156    I::Range: Range,
1157{
1158    const ESC: [char; 2] = ['\'', '\\'];
1159    (position(), between(string("r\'"), token('\''), escaped_string(&ESC))).map(
1160        |(pos, s): (_, String)| ExprKind::Constant(Value::String(s.into())).to_expr(pos),
1161    )
1162}
1163
1164parser! {
1165    fn tuple_pattern[I]()(I) -> StructurePattern
1166    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1167    {
1168        (
1169            optional(attempt(spfname().skip(sptoken('@')))),
1170            between(sptoken('('), sptoken(')'), sep_by1(structure_pattern(), csep())),
1171        )
1172            .then(|(all, binds): (Option<ArcStr>, SmallVec<[StructurePattern; 8]>)| {
1173                if binds.len() < 2 {
1174                    unexpected_any("tuples must have at least 2 elements").left()
1175                } else {
1176                    value(StructurePattern::Tuple { all, binds: Arc::from_iter(binds) })
1177                        .right()
1178                }
1179            })
1180    }
1181}
1182
1183parser! {
1184    fn variant_pattern[I]()(I) -> StructurePattern
1185    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1186    {
1187        (
1188            optional(attempt(spfname().skip(sptoken('@')))),
1189            sptoken('`').with(typname()),
1190            optional(attempt(between(
1191                sptoken('('),
1192                sptoken(')'),
1193                sep_by1(structure_pattern(), csep()),
1194            ))),
1195        )
1196            .map(
1197                |(all, tag, binds): (
1198                    Option<ArcStr>,
1199                    ArcStr,
1200                    Option<SmallVec<[StructurePattern; 8]>>,
1201                )| {
1202                    let binds = match binds {
1203                        None => smallvec![],
1204                        Some(a) => a,
1205                    };
1206                    StructurePattern::Variant { all, tag, binds: Arc::from_iter(binds) }
1207                },
1208            )
1209    }
1210}
1211
1212parser! {
1213    fn struct_pattern[I]()(I) -> StructurePattern
1214    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1215    {
1216        (
1217            optional(attempt(spfname().skip(sptoken('@')))),
1218            between(
1219                sptoken('{'),
1220                sptoken('}'),
1221                sep_by1(
1222                    choice((
1223                        attempt((spfname().skip(sptoken(':')), structure_pattern()))
1224                            .map(|(s, p)| (s, p, true)),
1225                        attempt(spfname()).map(|s| {
1226                            let p = StructurePattern::Bind(s.clone());
1227                            (s, p, true)
1228                        }),
1229                        spstring("..")
1230                            .map(|_| (literal!(""), StructurePattern::Ignore, false)),
1231                    )),
1232                    csep(),
1233                ),
1234            ),
1235        )
1236            .then(
1237                |(all, mut binds): (
1238                    Option<ArcStr>,
1239                    SmallVec<[(ArcStr, StructurePattern, bool); 8]>,
1240                )| {
1241                    let mut exhaustive = true;
1242                    binds.retain(|(_, _, ex)| {
1243                        exhaustive &= *ex;
1244                        *ex
1245                    });
1246                    binds.sort_by_key(|(s, _, _)| s.clone());
1247                    let s = binds.iter().map(|(s, _, _)| s).collect::<FxHashSet<_>>();
1248                    if s.len() < binds.len() {
1249                        unexpected_any("struct fields must be unique").left()
1250                    } else {
1251                        let binds = Arc::from_iter(binds.into_iter().map(|(s, p, _)| (s, p)));
1252                        value(StructurePattern::Struct { all, exhaustive, binds }).right()
1253                    }
1254                },
1255            )
1256    }
1257}
1258
1259parser! {
1260    fn structure_pattern[I]()(I) -> StructurePattern
1261    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1262    {
1263        choice((
1264            attempt(slice_pattern()),
1265            attempt(tuple_pattern()),
1266            attempt(struct_pattern()),
1267            attempt(variant_pattern()),
1268            attempt(parse_value(&VAL_ESC).skip(not_followed_by(token('_'))))
1269                .map(|v| StructurePattern::Literal(v)),
1270            attempt(sptoken('_')).map(|_| StructurePattern::Ignore),
1271            spfname().map(|name| StructurePattern::Bind(name)),
1272        ))
1273    }
1274}
1275
1276parser! {
1277    fn pattern[I]()(I) -> Pattern
1278    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1279    {
1280        (
1281            optional(attempt(typexp().skip(space().with(spstring("as "))))),
1282            structure_pattern(),
1283            optional(attempt(space().with(spstring("if").with(space()).with(expr())))),
1284        )
1285            .map(
1286                |(type_predicate, structure_predicate, guard): (
1287                    Option<Type>,
1288                    StructurePattern,
1289                    Option<Expr>,
1290                )| { Pattern { type_predicate, structure_predicate, guard } },
1291            )
1292    }
1293}
1294
1295parser! {
1296    fn select[I]()(I) -> Expr
1297    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1298    {
1299        (
1300            position(),
1301            string("select").with(space()).with((
1302                expr(),
1303                between(
1304                    sptoken('{'),
1305                    sptoken('}'),
1306                    sep_by1((pattern(), spstring("=>").with(expr())), csep()),
1307                ),
1308            )),
1309        )
1310            .map(|(pos, (arg, arms)): (_, (Expr, Vec<(Pattern, Expr)>))| {
1311                ExprKind::Select { arg: Arc::new(arg), arms: Arc::from(arms) }.to_expr(pos)
1312            })
1313    }
1314}
1315
1316parser! {
1317    fn cast[I]()(I) -> Expr
1318    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1319    {
1320        (
1321            position(),
1322            string("cast").with(between(token('<'), sptoken('>'), typexp())),
1323            between(sptoken('('), sptoken(')'), expr()),
1324        )
1325            .map(|(pos, typ, e)| ExprKind::TypeCast { expr: Arc::new(e), typ }.to_expr(pos))
1326    }
1327}
1328
1329parser! {
1330    fn typedef[I]()(I) -> Expr
1331    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1332    {
1333        (
1334            position(),
1335            string("type").with(sptypname()),
1336            optional(attempt(between(
1337                sptoken('<'),
1338                sptoken('>'),
1339                sep_by1((tvar(), optional(attempt(sptoken(':').with(typexp())))), csep()),
1340            ))),
1341            sptoken('=').with(typexp()),
1342        )
1343            .map(|(pos, name, params, typ)| {
1344                let params = params
1345                    .map(|ps: SmallVec<[(TVar, Option<Type>); 8]>| {
1346                        Arc::from_iter(ps.into_iter())
1347                    })
1348                    .unwrap_or_else(|| Arc::<[(TVar, Option<Type>)]>::from(Vec::new()));
1349                ExprKind::TypeDef { name, params, typ }.to_expr(pos)
1350            })
1351    }
1352}
1353
1354parser! {
1355    fn tuple[I]()(I) -> Expr
1356    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1357    {
1358        (position(), between(token('('), sptoken(')'), sep_by1(expr(), csep()))).then(
1359            |(pos, exprs): (_, SmallVec<[Expr; 8]>)| {
1360                if exprs.len() < 2 {
1361                    unexpected_any("tuples must have at least 2 elements").left()
1362                } else {
1363                    value(ExprKind::Tuple { args: Arc::from_iter(exprs) }.to_expr(pos))
1364                        .right()
1365                }
1366            },
1367        )
1368    }
1369}
1370
1371parser! {
1372    fn structure[I]()(I) -> Expr
1373    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1374    {
1375        (
1376            position(),
1377            between(
1378                token('{'),
1379                sptoken('}'),
1380                sep_by1((spfname(), optional(attempt(sptoken(':')).with(expr()))), csep()),
1381            ),
1382        )
1383            .then(|(pos, mut exprs): (_, SmallVec<[(ArcStr, Option<Expr>); 8]>)| {
1384                let s = exprs.iter().map(|(n, _)| n).collect::<FxHashSet<_>>();
1385                if s.len() < exprs.len() {
1386                    return unexpected_any("struct fields must be unique").left();
1387                }
1388                exprs.sort_by_key(|(n, _)| n.clone());
1389                let args = exprs.into_iter().map(|(n, e)| match e {
1390                    Some(e) => (n, e),
1391                    None => {
1392                        let e = ExprKind::Ref { name: [n.clone()].into() }.to_expr(pos);
1393                        (n, e)
1394                    }
1395                });
1396                value(ExprKind::Struct { args: Arc::from_iter(args) }.to_expr(pos)).right()
1397            })
1398    }
1399}
1400
1401parser! {
1402    fn variant[I]()(I) -> Expr
1403    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1404    {
1405        (
1406            position(),
1407            token('`').with(typname()),
1408            optional(attempt(between(token('('), sptoken(')'), sep_by1(expr(), csep())))),
1409        )
1410            .map(|(pos, tag, args): (_, ArcStr, Option<SmallVec<[Expr; 5]>>)| {
1411                let args = match args {
1412                    None => smallvec![],
1413                    Some(a) => a,
1414                };
1415                ExprKind::Variant { tag, args: Arc::from_iter(args.into_iter()) }.to_expr(pos)
1416            })
1417    }
1418}
1419
1420parser! {
1421    fn structwith[I]()(I) -> Expr
1422    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1423    {
1424        (
1425            position(),
1426            between(
1427                token('{'),
1428                sptoken('}'),
1429                (
1430                    ref_pexp().skip(space()).skip(spstring("with")).skip(space()),
1431                    sep_by1((spfname(), optional(attempt(sptoken(':').with(expr())))), csep()),
1432                ),
1433            ),
1434        )
1435            .then(
1436                |(pos, (source, mut exprs)): (_, (Expr, SmallVec<[(ArcStr, Option<Expr>); 8]>))| {
1437                    let s = exprs.iter().map(|(n, _)| n).collect::<FxHashSet<_>>();
1438                    if s.len() < exprs.len() {
1439                        return unexpected_any("struct fields must be unique").left();
1440                    }
1441                    exprs.sort_by_key(|(n, _)| n.clone());
1442                    let exprs = exprs.into_iter().map(|(name, e)| match e {
1443                        Some(e) => (name, e),
1444                        None => {
1445                            let e = ExprKind::Ref { name: ModPath::from([name.clone()]) }.to_expr(pos);
1446                            (name, e)
1447                        }
1448                    });
1449                    let e = ExprKind::StructWith {
1450                        source: Arc::new(source),
1451                        replace: Arc::from_iter(exprs),
1452                    }
1453                    .to_expr(pos);
1454                    value(e).right()
1455                },
1456            )
1457    }
1458}
1459
1460parser! {
1461    fn byref[I]()(I) -> Expr
1462    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1463    {
1464        (position(), token('&').with(expr()))
1465            .map(|(pos, expr)| ExprKind::ByRef(Arc::new(expr)).to_expr(pos))
1466    }
1467}
1468
1469parser! {
1470    fn byref_arith[I]()(I) -> Expr
1471    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1472    {
1473        (position(), token('&').with(arith_term()))
1474            .map(|(pos, expr)| ExprKind::ByRef(Arc::new(expr)).to_expr(pos))
1475    }
1476}
1477
1478parser! {
1479    fn deref[I]()(I) -> Expr
1480    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1481    {
1482        (position(), token('*').with(expr()))
1483            .map(|(pos, expr)| ExprKind::Deref(Arc::new(expr)).to_expr(pos))
1484    }
1485}
1486
1487parser! {
1488    fn expr[I]()(I) -> Expr
1489    where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1490    {
1491        choice((
1492            attempt(choice((
1493                attempt(spaces().with(module())),
1494                attempt(spaces().with(use_module())),
1495                attempt(spaces().with(typedef())),
1496                attempt(spaces().with(raw_string())),
1497                attempt(spaces().with(array())),
1498                attempt(spaces().with(byref())),
1499                attempt(spaces().with(connect())),
1500                attempt(spaces().with(arith())),
1501                attempt(spaces().with(qop(deref()))),
1502                attempt(spaces().with(tuple())),
1503                attempt(spaces().with(between(token('('), sptoken(')'), expr()))),
1504                attempt(spaces().with(structure())),
1505                attempt(spaces().with(variant())),
1506            ))),
1507            attempt(spaces().with(qop(apply()))),
1508            attempt(spaces().with(structwith())),
1509            attempt(spaces().with(qop(arrayref()))),
1510            attempt(spaces().with(qop(tupleref()))),
1511            attempt(spaces().with(qop(structref()))),
1512            attempt(spaces().with(qop(do_block()))),
1513            attempt(spaces().with(lambda())),
1514            attempt(spaces().with(letbind())),
1515            attempt(spaces().with(qop(select()))),
1516            attempt(spaces().with(qop(cast()))),
1517            attempt(spaces().with(qop(any()))),
1518            attempt(spaces().with(interpolated())),
1519            attempt(spaces().with(literal())),
1520            attempt(spaces().with(qop(reference())))
1521        ))
1522    }
1523}
1524
1525/// Parse one or more expressions
1526///
1527/// followed by (optional) whitespace and then eof. At least one
1528/// expression is required otherwise this function will fail.
1529pub fn parse(ori: Origin) -> anyhow::Result<Arc<[Expr]>> {
1530    let ori = Arc::new(ori);
1531    set_origin(ori.clone());
1532    let r: Vec<Expr> = sep_by1(expr(), attempt(sptoken(';')))
1533        .skip(spaces())
1534        .skip(eof())
1535        .easy_parse(position::Stream::new(&*ori.text))
1536        .map(|(r, _)| r)
1537        .map_err(|e| anyhow::anyhow!(format!("{}", e)))?;
1538    Ok(Arc::from(r))
1539}
1540
1541/// Parse one and only one expression.
1542pub fn parse_one(s: &str) -> anyhow::Result<Expr> {
1543    expr()
1544        .skip(spaces())
1545        .skip(eof())
1546        .easy_parse(position::Stream::new(&*s))
1547        .map(|(r, _)| r)
1548        .map_err(|e| anyhow::anyhow!(format!("{e}")))
1549}
1550
1551/// Parse a fntype
1552pub fn parse_fn_type(s: &str) -> anyhow::Result<FnType> {
1553    fntype()
1554        .skip(spaces())
1555        .skip(eof())
1556        .easy_parse(position::Stream::new(s))
1557        .map(|(r, _)| r)
1558        .map_err(|e| anyhow::anyhow!(format!("{e}")))
1559}
1560
1561pub(super) fn parse_modpath(s: &str) -> anyhow::Result<ModPath> {
1562    modpath()
1563        .skip(spaces())
1564        .skip(eof())
1565        .easy_parse(position::Stream::new(s))
1566        .map(|(r, _)| r)
1567        .map_err(|e| anyhow::anyhow!(format!("{e}")))
1568}