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", "i8", "u8", "i16", "u16", "u32", "v32", "i32", "z32", "u64", "v64",
63 "i64", "z64", "f32", "f64", "decimal", "datetime", "duration", "bool", "string",
64 "bytes", "result", "null", "_", "?", "fn", "Array", "Map", "any", "Any", "use",
65 "rec", "catch", "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("i8").map(|_| Typ::I8)),
691 attempt(spstring("u8").map(|_| Typ::U8)),
692 attempt(spstring("i16").map(|_| Typ::I16)),
693 attempt(spstring("u16").map(|_| Typ::U16)),
694 attempt(spstring("u32").map(|_| Typ::U32)),
695 attempt(spstring("v32").map(|_| Typ::V32)),
696 attempt(spstring("i32").map(|_| Typ::I32)),
697 attempt(spstring("z32").map(|_| Typ::Z32)),
698 attempt(spstring("u64").map(|_| Typ::U64)),
699 attempt(spstring("v64").map(|_| Typ::V64)),
700 attempt(spstring("i64").map(|_| Typ::I64)),
701 attempt(spstring("z64").map(|_| Typ::Z64)),
702 attempt(spstring("f32").map(|_| Typ::F32)),
703 attempt(spstring("f64").map(|_| Typ::F64)),
704 attempt(spstring("decimal").map(|_| Typ::Decimal)),
705 attempt(spstring("datetime").map(|_| Typ::DateTime)),
706 attempt(spstring("duration").map(|_| Typ::Duration)),
707 attempt(spstring("bool").map(|_| Typ::Bool)),
708 attempt(spstring("string").map(|_| Typ::String)),
709 attempt(spstring("bytes").map(|_| Typ::Bytes)),
710 attempt(spstring("error").map(|_| Typ::Error)),
711 attempt(spstring("array").map(|_| Typ::Array)),
712 attempt(spstring("null").map(|_| Typ::Null)),
713 ))
714 .skip(not_followed_by(choice((alpha_num(), token('_')))))
715}
716
717parser! {
718 fn fntype[I]()(I) -> FnType
719 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
720 {
721 spstring("fn")
722 .with((
723 optional(attempt(between(
724 token('<'),
725 sptoken('>'),
726 sep_by1((tvar().skip(sptoken(':')), typexp()), csep()),
727 )))
728 .map(|cs: Option<LPooled<Vec<(TVar, Type)>>>| match cs {
729 Some(cs) => Arc::new(RwLock::new(cs)),
730 None => Arc::new(RwLock::new(LPooled::take())),
731 }),
732 between(
733 token('('),
734 sptoken(')'),
735 sep_by(
736 choice((
737 attempt(
738 (
739 spaces()
740 .with(optional(token('?')).map(|o| o.is_some()))
741 .skip(token('#')),
742 fname().skip(token(':')),
743 typexp(),
744 )
745 .map(
746 |(optional, name, typ)| {
747 Either::Left(FnArgType {
748 label: Some((name.into(), optional)),
749 typ,
750 })
751 },
752 ),
753 ),
754 attempt(
755 typexp()
756 .map(|typ| Either::Left(FnArgType { label: None, typ })),
757 ),
758 attempt(
759 spstring("@args:").with(typexp()).map(|e| Either::Right(e)),
760 ),
761 )),
762 csep(),
763 ),
764 ),
765 spstring("->").with(typexp()),
766 optional(attempt(space().with(spstring("throws")).with(space()).with(typexp())))
767 ))
768 .then(
769 |(constraints, mut args, rtype, throws): (
770 Arc<RwLock<LPooled<Vec<(TVar, Type)>>>>,
771 Vec<Either<FnArgType, Type>>,
772 Type,
773 Option<Type>
774 )| {
775 let vargs = match args.pop() {
776 None => None,
777 Some(Either::Right(t)) => Some(t),
778 Some(Either::Left(t)) => {
779 args.push(Either::Left(t));
780 None
781 }
782 };
783 if !args.iter().all(|a| a.is_left()) {
784 return unexpected_any(
785 "vargs must appear once at the end of the args",
786 )
787 .left();
788 }
789 let args = Arc::from_iter(args.into_iter().map(|t| match t {
790 Either::Left(t) => t,
791 Either::Right(_) => unreachable!(),
792 }));
793 let mut anon = false;
794 for a in args.iter() {
795 if anon && a.label.is_some() {
796 return unexpected_any(
797 "anonymous args must appear after labeled args",
798 )
799 .left();
800 }
801 anon |= a.label.is_none();
802 }
803 let throws = throws.unwrap_or(Type::Bottom);
804 value(FnType { args, vargs, rtype, constraints, throws }).right()
805 },
806 )
807 }
808}
809
810fn tvar<I>() -> impl Parser<I, Output = TVar>
811where
812 I: RangeStream<Token = char>,
813 I::Error: ParseError<I::Token, I::Range, I::Position>,
814 I::Range: Range,
815{
816 sptoken('\'').with(fname()).map(TVar::empty_named)
817}
818
819parser! {
820 fn typexp[I]()(I) -> Type
821 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
822 {
823 choice((
824 attempt(sptoken('&').with(typexp()).map(|t| Type::ByRef(Arc::new(t)))),
825 attempt(sptoken('_').map(|_| Type::Bottom)),
826 attempt(
827 between(sptoken('['), sptoken(']'), sep_by(typexp(), csep()))
828 .map(|mut ts: LPooled<Vec<Type>>| Type::flatten_set(ts.drain(..))),
829 ),
830 attempt(between(sptoken('('), sptoken(')'), sep_by1(typexp(), csep())).map(
831 |mut exps: LPooled<Vec<Type>>| {
832 if exps.len() == 1 {
833 exps.pop().unwrap()
834 } else {
835 Type::Tuple(Arc::from_iter(exps.drain(..)))
836 }
837 },
838 )),
839 attempt(
840 between(
841 sptoken('{'),
842 sptoken('}'),
843 sep_by1((spfname().skip(sptoken(':')), typexp()), csep()),
844 )
845 .then(|mut exps: LPooled<Vec<(ArcStr, Type)>>| {
846 let s = exps.iter().map(|(n, _)| n).collect::<LPooled<FxHashSet<_>>>();
847 if s.len() < exps.len() {
848 return unexpected_any("struct field names must be unique").left();
849 }
850 drop(s);
851 exps.sort_by_key(|(n, _)| n.clone());
852 value(Type::Struct(Arc::from_iter(exps.drain(..)))).right()
853 }),
854 ),
855 attempt(
856 (
857 sptoken('`').with(ident(true)),
858 optional(attempt(between(
859 token('('),
860 sptoken(')'),
861 sep_by1(typexp(), csep()),
862 ))),
863 )
864 .map(|(tag, typs): (ArcStr, Option<LPooled<Vec<Type>>>)| {
865 let mut t = match typs {
866 None => LPooled::take(),
867 Some(v) => v,
868 };
869 Type::Variant(tag.clone(), Arc::from_iter(t.drain(..)))
870 }),
871 ),
872 attempt(fntype().map(|f| Type::Fn(Arc::new(f)))),
873 attempt(spstring("Array").with(between(sptoken('<'), sptoken('>'), typexp())))
874 .map(|t| Type::Array(Arc::new(t))),
875 attempt(spstring("Map").with(
876 between(sptoken('<'), sptoken('>'),
877 (typexp().skip(sptoken(',')), typexp())
878 )))
879 .map(|(k, v)| Type::Map { key: Arc::new(k), value: Arc::new(v) }),
880 attempt(spstring("Error").with(between(sptoken('<'), sptoken('>'), typexp())))
881 .map(|t| Type::Error(Arc::new(t))),
882 attempt((
883 sptypath(),
884 optional(attempt(between(
885 sptoken('<'),
886 sptoken('>'),
887 sep_by1(typexp(), csep()),
888 ))),
889 ))
890 .map(|(n, params): (ModPath, Option<LPooled<Vec<Type>>>)| {
891 let params = params
892 .map(|mut a| Arc::from_iter(a.drain(..)))
893 .unwrap_or_else(|| Arc::from_iter([]));
894 Type::Ref { scope: ModPath::root(), name: n, params }
895 }),
896 attempt(spstring("Any")).map(|_| Type::Any),
897 attempt(typeprim()).map(|typ| Type::Primitive(typ.into())),
898 attempt(tvar()).map(|tv| Type::TVar(tv)),
899 ))
900 }
901}
902
903parser! {
904 fn lambda_args[I]()(I) -> (LPooled<Vec<Arg>>, Option<Option<Type>>)
905 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
906 {
907 sep_by(
908 (
909 choice((
910 attempt(spaces().with(structure_pattern())).map(|p| (false, p)),
911 attempt(spaces().with(token('#').with(fname())))
912 .map(|b| (true, StructurePattern::Bind(b))),
913 attempt(spstring("@args"))
914 .map(|s| (false, StructurePattern::Bind(ArcStr::from(s)))),
915 )),
916 optional(attempt(sptoken(':').with(typexp()))),
917 optional(attempt(sptoken('=').with(expr()))),
918 ),
919 csep(),
920 )
921 .then(|v: Vec<((bool, StructurePattern), Option<Type>, Option<Expr>)>| {
922 let args = v
923 .into_iter()
924 .map(|((labeled, pattern), constraint, default)| {
925 if !labeled && default.is_some() {
926 bail!("labeled")
927 } else {
928 Ok(Arg { labeled: labeled.then_some(default), pattern, constraint })
929 }
930 })
931 .collect::<Result<LPooled<Vec<_>>>>();
932 match args {
933 Ok(a) => value(a).right(),
934 Err(_) => {
935 unexpected_any("only labeled arguments may have a default value").left()
936 }
937 }
938 })
939 .then(|mut v: LPooled<Vec<Arg>>| {
941 match v.iter().enumerate().find(|(_, a)| match &a.pattern {
942 StructurePattern::Bind(n) if n == "@args" => true,
943 _ => false,
944 }) {
945 None => value((v, None)).left(),
946 Some((i, _)) => {
947 if i == v.len() - 1 {
948 let a = v.pop().unwrap();
949 value((v, Some(a.constraint))).left()
950 } else {
951 unexpected_any("@args must be the last argument").right()
952 }
953 }
954 }
955 })
956 .then(|(v, vargs): (LPooled<Vec<Arg>>, Option<Option<Type>>)| {
958 let mut anon = false;
959 for a in v.iter() {
960 if a.labeled.is_some() && anon {
961 return unexpected_any("labeled args must come before anon args").right();
962 }
963 anon |= a.labeled.is_none();
964 }
965 value((v, vargs)).left()
966 })
967 }
968}
969
970parser! {
971 fn lambda[I]()(I) -> Expr
972 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
973 {
974 (
975 position(),
976 attempt(sep_by((tvar().skip(sptoken(':')), typexp()), csep()))
977 .map(|mut tvs: LPooled<Vec<(TVar, Type)>>| Arc::from_iter(tvs.drain(..))),
978 between(sptoken('|'), sptoken('|'), lambda_args()),
979 optional(attempt(spstring("->").with(typexp()))),
980 optional(attempt(space().with(spstring("throws").with(space()).with(typexp())))),
981 space().with(choice((
982 attempt(sptoken('\'').with(fname()).skip(not_followed_by(sptoken(':'))))
983 .map(Either::Right),
984 expr().map(|e| Either::Left(e)),
985 ))),
986 )
987 .map(|(pos, constraints, (mut args, vargs), rtype, throws, body)| {
988 let args = Arc::from_iter(args.drain(..));
989 ExprKind::Lambda(Arc::new(Lambda { args, vargs, rtype, throws, constraints, body }))
990 .to_expr(pos)
991 })
992 }
993}
994
995parser! {
996 fn letbind[I]()(I) -> Expr
997 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
998 {
999 (
1000 position(),
1001 doc_comment(),
1002 optional(string("pub").skip(space())).map(|o| o.is_some()),
1003 spstring("let")
1004 .with(space())
1005 .with((
1006 optional(attempt(spstring("rec").with(space()))),
1007 structure_pattern(),
1008 optional(attempt(sptoken(':').with(typexp())))
1009 ))
1010 .skip(spstring("=")),
1011 expr(),
1012 )
1013 .map(|(pos, doc, export, (rec, pattern, typ), value)| {
1014 let rec = rec.is_some();
1015 ExprKind::Bind(Arc::new(Bind { rec, doc, export, pattern, typ, value }))
1016 .to_expr(pos)
1017 })
1018 }
1019}
1020
1021parser! {
1022 fn connect[I]()(I) -> Expr
1023 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1024 {
1025 (position(), optional(token('*')), spmodpath().skip(spstring("<-")), expr()).map(
1026 |(pos, deref, name, e)| {
1027 ExprKind::Connect { name, value: Arc::new(e), deref: deref.is_some() }
1028 .to_expr(pos)
1029 },
1030 )
1031 }
1032}
1033
1034fn literal<I>() -> impl Parser<I, Output = Expr>
1035where
1036 I: RangeStream<Token = char, Position = SourcePosition>,
1037 I::Error: ParseError<I::Token, I::Range, I::Position>,
1038 I::Range: Range,
1039{
1040 (position(), parse_value(&VAL_MUST_ESC, &VAL_ESC).skip(not_followed_by(token('_'))))
1041 .then(|(pos, v)| match v {
1042 Value::String(_) => {
1043 unexpected_any("parse error in string interpolation").left()
1044 }
1045 v => value(ExprKind::Constant(v).to_expr(pos)).right(),
1046 })
1047}
1048
1049fn reference<I>() -> impl Parser<I, Output = Expr>
1050where
1051 I: RangeStream<Token = char, Position = SourcePosition>,
1052 I::Error: ParseError<I::Token, I::Range, I::Position>,
1053 I::Range: Range,
1054{
1055 (position(), modpath()).map(|(pos, name)| ExprKind::Ref { name }.to_expr(pos))
1056}
1057
1058parser! {
1059 fn deref_arith[I]()(I) -> Expr
1060 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1061 {
1062 (position(), token('*').with(arith_term()))
1063 .map(|(pos, expr)| ExprKind::Deref(Arc::new(expr)).to_expr(pos))
1064 }
1065}
1066
1067parser! {
1068 fn qop[I, P](p: P)(I) -> Expr
1069 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range, P: Parser<I, Output = Expr>]
1070 {
1071 enum Op {
1072 Qop,
1073 OrNever,
1074 }
1075 (
1076 position(),
1077 p,
1078 optional(choice((
1079 attempt(sptoken('?')).map(|_| Op::Qop),
1080 attempt(sptoken('$')).map(|_| Op::OrNever)
1081 )))
1082 ).map(|(pos, e, qop)| match qop {
1083 None => e,
1084 Some(Op::Qop) => ExprKind::Qop(Arc::new(e)).to_expr(pos),
1085 Some(Op::OrNever) => ExprKind::OrNever(Arc::new(e)).to_expr(pos)
1086 })
1087 }
1088}
1089
1090parser! {
1091 fn arith_term[I]()(I) -> Expr
1092 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1093 {
1094 choice((
1095 attempt(spaces().with(qop(deref_arith()))),
1096 attempt(spaces().with(raw_string())),
1097 attempt(spaces().with(array())),
1098 attempt(spaces().with(byref_arith())),
1099 attempt(spaces().with(tuple())),
1100 attempt(spaces().with(structure())),
1101 attempt(spaces().with(map())),
1102 attempt(spaces().with(variant())),
1103 attempt(spaces().with(structwith())),
1104 attempt(spaces().with(qop(arrayref()))),
1105 attempt(spaces().with(qop(tupleref()))),
1106 attempt(spaces().with(qop(structref()))),
1107 attempt(spaces().with(qop(mapref()))),
1108 attempt(spaces().with(qop(apply()))),
1109 attempt(spaces().with(qop(do_block()))),
1110 attempt(spaces().with(qop(select()))),
1111 attempt(spaces().with(qop(cast()))),
1112 attempt(spaces().with(qop(any()))),
1113 attempt(spaces().with(interpolated())),
1114 attempt(spaces().with(literal())),
1115 attempt(spaces().with(qop(reference()))),
1116 attempt(
1117 (position(), sptoken('!').with(arith()))
1118 .map(|(pos, expr)| ExprKind::Not { expr: Arc::new(expr) }.to_expr(pos)),
1119 ),
1120 attempt(between(sptoken('('), sptoken(')'), arith())),
1121 ))
1122 .skip(spaces())
1123 }
1124}
1125
1126parser! {
1127 fn arith[I]()(I) -> Expr
1128 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1129 {
1130 choice((
1131 attempt(chainl1(
1132 arith_term(),
1133 choice((
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 attempt(spstring("<")),
1145 attempt(spstring("&&")),
1146 attempt(spstring("||")),
1147 attempt(spstring("~")),
1148 ))
1149 .map(|op: &str| match op {
1150 "+" => |lhs: Expr, rhs: Expr| {
1151 let pos = lhs.pos;
1152 ExprKind::Add { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1153 },
1154 "-" => |lhs: Expr, rhs: Expr| {
1155 let pos = lhs.pos;
1156 ExprKind::Sub { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1157 },
1158 "*" => |lhs: Expr, rhs: Expr| {
1159 let pos = lhs.pos;
1160 ExprKind::Mul { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1161 },
1162 "/" => |lhs: Expr, rhs: Expr| {
1163 let pos = lhs.pos;
1164 ExprKind::Div { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1165 },
1166 "%" => |lhs: Expr, rhs: Expr| {
1167 let pos = lhs.pos;
1168 ExprKind::Mod { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1169 },
1170 "==" => |lhs: Expr, rhs: Expr| {
1171 let pos = lhs.pos;
1172 ExprKind::Eq { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1173 },
1174 "!=" => |lhs: Expr, rhs: Expr| {
1175 let pos = lhs.pos;
1176 ExprKind::Ne { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1177 },
1178 ">" => |lhs: Expr, rhs: Expr| {
1179 let pos = lhs.pos;
1180 ExprKind::Gt { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1181 },
1182 "<" => |lhs: Expr, rhs: Expr| {
1183 let pos = lhs.pos;
1184 ExprKind::Lt { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1185 },
1186 ">=" => |lhs: Expr, rhs: Expr| {
1187 let pos = lhs.pos;
1188 ExprKind::Gte { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1189 },
1190 "<=" => |lhs: Expr, rhs: Expr| {
1191 let pos = lhs.pos;
1192 ExprKind::Lte { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1193 },
1194 "&&" => |lhs: Expr, rhs: Expr| {
1195 let pos = lhs.pos;
1196 ExprKind::And { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1197 },
1198 "||" => |lhs: Expr, rhs: Expr| {
1199 let pos = lhs.pos;
1200 ExprKind::Or { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1201 },
1202 "~" => |lhs: Expr, rhs: Expr| {
1203 let pos = lhs.pos;
1204 ExprKind::Sample { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }
1205 .to_expr(pos)
1206 },
1207 _ => unreachable!(),
1208 }),
1209 )),
1210 attempt((position(), sptoken('!').with(arith_term())))
1211 .map(|(pos, expr)| ExprKind::Not { expr: Arc::new(expr) }.to_expr(pos)),
1212 attempt(between(sptoken('('), sptoken(')'), arith())),
1213 ))
1214 }
1215}
1216
1217parser! {
1218 fn slice_pattern[I]()(I) -> StructurePattern
1219 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1220 {
1221 macro_rules! all_left {
1222 ($pats:expr) => {{
1223 let mut err = false;
1224 let pats: Arc<[StructurePattern]> =
1225 Arc::from_iter($pats.drain(..).map(|s| match s {
1226 Either::Left(s) => s,
1227 Either::Right(_) => {
1228 err = true;
1229 StructurePattern::Ignore
1230 }
1231 }));
1232 if err {
1233 return unexpected_any("invalid pattern").left();
1234 }
1235 pats
1236 }};
1237 }
1238 (
1239 optional(attempt(spfname().skip(sptoken('@')))),
1240 between(
1241 sptoken('['),
1242 sptoken(']'),
1243 sep_by(
1244 choice((
1245 attempt(spstring("..")).map(|_| Either::Right(None)),
1246 attempt(spfname().skip(spstring("..")))
1247 .map(|n| Either::Right(Some(n))),
1248 structure_pattern().map(|p| Either::Left(p)),
1249 )),
1250 csep(),
1251 ),
1252 ),
1253 )
1254 .then(
1255 |(all, mut pats): (
1256 Option<ArcStr>,
1257 LPooled<Vec<Either<StructurePattern, Option<ArcStr>>>>,
1258 )| {
1259 if pats.len() == 0 {
1260 value(StructurePattern::Slice { all, binds: Arc::from_iter([]) })
1261 .right()
1262 } else if pats.len() == 1 {
1263 match pats.pop().unwrap() {
1264 Either::Left(s) => value(StructurePattern::Slice {
1265 all,
1266 binds: Arc::from_iter([s]),
1267 })
1268 .right(),
1269 Either::Right(_) => {
1270 unexpected_any("invalid singular range match").left()
1271 }
1272 }
1273 } else {
1274 match (&pats[0], &pats[pats.len() - 1]) {
1275 (Either::Right(_), Either::Right(_)) => {
1276 unexpected_any("invalid pattern").left()
1277 }
1278 (Either::Right(_), Either::Left(_)) => {
1279 let head = pats.remove(0).right().unwrap();
1280 let suffix = all_left!(pats);
1281 value(StructurePattern::SliceSuffix { all, head, suffix })
1282 .right()
1283 }
1284 (Either::Left(_), Either::Right(_)) => {
1285 let tail = pats.pop().unwrap().right().unwrap();
1286 let prefix = all_left!(pats);
1287 value(StructurePattern::SlicePrefix { all, tail, prefix })
1288 .right()
1289 }
1290 (Either::Left(_), Either::Left(_)) => {
1291 value(StructurePattern::Slice { all, binds: all_left!(pats) })
1292 .right()
1293 }
1294 }
1295 }
1296 },
1297 )
1298 }
1299}
1300
1301fn raw_string<I>() -> impl Parser<I, Output = Expr>
1302where
1303 I: RangeStream<Token = char, Position = SourcePosition>,
1304 I::Error: ParseError<I::Token, I::Range, I::Position>,
1305 I::Range: Range,
1306{
1307 static MUST_ESC: [char; 2] = ['\\', '\''];
1308 static ESC: LazyLock<Escape> =
1309 LazyLock::new(|| Escape::new('\\', &MUST_ESC, &[], None).unwrap());
1310 (position(), between(string("r\'"), token('\''), escaped_string(&MUST_ESC, &ESC)))
1311 .map(|(pos, s): (_, String)| {
1312 ExprKind::Constant(Value::String(s.into())).to_expr(pos)
1313 })
1314}
1315
1316parser! {
1317 fn tuple_pattern[I]()(I) -> StructurePattern
1318 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1319 {
1320 (
1321 optional(attempt(spfname().skip(sptoken('@')))),
1322 between(sptoken('('), sptoken(')'), sep_by1(structure_pattern(), csep())),
1323 )
1324 .then(|(all, mut binds): (Option<ArcStr>, LPooled<Vec<StructurePattern>>)| {
1325 if binds.len() < 2 {
1326 unexpected_any("tuples must have at least 2 elements").left()
1327 } else {
1328 value(StructurePattern::Tuple { all, binds: Arc::from_iter(binds.drain(..)) })
1329 .right()
1330 }
1331 })
1332 }
1333}
1334
1335parser! {
1336 fn variant_pattern[I]()(I) -> StructurePattern
1337 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1338 {
1339 (
1340 optional(attempt(spfname().skip(sptoken('@')))),
1341 sptoken('`').with(typname()),
1342 optional(attempt(between(
1343 sptoken('('),
1344 sptoken(')'),
1345 sep_by1(structure_pattern(), csep()),
1346 ))),
1347 )
1348 .map(
1349 |(all, tag, binds): (
1350 Option<ArcStr>,
1351 ArcStr,
1352 Option<LPooled<Vec<StructurePattern>>>,
1353 )| {
1354 let mut binds = match binds {
1355 None => LPooled::take(),
1356 Some(a) => a,
1357 };
1358 StructurePattern::Variant { all, tag, binds: Arc::from_iter(binds.drain(..)) }
1359 },
1360 )
1361 }
1362}
1363
1364parser! {
1365 fn struct_pattern[I]()(I) -> StructurePattern
1366 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1367 {
1368 (
1369 optional(attempt(spfname().skip(sptoken('@')))),
1370 between(
1371 sptoken('{'),
1372 sptoken('}'),
1373 sep_by1(
1374 choice((
1375 attempt((spfname().skip(sptoken(':')), structure_pattern()))
1376 .map(|(s, p)| (s, p, true)),
1377 attempt(spfname()).map(|s| {
1378 let p = StructurePattern::Bind(s.clone());
1379 (s, p, true)
1380 }),
1381 spstring("..")
1382 .map(|_| (literal!(""), StructurePattern::Ignore, false)),
1383 )),
1384 csep(),
1385 ),
1386 ),
1387 )
1388 .then(
1389 |(all, mut binds): (
1390 Option<ArcStr>,
1391 LPooled<Vec<(ArcStr, StructurePattern, bool)>>,
1392 )| {
1393 let mut exhaustive = true;
1394 binds.retain(|(_, _, ex)| {
1395 exhaustive &= *ex;
1396 *ex
1397 });
1398 binds.sort_by_key(|(s, _, _)| s.clone());
1399 let s = binds.iter().map(|(s, _, _)| s).collect::<LPooled<FxHashSet<_>>>();
1400 if s.len() < binds.len() {
1401 unexpected_any("struct fields must be unique").left()
1402 } else {
1403 drop(s);
1404 let binds = Arc::from_iter(binds.drain(..).map(|(s, p, _)| (s, p)));
1405 value(StructurePattern::Struct { all, exhaustive, binds }).right()
1406 }
1407 },
1408 )
1409 }
1410}
1411
1412parser! {
1413 fn structure_pattern[I]()(I) -> StructurePattern
1414 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1415 {
1416 choice((
1417 attempt(slice_pattern()),
1418 attempt(tuple_pattern()),
1419 attempt(struct_pattern()),
1420 attempt(variant_pattern()),
1421 attempt(parse_value(&VAL_MUST_ESC, &VAL_ESC).skip(not_followed_by(token('_'))))
1422 .map(|v| StructurePattern::Literal(v)),
1423 attempt(sptoken('_')).map(|_| StructurePattern::Ignore),
1424 spfname().map(|name| StructurePattern::Bind(name)),
1425 ))
1426 }
1427}
1428
1429parser! {
1430 fn pattern[I]()(I) -> Pattern
1431 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1432 {
1433 (
1434 optional(attempt(typexp().skip(space().with(spstring("as "))))),
1435 structure_pattern(),
1436 optional(attempt(space().with(spstring("if").with(space()).with(expr())))),
1437 )
1438 .map(
1439 |(type_predicate, structure_predicate, guard): (
1440 Option<Type>,
1441 StructurePattern,
1442 Option<Expr>,
1443 )| { Pattern { type_predicate, structure_predicate, guard } },
1444 )
1445 }
1446}
1447
1448parser! {
1449 fn select[I]()(I) -> Expr
1450 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1451 {
1452 (
1453 position(),
1454 string("select").with(space()).with((
1455 expr(),
1456 between(
1457 sptoken('{'),
1458 sptoken('}'),
1459 sep_by1((pattern(), spstring("=>").with(expr())), csep()),
1460 ),
1461 )),
1462 )
1463 .map(|(pos, (arg, arms)): (_, (Expr, Vec<(Pattern, Expr)>))| {
1464 ExprKind::Select { arg: Arc::new(arg), arms: Arc::from(arms) }.to_expr(pos)
1465 })
1466 }
1467}
1468
1469parser! {
1470 fn cast[I]()(I) -> Expr
1471 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1472 {
1473 (
1474 position(),
1475 string("cast").with(between(token('<'), sptoken('>'), typexp())),
1476 between(sptoken('('), sptoken(')'), expr()),
1477 )
1478 .map(|(pos, typ, e)| ExprKind::TypeCast { expr: Arc::new(e), typ }.to_expr(pos))
1479 }
1480}
1481
1482parser! {
1483 fn typedef[I]()(I) -> Expr
1484 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1485 {
1486 (
1487 position(),
1488 string("type").with(sptypname()),
1489 optional(attempt(between(
1490 sptoken('<'),
1491 sptoken('>'),
1492 sep_by1((tvar(), optional(attempt(sptoken(':').with(typexp())))), csep()),
1493 ))),
1494 sptoken('=').with(typexp()),
1495 )
1496 .map(|(pos, name, params, typ)| {
1497 let params = params
1498 .map(|mut ps: LPooled<Vec<(TVar, Option<Type>)>>| {
1499 Arc::from_iter(ps.drain(..))
1500 })
1501 .unwrap_or_else(|| Arc::<[(TVar, Option<Type>)]>::from(Vec::new()));
1502 ExprKind::TypeDef(TypeDef { name, params, typ }).to_expr(pos)
1503 })
1504 }
1505}
1506
1507parser! {
1508 fn tuple[I]()(I) -> Expr
1509 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1510 {
1511 (position(), between(token('('), sptoken(')'), sep_by1(expr(), csep()))).then(
1512 |(pos, mut exprs): (_, LPooled<Vec<Expr>>)| {
1513 if exprs.len() < 2 {
1514 unexpected_any("tuples must have at least 2 elements").left()
1515 } else {
1516 value(ExprKind::Tuple { args: Arc::from_iter(exprs.drain(..)) }.to_expr(pos))
1517 .right()
1518 }
1519 },
1520 )
1521 }
1522}
1523
1524parser! {
1525 fn structure[I]()(I) -> Expr
1526 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1527 {
1528 (
1529 position(),
1530 between(
1531 token('{'),
1532 sptoken('}'),
1533 sep_by1((spfname(), optional(attempt(sptoken(':')).with(expr()))), csep()),
1534 ),
1535 )
1536 .then(|(pos, mut exprs): (_, LPooled<Vec<(ArcStr, Option<Expr>)>>)| {
1537 let s = exprs.iter().map(|(n, _)| n).collect::<LPooled<FxHashSet<_>>>();
1538 if s.len() < exprs.len() {
1539 return unexpected_any("struct fields must be unique").left();
1540 }
1541 drop(s);
1542 exprs.sort_by_key(|(n, _)| n.clone());
1543 let args = exprs.drain(..).map(|(n, e)| match e {
1544 Some(e) => (n, e),
1545 None => {
1546 let e = ExprKind::Ref { name: [n.clone()].into() }.to_expr(pos);
1547 (n, e)
1548 }
1549 });
1550 value(ExprKind::Struct { args: Arc::from_iter(args) }.to_expr(pos)).right()
1551 })
1552 }
1553}
1554
1555parser! {
1556 fn map[I]()(I) -> Expr
1557 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1558 {
1559 (
1560 position(),
1561 between(
1562 token('{'),
1563 sptoken('}'),
1564 sep_by((expr(), spstring("=>").with(expr())), csep()),
1565 ),
1566 )
1567 .map(|(pos, mut args): (_, LPooled<Vec<(Expr, Expr)>>)| {
1568 ExprKind::Map { args: Arc::from_iter(args.drain(..)) }.to_expr(pos)
1569 })
1570 }
1571}
1572
1573parser! {
1574 fn variant[I]()(I) -> Expr
1575 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1576 {
1577 (
1578 position(),
1579 token('`').with(ident(true)),
1580 optional(attempt(between(token('('), sptoken(')'), sep_by1(expr(), csep())))),
1581 )
1582 .map(|(pos, tag, args): (_, ArcStr, Option<LPooled<Vec<Expr>>>)| {
1583 let mut args = match args {
1584 None => LPooled::take(),
1585 Some(a) => a,
1586 };
1587 ExprKind::Variant { tag, args: Arc::from_iter(args.drain(..)) }.to_expr(pos)
1588 })
1589 }
1590}
1591
1592parser! {
1593 fn structwith[I]()(I) -> Expr
1594 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1595 {
1596 (
1597 position(),
1598 between(
1599 token('{'),
1600 sptoken('}'),
1601 (
1602 ref_pexp().skip(space()).skip(spstring("with")).skip(space()),
1603 sep_by1((spfname(), optional(attempt(sptoken(':').with(expr())))), csep()),
1604 ),
1605 ),
1606 )
1607 .then(
1608 |(pos, (source, mut exprs)): (_, (Expr, LPooled<Vec<(ArcStr, Option<Expr>)>>))| {
1609 let s = exprs.iter().map(|(n, _)| n).collect::<LPooled<FxHashSet<_>>>();
1610 if s.len() < exprs.len() {
1611 return unexpected_any("struct fields must be unique").left();
1612 }
1613 drop(s);
1614 exprs.sort_by_key(|(n, _)| n.clone());
1615 let exprs = exprs.drain(..).map(|(name, e)| match e {
1616 Some(e) => (name, e),
1617 None => {
1618 let e = ExprKind::Ref { name: ModPath::from([name.clone()]) }.to_expr(pos);
1619 (name, e)
1620 }
1621 });
1622 let e = ExprKind::StructWith {
1623 source: Arc::new(source),
1624 replace: Arc::from_iter(exprs),
1625 }
1626 .to_expr(pos);
1627 value(e).right()
1628 },
1629 )
1630 }
1631}
1632
1633parser! {
1634 fn try_catch[I]()(I) -> Expr
1635 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1636 {
1637 (
1638 position().skip(string("try")).skip(space()),
1639 sep_by1(expr(), attempt(sptoken(';'))),
1640 spstring("catch").with(
1641 between(
1642 sptoken('('),
1643 sptoken(')'),
1644 (spfname(), optional(attempt(sptoken(':').with(typexp()))))
1645 )
1646 ),
1647 spstring("=>").with(expr())
1648 )
1649 .map(|(pos, mut exprs, (bind, constraint), handler):
1650 (_, LPooled<Vec<Expr>>, _, _)|
1651 {
1652 ExprKind::TryCatch(Arc::new(TryCatch {
1653 bind,
1654 constraint,
1655 exprs: Arc::from_iter(exprs.drain(..)),
1656 handler: Arc::new(handler)
1657 })).to_expr(pos)
1658 })
1659 }
1660}
1661
1662parser! {
1663 fn byref[I]()(I) -> Expr
1664 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1665 {
1666 (position(), token('&').with(expr()))
1667 .map(|(pos, expr)| ExprKind::ByRef(Arc::new(expr)).to_expr(pos))
1668 }
1669}
1670
1671parser! {
1672 fn byref_arith[I]()(I) -> Expr
1673 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1674 {
1675 (position(), token('&').with(arith_term()))
1676 .map(|(pos, expr)| ExprKind::ByRef(Arc::new(expr)).to_expr(pos))
1677 }
1678}
1679
1680parser! {
1681 fn deref[I]()(I) -> Expr
1682 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1683 {
1684 (position(), token('*').with(expr()))
1685 .map(|(pos, expr)| ExprKind::Deref(Arc::new(expr)).to_expr(pos))
1686 }
1687}
1688
1689parser! {
1690 fn expr[I]()(I) -> Expr
1691 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1692 {
1693 choice((
1694 attempt(choice((
1695 attempt(spaces().with(try_catch())),
1696 attempt(spaces().with(module())),
1697 attempt(spaces().with(use_module())),
1698 attempt(spaces().with(typedef())),
1699 attempt(spaces().with(raw_string())),
1700 attempt(spaces().with(array())),
1701 attempt(spaces().with(byref())),
1702 attempt(spaces().with(connect())),
1703 attempt(spaces().with(arith())),
1704 attempt(spaces().with(qop(mapref()))),
1705 attempt(spaces().with(qop(arrayref()))),
1706 attempt(spaces().with(qop(tupleref()))),
1707 attempt(spaces().with(qop(structref()))),
1708 attempt(spaces().with(qop(deref()))),
1709 attempt(spaces().with(qop(apply()))),
1710 attempt(spaces().with(tuple())),
1711 attempt(spaces().with(between(token('('), sptoken(')'), expr()))),
1712 ))),
1713 attempt(spaces().with(structure())),
1714 attempt(spaces().with(map())),
1715 attempt(spaces().with(variant())),
1716 attempt(spaces().with(structwith())),
1717 attempt(spaces().with(qop(do_block()))),
1718 attempt(spaces().with(lambda())),
1719 attempt(spaces().with(letbind())),
1720 attempt(spaces().with(qop(select()))),
1721 attempt(spaces().with(qop(cast()))),
1722 attempt(spaces().with(qop(any()))),
1723 attempt(spaces().with(interpolated())),
1724 attempt(spaces().with(literal())),
1725 attempt(spaces().with(qop(reference())))
1726 ))
1727 }
1728}
1729
1730pub fn parse(ori: Origin) -> anyhow::Result<Arc<[Expr]>> {
1735 let ori = Arc::new(ori);
1736 set_origin(ori.clone());
1737 let mut r: LPooled<Vec<Option<Expr>>> = sep_by1(
1738 choice((expr().map(Some), look_ahead(spaces().with(eof())).map(|_| None))),
1739 attempt(sptoken(';')),
1740 )
1741 .skip(spaces())
1742 .skip(eof())
1743 .easy_parse(position::Stream::new(&*ori.text))
1744 .map(|(r, _)| r)
1745 .map_err(|e| anyhow::anyhow!(format!("{}", e)))?;
1746 Ok(Arc::from_iter(r.drain(..).filter_map(|e| e)))
1747}
1748
1749pub fn parse_one(s: &str) -> anyhow::Result<Expr> {
1751 expr()
1752 .skip(spaces())
1753 .skip(eof())
1754 .easy_parse(position::Stream::new(&*s))
1755 .map(|(r, _)| r)
1756 .map_err(|e| anyhow::anyhow!(format!("{e}")))
1757}
1758
1759pub fn test_parse_mapref(s: &str) -> anyhow::Result<Expr> {
1760 mapref()
1761 .skip(spaces())
1762 .skip(eof())
1763 .easy_parse(position::Stream::new(&*s))
1764 .map(|(r, _)| r)
1765 .map_err(|e| anyhow::anyhow!(format!("{e}")))
1766}
1767
1768pub fn parse_fn_type(s: &str) -> anyhow::Result<FnType> {
1770 fntype()
1771 .skip(spaces())
1772 .skip(eof())
1773 .easy_parse(position::Stream::new(s))
1774 .map(|(r, _)| r)
1775 .map_err(|e| anyhow::anyhow!(format!("{e}")))
1776}
1777
1778pub fn parse_type(s: &str) -> anyhow::Result<Type> {
1780 typexp()
1781 .skip(spaces())
1782 .skip(eof())
1783 .easy_parse(position::Stream::new(s))
1784 .map(|(r, _)| r)
1785 .map_err(|e| anyhow::anyhow!(format!("{e}")))
1786}
1787
1788pub(super) fn parse_modpath(s: &str) -> anyhow::Result<ModPath> {
1789 modpath()
1790 .skip(spaces())
1791 .skip(eof())
1792 .easy_parse(position::Stream::new(s))
1793 .map(|(r, _)| r)
1794 .map_err(|e| anyhow::anyhow!(format!("{e}")))
1795}