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