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