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