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