graphix_compiler/expr/parser/
mod.rs

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