1use alloc::vec::Vec;
19
20use muon::{Chain, Group, Item, Seq};
21use num_bigint::BigInt;
22
23use crate::builtins::Builtin;
24use crate::code::{len32, Builder, ChunkId, HomeLeaf, Member, Node, NodeId, Pat, PatId, Run, Text};
25use crate::module::{ImportSpec, ModuleName};
26use crate::resolve::{Barrier, Ref, Scope};
27use crate::source::{report, ChunkSpan, DocSource, Pos};
28use crate::sym::Sym;
29use crate::Ctx;
30
31fn text(s: &str) -> Text {
33 Text::from(s)
34}
35
36#[derive(Debug, Clone, PartialEq, Eq)]
39pub enum Error {
40 Syntax(muon::ParseError),
42 Parse(ParseError, muon::Span),
45}
46
47impl Error {
48 pub fn span(&self) -> muon::Span {
51 match self {
52 Error::Syntax(e) => muon::Span {
53 offset: e.offset as Pos,
54 length: 0,
55 },
56 Error::Parse(_, span) => *span,
57 }
58 }
59
60 pub fn report(&self, name: &str, text: &str) -> alloc::string::String {
64 let message = match self {
65 Error::Syntax(e) => alloc::format!("syntax error: {:?}", e.kind),
66 Error::Parse(e, _) => alloc::format!("parse error: {e:?}"),
67 };
68 report(name, text, self.span(), &message)
69 }
70}
71
72#[derive(Debug, Clone, PartialEq, Eq)]
76pub enum ParseError {
77 EmptyProgram,
79 MultipleExpressions,
82 EmptyChain,
84 AbsWithoutBody,
86 BadBinder,
89 UnexpectedBinder,
92 BadSymbol,
96 CombinatorDeferred,
100 DiscardReference,
103 ReservedName,
106 MalformedNumber,
110 PunctAtAtom,
115 MalformedMapKey,
119 LetMissingBinders,
122 LetMissingBody,
124 RecurMissingBinders,
127 RecurMissingBody,
129 RecurShadowsOuter(Text),
134 MalformedBinding,
137 ReservedKeyword,
140 BadPattern,
143 ComparandNotAtom,
147 BareLiteralHeader,
154 LoneSurrogate,
158 LetOrUnparenthesized,
162 UnknownType,
165 OrBindersMismatch,
167 MalformedPipe,
170 UnboundName(Text),
177 BadModuleItemName,
182 DuplicateModuleItem,
188 MalformedImport,
194 MisplacedImport,
200 MalformedConst,
206 MisplacedConst,
212 ShadowsImport(Text),
217 ShadowsIota(Text),
220 MalformedLocal,
226 MisplacedLocal,
231 ShadowsLocal(Text),
234 ShadowsItem(Text),
241 UnknownReserved(Text),
249 DuplicateReserved(Text),
253 MisplacedReserved,
259 OutsideModule(Text),
266 NotAPrototype(Text),
272 BinderRunGlued,
277 FloatLiteralUnsupported,
283 ReservedLiteralForm,
291 BareListLiteral,
295 BareMapLiteral,
303 BlockTrailingBinding,
309 CaseMissingArms,
313 CaseSubjectExtra,
317 ArmNotBinder,
320 ArmMissingBody,
323 WhenMissingCond,
326}
327
328#[derive(Debug)]
332struct Failure(ParseError, ChunkSpan);
333
334type Parsed<T> = Result<T, Failure>;
336
337impl From<ParseError> for Failure {
338 fn from(error: ParseError) -> Self {
339 Failure(error, ChunkSpan::NONE)
340 }
341}
342
343impl Failure {
344 fn or_at(self, span: impl FnOnce() -> ChunkSpan) -> Self {
346 match self.1.get() {
347 Some(_) => self,
348 None => Failure(self.0, span()),
349 }
350 }
351
352 fn into_error(self, src: Source<'_>) -> Error {
355 let span = self.1.in_doc(src.base).unwrap_or_default();
356 Error::Parse(self.0, span)
357 }
358}
359
360pub(crate) enum Root<'p> {
366 Closed,
368 Open,
370 Prelude(&'p [Text]),
372}
373
374impl Ctx {
375 pub(crate) fn compile_expr(&self, src: &str, root: Root<'_>) -> Result<ChunkId, Error> {
378 let seq = muon::parse(src).map_err(Error::Syntax)?;
379 let (names, auto_bind) = match root {
380 Root::Closed => (Vec::new(), false),
381 Root::Open => (Vec::new(), true),
382 Root::Prelude(prelude) => (prelude.iter().map(|n| self.intern(n)).collect(), false),
383 };
384 let scope = Scope::new(self, names, 0, auto_bind, Vec::new());
385 let mut b = Builder::new();
386 let src = Source {
387 text: src,
388 base: b.add_doc(None, src),
389 };
390 let mut p = Parser::new(self, scope, b, src);
391 let top = p.b.enter_module();
392 let (body, span) = p.program(&seq).map_err(|f| f.into_error(src))?;
393 let body = p.b.push(body, span);
394 let mark = p.b.member_scratch.len();
395 p.b.leave_module(top, None, mark, 0, 0, &[], Vec::new(), body);
396 Ok(self.add_built(p.b, None, "__eval_"))
397 }
398
399 pub(crate) fn compile_source(
408 &self,
409 src: &str,
410 frame: &[Text],
411 name: Option<ModuleName>,
412 doc: Option<DocSource>,
413 ) -> Result<ChunkId, Error> {
414 let seq = muon::parse(src).map_err(Error::Syntax)?;
415 let b = self.emit_module(&seq, src, doc, frame, name.clone())?;
416 Ok(self.add_built(b, name, "__module_"))
417 }
418
419 fn emit_module(
420 &self,
421 seq: &Seq<'_>,
422 src: &str,
423 doc: Option<DocSource>,
424 frame: &[Text],
425 name: Option<ModuleName>,
426 ) -> Result<Builder, Error> {
427 let mut b = Builder::new();
428 let source = Source {
429 text: src,
430 base: b.add_doc(doc, src),
431 };
432 let chains = chain_slices(seq);
433 let decls = declarations(&chains, self, source).map_err(|f| f.into_error(source))?;
434 let items = sorted(&decls.items);
435 let locals = sorted(&decls.locals);
436 let iotas = sorted(&decls.iotas);
437 let mut slots: Vec<Sym> = decls.imports.iter().map(|(n, _)| *n).collect();
440 slots.extend(frame.iter().map(|n| self.intern(n)));
441 let members = Barrier::Module {
442 items: items.clone(),
443 locals: locals.clone(),
444 iotas: iotas.clone(),
445 };
446 let scope = Scope::new(
447 self,
448 slots.clone(),
449 decls.imports.len(),
450 false,
451 alloc::vec![members],
452 );
453 let mut p = Parser::new(self, scope, b, source);
454 let top = p.b.enter_module();
455 let (mark, body) = p
456 .members(&decls, &items, &locals, &iotas)
457 .map_err(|f| f.into_error(source))?;
458 let specs = decls.imports.into_iter().map(|(_, spec)| spec).collect();
459 let (n_items, n_locals) = (len32(items.len()), len32(locals.len()));
460 p.b.leave_module(top, name, mark, n_items, n_locals, &slots, specs, body);
461 Ok(p.b)
462 }
463}
464
465#[derive(Clone, Copy)]
468struct Source<'s> {
469 text: &'s str,
470 base: Pos,
471}
472
473impl Source<'_> {
474 fn item(self, item: &Item<'_>) -> ChunkSpan {
476 let span = item.span(self.text);
477 ChunkSpan::new(self.base + span.offset, span.length)
478 }
479
480 fn items(self, items: &[&Item<'_>]) -> ChunkSpan {
483 match items {
484 [] => ChunkSpan::NONE,
485 [item] => self.item(item),
486 [first, .., last] => self.item(first).join(self.item(last)),
487 }
488 }
489
490 fn group(self, group: &Group<'_>) -> ChunkSpan {
492 ChunkSpan::new(self.base + group.span.offset, group.span.length)
493 }
494}
495
496fn sorted(names: &[Sym]) -> Vec<Sym> {
498 let mut names = names.to_vec();
499 names.sort();
500 names
501}
502
503enum Decl<'b, 'a> {
510 Item(Sym, Vec<&'b Item<'a>>),
512 Forward(Sym),
515 Local(Sym, Vec<&'b Item<'a>>),
517 Main(Vec<&'b Item<'a>>),
519}
520
521struct Decls<'b, 'a> {
523 bodies: Vec<(Decl<'b, 'a>, ChunkSpan)>,
525 spans: Vec<(Sym, ChunkSpan)>,
528 items: Vec<Sym>,
530 locals: Vec<Sym>,
532 iotas: Vec<Sym>,
534 imports: Vec<(Sym, ImportSpec)>,
536 has_main: bool,
537}
538
539impl Decls<'_, '_> {
540 fn span(&self, name: Sym) -> ChunkSpan {
544 match self.spans.binary_search_by(|(n, _)| n.cmp(&name)) {
545 Ok(i) => self.spans[i].1,
546 Err(_) => ChunkSpan::NONE,
547 }
548 }
549}
550
551fn declarations<'b, 'a>(
558 chains: &[Vec<&'b Item<'a>>],
559 ctx: &Ctx,
560 src: Source<'_>,
561) -> Parsed<Decls<'b, 'a>> {
562 let mut d = Decls {
563 bodies: Vec::new(),
564 spans: Vec::new(),
565 items: Vec::new(),
566 locals: Vec::new(),
567 iotas: Vec::new(),
568 imports: Vec::new(),
569 has_main: false,
570 };
571 let mut re = Reexports::default();
572 for ci in chains {
573 declaration(ci, ctx, src, &mut d, &mut re).map_err(|f| f.or_at(|| src.items(ci)))?;
574 }
575 let dup = |name: &Sym| {
578 let span = d.spans.iter().rev().find(|(n, _)| n == name);
579 Err(Failure(
580 ParseError::DuplicateModuleItem,
581 span.map_or(ChunkSpan::NONE, |(_, span)| *span),
582 ))
583 };
584 for (name, _) in &d.imports {
585 if d.iotas.contains(name) || !re.imports.contains(name) && d.items.contains(name) {
586 return dup(name);
587 }
588 }
589 for iota in &d.iotas {
590 if !re.iotas.contains(iota) && d.items.contains(iota) {
591 return dup(iota);
592 }
593 }
594 for name in &d.locals {
595 let taken = d.items.contains(name)
596 || d.iotas.contains(name)
597 || d.imports.iter().any(|(n, _)| n == name);
598 if taken {
599 return dup(name);
600 }
601 }
602 d.spans.sort_by_key(|(name, _)| *name);
604 Ok(d)
605}
606
607#[derive(Default)]
609struct Reexports {
610 imports: Vec<Sym>,
611 iotas: Vec<Sym>,
612}
613
614fn declaration<'b, 'a>(
616 ci: &[&'b Item<'a>],
617 ctx: &Ctx,
618 src: Source<'_>,
619 d: &mut Decls<'b, 'a>,
620 re: &mut Reexports,
621) -> Parsed<()> {
622 let span = src.items(ci);
623 let split = ci.iter().position(|it| matches!(it, Item::Punct("=")));
624 if split.is_none() && head_keyword(ci[0]) == Some("import") {
625 let (name, spec) = parse_private_import(ci, ctx, src)?;
626 push_import(&mut d.imports, name, spec)?;
627 return Ok(());
628 }
629 if split.is_none() && head_keyword(ci[0]) == Some("const") {
630 for (name, span) in parse_const_decl(ci, ctx, src)? {
631 push_name(&mut d.iotas, name)?;
632 d.spans.push((name, span));
633 }
634 return Ok(());
635 }
636 if split.is_none() && head_keyword(ci[0]) == Some("local") {
637 for (name, body, span) in parse_local_group(ci, ctx, src)? {
638 push_name(&mut d.locals, name)?;
639 d.spans.push((name, span));
640 d.bodies.push((Decl::Local(name, body), span));
641 }
642 return Ok(());
643 }
644 let eq = split.ok_or(ParseError::MalformedBinding)?;
645 if ci[eq + 1..].iter().any(|it| matches!(it, Item::Punct("="))) {
646 return Err(ParseError::MalformedBinding.into());
647 }
648 let (head, tail) = (&ci[..eq], &ci[eq + 1..]);
649 if head.is_empty() || tail.is_empty() {
650 return Err(ParseError::MalformedBinding.into());
651 }
652 if head.len() > 1 && head_keyword(head[0]) == Some("const") {
653 return Err(ParseError::MalformedConst.into());
654 }
655 if head.len() > 1 && head_keyword(head[0]) == Some("local") {
656 let name = plain_name(&head[1..], ParseError::MalformedLocal, ctx, src)?;
657 push_name(&mut d.locals, name)?;
658 d.spans.push((name, span));
659 d.bodies.push((Decl::Local(name, tail.to_vec()), span));
660 return Ok(());
661 }
662 if let [Item::Sym(s)] = head {
663 if let Some(reserved) = reserved_moditem(s) {
664 if d.has_main {
665 let error = ParseError::DuplicateReserved(text(reserved));
666 return Err(Failure(error, src.items(head)));
667 }
668 d.has_main = true;
669 d.bodies.push((Decl::Main(tail.to_vec()), span));
670 return Ok(());
671 }
672 if s.starts_with("__") {
673 let error = ParseError::UnknownReserved(text(s));
674 return Err(Failure(error, src.items(head)));
675 }
676 }
677 let name = plain_name(head, ParseError::BadModuleItemName, ctx, src)?;
678 if d.items.contains(&name) {
679 return Err(ParseError::DuplicateModuleItem.into());
680 }
681 if head_keyword(tail[0]) == Some("import") {
682 let spec = parse_import_spec(tail)?;
683 push_import(&mut d.imports, name, spec)?;
684 re.imports.push(name);
685 d.items.push(name);
686 d.spans.push((name, span));
687 d.bodies.push((Decl::Forward(name), span));
688 return Ok(());
689 }
690 if head_keyword(tail[0]) == Some("const") {
691 if tail.len() != 1 {
692 return Err(ParseError::MalformedConst.into());
693 }
694 push_name(&mut d.iotas, name)?;
695 re.iotas.push(name);
696 d.items.push(name);
697 d.spans.push((name, span));
698 d.bodies.push((Decl::Forward(name), span));
699 return Ok(());
700 }
701 d.items.push(name);
702 d.spans.push((name, span));
703 d.bodies.push((Decl::Item(name, tail.to_vec()), span));
704 Ok(())
705}
706
707fn reserved_moditem(name: &str) -> Option<&'static str> {
716 match name {
717 "__main" => Some("__main"),
718 _ => None,
719 }
720}
721
722fn push_import(imports: &mut Vec<(Sym, ImportSpec)>, name: Sym, spec: ImportSpec) -> Parsed<()> {
724 if imports.iter().any(|(n, _)| *n == name) {
725 return Err(ParseError::DuplicateModuleItem.into());
726 }
727 imports.push((name, spec));
728 Ok(())
729}
730
731fn push_name(names: &mut Vec<Sym>, name: Sym) -> Parsed<()> {
733 if names.contains(&name) {
734 return Err(ParseError::DuplicateModuleItem.into());
735 }
736 names.push(name);
737 Ok(())
738}
739
740fn parse_private_import<'a>(
746 ci: &[&Item<'a>],
747 ctx: &Ctx,
748 src: Source<'_>,
749) -> Parsed<(Sym, ImportSpec)> {
750 let rest: Vec<&Item<'a>> = match ci[0] {
751 Item::Run(members) => members[1..]
752 .iter()
753 .map(|it| it as &Item<'a>)
754 .chain(ci[1..].iter().copied())
755 .collect(),
756 _ => ci[1..].to_vec(),
757 };
758 match rest.as_slice() {
759 [Item::Str(spec), Item::Sym("as"), rest @ ..] if !rest.is_empty() => {
760 let name = plain_name(rest, ParseError::BadModuleItemName, ctx, src)?;
761 Ok((name, decode_str(spec)?))
762 }
763 _ => Err(ParseError::MalformedImport.into()),
764 }
765}
766
767fn parse_const_decl<'a>(
775 ci: &[&Item<'a>],
776 ctx: &Ctx,
777 src: Source<'_>,
778) -> Parsed<Vec<(Sym, ChunkSpan)>> {
779 let rest: Vec<&Item<'a>> = match ci[0] {
782 Item::Run(members) => members[1..].iter().map(|it| it as &Item<'a>).collect(),
783 _ => ci[1..].to_vec(),
784 };
785 match rest.as_slice() {
786 [Item::Parens(Group { seq, .. }), ..] => {
787 let mut names = Vec::new();
788 for c in chain_slices(seq) {
789 let name = plain_name(&c, ParseError::MalformedConst, ctx, src)?;
790 names.push((name, src.items(&c)));
791 }
792 Ok(names)
793 }
794 rest if !rest.is_empty() => {
795 let name = plain_name(rest, ParseError::MalformedConst, ctx, src)?;
796 Ok(alloc::vec![(name, src.items(rest))])
797 }
798 _ => Err(ParseError::MalformedConst.into()),
799 }
800}
801
802#[allow(clippy::type_complexity)]
807fn parse_local_group<'b, 'a>(
808 ci: &[&'b Item<'a>],
809 ctx: &Ctx,
810 src: Source<'_>,
811) -> Parsed<Vec<(Sym, Vec<&'b Item<'a>>, ChunkSpan)>> {
812 let group = match ci[0] {
813 Item::Run(members) => members.get(1),
814 _ => ci.get(1).copied(),
815 };
816 let Some(Item::Parens(Group { seq, .. })) = group else {
817 return Err(ParseError::MalformedLocal.into());
818 };
819 let mut bindings = Vec::new();
820 for c in chain_slices(seq) {
821 let malformed = || Failure(ParseError::MalformedLocal, src.items(&c));
822 let eq = c
823 .iter()
824 .position(|it| matches!(it, Item::Punct("=")))
825 .ok_or_else(malformed)?;
826 let (head, tail) = (&c[..eq], &c[eq + 1..]);
827 if head.is_empty() || tail.is_empty() {
828 return Err(malformed());
829 }
830 if tail.iter().any(|it| matches!(it, Item::Punct("="))) {
831 return Err(malformed());
832 }
833 bindings.push((
834 plain_name(head, ParseError::MalformedLocal, ctx, src)?,
835 tail.to_vec(),
836 src.items(&c),
837 ));
838 }
839 Ok(bindings)
840}
841
842fn parse_import_spec(tail: &[&Item<'_>]) -> Parsed<ImportSpec> {
845 let spec = match tail {
846 [_import, Item::Str(spec)] => spec,
847 [Item::Run(members)] => match members.as_slice() {
848 [_import, Item::Str(spec)] => spec,
849 _ => return Err(ParseError::MalformedImport.into()),
850 },
851 _ => return Err(ParseError::MalformedImport.into()),
852 };
853 decode_str(spec)
854}
855
856fn plain_name(items: &[&Item<'_>], bad: ParseError, ctx: &Ctx, src: Source<'_>) -> Parsed<Sym> {
859 plain_name_at(items, bad, ctx).map_err(|f| f.or_at(|| src.items(items)))
860}
861
862fn plain_name_at(items: &[&Item<'_>], bad: ParseError, ctx: &Ctx) -> Parsed<Sym> {
864 match items {
865 [Item::Sym(s)] if is_keyword(s) => Err(ParseError::ReservedKeyword.into()),
866 [Item::Sym(s)] if s.starts_with("__") => Err(ParseError::ReservedName.into()),
867 [Item::Sym(s)] if reads_as_number(s) || *s == "_" => Err(bad.into()),
868 [Item::Sym(s)] => Ok(ctx.intern(s)),
869 _ => Err(bad.into()),
870 }
871}
872
873fn reads_as_number(s: &str) -> bool {
875 parse_int(s).is_some() || s.as_bytes()[0].is_ascii_digit()
876}
877
878#[derive(Debug, Clone, Copy, PartialEq, Eq)]
888enum Slot {
889 Value,
891 Applied,
894 AppliedElems,
897 Body,
900}
901
902type Spanned = (Node, ChunkSpan);
904
905enum Built {
907 Node(Node, ChunkSpan),
909 Spine(Spine),
912}
913
914struct Spine {
917 mark: usize,
918 callee: Option<Builtin>,
920 span: ChunkSpan,
922}
923
924struct Head {
927 pats: usize,
928 chain: Option<usize>,
932}
933
934enum SymRef {
936 Home,
937 Int(BigInt),
938 Builtin(Builtin),
939 Name(Sym),
940}
941
942const MAX_HEAD: usize = u8::MAX as usize;
945
946struct Parser<'c, 's> {
948 ctx: &'c Ctx,
949 b: Builder,
950 scope: Scope<'c>,
951 heads: Vec<Head>,
953 src: Source<'s>,
955}
956
957impl<'c, 's> Parser<'c, 's> {
958 fn new(ctx: &'c Ctx, scope: Scope<'c>, b: Builder, src: Source<'s>) -> Self {
960 Parser {
961 ctx,
962 b,
963 scope,
964 heads: Vec::new(),
965 src,
966 }
967 }
968
969 fn program(&mut self, seq: &Seq<'_>) -> Parsed<Spanned> {
971 match chain_slices(seq).as_slice() {
972 [] => Err(ParseError::EmptyProgram.into()),
973 [items] => {
974 let built = self.expr(items, Slot::Value)?;
975 Ok(self.close(built))
976 }
977 [_, second, ..] => Err(Failure(
978 ParseError::MultipleExpressions,
979 self.src.items(second),
980 )),
981 }
982 }
983
984 fn members(
991 &mut self,
992 decls: &Decls<'_, '_>,
993 items: &[Sym],
994 locals: &[Sym],
995 iotas: &[Sym],
996 ) -> Parsed<(usize, NodeId)> {
997 let mark = self.b.member_scratch.len();
998 for &name in items.iter().chain(locals).chain(iotas) {
999 let member = Member {
1000 name,
1001 node: NodeId::NONE,
1002 };
1003 self.b.member_scratch.push((member, decls.span(name)));
1004 }
1005 let slot = |name: Sym, names: &[Sym]| {
1006 names
1007 .binary_search(&name)
1008 .expect("a declared name has a slot")
1009 };
1010 let mut main = NodeId::NONE;
1011 for (decl, span) in &decls.bodies {
1012 let (index, node) = match decl {
1013 Decl::Item(name, body) => (slot(*name, items), self.body(body)?),
1014 Decl::Forward(name) => {
1015 let node = self.name_ref(*name).map_err(|f| f.or_at(|| *span))?;
1016 (slot(*name, items), self.b.push(node, *span))
1017 }
1018 Decl::Local(name, body) => (items.len() + slot(*name, locals), self.body(body)?),
1019 Decl::Main(body) => {
1020 main = self.body(body)?;
1021 continue;
1022 }
1023 };
1024 self.b.member_scratch[mark + index].0.node = node;
1025 }
1026 Ok((mark, main))
1027 }
1028
1029 fn body(&mut self, items: &[&Item<'_>]) -> Parsed<NodeId> {
1031 let built = self.expr(items, Slot::Value)?;
1032 Ok(self.child(built))
1033 }
1034
1035 fn close(&mut self, built: Built) -> Spanned {
1041 match built {
1042 Built::Node(node, span) => (node, span),
1043 Built::Spine(spine) => self.close_spine(spine),
1044 }
1045 }
1046
1047 fn child(&mut self, built: Built) -> NodeId {
1049 let (node, span) = self.close(built);
1050 self.b.push(node, span)
1051 }
1052
1053 fn close_spine(&mut self, spine: Spine) -> Spanned {
1055 let len = self.b.scratch.len() - spine.mark;
1056 if len == 1 {
1057 return self.b.scratch.pop().expect("a spine has a callee");
1058 }
1059 let app = Node::App {
1060 len: len32(len),
1061 args: self.b.push_run(Run::App, spine.mark),
1062 };
1063 (app, spine.span)
1064 }
1065
1066 fn start(&mut self, callee: Spanned) -> Spine {
1068 let mark = self.b.scratch.len();
1069 self.b.scratch.push(callee);
1070 Spine {
1071 mark,
1072 callee: builtin_of(callee.0),
1073 span: callee.1,
1074 }
1075 }
1076
1077 fn open(&mut self, built: Built) -> Spine {
1081 match built {
1082 Built::Spine(spine) => spine,
1083 Built::Node(Node::App { len, args }, span) => {
1084 let mark = self.b.scratch.len();
1085 for i in 0..len {
1086 let node = self.b.node(args.nth(i));
1087 self.b.scratch.push(node);
1088 }
1089 Spine {
1090 mark,
1091 callee: builtin_of(self.b.scratch[mark].0),
1092 span,
1093 }
1094 }
1095 Built::Node(node, span) => self.start((node, span)),
1096 }
1097 }
1098
1099 fn arg_slot(&self, spine: &Spine) -> Slot {
1101 let i = self.b.scratch.len() - spine.mark - 1;
1102 match spine.callee {
1103 Some(op) if op.applies_arg(i) => Slot::Applied,
1104 Some(op) if op.applies_elements_of(i) => Slot::AppliedElems,
1105 _ => Slot::Value,
1106 }
1107 }
1108
1109 fn next_slot(&self, spine: &Option<Spine>) -> Slot {
1112 match spine {
1113 None => Slot::Applied,
1114 Some(spine) => self.arg_slot(spine),
1115 }
1116 }
1117
1118 fn extend(&mut self, spine: &mut Spine, arg: Spanned) {
1122 spine.span = spine.span.join(arg.1);
1123 if self.b.scratch.len() - spine.mark == 1 {
1124 if let (Some(ns), Node::Symbol(m)) = (spine.callee, arg.0) {
1125 if let Some(op) = ns.member(m) {
1126 self.b.scratch[spine.mark] = (Node::Builtin(op), spine.span);
1127 spine.callee = Some(op);
1128 return;
1129 }
1130 }
1131 }
1132 self.b.scratch.push(arg);
1133 }
1134
1135 fn push_arg(&mut self, spine: &mut Option<Spine>, arg: Spanned) {
1137 match spine {
1138 None => *spine = Some(self.start(arg)),
1139 Some(spine) => self.extend(spine, arg),
1140 }
1141 }
1142
1143 fn expr(&mut self, items: &[&Item<'_>], slot: Slot) -> Parsed<Built> {
1151 let src = self.src;
1152 self.pipeline(items, slot)
1153 .map_err(|f| f.or_at(|| src.items(items)))
1154 }
1155
1156 fn pipeline(&mut self, items: &[&Item<'_>], slot: Slot) -> Parsed<Built> {
1158 if items.is_empty() {
1159 return Err(ParseError::EmptyChain.into());
1160 }
1161 match items.iter().rposition(|it| matches!(it, Item::Punct("|>"))) {
1165 None => self.segment(items, slot),
1166 Some(k) => {
1167 let (left, right) = (&items[..k], &items[k + 1..]);
1168 if left.is_empty() || right.is_empty() {
1169 let pipe = self.src.item(items[k]);
1170 return Err(Failure(ParseError::MalformedPipe, pipe));
1171 }
1172 let r = self.segment(right, Slot::Applied)?;
1173 let mut spine = self.open(r);
1174 let slot = self.arg_slot(&spine);
1175 let l = self.expr(left, slot)?;
1176 let l = self.close(l);
1177 self.extend(&mut spine, l);
1178 Ok(Built::Spine(spine))
1179 }
1180 }
1181 }
1182
1183 fn segment(&mut self, items: &[&Item<'_>], slot: Slot) -> Parsed<Built> {
1188 match items.iter().position(|it| is_split_point(it)) {
1189 None => self.app_spine(items, slot),
1190 Some(0) => match head_keyword(items[0]) {
1191 Some("let") | Some("recur") => self.let_or_recur(items[0], items, slot),
1192 Some("case") => self.case(items, slot),
1193 _ => self.binder(items, slot),
1194 },
1195 Some(k) => {
1196 let f = self.segment(&items[..k], Slot::Applied)?;
1197 let mut spine = self.open(f);
1198 let slot = self.arg_slot(&spine);
1199 let arg = self.segment(&items[k..], slot)?;
1200 let arg = self.close(arg);
1201 self.extend(&mut spine, arg);
1202 Ok(Built::Spine(spine))
1203 }
1204 }
1205 }
1206
1207 fn app_spine(&mut self, items: &[&Item<'_>], slot: Slot) -> Parsed<Built> {
1211 if let [item] = items {
1212 match item {
1213 Item::Parens(group) => return self.group(group, slot),
1214 Item::Run(_) => {}
1215 _ => return self.aexpr(item, slot),
1216 }
1217 }
1218 let mut spine: Option<Spine> = None;
1219 for (i, it) in items.iter().enumerate() {
1220 match *it {
1221 Item::Run(members) if i == 0 => {
1222 let src = self.src;
1223 check_run_head(members).map_err(|f| f.or_at(|| src.item(it)))?;
1224 let members = if is_self_head(members) {
1225 let new = self.home(HomeLeaf::New)?;
1226 let span = self.src.item(&members[0]);
1227 self.push_arg(&mut spine, (new, span));
1228 &members[1..]
1229 } else {
1230 &members[..]
1231 };
1232 for m in members {
1233 self.expand_arg(m, &mut spine)?;
1234 }
1235 }
1236 Item::Prefixed { sigil: '#', item }
1237 if i == 0 && matches!(item.as_ref(), Item::Sym("Self")) =>
1238 {
1239 let new = self.home(HomeLeaf::New)?;
1240 let span = self.src.item(it);
1241 self.push_arg(&mut spine, (new, span));
1242 }
1243 _ => self.expand_arg(it, &mut spine)?,
1244 }
1245 }
1246 let spine = spine.expect("a spine has at least one item");
1247 let len = self.b.scratch.len() - spine.mark;
1248 if len == 1 {
1249 if let Node::Home {
1250 leaf: HomeLeaf::New,
1251 ..
1252 } = self.b.scratch[spine.mark].0
1253 {
1254 let span = self.b.scratch[spine.mark].1;
1255 return Err(Failure(ParseError::ReservedLiteralForm, span));
1256 }
1257 let (node, span) = self.close_spine(spine);
1258 return Ok(Built::Node(node, span));
1259 }
1260 Ok(Built::Spine(spine))
1261 }
1262
1263 fn expand_arg(&mut self, item: &Item<'_>, spine: &mut Option<Spine>) -> Parsed<()> {
1267 match item {
1268 Item::Parens(group) => {
1269 let chains = chain_slices(&group.seq);
1270 if chains.is_empty() {
1271 let span = self.src.group(group);
1272 self.push_arg(spine, (Node::Unit, span));
1273 }
1274 for chain in &chains {
1275 let slot = self.next_slot(spine);
1276 let arg = self.expr(chain, slot)?;
1277 let arg = self.close(arg);
1278 self.push_arg(spine, arg);
1279 }
1280 if let Some(spine) = spine {
1282 spine.span = spine.span.join(self.src.group(group));
1283 }
1284 Ok(())
1285 }
1286 Item::Prefixed { sigil: '.', item }
1287 if matches!(item.as_ref(), Item::Sym("Self")) && spine.is_some() =>
1288 {
1289 let acc = self.close_spine(spine.take().expect("checked"));
1290 let value = self.home(HomeLeaf::Value)?;
1291 let value_span = self.src.item(item);
1292 let span = acc.1.join(value_span);
1293 let mark = self.b.scratch.len();
1294 self.b.scratch.push((value, value_span));
1295 self.b.scratch.push(acc);
1296 let read = Node::App {
1297 len: 2,
1298 args: self.b.push_run(Run::App, mark),
1299 };
1300 *spine = Some(self.start((read, span)));
1301 Ok(())
1302 }
1303 _ => {
1304 let slot = self.next_slot(spine);
1305 let arg = self.aexpr(item, slot)?;
1306 let arg = self.close(arg);
1307 self.push_arg(spine, arg);
1308 Ok(())
1309 }
1310 }
1311 }
1312
1313 fn group(&mut self, group: &Group<'_>, slot: Slot) -> Parsed<Built> {
1316 let chains = chain_slices(&group.seq);
1317 match chains.as_slice() {
1318 [] => Ok(Built::Node(Node::Unit, self.src.group(group))),
1319 [chain] => self.expr(chain, slot),
1320 chains => {
1321 let mut spine = None;
1322 for chain in chains {
1323 let slot = self.next_slot(&spine);
1324 let arg = self.expr(chain, slot)?;
1325 let arg = self.close(arg);
1326 self.push_arg(&mut spine, arg);
1327 }
1328 let mut spine = spine.expect("a group of several chains");
1329 spine.span = self.src.group(group);
1330 Ok(Built::Spine(spine))
1331 }
1332 }
1333 }
1334
1335 fn aexpr(&mut self, item: &Item<'_>, slot: Slot) -> Parsed<Built> {
1337 let src = self.src;
1338 self.atom_expr(item, slot)
1339 .map_err(|f| f.or_at(|| src.item(item)))
1340 }
1341
1342 fn atom_expr(&mut self, item: &Item<'_>, slot: Slot) -> Parsed<Built> {
1344 let node = match item {
1345 Item::Sym(s) => self.sym(s)?,
1346 Item::Prefixed { sigil: '.', item } => self.dot_symbol(item)?,
1347 Item::Brackets(_) => return Err(ParseError::BareListLiteral.into()),
1348 Item::Parens(group) => return self.group(group, slot),
1349 Item::Str(s) => self.b.str(decode_str(s)?),
1350 Item::Braces(group) => return self.block(group, slot),
1351 Item::Punct(".") => return Err(ParseError::CombinatorDeferred.into()),
1352 Item::Punct(_) => return Err(ParseError::PunctAtAtom.into()),
1353 Item::Comm(_) => return Err(ParseError::EmptyChain.into()),
1354 Item::Prefixed { sigil: '#', item } => match item.as_ref() {
1355 Item::Brackets(Group { seq, .. }) => self.list(seq, slot)?,
1356 Item::Braces(Group { seq, .. }) => self.map(seq)?,
1357 _ => return Err(ParseError::ReservedLiteralForm.into()),
1358 },
1359 Item::Prefixed { .. } => return Err(ParseError::UnexpectedBinder.into()),
1360 Item::Run(members) => {
1361 check_run_head(members)?;
1362 let items: Vec<&Item<'_>> = members.iter().collect();
1363 return self.expr(&items, slot);
1364 }
1365 };
1366 Ok(Built::Node(node, self.src.item(item)))
1367 }
1368
1369 fn sym(&mut self, s: &str) -> Parsed<Node> {
1371 let r = classify(s, self.ctx)?;
1372 self.resolve_sym(r)
1373 }
1374
1375 fn resolve_sym(&mut self, r: SymRef) -> Parsed<Node> {
1376 match r {
1377 SymRef::Home => self.home(HomeLeaf::Module),
1378 SymRef::Int(n) => Ok(self.b.int(n)),
1379 SymRef::Builtin(op) => Ok(Node::Builtin(op)),
1380 SymRef::Name(name) => self.name_ref(name),
1381 }
1382 }
1383
1384 fn name_ref(&mut self, name: Sym) -> Parsed<Node> {
1386 Ok(match self.scope.reference(name)? {
1387 Ref::Local(index) => Node::Local { name, index },
1388 Ref::Item { index, depth } => Node::ModItem { index, depth, name },
1389 Ref::Builtin(op) => Node::Builtin(op),
1390 })
1391 }
1392
1393 fn home(&mut self, leaf: HomeLeaf) -> Parsed<Node> {
1395 let depth = self
1396 .scope
1397 .home_depth()
1398 .ok_or_else(|| ParseError::OutsideModule(text(leaf.name())))?;
1399 Ok(Node::Home { leaf, depth })
1400 }
1401
1402 fn dot_symbol(&mut self, item: &Item<'_>) -> Parsed<Node> {
1404 match item {
1405 Item::Sym(s) => Ok(Node::Symbol(self.ctx.intern(s))),
1406 _ => Err(ParseError::BadSymbol.into()),
1407 }
1408 }
1409
1410 fn list(&mut self, seq: &Seq<'_>, slot: Slot) -> Parsed<Node> {
1414 let elem_slot = match slot {
1415 Slot::AppliedElems => Slot::Applied,
1416 _ => Slot::Value,
1417 };
1418 let chains = chain_slices(seq);
1419 let mark = self.b.scratch.len();
1420 for chain in &chains {
1421 let elem = self.expr(chain, elem_slot)?;
1422 let elem = self.close(elem);
1423 self.b.scratch.push(elem);
1424 }
1425 Ok(Node::List {
1426 len: len32(chains.len()),
1427 elems: self.b.push_run(Run::List, mark),
1428 })
1429 }
1430
1431 fn map(&mut self, seq: &Seq<'_>) -> Parsed<Node> {
1436 let chains = chain_slices(seq);
1437 let n = chains.len();
1438 let mark = self.b.scratch.len();
1439 self.b
1440 .scratch
1441 .resize(mark + 2 * n, (Node::Unit, ChunkSpan::NONE));
1442 for (i, chain) in chains.iter().enumerate() {
1443 let src = self.src;
1444 let (key, value) = self
1445 .entry(chain)
1446 .map_err(|f| f.or_at(|| src.items(chain)))?;
1447 self.b.scratch[mark + i] = key;
1448 self.b.scratch[mark + n + i] = value;
1449 }
1450 Ok(Node::Map {
1451 len: len32(n),
1452 entries: self.b.push_run(Run::Map, mark),
1453 })
1454 }
1455
1456 fn entry(&mut self, items: &[&Item<'_>]) -> Parsed<(Spanned, Spanned)> {
1462 if items.len() < 2 || !matches!(items[1], Item::Punct(":")) {
1463 return Err(ParseError::MalformedMapKey.into());
1464 }
1465 let src = self.src;
1466 let key = self
1467 .map_key(items[0])
1468 .map_err(|f| f.or_at(|| src.item(items[0])))?;
1469 let value_items = &items[2..];
1470 let value = if value_items.is_empty() {
1471 (Node::Unit, self.src.item(items[1]))
1473 } else {
1474 let value = self.expr(value_items, Slot::Value)?;
1475 self.close(value)
1476 };
1477 Ok((key, value))
1478 }
1479
1480 fn map_key(&mut self, item: &Item<'_>) -> Parsed<Spanned> {
1489 match item {
1490 Item::Sym(s) if s.as_bytes()[0].is_ascii_digit() => {
1491 Err(ParseError::MalformedMapKey.into())
1492 }
1493 Item::Sym(s) => Ok((Node::Symbol(self.ctx.intern(s)), self.src.item(item))),
1494 Item::Braces(_) => Err(ParseError::BareMapLiteral.into()),
1497 Item::Prefixed { sigil: '.', .. }
1498 | Item::Prefixed { sigil: '#', .. }
1499 | Item::Brackets(_)
1500 | Item::Parens(_)
1501 | Item::Str(_) => {
1502 let key = self.aexpr(item, Slot::Value)?;
1503 Ok(self.close(key))
1504 }
1505 Item::Run(members) => {
1509 let head =
1510 check_path(members, self.ctx).map_err(|_| ParseError::MalformedMapKey)?;
1511 self.path(head, members)
1512 }
1513 _ => Err(ParseError::MalformedMapKey.into()),
1514 }
1515 }
1516
1517 fn block(&mut self, group: &Group<'_>, slot: Slot) -> Parsed<Built> {
1522 if braces_contain_colon(&group.seq) {
1523 return Err(ParseError::BareMapLiteral.into());
1524 }
1525 let span = self.src.group(group);
1526 self.build_block(chain_slices(&group.seq), slot, span)
1527 }
1528
1529 fn build_block(
1544 &mut self,
1545 clauses: Vec<Vec<&Item<'_>>>,
1546 slot: Slot,
1547 span: ChunkSpan,
1548 ) -> Parsed<Built> {
1549 let Some((last, leading)) = clauses.split_last() else {
1550 return Ok(Built::Node(Node::Unit, span));
1551 };
1552 if clause_is_binding(last) {
1553 let span = self.src.items(last);
1554 return Err(Failure(ParseError::BlockTrailingBinding, span));
1555 }
1556 if leading.is_empty() {
1557 return self.expr(last, slot);
1558 }
1559 let (mark, pat_mark) = (self.b.scratch.len(), self.b.pat_scratch.len());
1560 let locals = self.scope.mark();
1561 for ci in leading {
1562 let (pat, value) = if clause_is_binding(ci) {
1563 let src = self.src;
1564 let (head, tail) = split_binding(ci).map_err(|f| f.or_at(|| src.items(ci)))?;
1565 let value = self.expr(tail, Slot::Value)?;
1566 let value = self.close(value);
1567 ((self.pattern(head)?, self.src.items(head)), value)
1568 } else {
1569 let value = self.expr(ci, Slot::Value)?;
1570 ((Pat::None, ChunkSpan::NONE), self.close(value))
1571 };
1572 self.b.pat_scratch.push(pat);
1573 self.b.scratch.push(value);
1574 }
1575 let value = self.expr(last, Slot::Value)?;
1576 let value = self.close(value);
1577 self.b.pat_scratch.push((Pat::None, ChunkSpan::NONE));
1578 self.b.scratch.push(value);
1579 self.scope.truncate(locals);
1580 let block = Node::Block {
1581 len: len32(clauses.len()),
1582 binds: self.b.push_pat_run(Run::Block, pat_mark),
1583 exprs: self.b.push_run(Run::Block, mark),
1584 };
1585 Ok(Built::Node(block, span))
1586 }
1587
1588 fn let_or_recur(&mut self, head: &Item<'_>, items: &[&Item<'_>], slot: Slot) -> Parsed<Built> {
1591 let is_recur = head_keyword(head) == Some("recur");
1592 let at = self.src.items(&items[..items.len().min(2)]);
1594 let missing = || {
1595 let error = if is_recur {
1596 ParseError::RecurMissingBinders
1597 } else {
1598 ParseError::LetMissingBinders
1599 };
1600 Failure(error, at)
1601 };
1602 let (group_item, body_items): (&Item<'_>, &[&Item<'_>]) = match head {
1603 Item::Run(members) if members.len() == 2 => (&members[1], &items[1..]),
1604 Item::Run(_) => return Err(missing()),
1605 _ => (*items.get(1).ok_or_else(missing)?, &items[2..]),
1606 };
1607 let group = match group_item {
1608 Item::Parens(Group { seq, .. }) => seq,
1609 _ => return Err(missing()),
1610 };
1611 let span = self.src.items(items);
1612 if is_recur {
1613 self.recur(group, body_items, slot, span)
1614 } else {
1615 self.let_block(group, body_items, slot, span)
1616 }
1617 }
1618
1619 fn let_block(
1622 &mut self,
1623 group: &Seq<'_>,
1624 body_items: &[&Item<'_>],
1625 slot: Slot,
1626 span: ChunkSpan,
1627 ) -> Parsed<Built> {
1628 if body_items.is_empty() {
1629 return Err(ParseError::LetMissingBody.into());
1630 }
1631 let mut clauses = chain_slices(group);
1632 for ci in &clauses {
1633 if !clause_is_binding(ci) {
1634 return Err(Failure(ParseError::MalformedBinding, self.src.items(ci)));
1635 }
1636 }
1637 clauses.push(body_items.to_vec());
1638 self.build_block(clauses, slot, span)
1639 }
1640
1641 fn recur(
1646 &mut self,
1647 group: &Seq<'_>,
1648 body_items: &[&Item<'_>],
1649 slot: Slot,
1650 span: ChunkSpan,
1651 ) -> Parsed<Built> {
1652 if body_items.is_empty() {
1653 return Err(ParseError::RecurMissingBody.into());
1654 }
1655 let chains = chain_slices(group);
1656 let decls = declarations(&chains, self.ctx, self.src)?;
1657 if !decls.imports.is_empty() {
1658 return Err(ParseError::MisplacedImport.into());
1659 }
1660 if let Some(&iota) = decls.iotas.first() {
1661 return Err(Failure(ParseError::MisplacedConst, decls.span(iota)));
1662 }
1663 if let Some(&local) = decls.locals.first() {
1664 return Err(Failure(ParseError::MisplacedLocal, decls.span(local)));
1665 }
1666 if let Some((_, span)) = decls
1667 .bodies
1668 .iter()
1669 .find(|(d, _)| matches!(d, Decl::Main(_)))
1670 {
1671 return Err(Failure(ParseError::MisplacedReserved, *span));
1672 }
1673 if decls.items.is_empty() {
1674 return self.segment(body_items, slot);
1675 }
1676 let items = sorted(&decls.items);
1677 self.scope.push_group(items.clone()).map_err(|e| {
1678 let at = match &e {
1679 ParseError::RecurShadowsOuter(name) => decls.span(self.ctx.intern(name)),
1680 _ => span,
1681 };
1682 Failure(e, at)
1683 })?;
1684 let id = self.b.enter_module();
1685 let (mark, _) = self.members(&decls, &items, &[], &[])?;
1686 let body = self.segment(body_items, Slot::Value)?;
1687 let body = self.child(body);
1688 self.scope.pop_group();
1689 let n = len32(items.len());
1690 self.b
1691 .leave_module(id, None, mark, n, 0, &[], Vec::new(), body);
1692 Ok(Built::Node(Node::Recur(id), span))
1693 }
1694
1695 fn case(&mut self, items: &[&Item<'_>], slot: Slot) -> Parsed<Built> {
1698 let span = self.src.items(items);
1699 let missing = || Failure(ParseError::CaseMissingArms, span);
1700 let mut rest: Vec<&Item<'_>> = Vec::new();
1701 if let Item::Run(members) = items[0] {
1702 rest.extend(members[1..].iter());
1703 }
1704 rest.extend_from_slice(&items[1..]);
1705 let (last, subject_items) = rest.split_last().ok_or_else(missing)?;
1706 let arms = match last {
1707 Item::Braces(Group { seq, .. }) => chain_slices(seq),
1708 _ => return Err(missing()),
1709 };
1710 if arms.is_empty() {
1711 return Err(missing());
1712 }
1713 match subject_items {
1714 [] => {
1715 let arg = self.ctx.intern("__arg");
1716 let depth = self.begin_abs(slot);
1718 self.param(span, |p| {
1719 p.scope.bind(arg)?;
1720 Ok(Pat::Bind(arg))
1721 })?;
1722 let subject = self.name_ref(arg)?;
1723 let body = self.case_node((subject, span), &arms)?;
1724 self.end_abs(depth, Built::Node(body, span), span)
1725 }
1726 [subject] => {
1727 let subject = self.aexpr(subject, Slot::Value)?;
1728 let subject = self.close(subject);
1729 Ok(Built::Node(self.case_node(subject, &arms)?, span))
1730 }
1731 _ => Err(Failure(
1732 ParseError::CaseSubjectExtra,
1733 self.src.items(subject_items),
1734 )),
1735 }
1736 }
1737
1738 fn case_node(&mut self, subject: Spanned, arms: &[Vec<&Item<'_>>]) -> Parsed<Node> {
1740 let (mark, pat_mark) = (self.b.scratch.len(), self.b.pat_scratch.len());
1741 for items in arms {
1742 let inner = match items.first() {
1743 Some(Item::Prefixed { sigil: '&', item }) => item.as_ref(),
1744 _ => return Err(Failure(ParseError::ArmNotBinder, self.src.items(items))),
1745 };
1746 if is_bare_literal_header(inner) {
1747 let span = self.src.item(inner);
1748 return Err(Failure(ParseError::BareLiteralHeader, span));
1749 }
1750 let locals = self.scope.mark();
1751 let base = (self.pattern(&[inner])?, self.src.item(inner));
1752 let (pat, rest) = self.guarded(base, &items[1..])?;
1753 if rest.is_empty() {
1754 return Err(Failure(ParseError::ArmMissingBody, self.src.items(items)));
1755 }
1756 let body = self.expr(rest, Slot::Value)?;
1757 let body = self.close(body);
1758 self.scope.truncate(locals);
1759 self.b.pat_scratch.push(pat);
1760 self.b.scratch.push(body);
1761 }
1762 self.b.scratch.push(subject);
1763 Ok(Node::Case {
1764 len: len32(arms.len()),
1765 conds: self.b.push_pat_run(Run::Case, pat_mark),
1766 exprs: self.b.push_run(Run::Case, mark),
1767 })
1768 }
1769
1770 fn binder(&mut self, items: &[&Item<'_>], slot: Slot) -> Parsed<Built> {
1780 if items.len() == 1 {
1781 return Err(ParseError::AbsWithoutBody.into());
1782 }
1783 let inner = match items[0] {
1784 Item::Prefixed { sigil: '&', item } => item.as_ref(),
1785 _ => return Err(ParseError::UnexpectedBinder.into()),
1786 };
1787 let span = self.src.items(items);
1788 let depth = self.begin_abs(slot);
1789 let rest = if matches!(items.get(1), Some(it) if is_when_kw(it))
1790 && !matches!(inner, Item::Parens(_))
1791 {
1792 if is_bare_literal_header(inner) {
1793 let span = self.src.item(inner);
1794 return Err(Failure(ParseError::BareLiteralHeader, span));
1795 }
1796 let mut rest: &[&Item<'_>] = &[];
1797 let base_span = self.src.item(inner);
1798 self.param_spanned(|p| {
1799 let base = (p.pattern(&[inner])?, base_span);
1800 let (pat, after) = p.guarded(base, &items[1..])?;
1801 rest = after;
1802 Ok(pat)
1803 })?;
1804 if rest.is_empty() {
1805 return Err(ParseError::AbsWithoutBody.into());
1806 }
1807 rest
1808 } else {
1809 match inner {
1810 Item::Parens(group) => {
1814 let params = chain_slices(&group.seq);
1815 if params.is_empty() {
1816 self.param(self.src.group(group), |_| Ok(Pat::Unit))?;
1817 }
1818 for chain in ¶ms {
1819 self.param(self.src.items(chain), |p| p.pattern(chain))?;
1820 }
1821 }
1822 it if is_bare_literal_header(it) => {
1826 let span = self.src.item(it);
1827 return Err(Failure(ParseError::BareLiteralHeader, span));
1828 }
1829 other => self.param(self.src.item(other), |p| p.pattern(&[other]))?,
1830 }
1831 &items[1..]
1832 };
1833 let body = self.segment(rest, Slot::Body)?;
1834 self.end_abs(depth, body, span)
1835 }
1836
1837 fn begin_abs(&mut self, slot: Slot) -> usize {
1841 let depth = self.heads.len();
1842 if slot != Slot::Body {
1843 self.open_head(slot == Slot::Applied);
1844 }
1845 depth
1846 }
1847
1848 fn open_head(&mut self, chain: bool) {
1851 let pats = self.b.pat_scratch.len();
1852 let chain = if chain {
1853 Some(self.scope.mark())
1854 } else {
1855 self.scope.push_level();
1856 None
1857 };
1858 self.heads.push(Head { pats, chain });
1859 }
1860
1861 fn param(
1865 &mut self,
1866 span: ChunkSpan,
1867 parse: impl FnOnce(&mut Self) -> Parsed<Pat>,
1868 ) -> Parsed<()> {
1869 self.param_spanned(|p| Ok((parse(p)?, span)))
1870 }
1871
1872 fn param_spanned(
1874 &mut self,
1875 parse: impl FnOnce(&mut Self) -> Parsed<(Pat, ChunkSpan)>,
1876 ) -> Parsed<()> {
1877 let head = self.heads.last().expect("a parameter has a head");
1878 if self.b.pat_scratch.len() - head.pats == MAX_HEAD {
1879 self.open_head(false);
1880 }
1881 let pat = parse(self)?;
1882 self.b.pat_scratch.push(pat);
1883 Ok(())
1884 }
1885
1886 fn end_abs(&mut self, depth: usize, body: Built, span: ChunkSpan) -> Parsed<Built> {
1890 let mut body = self.close(body);
1891 while self.heads.len() > depth {
1892 let head = self.heads.pop().expect("an open head");
1893 let plan = match head.chain {
1894 Some(mark) => {
1895 self.scope.truncate(mark);
1896 None
1897 }
1898 None => Some(self.scope.pop_level()),
1899 };
1900 body = (self.b.lambda(head.pats, body, plan.as_deref(), span), span);
1901 }
1902 Ok(Built::Node(body.0, body.1))
1903 }
1904
1905 fn guarded<'i, 'a>(
1910 &mut self,
1911 mut pat: (Pat, ChunkSpan),
1912 mut items: &'i [&'i Item<'a>],
1913 ) -> Parsed<((Pat, ChunkSpan), &'i [&'i Item<'a>])> {
1914 while !items.is_empty() && is_when_kw(items[0]) {
1915 let missing = Failure(
1917 ParseError::WhenMissingCond,
1918 self.src.items(&items[..items.len().min(2)]),
1919 );
1920 let (group, next): (&Seq<'a>, &[&Item<'a>]) = match items[0] {
1921 Item::Run(members) if members.len() == 2 => match &members[1] {
1922 Item::Parens(Group { seq, .. }) => (seq, &items[1..]),
1923 _ => return Err(missing),
1924 },
1925 Item::Run(_) => return Err(missing),
1926 _ => match items.get(1) {
1927 Some(Item::Parens(Group { seq, .. })) => (seq, &items[2..]),
1928 _ => return Err(missing),
1929 },
1930 };
1931 let Some(chain) = single_chain(group).filter(|chain| !chain.is_empty()) else {
1932 return Err(missing);
1933 };
1934 let inner = self.b.push_pat(pat.0, pat.1);
1935 let (gpat, cond) = if clause_is_binding(&chain) {
1936 let src = self.src;
1937 let (head, tail) =
1938 split_binding(&chain).map_err(|f| f.or_at(|| src.items(&chain)))?;
1939 let cond = self.expr(tail, Slot::Value)?;
1940 let cond = self.child(cond);
1941 let gpat = self.pattern(head)?;
1942 (self.b.push_pat(gpat, self.src.items(head)), cond)
1943 } else {
1944 let cond = self.expr(&chain, Slot::Value)?;
1945 (PatId::NONE, self.child(cond))
1946 };
1947 let guard = self.src.items(&items[..items.len() - next.len()]);
1948 pat = (Pat::When { inner, gpat, cond }, pat.1.join(guard));
1949 items = next;
1950 }
1951 Ok((pat, items))
1952 }
1953
1954 fn pattern(&mut self, items: &[&Item<'_>]) -> Parsed<Pat> {
1962 let src = self.src;
1963 self.or_pattern(items)
1964 .map_err(|f| f.or_at(|| src.items(items)))
1965 }
1966
1967 fn or_pattern(&mut self, items: &[&Item<'_>]) -> Parsed<Pat> {
1969 if items.is_empty() {
1970 return Err(ParseError::BadPattern.into());
1971 }
1972 if let Some(idx) = items.iter().position(|it| matches!(it, Item::Punct("|"))) {
1973 let mark = self.scope.mark();
1974 let left = self.pattern(&items[..idx])?;
1975 let left_names: Vec<Sym> = self.scope.bound_since(mark).to_vec();
1976 self.scope.truncate(mark);
1977 let right = self.pattern(&items[idx + 1..])?;
1978 if self.scope.bound_since(mark) != left_names.as_slice() {
1979 return Err(ParseError::OrBindersMismatch.into());
1980 }
1981 let left = self.b.push_pat(left, self.src.items(&items[..idx]));
1982 let right = self.b.push_pat(right, self.src.items(&items[idx + 1..]));
1983 return Ok(Pat::Or(left, right));
1984 }
1985 match items[0] {
1986 Item::Punct("<") => return Ok(Pat::Less(self.comparand(&items[1..])?)),
1987 Item::Punct(">") => return Ok(Pat::Greater(self.comparand(&items[1..])?)),
1988 _ => {}
1989 }
1990 if let Some(idx) = items.iter().position(|it| matches!(it, Item::Punct("="))) {
1991 if idx == 0 {
1992 return Ok(Pat::Equal(self.comparand(&items[1..])?));
1993 }
1994 let name = plain_name(&items[..idx], ParseError::BadPattern, self.ctx, self.src)?;
1995 self.scope.bind(name)?;
1996 let inner = self.pattern(&items[idx + 1..])?;
1997 let span = self.src.items(&items[idx + 1..]);
1998 return Ok(Pat::At(name, self.b.push_pat(inner, span)));
1999 }
2000 self.narrowed(items)
2001 }
2002
2003 fn comparand(&mut self, items: &[&Item<'_>]) -> Parsed<NodeId> {
2006 let node = match items {
2007 [it] => match it {
2008 Item::Sym(s) => self.sym(s)?,
2009 Item::Prefixed { sigil: '.', item } => self.dot_symbol(item)?,
2010 Item::Str(s) => self.b.str(decode_str(s)?),
2011 Item::Run(members) => {
2012 let head = check_path(members, self.ctx)?;
2013 self.path(head, members)?.0
2014 }
2015 _ => return Err(Failure(ParseError::ComparandNotAtom, self.src.items(items))),
2016 },
2017 _ => return Err(Failure(ParseError::ComparandNotAtom, self.src.items(items))),
2018 };
2019 Ok(self.b.push(node, self.src.items(items)))
2020 }
2021
2022 fn narrowed(&mut self, items: &[&Item<'_>]) -> Parsed<Pat> {
2025 if let Item::Sym("Self") = items[0] {
2026 if items.len() < 2 {
2027 return Err(ParseError::BadPattern.into());
2028 }
2029 let depth = self
2030 .scope
2031 .home_depth()
2032 .ok_or_else(|| ParseError::OutsideModule(text("Self")))?;
2033 let inner = self.pattern(&items[1..])?;
2034 return Ok(Pat::Unwrap {
2035 depth,
2036 inner: self.b.push_pat(inner, self.src.items(&items[1..])),
2037 });
2038 }
2039 if let Item::Parens(Group { seq, .. }) = items[0] {
2040 if let Some(chain) = single_chain(seq) {
2041 if !chain.is_empty() && matches!(chain[0], Item::Sym("as")) {
2042 let proto = self.proto(&chain[1..])?;
2043 let inner = self.pattern(&items[1..])?;
2044 return Ok(self.typed(proto, (inner, self.src.items(&items[1..]))));
2045 }
2046 }
2047 }
2048 if let Some(idx) = items.iter().position(|it| matches!(it, Item::Sym("as"))) {
2049 let proto = self.proto(&items[idx + 1..])?;
2050 let inner = self.atom(&items[..idx])?;
2051 return Ok(self.typed(proto, (inner, self.src.items(&items[..idx]))));
2052 }
2053 self.atom(items)
2054 }
2055
2056 fn proto(&mut self, items: &[&Item<'_>]) -> Parsed<Proto> {
2059 let src = self.src;
2060 self.proto_ref(items)
2061 .map_err(|f| f.or_at(|| src.items(items)))
2062 }
2063
2064 fn proto_ref(&mut self, items: &[&Item<'_>]) -> Parsed<Proto> {
2066 let node = match items {
2067 [Item::Sym(s)] => match classify(s, self.ctx)? {
2068 SymRef::Int(_) => return Err(ParseError::UnknownType.into()),
2069 r => self.resolve_sym(r)?,
2070 },
2071 [Item::Run(members)] => {
2072 let head = check_path(members, self.ctx)?;
2073 self.path(head, members)?.0
2074 }
2075 _ => return Err(ParseError::UnknownType.into()),
2076 };
2077 match node {
2078 Node::Builtin(op) => match op.proto_kind() {
2079 Some(kind) => Ok(Proto::Kind(kind)),
2080 None => Err(ParseError::NotAPrototype(text(op.name())).into()),
2081 },
2082 node => Ok(Proto::Ref(self.b.push(node, self.src.items(items)))),
2083 }
2084 }
2085
2086 fn typed(&mut self, proto: Proto, inner: (Pat, ChunkSpan)) -> Pat {
2088 let inner = self.b.push_pat(inner.0, inner.1);
2089 match proto {
2090 Proto::Kind(kind) => Pat::TypeKind(kind, inner),
2091 Proto::Ref(node) => Pat::TypeRef(node, inner),
2092 }
2093 }
2094
2095 fn path(&mut self, head: SymRef, members: &[Item<'_>]) -> Parsed<Spanned> {
2100 let mut acc = (self.resolve_sym(head)?, self.src.item(&members[0]));
2101 for m in &members[1..] {
2102 let Item::Prefixed { sigil: '.', item } = m else {
2103 unreachable!("checked by check_path")
2104 };
2105 let symbol = self.dot_symbol(item)?;
2106 let Node::Symbol(name) = symbol else {
2107 unreachable!("a dotted segment is a symbol")
2108 };
2109 let span = self.src.item(m);
2110 if let Some(op) = builtin_of(acc.0).and_then(|ns| ns.member(name)) {
2111 acc = (Node::Builtin(op), acc.1.join(span));
2112 continue;
2113 }
2114 let mark = self.b.scratch.len();
2115 let joined = acc.1.join(span);
2116 self.b.scratch.push(acc);
2117 self.b.scratch.push((symbol, span));
2118 let app = Node::App {
2119 len: 2,
2120 args: self.b.push_run(Run::App, mark),
2121 };
2122 acc = (app, joined);
2123 }
2124 Ok(acc)
2125 }
2126
2127 fn atom(&mut self, items: &[&Item<'_>]) -> Parsed<Pat> {
2129 match items {
2130 [it] => self.atom_item(it),
2131 _ => Err(ParseError::BadPattern.into()),
2132 }
2133 }
2134
2135 fn atom_item(&mut self, item: &Item<'_>) -> Parsed<Pat> {
2137 let src = self.src;
2138 self.atom_pattern(item)
2139 .map_err(|f| f.or_at(|| src.item(item)))
2140 }
2141
2142 fn atom_pattern(&mut self, item: &Item<'_>) -> Parsed<Pat> {
2144 match item {
2145 Item::Sym("_") => Ok(Pat::Discard),
2146 Item::Sym(s) if is_keyword(s) => Err(ParseError::ReservedKeyword.into()),
2147 Item::Sym(s) if s.starts_with("__") => Err(ParseError::ReservedName.into()),
2148 Item::Sym(s) => match parse_int(s) {
2149 Some(n) => {
2150 let node = self.b.int(n);
2151 Ok(Pat::Equal(self.b.push(node, self.src.item(item))))
2152 }
2153 None if s.as_bytes()[0].is_ascii_digit() => Err(ParseError::MalformedNumber.into()),
2154 None => {
2155 let name = self.ctx.intern(s);
2156 self.scope.bind(name)?;
2157 Ok(Pat::Bind(name))
2158 }
2159 },
2160 Item::Prefixed {
2161 sigil: '.',
2162 item: inner,
2163 } => {
2164 let node = self.dot_symbol(inner)?;
2165 Ok(Pat::Equal(self.b.push(node, self.src.item(item))))
2166 }
2167 Item::Str(s) => {
2168 let node = self.b.str(decode_str(s)?);
2169 Ok(Pat::Equal(self.b.push(node, self.src.item(item))))
2170 }
2171 Item::Brackets(_) => Err(ParseError::BareListLiteral.into()),
2172 Item::Parens(Group { seq, .. }) => match single_chain(seq) {
2173 Some(chain) if !chain.is_empty() => self.pattern(&chain),
2174 _ => Err(ParseError::BadPattern.into()),
2175 },
2176 Item::Braces(_) => Err(ParseError::BareMapLiteral.into()),
2177 Item::Prefixed { sigil: '#', item } => match item.as_ref() {
2178 Item::Brackets(Group { seq, .. }) => self.list_pattern(seq),
2179 Item::Braces(Group { seq, .. }) => self.map_pattern(seq),
2180 _ => Err(ParseError::ReservedLiteralForm.into()),
2181 },
2182 _ => Err(ParseError::BadPattern.into()),
2183 }
2184 }
2185
2186 fn rest(&mut self, rest: Option<&str>, span: ChunkSpan) -> Parsed<PatId> {
2188 let pat = match rest {
2189 Some(name) => {
2190 let name = self.ctx.intern(name);
2191 self.scope.bind(name)?;
2192 Pat::Bind(name)
2193 }
2194 None => Pat::Discard,
2195 };
2196 Ok(self.b.push_pat(pat, span))
2197 }
2198
2199 fn list_pattern(&mut self, seq: &Seq<'_>) -> Parsed<Pat> {
2202 let chains = chain_slices(seq);
2203 let (elems, rest) = split_rest(&chains)?;
2204 let rest = match rest {
2205 Some(rest) => self.rest(rest, self.rest_span(&chains))?,
2206 None => PatId::NONE,
2207 };
2208 let mark = self.b.pat_scratch.len();
2209 for chain in elems {
2210 let pat = self.pattern(chain)?;
2211 self.b.pat_scratch.push((pat, self.src.items(chain)));
2212 }
2213 Ok(Pat::List {
2214 len: len32(elems.len()),
2215 elems: self.b.push_pat_run(Run::PatList, mark),
2216 rest,
2217 })
2218 }
2219
2220 fn map_pattern(&mut self, seq: &Seq<'_>) -> Parsed<Pat> {
2226 let chains = chain_slices(seq);
2227 let (entries, rest) = split_rest(&chains)?;
2228 let mut keys = Vec::with_capacity(entries.len());
2229 for chain in entries {
2230 let malformed = || Failure(ParseError::MalformedMapKey, self.src.items(chain));
2231 let colon = chain
2232 .iter()
2233 .position(|it| matches!(it, Item::Punct(":")))
2234 .ok_or_else(malformed)?;
2235 if colon == 0 || colon + 1 == chain.len() {
2236 return Err(malformed());
2237 }
2238 let key = match &chain[..colon] {
2239 [Item::Sym(s)] if s.as_bytes()[0].is_ascii_digit() => return Err(malformed()),
2240 [Item::Sym(_)] | [Item::Run(_)] => true,
2241 key => is_lookup(key),
2242 };
2243 keys.push((colon, key));
2244 }
2245 let n = entries.len();
2246 let mark = self.b.pat_scratch.len();
2247 self.b
2248 .pat_scratch
2249 .resize(mark + 2 * n, (Pat::None, ChunkSpan::NONE));
2250 for (i, (chain, &(colon, lookup))) in entries.iter().zip(&keys).enumerate() {
2251 if lookup {
2252 let node = match &chain[..colon] {
2253 [Item::Sym(s)] => Node::Symbol(self.ctx.intern(s)),
2254 [Item::Run(members)] => {
2255 let head = check_path(members, self.ctx)?;
2256 self.path(head, members)?.0
2257 }
2258 key => self.lookup_expr(key)?,
2259 };
2260 let span = self.src.items(&chain[..colon]);
2261 self.b.pat_scratch[mark + i] = (Pat::Lookup(self.b.push(node, span)), span);
2262 }
2263 }
2264 for (i, (chain, &(colon, lookup))) in entries.iter().zip(&keys).enumerate() {
2265 if lookup {
2266 let value = self.pattern(&chain[colon + 1..])?;
2267 let span = self.src.items(&chain[colon + 1..]);
2268 self.b.pat_scratch[mark + n + i] = (value, span);
2269 }
2270 }
2271 for (i, (chain, &(colon, lookup))) in entries.iter().zip(&keys).enumerate() {
2272 if !lookup {
2273 let key = self.pattern(&chain[..colon])?;
2274 self.b.pat_scratch[mark + i] = (key, self.src.items(&chain[..colon]));
2275 let value = self.pattern(&chain[colon + 1..])?;
2276 let span = self.src.items(&chain[colon + 1..]);
2277 self.b.pat_scratch[mark + n + i] = (value, span);
2278 }
2279 }
2280 let rest = match rest {
2281 Some(rest) => self.rest(rest, self.rest_span(&chains))?,
2282 None => PatId::NONE,
2283 };
2284 Ok(Pat::Map {
2285 len: len32(n),
2286 entries: self.b.push_pat_run(Run::PatMap, mark),
2287 rest,
2288 })
2289 }
2290
2291 fn rest_span(&self, chains: &[Vec<&Item<'_>>]) -> ChunkSpan {
2293 chains
2294 .last()
2295 .map_or(ChunkSpan::NONE, |chain| self.src.items(chain))
2296 }
2297
2298 fn lookup_expr(&mut self, items: &[&Item<'_>]) -> Parsed<Node> {
2300 if let Some(Item::Punct("=")) = items.first() {
2301 let node = self.comparand(&items[1..])?;
2302 return Ok(self.b.node(node).0);
2303 }
2304 match items {
2305 [Item::Parens(Group { seq, .. })] => {
2306 let chain = single_chain(seq).expect("checked by is_lookup");
2307 self.lookup_expr(&chain)
2308 }
2309 [Item::Sym(s)] => Ok(self.b.int(parse_int(s).expect("checked by is_lookup"))),
2310 [Item::Prefixed { sigil: '.', item }] => self.dot_symbol(item),
2311 [Item::Str(s)] => Ok(self.b.str(decode_str(s)?)),
2312 _ => unreachable!("checked by is_lookup"),
2313 }
2314 }
2315}
2316
2317enum Proto {
2319 Kind(crate::builtins::TyKind),
2321 Ref(NodeId),
2323}
2324
2325fn builtin_of(node: Node) -> Option<Builtin> {
2327 match node {
2328 Node::Builtin(op) => Some(op),
2329 _ => None,
2330 }
2331}
2332
2333fn classify(s: &str, ctx: &Ctx) -> Parsed<SymRef> {
2336 if s == "Self" {
2337 return Ok(SymRef::Home);
2338 }
2339 if is_keyword(s) {
2340 return Err(ParseError::ReservedKeyword.into());
2341 }
2342 if s == "_" {
2343 Err(ParseError::DiscardReference.into())
2344 } else if let Some(n) = parse_int(s) {
2345 Ok(SymRef::Int(n))
2346 } else if s.as_bytes()[0].is_ascii_digit() {
2347 Err(ParseError::MalformedNumber.into())
2348 } else if s.starts_with("__") {
2349 match Builtin::from_name(s) {
2350 Some(op) => Ok(SymRef::Builtin(op)),
2351 None => Err(ParseError::UnknownReserved(text(s)).into()),
2352 }
2353 } else {
2354 Ok(SymRef::Name(ctx.intern(s)))
2355 }
2356}
2357
2358fn check_path(members: &[Item<'_>], ctx: &Ctx) -> Parsed<SymRef> {
2361 if members.len() < 2 {
2362 return Err(ParseError::ComparandNotAtom.into());
2363 }
2364 let head = match &members[0] {
2365 Item::Sym(s) => classify(s, ctx)?,
2366 _ => return Err(ParseError::ComparandNotAtom.into()),
2367 };
2368 for m in &members[1..] {
2369 if !matches!(m, Item::Prefixed { sigil: '.', .. }) {
2370 return Err(ParseError::ComparandNotAtom.into());
2371 }
2372 }
2373 for m in &members[1..] {
2374 if let Item::Prefixed { item, .. } = m {
2375 if !matches!(item.as_ref(), Item::Sym(_)) {
2376 return Err(ParseError::BadSymbol.into());
2377 }
2378 }
2379 }
2380 Ok(head)
2381}
2382
2383fn is_lookup(items: &[&Item<'_>]) -> bool {
2386 if items.is_empty() || items.iter().any(|it| matches!(it, Item::Punct("|"))) {
2387 return false;
2388 }
2389 if matches!(items[0], Item::Punct("<") | Item::Punct(">")) {
2390 return false;
2391 }
2392 if let Some(idx) = items.iter().position(|it| matches!(it, Item::Punct("="))) {
2393 return idx == 0;
2394 }
2395 if matches!(items[0], Item::Sym("Self")) || items.iter().any(|it| matches!(it, Item::Sym("as")))
2396 {
2397 return false;
2398 }
2399 match items {
2400 [Item::Sym(s)] => !is_keyword(s) && !s.starts_with("__") && parse_int(s).is_some(),
2401 [Item::Prefixed { sigil: '.', .. }] | [Item::Str(_)] => true,
2402 [Item::Parens(Group { seq, .. })] => match single_chain(seq) {
2403 Some(chain) => is_lookup(&chain) && !starts_with_as(&chain),
2404 None => false,
2405 },
2406 _ => false,
2407 }
2408}
2409
2410fn starts_with_as(chain: &[&Item<'_>]) -> bool {
2412 matches!(chain.first(), Some(Item::Sym("as")))
2413}
2414
2415#[allow(clippy::type_complexity)]
2419fn split_rest<'c, 'b, 'a>(
2420 chains: &'c [Vec<&'b Item<'a>>],
2421) -> Parsed<(&'c [Vec<&'b Item<'a>>], Option<Option<&'a str>>)> {
2422 let n = chains.len();
2423 for (i, chain) in chains.iter().enumerate() {
2424 if as_rest(chain).is_some() && i != n - 1 {
2425 return Err(ParseError::BadPattern.into());
2426 }
2427 }
2428 match chains.split_last() {
2429 Some((last, entries)) => match as_rest(last) {
2430 Some(rest) => Ok((entries, Some(rest))),
2431 None => Ok((chains, None)),
2432 },
2433 None => Ok((chains, None)),
2434 }
2435}
2436
2437fn as_rest<'a>(chain: &[&Item<'a>]) -> Option<Option<&'a str>> {
2439 let [Item::Prefixed {
2440 sigil: '.',
2441 item: a,
2442 }] = chain
2443 else {
2444 return None;
2445 };
2446 let Item::Prefixed {
2447 sigil: '.',
2448 item: b,
2449 } = a.as_ref()
2450 else {
2451 return None;
2452 };
2453 match b.as_ref() {
2454 Item::Prefixed {
2455 sigil: '.',
2456 item: c,
2457 } => match c.as_ref() {
2458 Item::Sym(name) => Some(Some(name)),
2459 _ => None,
2460 },
2461 Item::Punct(".") => Some(None),
2462 _ => None,
2463 }
2464}
2465
2466#[allow(clippy::type_complexity)]
2469fn split_binding<'i, 'a>(
2470 items: &'i [&'i Item<'a>],
2471) -> Parsed<(&'i [&'i Item<'a>], &'i [&'i Item<'a>])> {
2472 let mut eq = None;
2473 for (i, it) in items.iter().enumerate() {
2474 if matches!(it, Item::Punct("=")) {
2475 if eq.is_some() {
2476 return Err(ParseError::MalformedBinding.into());
2477 }
2478 eq = Some(i);
2479 }
2480 }
2481 let eq = eq.ok_or(ParseError::MalformedBinding)?;
2482 let (head, tail) = (&items[..eq], &items[eq + 1..]);
2483 if head.is_empty() || tail.is_empty() {
2484 return Err(ParseError::MalformedBinding.into());
2485 }
2486 if head.iter().any(|it| matches!(it, Item::Punct("|"))) {
2487 return Err(ParseError::LetOrUnparenthesized.into());
2488 }
2489 if let [it] = head {
2490 if is_bare_literal_header(it) {
2491 return Err(ParseError::BareLiteralHeader.into());
2492 }
2493 }
2494 Ok((head, tail))
2495}
2496
2497fn check_run_head(members: &[Item<'_>]) -> Parsed<()> {
2499 if matches!(&members[0], Item::Prefixed { sigil: '&', .. }) {
2500 return Err(ParseError::BinderRunGlued.into());
2501 }
2502 if let (
2503 Item::Sym(head),
2504 Some(Item::Prefixed {
2505 sigil: '.',
2506 item: seg,
2507 }),
2508 ) = (&members[0], members.get(1))
2509 {
2510 if parse_int(head).is_some() && is_dot_number(seg) {
2511 return Err(ParseError::FloatLiteralUnsupported.into());
2512 }
2513 }
2514 Ok(())
2515}
2516
2517fn is_dot_number(item: &Item<'_>) -> bool {
2519 match item {
2520 Item::Sym(s) => parse_int(s).is_some(),
2521 _ => false,
2522 }
2523}
2524
2525fn is_self_head(members: &[Item<'_>]) -> bool {
2527 matches!(
2528 members.first(),
2529 Some(Item::Prefixed { sigil: '#', item })
2530 if matches!(item.as_ref(), Item::Sym("Self"))
2531 )
2532}
2533
2534fn decode_str(raw: &str) -> Parsed<Text> {
2537 let b = raw.as_bytes();
2538 let mut out = alloc::string::String::with_capacity(raw.len());
2539 let mut i = 0;
2540 let mut chunk = 0;
2541 while i < b.len() {
2542 if b[i] != b'\\' {
2543 i += 1;
2544 continue;
2545 }
2546 out.push_str(&raw[chunk..i]);
2547 match b[i + 1] {
2548 b'"' => out.push('"'),
2549 b'\\' => out.push('\\'),
2550 b'/' => out.push('/'),
2551 b'n' => out.push('\n'),
2552 b't' => out.push('\t'),
2553 b'r' => out.push('\r'),
2554 b'b' => out.push('\u{8}'),
2555 b'f' => out.push('\u{c}'),
2556 b'u' => {
2557 let hi = hex4(&b[i + 2..i + 6]);
2558 i += 6;
2559 if (0xD800..=0xDBFF).contains(&hi) {
2560 let lo = match (b.get(i), b.get(i + 1)) {
2561 (Some(b'\\'), Some(b'u')) => hex4(&b[i + 2..i + 6]),
2562 _ => return Err(ParseError::LoneSurrogate.into()),
2563 };
2564 if !(0xDC00..=0xDFFF).contains(&lo) {
2565 return Err(ParseError::LoneSurrogate.into());
2566 }
2567 let c = 0x1_0000 + ((hi - 0xD800) << 10) + (lo - 0xDC00);
2568 out.push(char::from_u32(c).expect("combined surrogate pair"));
2569 i += 6;
2570 } else if (0xDC00..=0xDFFF).contains(&hi) {
2571 return Err(ParseError::LoneSurrogate.into());
2572 } else {
2573 out.push(char::from_u32(hi).expect("non-surrogate BMP scalar"));
2574 }
2575 chunk = i;
2576 continue;
2577 }
2578 _ => unreachable!("Muon validated the <str> escape grammar"),
2579 }
2580 i += 2;
2581 chunk = i;
2582 }
2583 out.push_str(&raw[chunk..]);
2584 Ok(Text::from(out.as_str()))
2585}
2586
2587fn hex4(b: &[u8]) -> u32 {
2589 b.iter()
2590 .fold(0, |v, &c| v * 16 + (c as char).to_digit(16).unwrap())
2591}
2592
2593pub(crate) fn parse_int(s: &str) -> Option<BigInt> {
2595 let (neg, body) = match s.as_bytes().first()? {
2596 b'-' => (true, &s[1..]),
2597 b'+' => (false, &s[1..]),
2598 _ => (false, s),
2599 };
2600 let (radix, digits) =
2601 if let Some(h) = body.strip_prefix("0x").or_else(|| body.strip_prefix("0X")) {
2602 (16u32, h)
2603 } else if let Some(b) = body.strip_prefix("0b").or_else(|| body.strip_prefix("0B")) {
2604 (2, b)
2605 } else {
2606 (10, body)
2607 };
2608 let mut cleaned = alloc::string::String::new();
2609 let mut after_sep = true;
2610 for &c in digits.as_bytes() {
2611 if c == b'_' {
2612 if after_sep {
2613 return None;
2614 }
2615 after_sep = true;
2616 } else {
2617 cleaned.push(c as char);
2618 after_sep = false;
2619 }
2620 }
2621 if after_sep || cleaned.is_empty() {
2622 return None;
2623 }
2624 let mag = BigInt::parse_bytes(cleaned.as_bytes(), radix)?;
2625 Some(if neg { -mag } else { mag })
2626}
2627
2628fn clause_is_binding(items: &[&Item<'_>]) -> bool {
2633 items.iter().any(|it| matches!(it, Item::Punct("=")))
2634}
2635
2636fn is_bare_literal_header(item: &Item<'_>) -> bool {
2642 match item {
2643 Item::Sym(s) => parse_int(s).is_some(),
2644 Item::Prefixed { sigil: '.', .. } => true,
2645 Item::Str(_) => true,
2646 _ => false,
2647 }
2648}
2649
2650fn is_when_kw(item: &Item) -> bool {
2652 head_keyword(item) == Some("when")
2653}
2654
2655fn chain_slices<'a, 'b>(seq: &'b Seq<'a>) -> Vec<Vec<&'b Item<'a>>> {
2657 let chains = seq
2658 .0
2659 .iter()
2660 .filter(|c| !is_comment_only(c))
2661 .map(|c| {
2662 c.0.iter()
2663 .filter(|it| !matches!(it, Item::Comm(_)))
2664 .collect()
2665 })
2666 .collect();
2667 join_chains(chains)
2668}
2669
2670fn braces_contain_colon(seq: &Seq<'_>) -> bool {
2673 for chain in seq.0.iter().filter(|c| !is_comment_only(c)) {
2674 let items: Vec<&Item<'_>> = chain
2675 .0
2676 .iter()
2677 .filter(|it| !matches!(it, Item::Comm(_)))
2678 .collect();
2679 if items.len() >= 2 && matches!(items[1], Item::Punct(":")) {
2680 return true;
2681 }
2682 }
2683 false
2684}
2685
2686fn join_chains<'a, 'b>(chains: Vec<Vec<&'b Item<'a>>>) -> Vec<Vec<&'b Item<'a>>> {
2690 let mut out: Vec<Vec<&'b Item<'a>>> = Vec::with_capacity(chains.len());
2691 for chain in chains {
2692 let join = matches!(out.last(), Some(prev) if trailing_join(prev) || leading_join(&chain));
2693 if join {
2694 out.last_mut().unwrap().extend(chain);
2695 } else {
2696 out.push(chain);
2697 }
2698 }
2699 out
2700}
2701
2702fn trailing_join(chain: &[&Item]) -> bool {
2704 match chain.last() {
2705 Some(Item::Prefixed { sigil: '&', .. }) => true,
2706 Some(Item::Punct("=")) | Some(Item::Punct("|>")) => true,
2707 _ => {
2708 let n = chain.len();
2709 n >= 2
2710 && matches!(chain[n - 2], Item::Sym("when"))
2711 && matches!(chain[n - 1], Item::Parens(_))
2712 }
2713 }
2714}
2715
2716fn leading_join(chain: &[&Item]) -> bool {
2718 match chain.first() {
2719 Some(Item::Punct("|>")) => true,
2720 Some(first) => matches!(head_keyword(first), Some("elif" | "else" | "catch")),
2721 None => false,
2722 }
2723}
2724
2725fn single_chain<'a, 'b>(seq: &'b Seq<'a>) -> Option<Vec<&'b Item<'a>>> {
2727 let mut chains = chain_slices(seq).into_iter();
2728 let first = chains.next()?;
2729 if chains.next().is_some() {
2730 return None;
2731 }
2732 Some(first)
2733}
2734
2735fn is_comment_only(chain: &Chain) -> bool {
2737 chain.0.iter().all(|it| matches!(it, Item::Comm(_)))
2738}
2739
2740fn is_keyword(s: &str) -> bool {
2742 matches!(
2743 s,
2744 "Self"
2745 | "let"
2746 | "recur"
2747 | "import"
2748 | "const"
2749 | "local"
2750 | "with"
2751 | "as"
2752 | "when"
2753 | "match"
2754 | "case"
2755 | "of"
2756 | "if"
2757 | "elif"
2758 | "else"
2759 | "catch"
2760 )
2761}
2762
2763pub fn is_bindable_name(name: &str) -> bool {
2765 muon::is_sym(name)
2766 && !is_keyword(name)
2767 && !name.starts_with("__")
2768 && name != "_"
2769 && !reads_as_number(name)
2770}
2771
2772fn is_split_point(item: &Item) -> bool {
2774 is_binder(item)
2775 || matches!(
2776 head_keyword(item),
2777 Some("let") | Some("recur") | Some("case")
2778 )
2779}
2780
2781fn is_binder(item: &Item) -> bool {
2783 matches!(item, Item::Prefixed { sigil: '&', .. })
2784}
2785
2786fn head_keyword<'a>(item: &Item<'a>) -> Option<&'a str> {
2788 match item {
2789 Item::Sym(s) if is_keyword(s) => Some(s),
2790 Item::Run(members) => match members.first() {
2791 Some(Item::Sym(s)) if is_keyword(s) => Some(s),
2792 _ => None,
2793 },
2794 _ => None,
2795 }
2796}