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