1use crate::{
2 expr::{
3 get_origin, set_origin, Arg, Bind, Expr, ExprId, ExprKind, Lambda, ModPath,
4 ModuleKind, Origin, Pattern, StructurePattern,
5 },
6 typ::{FnArgType, FnType, TVar, Type},
7};
8use anyhow::{bail, Result};
9use arcstr::{literal, ArcStr};
10use combine::{
11 attempt, between, chainl1, choice, eof, look_ahead, many, many1, none_of,
12 not_followed_by, optional,
13 parser::{
14 char::{alpha_num, digit, space, string},
15 combinator::recognize,
16 range::{take_while, take_while1},
17 },
18 position, sep_by, sep_by1, skip_many,
19 stream::{
20 position::{self, SourcePosition},
21 Range,
22 },
23 token, unexpected_any, value, EasyParser, ParseError, Parser, RangeStream,
24};
25use compact_str::CompactString;
26use fxhash::FxHashSet;
27use netidx::{
28 path::Path,
29 publisher::{Typ, Value},
30 utils::Either,
31};
32use netidx_value::parser::{escaped_string, int, value as parse_value, VAL_ESC};
33use parking_lot::RwLock;
34use smallvec::{smallvec, SmallVec};
35use std::sync::LazyLock;
36use triomphe::Arc;
37
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 module[I]()(I) -> Expr
355 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
356 {
357 (
358 position(),
359 optional(string("pub").skip(space())).map(|o| o.is_some()),
360 spstring("mod").with(space()).with(spfname()),
361 optional(attempt(between(sptoken('{'), sptoken('}'), sep_by(expr(), attempt(sptoken(';'))))))
362 .map(|m: Option<Vec<Expr>>| match m {
363 Some(m) => ModuleKind::Inline(Arc::from(m)),
364 None => ModuleKind::Unresolved
365 }),
366 )
367 .map(|(pos, export, name, value)| {
368 ExprKind::Module { name, export, value }.to_expr(pos)
369 })
370 }
371}
372
373fn use_module<I>() -> impl Parser<I, Output = Expr>
374where
375 I: RangeStream<Token = char, Position = SourcePosition>,
376 I::Error: ParseError<I::Token, I::Range, I::Position>,
377 I::Range: Range,
378{
379 (position(), string("use").with(space()).with(spmodpath()))
380 .map(|(pos, name)| ExprKind::Use { name }.to_expr(pos))
381}
382
383parser! {
384 fn do_block[I]()(I) -> Expr
385 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
386 {
387 (
388 position(),
389 between(token('{'), sptoken('}'), sep_by1(expr(), attempt(sptoken(';')))),
390 )
391 .then(|(pos, args): (_, Vec<Expr>)| {
392 if args.len() < 2 {
393 unexpected_any("do must contain at least 2 expressions").left()
394 } else {
395 value(ExprKind::Do { exprs: Arc::from(args) }.to_expr(pos)).right()
396 }
397 })
398 }
399}
400
401parser! {
402 fn array[I]()(I) -> Expr
403 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
404 {
405 (position(), between(token('['), sptoken(']'), sep_by(expr(), csep()))).map(
406 |(pos, args): (_, SmallVec<[Expr; 4]>)| {
407 ExprKind::Array { args: Arc::from_iter(args.into_iter()) }.to_expr(pos)
408 },
409 )
410 }
411}
412
413parser! {
414 fn apply_pexp[I]()(I) -> Expr
415 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
416 {
417 choice((
418 attempt(spaces().with(qop(reference()))),
419 between(sptoken('('), sptoken(')'), expr()),
420 ))
421 }
422}
423
424parser! {
425 fn ref_pexp[I]()(I) -> Expr
426 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
427 {
428 choice((
429 attempt(spaces().with(qop(reference()))),
430 between(sptoken('('), sptoken(')'), expr()),
431 ))
432 }
433}
434
435parser! {
436 fn structref[I]()(I) -> Expr
437 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
438 {
439 (position(), ref_pexp().skip(sptoken('.')), spfname()).map(|(pos, source, field)| {
440 ExprKind::StructRef { source: Arc::new(source), field }.to_expr(pos)
441 })
442 }
443}
444
445parser! {
446 fn tupleref[I]()(I) -> Expr
447 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
448 {
449 (position(), ref_pexp().skip(sptoken('.')), int::<_, usize>()).map(
450 |(pos, source, field)| {
451 ExprKind::TupleRef { source: Arc::new(source), field }.to_expr(pos)
452 },
453 )
454 }
455}
456
457parser! {
458 fn arrayref[I]()(I) -> Expr
459 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
460 {
461 (
462 position(),
463 ref_pexp(),
464 between(
465 token('['),
466 sptoken(']'),
467 choice((
468 attempt(
469 (
470 position(),
471 spaces().with(optional(many1(digit()))).skip(spstring("..")),
472 spaces().with(optional(many1(digit()))),
473 )
474 .skip(look_ahead(sptoken(']'))),
475 )
476 .map(
477 |(pos, start, end): (
478 _,
479 Option<CompactString>,
480 Option<CompactString>,
481 )| {
482 let start = start.map(|i| Value::U64(i.parse().unwrap()));
483 let start = start.map(|e| ExprKind::Constant(e).to_expr(pos));
484 let end = end.map(|i| Value::U64(i.parse().unwrap()));
485 let end = end.map(|e| ExprKind::Constant(e).to_expr(pos));
486 Either::Left((start, end))
487 },
488 ),
489 attempt((
490 optional(attempt(expr())).skip(spstring("..")),
491 optional(attempt(expr())),
492 ))
493 .map(|(start, end)| Either::Left((start, end))),
494 attempt(expr()).map(|e| Either::Right(e)),
495 )),
496 ),
497 )
498 .map(|(pos, a, args)| match args {
499 Either::Left((start, end)) => ExprKind::ArraySlice {
500 source: Arc::new(a),
501 start: start.map(Arc::new),
502 end: end.map(Arc::new),
503 }
504 .to_expr(pos),
505 Either::Right(i) => {
506 ExprKind::ArrayRef { source: Arc::new(a), i: Arc::new(i) }.to_expr(pos)
507 }
508 })
509 }
510}
511
512parser! {
513 fn apply[I]()(I) -> Expr
514 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
515 {
516 (
517 position(),
518 apply_pexp(),
519 between(
520 sptoken('('),
521 sptoken(')'),
522 sep_by(
523 choice((
524 attempt((sptoken('#').with(fname()).skip(token(':')), expr()))
525 .map(|(n, e)| (Some(n), e)),
526 attempt((
527 position(),
528 sptoken('#').with(fname()),
529 ))
530 .map(|(pos, n)| {
531 let e = ExprKind::Ref { name: [n.clone()].into() }.to_expr(pos);
532 (Some(n), e)
533 }),
534 expr().map(|e| (None, e)),
535 )),
536 csep(),
537 ),
538 ),
539 )
540 .then(|(pos, function, args): (_, Expr, Vec<(Option<ArcStr>, Expr)>)| {
541 let mut anon = false;
542 for (a, _) in &args {
543 if a.is_some() && anon {
544 return unexpected_any(
545 "labeled arguments must come before anonymous arguments",
546 )
547 .right();
548 }
549 anon |= a.is_none();
550 }
551 value((pos, function, args)).left()
552 })
553 .map(|(pos, function, args): (_, Expr, Vec<(Option<ArcStr>, Expr)>)| {
554 ExprKind::Apply { function: Arc::new(function), args: Arc::from(args) }
555 .to_expr(pos)
556 })
557 }
558}
559
560parser! {
561 fn any[I]()(I) -> Expr
562 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
563 {
564 (
565 position(),
566 string("any").with(between(sptoken('('), sptoken(')'), sep_by(expr(), csep()))),
567 )
568 .map(|(pos, args): (_, Vec<Expr>)| {
569 ExprKind::Any { args: Arc::from(args) }.to_expr(pos)
570 })
571 }
572}
573
574fn typeprim<I>() -> impl Parser<I, Output = Typ>
575where
576 I: RangeStream<Token = char>,
577 I::Error: ParseError<I::Token, I::Range, I::Position>,
578 I::Range: Range,
579{
580 choice((
581 attempt(spstring("u32").map(|_| Typ::U32)),
582 attempt(spstring("v32").map(|_| Typ::V32)),
583 attempt(spstring("i32").map(|_| Typ::I32)),
584 attempt(spstring("z32").map(|_| Typ::Z32)),
585 attempt(spstring("u64").map(|_| Typ::U64)),
586 attempt(spstring("v64").map(|_| Typ::V64)),
587 attempt(spstring("i64").map(|_| Typ::I64)),
588 attempt(spstring("z64").map(|_| Typ::Z64)),
589 attempt(spstring("f32").map(|_| Typ::F32)),
590 attempt(spstring("f64").map(|_| Typ::F64)),
591 attempt(spstring("decimal").map(|_| Typ::Decimal)),
592 attempt(spstring("datetime").map(|_| Typ::DateTime)),
593 attempt(spstring("duration").map(|_| Typ::Duration)),
594 attempt(spstring("bool").map(|_| Typ::Bool)),
595 attempt(spstring("string").map(|_| Typ::String)),
596 attempt(spstring("bytes").map(|_| Typ::Bytes)),
597 attempt(spstring("error").map(|_| Typ::Error)),
598 attempt(spstring("array").map(|_| Typ::Array)),
599 attempt(spstring("null").map(|_| Typ::Null)),
600 ))
601 .skip(not_followed_by(choice((alpha_num(), token('_')))))
602}
603
604parser! {
605 fn fntype[I]()(I) -> FnType
606 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
607 {
608 spstring("fn")
609 .with((
610 optional(attempt(between(
611 token('<'),
612 sptoken('>'),
613 sep_by1((tvar().skip(sptoken(':')), typexp()), csep()),
614 )))
615 .map(|cs: Option<SmallVec<[(TVar, Type); 4]>>| match cs {
616 Some(cs) => Arc::new(RwLock::new(cs.into_iter().collect())),
617 None => Arc::new(RwLock::new(vec![])),
618 }),
619 between(
620 token('('),
621 sptoken(')'),
622 sep_by(
623 choice((
624 attempt(
625 (
626 spaces()
627 .with(optional(token('?')).map(|o| o.is_some()))
628 .skip(token('#')),
629 fname().skip(token(':')),
630 typexp(),
631 )
632 .map(
633 |(optional, name, typ)| {
634 Either::Left(FnArgType {
635 label: Some((name.into(), optional)),
636 typ,
637 })
638 },
639 ),
640 ),
641 attempt(
642 typexp()
643 .map(|typ| Either::Left(FnArgType { label: None, typ })),
644 ),
645 attempt(
646 spstring("@args:").with(typexp()).map(|e| Either::Right(e)),
647 ),
648 )),
649 csep(),
650 ),
651 ),
652 spstring("->").with(typexp()),
653 ))
654 .then(
655 |(constraints, mut args, rtype): (
656 Arc<RwLock<Vec<(TVar, Type)>>>,
657 Vec<Either<FnArgType, Type>>,
658 Type,
659 )| {
660 let vargs = match args.pop() {
661 None => None,
662 Some(Either::Right(t)) => Some(t),
663 Some(Either::Left(t)) => {
664 args.push(Either::Left(t));
665 None
666 }
667 };
668 if !args.iter().all(|a| a.is_left()) {
669 return unexpected_any(
670 "vargs must appear once at the end of the args",
671 )
672 .left();
673 }
674 let args = Arc::from_iter(args.into_iter().map(|t| match t {
675 Either::Left(t) => t,
676 Either::Right(_) => unreachable!(),
677 }));
678 let mut anon = false;
679 for a in args.iter() {
680 if anon && a.label.is_some() {
681 return unexpected_any(
682 "anonymous args must appear after labeled args",
683 )
684 .left();
685 }
686 anon |= a.label.is_none();
687 }
688 value(FnType { args, vargs, rtype, constraints }).right()
689 },
690 )
691 }
692}
693
694fn tvar<I>() -> impl Parser<I, Output = TVar>
695where
696 I: RangeStream<Token = char>,
697 I::Error: ParseError<I::Token, I::Range, I::Position>,
698 I::Range: Range,
699{
700 sptoken('\'').with(fname()).map(TVar::empty_named)
701}
702
703parser! {
704 fn typexp[I]()(I) -> Type
705 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
706 {
707 choice((
708 attempt(sptoken('&').with(typexp()).map(|t| Type::ByRef(Arc::new(t)))),
709 attempt(sptoken('_').map(|_| Type::Bottom)),
710 attempt(
711 between(sptoken('['), sptoken(']'), sep_by(typexp(), csep()))
712 .map(|ts: SmallVec<[Type; 16]>| Type::flatten_set(ts)),
713 ),
714 attempt(between(sptoken('('), sptoken(')'), sep_by1(typexp(), csep())).then(
715 |exps: SmallVec<[Type; 16]>| {
716 if exps.len() < 2 {
717 unexpected_any("tuples must have at least 2 elements").left()
718 } else {
719 value(Type::Tuple(Arc::from_iter(exps))).right()
720 }
721 },
722 )),
723 attempt(
724 between(
725 sptoken('{'),
726 sptoken('}'),
727 sep_by1((spfname().skip(sptoken(':')), typexp()), csep()),
728 )
729 .then(|mut exps: SmallVec<[(ArcStr, Type); 16]>| {
730 let s = exps.iter().map(|(n, _)| n).collect::<FxHashSet<_>>();
731 if s.len() < exps.len() {
732 return unexpected_any("struct field names must be unique").left();
733 }
734 exps.sort_by_key(|(n, _)| n.clone());
735 value(Type::Struct(Arc::from_iter(exps))).right()
736 }),
737 ),
738 attempt(
739 (
740 sptoken('`').with(typname()),
741 optional(attempt(between(
742 token('('),
743 sptoken(')'),
744 sep_by1(typexp(), csep()),
745 ))),
746 )
747 .map(|(tag, typs): (ArcStr, Option<SmallVec<[Type; 5]>>)| {
748 let t = match typs {
749 None => smallvec![],
750 Some(v) => v,
751 };
752 Type::Variant(tag.clone(), Arc::from_iter(t))
753 }),
754 ),
755 attempt(fntype().map(|f| Type::Fn(Arc::new(f)))),
756 attempt(spstring("Array").with(between(sptoken('<'), sptoken('>'), typexp())))
757 .map(|t| Type::Array(Arc::new(t))),
758 attempt((
759 sptypath(),
760 optional(attempt(between(
761 sptoken('<'),
762 sptoken('>'),
763 sep_by1(typexp(), csep()),
764 ))),
765 ))
766 .map(|(n, params): (ModPath, Option<SmallVec<[Type; 8]>>)| {
767 let params = params
768 .map(|a| Arc::from_iter(a.into_iter()))
769 .unwrap_or_else(|| Arc::from_iter([]));
770 Type::Ref { scope: ModPath::root(), name: n, params }
771 }),
772 attempt(spstring("Any")).map(|_| Type::Any),
773 attempt(typeprim()).map(|typ| Type::Primitive(typ.into())),
774 attempt(tvar()).map(|tv| Type::TVar(tv)),
775 ))
776 }
777}
778
779parser! {
780 fn lambda_args[I]()(I) -> (Vec<Arg>, Option<Option<Type>>)
781 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
782 {
783 sep_by(
784 (
785 choice((
786 attempt(spaces().with(structure_pattern())).map(|p| (false, p)),
787 attempt(spaces().with(token('#').with(fname())))
788 .map(|b| (true, StructurePattern::Bind(b))),
789 attempt(spstring("@args"))
790 .map(|s| (false, StructurePattern::Bind(ArcStr::from(s)))),
791 )),
792 optional(attempt(sptoken(':').with(typexp()))),
793 optional(attempt(sptoken('=').with(expr()))),
794 ),
795 csep(),
796 )
797 .then(|v: Vec<((bool, StructurePattern), Option<Type>, Option<Expr>)>| {
798 let args = v
799 .into_iter()
800 .map(|((labeled, pattern), constraint, default)| {
801 if !labeled && default.is_some() {
802 bail!("labeled")
803 } else {
804 Ok(Arg { labeled: labeled.then_some(default), pattern, constraint })
805 }
806 })
807 .collect::<Result<Vec<_>>>();
808 match args {
809 Ok(a) => value(a).right(),
810 Err(_) => {
811 unexpected_any("only labeled arguments may have a default value").left()
812 }
813 }
814 })
815 .then(|mut v: Vec<Arg>| {
817 match v.iter().enumerate().find(|(_, a)| match &a.pattern {
818 StructurePattern::Bind(n) if n == "@args" => true,
819 _ => false,
820 }) {
821 None => value((v, None)).left(),
822 Some((i, _)) => {
823 if i == v.len() - 1 {
824 let a = v.pop().unwrap();
825 value((v, Some(a.constraint))).left()
826 } else {
827 unexpected_any("@args must be the last argument").right()
828 }
829 }
830 }
831 })
832 .then(|(v, vargs): (Vec<Arg>, Option<Option<Type>>)| {
834 let mut anon = false;
835 for a in &v {
836 if a.labeled.is_some() && anon {
837 return unexpected_any("labeled args must come before anon args").right();
838 }
839 anon |= a.labeled.is_none();
840 }
841 value((v, vargs)).left()
842 })
843 }
844}
845
846parser! {
847 fn lambda[I]()(I) -> Expr
848 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
849 {
850 (
851 position(),
852 attempt(sep_by((tvar().skip(sptoken(':')), typexp()), csep()))
853 .map(|tvs: SmallVec<[(TVar, Type); 4]>| Arc::from_iter(tvs)),
854 between(sptoken('|'), sptoken('|'), lambda_args()),
855 optional(attempt(spstring("->").with(typexp()).skip(space()))),
856 choice((
857 attempt(sptoken('\'').with(fname()).skip(not_followed_by(sptoken(':'))))
858 .map(Either::Right),
859 expr().map(|e| Either::Left(e)),
860 )),
861 )
862 .map(|(pos, constraints, (args, vargs), rtype, body)| {
863 let args = Arc::from_iter(args);
864 ExprKind::Lambda(Arc::new(Lambda { args, vargs, rtype, constraints, body }))
865 .to_expr(pos)
866 })
867 }
868}
869
870parser! {
871 fn letbind[I]()(I) -> Expr
872 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
873 {
874 (
875 position(),
876 doc_comment(),
877 optional(string("pub").skip(space())).map(|o| o.is_some()),
878 spstring("let")
879 .with(space())
880 .with((structure_pattern(), optional(attempt(sptoken(':').with(typexp())))))
881 .skip(spstring("=")),
882 expr(),
883 )
884 .map(|(pos, doc, export, (pattern, typ), value)| {
885 ExprKind::Bind(Arc::new(Bind { doc, export, pattern, typ, value }))
886 .to_expr(pos)
887 })
888 }
889}
890
891parser! {
892 fn connect[I]()(I) -> Expr
893 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
894 {
895 (position(), optional(token('*')), spmodpath().skip(spstring("<-")), expr()).map(
896 |(pos, deref, name, e)| {
897 ExprKind::Connect { name, value: Arc::new(e), deref: deref.is_some() }
898 .to_expr(pos)
899 },
900 )
901 }
902}
903
904fn literal<I>() -> impl Parser<I, Output = Expr>
905where
906 I: RangeStream<Token = char, Position = SourcePosition>,
907 I::Error: ParseError<I::Token, I::Range, I::Position>,
908 I::Range: Range,
909{
910 (position(), parse_value(&GRAPHIX_ESC).skip(not_followed_by(token('_'))))
911 .map(|(pos, v)| ExprKind::Constant(v).to_expr(pos))
912}
913
914fn reference<I>() -> impl Parser<I, Output = Expr>
915where
916 I: RangeStream<Token = char, Position = SourcePosition>,
917 I::Error: ParseError<I::Token, I::Range, I::Position>,
918 I::Range: Range,
919{
920 (position(), modpath()).map(|(pos, name)| ExprKind::Ref { name }.to_expr(pos))
921}
922
923parser! {
924 fn deref_arith[I]()(I) -> Expr
925 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
926 {
927 (position(), token('*').with(arith_term()))
928 .map(|(pos, expr)| ExprKind::Deref(Arc::new(expr)).to_expr(pos))
929 }
930}
931
932parser! {
933 fn qop[I, P](p: P)(I) -> Expr
934 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range, P: Parser<I, Output = Expr>]
935 {
936 (position(), p, optional(attempt(sptoken('?')))).map(|(pos, e, qop)| match qop {
937 None => e,
938 Some(_) => ExprKind::Qop(Arc::new(e)).to_expr(pos),
939 })
940 }
941}
942
943parser! {
944 fn arith_term[I]()(I) -> Expr
945 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
946 {
947 choice((
948 attempt(spaces().with(qop(deref_arith()))),
949 attempt(spaces().with(raw_string())),
950 attempt(spaces().with(array())),
951 attempt(spaces().with(byref_arith())),
952 attempt(spaces().with(tuple())),
953 attempt(spaces().with(structure())),
954 attempt(spaces().with(variant())),
955 attempt(spaces().with(qop(apply()))),
956 attempt(spaces().with(structwith())),
957 attempt(spaces().with(qop(arrayref()))),
958 attempt(spaces().with(qop(tupleref()))),
959 attempt(spaces().with(qop(structref()))),
960 attempt(spaces().with(qop(do_block()))),
961 attempt(spaces().with(qop(select()))),
962 attempt(spaces().with(qop(cast()))),
963 attempt(spaces().with(qop(any()))),
964 attempt(spaces().with(interpolated())),
965 attempt(spaces().with(literal())),
966 attempt(spaces().with(qop(reference()))),
967 attempt(
968 (position(), sptoken('!').with(arith()))
969 .map(|(pos, expr)| ExprKind::Not { expr: Arc::new(expr) }.to_expr(pos)),
970 ),
971 attempt(between(sptoken('('), sptoken(')'), arith())),
972 ))
973 .skip(spaces())
974 }
975}
976
977parser! {
978 fn arith[I]()(I) -> Expr
979 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
980 {
981 choice((
982 attempt(chainl1(
983 arith_term(),
984 choice((
985 attempt(spstring("+")),
986 attempt(spstring("-")),
987 attempt(spstring("*")),
988 attempt(spstring("/")),
989 attempt(spstring("%")),
990 attempt(spstring("==")),
991 attempt(spstring("!=")),
992 attempt(spstring(">=")),
993 attempt(spstring("<=")),
994 attempt(spstring(">")),
995 attempt(spstring("<")),
996 attempt(spstring("&&")),
997 attempt(spstring("||")),
998 attempt(spstring("~")),
999 ))
1000 .map(|op: &str| match op {
1001 "+" => |lhs: Expr, rhs: Expr| {
1002 let pos = lhs.pos;
1003 ExprKind::Add { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1004 },
1005 "-" => |lhs: Expr, rhs: Expr| {
1006 let pos = lhs.pos;
1007 ExprKind::Sub { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1008 },
1009 "*" => |lhs: Expr, rhs: Expr| {
1010 let pos = lhs.pos;
1011 ExprKind::Mul { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1012 },
1013 "/" => |lhs: Expr, rhs: Expr| {
1014 let pos = lhs.pos;
1015 ExprKind::Div { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1016 },
1017 "%" => |lhs: Expr, rhs: Expr| {
1018 let pos = lhs.pos;
1019 ExprKind::Mod { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1020 },
1021 "==" => |lhs: Expr, rhs: Expr| {
1022 let pos = lhs.pos;
1023 ExprKind::Eq { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1024 },
1025 "!=" => |lhs: Expr, rhs: Expr| {
1026 let pos = lhs.pos;
1027 ExprKind::Ne { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1028 },
1029 ">" => |lhs: Expr, rhs: Expr| {
1030 let pos = lhs.pos;
1031 ExprKind::Gt { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1032 },
1033 "<" => |lhs: Expr, rhs: Expr| {
1034 let pos = lhs.pos;
1035 ExprKind::Lt { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1036 },
1037 ">=" => |lhs: Expr, rhs: Expr| {
1038 let pos = lhs.pos;
1039 ExprKind::Gte { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1040 },
1041 "<=" => |lhs: Expr, rhs: Expr| {
1042 let pos = lhs.pos;
1043 ExprKind::Lte { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1044 },
1045 "&&" => |lhs: Expr, rhs: Expr| {
1046 let pos = lhs.pos;
1047 ExprKind::And { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1048 },
1049 "||" => |lhs: Expr, rhs: Expr| {
1050 let pos = lhs.pos;
1051 ExprKind::Or { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }.to_expr(pos)
1052 },
1053 "~" => |lhs: Expr, rhs: Expr| {
1054 let pos = lhs.pos;
1055 ExprKind::Sample { lhs: Arc::new(lhs), rhs: Arc::new(rhs) }
1056 .to_expr(pos)
1057 },
1058 _ => unreachable!(),
1059 }),
1060 )),
1061 attempt((position(), sptoken('!').with(arith_term())))
1062 .map(|(pos, expr)| ExprKind::Not { expr: Arc::new(expr) }.to_expr(pos)),
1063 attempt(between(sptoken('('), sptoken(')'), arith())),
1064 ))
1065 }
1066}
1067
1068parser! {
1069 fn slice_pattern[I]()(I) -> StructurePattern
1070 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1071 {
1072 macro_rules! all_left {
1073 ($pats:expr) => {{
1074 let mut err = false;
1075 let pats: Arc<[StructurePattern]> =
1076 Arc::from_iter($pats.into_iter().map(|s| match s {
1077 Either::Left(s) => s,
1078 Either::Right(_) => {
1079 err = true;
1080 StructurePattern::Ignore
1081 }
1082 }));
1083 if err {
1084 return unexpected_any("invalid pattern").left();
1085 }
1086 pats
1087 }};
1088 }
1089 (
1090 optional(attempt(spfname().skip(sptoken('@')))),
1091 between(
1092 sptoken('['),
1093 sptoken(']'),
1094 sep_by(
1095 choice((
1096 attempt(spstring("..")).map(|_| Either::Right(None)),
1097 attempt(spfname().skip(spstring("..")))
1098 .map(|n| Either::Right(Some(n))),
1099 structure_pattern().map(|p| Either::Left(p)),
1100 )),
1101 csep(),
1102 ),
1103 ),
1104 )
1105 .then(
1106 |(all, mut pats): (
1107 Option<ArcStr>,
1108 SmallVec<[Either<StructurePattern, Option<ArcStr>>; 8]>,
1109 )| {
1110 if pats.len() == 0 {
1111 value(StructurePattern::Slice { all, binds: Arc::from_iter([]) })
1112 .right()
1113 } else if pats.len() == 1 {
1114 match pats.pop().unwrap() {
1115 Either::Left(s) => value(StructurePattern::Slice {
1116 all,
1117 binds: Arc::from_iter([s]),
1118 })
1119 .right(),
1120 Either::Right(_) => {
1121 unexpected_any("invalid singular range match").left()
1122 }
1123 }
1124 } else {
1125 match (&pats[0], &pats[pats.len() - 1]) {
1126 (Either::Right(_), Either::Right(_)) => {
1127 unexpected_any("invalid pattern").left()
1128 }
1129 (Either::Right(_), Either::Left(_)) => {
1130 let head = pats.remove(0).right().unwrap();
1131 let suffix = all_left!(pats);
1132 value(StructurePattern::SliceSuffix { all, head, suffix })
1133 .right()
1134 }
1135 (Either::Left(_), Either::Right(_)) => {
1136 let tail = pats.pop().unwrap().right().unwrap();
1137 let prefix = all_left!(pats);
1138 value(StructurePattern::SlicePrefix { all, tail, prefix })
1139 .right()
1140 }
1141 (Either::Left(_), Either::Left(_)) => {
1142 value(StructurePattern::Slice { all, binds: all_left!(pats) })
1143 .right()
1144 }
1145 }
1146 }
1147 },
1148 )
1149 }
1150}
1151
1152fn raw_string<I>() -> impl Parser<I, Output = Expr>
1153where
1154 I: RangeStream<Token = char, Position = SourcePosition>,
1155 I::Error: ParseError<I::Token, I::Range, I::Position>,
1156 I::Range: Range,
1157{
1158 const ESC: [char; 2] = ['\'', '\\'];
1159 (position(), between(string("r\'"), token('\''), escaped_string(&ESC))).map(
1160 |(pos, s): (_, String)| ExprKind::Constant(Value::String(s.into())).to_expr(pos),
1161 )
1162}
1163
1164parser! {
1165 fn tuple_pattern[I]()(I) -> StructurePattern
1166 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1167 {
1168 (
1169 optional(attempt(spfname().skip(sptoken('@')))),
1170 between(sptoken('('), sptoken(')'), sep_by1(structure_pattern(), csep())),
1171 )
1172 .then(|(all, binds): (Option<ArcStr>, SmallVec<[StructurePattern; 8]>)| {
1173 if binds.len() < 2 {
1174 unexpected_any("tuples must have at least 2 elements").left()
1175 } else {
1176 value(StructurePattern::Tuple { all, binds: Arc::from_iter(binds) })
1177 .right()
1178 }
1179 })
1180 }
1181}
1182
1183parser! {
1184 fn variant_pattern[I]()(I) -> StructurePattern
1185 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1186 {
1187 (
1188 optional(attempt(spfname().skip(sptoken('@')))),
1189 sptoken('`').with(typname()),
1190 optional(attempt(between(
1191 sptoken('('),
1192 sptoken(')'),
1193 sep_by1(structure_pattern(), csep()),
1194 ))),
1195 )
1196 .map(
1197 |(all, tag, binds): (
1198 Option<ArcStr>,
1199 ArcStr,
1200 Option<SmallVec<[StructurePattern; 8]>>,
1201 )| {
1202 let binds = match binds {
1203 None => smallvec![],
1204 Some(a) => a,
1205 };
1206 StructurePattern::Variant { all, tag, binds: Arc::from_iter(binds) }
1207 },
1208 )
1209 }
1210}
1211
1212parser! {
1213 fn struct_pattern[I]()(I) -> StructurePattern
1214 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1215 {
1216 (
1217 optional(attempt(spfname().skip(sptoken('@')))),
1218 between(
1219 sptoken('{'),
1220 sptoken('}'),
1221 sep_by1(
1222 choice((
1223 attempt((spfname().skip(sptoken(':')), structure_pattern()))
1224 .map(|(s, p)| (s, p, true)),
1225 attempt(spfname()).map(|s| {
1226 let p = StructurePattern::Bind(s.clone());
1227 (s, p, true)
1228 }),
1229 spstring("..")
1230 .map(|_| (literal!(""), StructurePattern::Ignore, false)),
1231 )),
1232 csep(),
1233 ),
1234 ),
1235 )
1236 .then(
1237 |(all, mut binds): (
1238 Option<ArcStr>,
1239 SmallVec<[(ArcStr, StructurePattern, bool); 8]>,
1240 )| {
1241 let mut exhaustive = true;
1242 binds.retain(|(_, _, ex)| {
1243 exhaustive &= *ex;
1244 *ex
1245 });
1246 binds.sort_by_key(|(s, _, _)| s.clone());
1247 let s = binds.iter().map(|(s, _, _)| s).collect::<FxHashSet<_>>();
1248 if s.len() < binds.len() {
1249 unexpected_any("struct fields must be unique").left()
1250 } else {
1251 let binds = Arc::from_iter(binds.into_iter().map(|(s, p, _)| (s, p)));
1252 value(StructurePattern::Struct { all, exhaustive, binds }).right()
1253 }
1254 },
1255 )
1256 }
1257}
1258
1259parser! {
1260 fn structure_pattern[I]()(I) -> StructurePattern
1261 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1262 {
1263 choice((
1264 attempt(slice_pattern()),
1265 attempt(tuple_pattern()),
1266 attempt(struct_pattern()),
1267 attempt(variant_pattern()),
1268 attempt(parse_value(&VAL_ESC).skip(not_followed_by(token('_'))))
1269 .map(|v| StructurePattern::Literal(v)),
1270 attempt(sptoken('_')).map(|_| StructurePattern::Ignore),
1271 spfname().map(|name| StructurePattern::Bind(name)),
1272 ))
1273 }
1274}
1275
1276parser! {
1277 fn pattern[I]()(I) -> Pattern
1278 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1279 {
1280 (
1281 optional(attempt(typexp().skip(space().with(spstring("as "))))),
1282 structure_pattern(),
1283 optional(attempt(space().with(spstring("if").with(space()).with(expr())))),
1284 )
1285 .map(
1286 |(type_predicate, structure_predicate, guard): (
1287 Option<Type>,
1288 StructurePattern,
1289 Option<Expr>,
1290 )| { Pattern { type_predicate, structure_predicate, guard } },
1291 )
1292 }
1293}
1294
1295parser! {
1296 fn select[I]()(I) -> Expr
1297 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1298 {
1299 (
1300 position(),
1301 string("select").with(space()).with((
1302 expr(),
1303 between(
1304 sptoken('{'),
1305 sptoken('}'),
1306 sep_by1((pattern(), spstring("=>").with(expr())), csep()),
1307 ),
1308 )),
1309 )
1310 .map(|(pos, (arg, arms)): (_, (Expr, Vec<(Pattern, Expr)>))| {
1311 ExprKind::Select { arg: Arc::new(arg), arms: Arc::from(arms) }.to_expr(pos)
1312 })
1313 }
1314}
1315
1316parser! {
1317 fn cast[I]()(I) -> Expr
1318 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1319 {
1320 (
1321 position(),
1322 string("cast").with(between(token('<'), sptoken('>'), typexp())),
1323 between(sptoken('('), sptoken(')'), expr()),
1324 )
1325 .map(|(pos, typ, e)| ExprKind::TypeCast { expr: Arc::new(e), typ }.to_expr(pos))
1326 }
1327}
1328
1329parser! {
1330 fn typedef[I]()(I) -> Expr
1331 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1332 {
1333 (
1334 position(),
1335 string("type").with(sptypname()),
1336 optional(attempt(between(
1337 sptoken('<'),
1338 sptoken('>'),
1339 sep_by1((tvar(), optional(attempt(sptoken(':').with(typexp())))), csep()),
1340 ))),
1341 sptoken('=').with(typexp()),
1342 )
1343 .map(|(pos, name, params, typ)| {
1344 let params = params
1345 .map(|ps: SmallVec<[(TVar, Option<Type>); 8]>| {
1346 Arc::from_iter(ps.into_iter())
1347 })
1348 .unwrap_or_else(|| Arc::<[(TVar, Option<Type>)]>::from(Vec::new()));
1349 ExprKind::TypeDef { name, params, typ }.to_expr(pos)
1350 })
1351 }
1352}
1353
1354parser! {
1355 fn tuple[I]()(I) -> Expr
1356 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1357 {
1358 (position(), between(token('('), sptoken(')'), sep_by1(expr(), csep()))).then(
1359 |(pos, exprs): (_, SmallVec<[Expr; 8]>)| {
1360 if exprs.len() < 2 {
1361 unexpected_any("tuples must have at least 2 elements").left()
1362 } else {
1363 value(ExprKind::Tuple { args: Arc::from_iter(exprs) }.to_expr(pos))
1364 .right()
1365 }
1366 },
1367 )
1368 }
1369}
1370
1371parser! {
1372 fn structure[I]()(I) -> Expr
1373 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1374 {
1375 (
1376 position(),
1377 between(
1378 token('{'),
1379 sptoken('}'),
1380 sep_by1((spfname(), optional(attempt(sptoken(':')).with(expr()))), csep()),
1381 ),
1382 )
1383 .then(|(pos, mut exprs): (_, SmallVec<[(ArcStr, Option<Expr>); 8]>)| {
1384 let s = exprs.iter().map(|(n, _)| n).collect::<FxHashSet<_>>();
1385 if s.len() < exprs.len() {
1386 return unexpected_any("struct fields must be unique").left();
1387 }
1388 exprs.sort_by_key(|(n, _)| n.clone());
1389 let args = exprs.into_iter().map(|(n, e)| match e {
1390 Some(e) => (n, e),
1391 None => {
1392 let e = ExprKind::Ref { name: [n.clone()].into() }.to_expr(pos);
1393 (n, e)
1394 }
1395 });
1396 value(ExprKind::Struct { args: Arc::from_iter(args) }.to_expr(pos)).right()
1397 })
1398 }
1399}
1400
1401parser! {
1402 fn variant[I]()(I) -> Expr
1403 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1404 {
1405 (
1406 position(),
1407 token('`').with(typname()),
1408 optional(attempt(between(token('('), sptoken(')'), sep_by1(expr(), csep())))),
1409 )
1410 .map(|(pos, tag, args): (_, ArcStr, Option<SmallVec<[Expr; 5]>>)| {
1411 let args = match args {
1412 None => smallvec![],
1413 Some(a) => a,
1414 };
1415 ExprKind::Variant { tag, args: Arc::from_iter(args.into_iter()) }.to_expr(pos)
1416 })
1417 }
1418}
1419
1420parser! {
1421 fn structwith[I]()(I) -> Expr
1422 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1423 {
1424 (
1425 position(),
1426 between(
1427 token('{'),
1428 sptoken('}'),
1429 (
1430 ref_pexp().skip(space()).skip(spstring("with")).skip(space()),
1431 sep_by1((spfname(), optional(attempt(sptoken(':').with(expr())))), csep()),
1432 ),
1433 ),
1434 )
1435 .then(
1436 |(pos, (source, mut exprs)): (_, (Expr, SmallVec<[(ArcStr, Option<Expr>); 8]>))| {
1437 let s = exprs.iter().map(|(n, _)| n).collect::<FxHashSet<_>>();
1438 if s.len() < exprs.len() {
1439 return unexpected_any("struct fields must be unique").left();
1440 }
1441 exprs.sort_by_key(|(n, _)| n.clone());
1442 let exprs = exprs.into_iter().map(|(name, e)| match e {
1443 Some(e) => (name, e),
1444 None => {
1445 let e = ExprKind::Ref { name: ModPath::from([name.clone()]) }.to_expr(pos);
1446 (name, e)
1447 }
1448 });
1449 let e = ExprKind::StructWith {
1450 source: Arc::new(source),
1451 replace: Arc::from_iter(exprs),
1452 }
1453 .to_expr(pos);
1454 value(e).right()
1455 },
1456 )
1457 }
1458}
1459
1460parser! {
1461 fn byref[I]()(I) -> Expr
1462 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1463 {
1464 (position(), token('&').with(expr()))
1465 .map(|(pos, expr)| ExprKind::ByRef(Arc::new(expr)).to_expr(pos))
1466 }
1467}
1468
1469parser! {
1470 fn byref_arith[I]()(I) -> Expr
1471 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1472 {
1473 (position(), token('&').with(arith_term()))
1474 .map(|(pos, expr)| ExprKind::ByRef(Arc::new(expr)).to_expr(pos))
1475 }
1476}
1477
1478parser! {
1479 fn deref[I]()(I) -> Expr
1480 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1481 {
1482 (position(), token('*').with(expr()))
1483 .map(|(pos, expr)| ExprKind::Deref(Arc::new(expr)).to_expr(pos))
1484 }
1485}
1486
1487parser! {
1488 fn expr[I]()(I) -> Expr
1489 where [I: RangeStream<Token = char, Position = SourcePosition>, I::Range: Range]
1490 {
1491 choice((
1492 attempt(choice((
1493 attempt(spaces().with(module())),
1494 attempt(spaces().with(use_module())),
1495 attempt(spaces().with(typedef())),
1496 attempt(spaces().with(raw_string())),
1497 attempt(spaces().with(array())),
1498 attempt(spaces().with(byref())),
1499 attempt(spaces().with(connect())),
1500 attempt(spaces().with(arith())),
1501 attempt(spaces().with(qop(deref()))),
1502 attempt(spaces().with(tuple())),
1503 attempt(spaces().with(between(token('('), sptoken(')'), expr()))),
1504 attempt(spaces().with(structure())),
1505 attempt(spaces().with(variant())),
1506 ))),
1507 attempt(spaces().with(qop(apply()))),
1508 attempt(spaces().with(structwith())),
1509 attempt(spaces().with(qop(arrayref()))),
1510 attempt(spaces().with(qop(tupleref()))),
1511 attempt(spaces().with(qop(structref()))),
1512 attempt(spaces().with(qop(do_block()))),
1513 attempt(spaces().with(lambda())),
1514 attempt(spaces().with(letbind())),
1515 attempt(spaces().with(qop(select()))),
1516 attempt(spaces().with(qop(cast()))),
1517 attempt(spaces().with(qop(any()))),
1518 attempt(spaces().with(interpolated())),
1519 attempt(spaces().with(literal())),
1520 attempt(spaces().with(qop(reference())))
1521 ))
1522 }
1523}
1524
1525pub fn parse(ori: Origin) -> anyhow::Result<Arc<[Expr]>> {
1530 let ori = Arc::new(ori);
1531 set_origin(ori.clone());
1532 let r: Vec<Expr> = sep_by1(expr(), attempt(sptoken(';')))
1533 .skip(spaces())
1534 .skip(eof())
1535 .easy_parse(position::Stream::new(&*ori.text))
1536 .map(|(r, _)| r)
1537 .map_err(|e| anyhow::anyhow!(format!("{}", e)))?;
1538 Ok(Arc::from(r))
1539}
1540
1541pub fn parse_one(s: &str) -> anyhow::Result<Expr> {
1543 expr()
1544 .skip(spaces())
1545 .skip(eof())
1546 .easy_parse(position::Stream::new(&*s))
1547 .map(|(r, _)| r)
1548 .map_err(|e| anyhow::anyhow!(format!("{e}")))
1549}
1550
1551pub fn parse_fn_type(s: &str) -> anyhow::Result<FnType> {
1553 fntype()
1554 .skip(spaces())
1555 .skip(eof())
1556 .easy_parse(position::Stream::new(s))
1557 .map(|(r, _)| r)
1558 .map_err(|e| anyhow::anyhow!(format!("{e}")))
1559}
1560
1561pub(super) fn parse_modpath(s: &str) -> anyhow::Result<ModPath> {
1562 modpath()
1563 .skip(spaces())
1564 .skip(eof())
1565 .easy_parse(position::Stream::new(s))
1566 .map(|(r, _)| r)
1567 .map_err(|e| anyhow::anyhow!(format!("{e}")))
1568}