1use crate::ast::error::ParseError;
2use crate::{AccessorKind, ParseResult, UnresolvedPackage, UnresolvedPackageGroup};
3use alloc::borrow::Cow;
4use alloc::boxed::Box;
5use alloc::format;
6use alloc::string::{String, ToString};
7use alloc::vec::Vec;
8#[cfg(feature = "std")]
9use anyhow::Context as _;
10use core::fmt;
11use core::mem;
12use core::result::Result;
13use lex::{Span, Token, Tokenizer};
14use semver::Version;
15#[cfg(feature = "std")]
16use std::path::Path;
17
18pub mod error;
19pub mod lex;
20
21pub use resolve::Resolver;
22mod resolve;
23pub mod toposort;
24
25pub use lex::validate_id;
26
27struct PackageFile<'a> {
29 package_id: Option<PackageName<'a>>,
31 decl_list: DeclList<'a>,
33}
34
35const MAX_ITEM_DEPTH: usize = 100;
37
38impl<'a> PackageFile<'a> {
39 fn parse(tokens: &mut Tokenizer<'a>) -> ParseResult<Self> {
44 let mut package_name_tokens_peek = tokens.clone();
45 let docs = parse_docs(&mut package_name_tokens_peek)?;
46
47 let package_id = if package_name_tokens_peek.eat(Token::Package)? {
50 let name = PackageName::parse(&mut package_name_tokens_peek, docs)?;
51 if package_name_tokens_peek.eat(Token::Semicolon)? {
52 *tokens = package_name_tokens_peek;
53 Some(name)
54 } else {
55 None
56 }
57 } else {
58 None
59 };
60 let decl_list = DeclList::parse_until(tokens, None, 0)?;
61 Ok(PackageFile {
62 package_id,
63 decl_list,
64 })
65 }
66
67 fn parse_nested(
69 tokens: &mut Tokenizer<'a>,
70 docs: Docs<'a>,
71 attributes: Vec<Attribute<'a>>,
72 depth: usize,
73 ) -> ParseResult<Self> {
74 let span = tokens.expect(Token::Package)?;
75 if !attributes.is_empty() {
76 return Err(ParseError::new_syntax(
77 span,
78 format!("cannot place attributes on nested packages"),
79 ));
80 }
81 if depth >= MAX_ITEM_DEPTH {
82 return Err(ParseError::new_syntax(span, "package nesting too deep"));
83 }
84 let package_id = PackageName::parse(tokens, docs)?;
85 tokens.expect(Token::LeftBrace)?;
86 let decl_list = DeclList::parse_until(tokens, Some(Token::RightBrace), depth + 1)?;
87 Ok(PackageFile {
88 package_id: Some(package_id),
89 decl_list,
90 })
91 }
92}
93
94#[derive(Default)]
130pub struct DeclList<'a> {
131 items: Vec<AstItem<'a>>,
132}
133
134impl<'a> DeclList<'a> {
135 fn parse_until(
136 tokens: &mut Tokenizer<'a>,
137 end: Option<Token>,
138 depth: usize,
139 ) -> ParseResult<DeclList<'a>> {
140 let mut items = Vec::new();
141 let mut docs = parse_docs(tokens)?;
142 loop {
143 match end {
144 Some(end) => {
145 if tokens.eat(end)? {
146 break;
147 }
148 }
149 None => {
150 if tokens.clone().next()?.is_none() {
151 break;
152 }
153 }
154 }
155 items.push(AstItem::parse(tokens, docs, depth)?);
156 docs = parse_docs(tokens)?;
157 }
158 Ok(DeclList { items })
159 }
160
161 fn for_each_path<'b>(
162 &'b self,
163 f: &mut dyn FnMut(
164 Option<&'b Id<'a>>,
165 &'b [Attribute<'a>],
166 &'b UsePath<'a>,
167 Option<&'b [UseName<'a>]>,
168 WorldOrInterface,
169 ) -> ParseResult<()>,
170 ) -> ParseResult<()> {
171 for item in self.items.iter() {
172 match item {
173 AstItem::World(world) => {
174 let mut imports = Vec::new();
179 let mut exports = Vec::new();
180 for item in world.items.iter() {
181 match item {
182 WorldItem::Use(u) => f(
183 None,
184 &u.attributes,
185 &u.from,
186 Some(&u.names),
187 WorldOrInterface::Interface,
188 )?,
189 WorldItem::Include(i) => f(
190 Some(&world.name),
191 &i.attributes,
192 &i.from,
193 None,
194 WorldOrInterface::World,
195 )?,
196 WorldItem::Type(_) => {}
197 WorldItem::Import(Import {
198 kind, attributes, ..
199 }) => imports.push((kind, attributes)),
200 WorldItem::Export(Export {
201 kind, attributes, ..
202 }) => exports.push((kind, attributes)),
203 }
204 }
205
206 let mut visit_kind =
207 |kind: &'b ExternKind<'a>, attrs: &'b [Attribute<'a>]| match kind {
208 ExternKind::Interface(_, items) => {
209 for item in items {
210 match item {
211 InterfaceItem::Use(u) => f(
212 None,
213 &u.attributes,
214 &u.from,
215 Some(&u.names),
216 WorldOrInterface::Interface,
217 )?,
218 _ => {}
219 }
220 }
221 Ok(())
222 }
223 ExternKind::Path(path) | ExternKind::NamedPath(_, path) => {
224 f(None, attrs, path, None, WorldOrInterface::Interface)
225 }
226 ExternKind::Func(..) => Ok(()),
227 };
228
229 for (kind, attrs) in imports {
230 visit_kind(kind, attrs)?;
231 }
232 for (kind, attrs) in exports {
233 visit_kind(kind, attrs)?;
234 }
235 }
236 AstItem::Interface(i) => {
237 for item in i.items.iter() {
238 match item {
239 InterfaceItem::Use(u) => f(
240 Some(&i.name),
241 &u.attributes,
242 &u.from,
243 Some(&u.names),
244 WorldOrInterface::Interface,
245 )?,
246 _ => {}
247 }
248 }
249 }
250 AstItem::Use(u) => {
251 f(
254 None,
255 &u.attributes,
256 &u.item,
257 None,
258 WorldOrInterface::Unknown,
259 )?;
260 }
261
262 AstItem::Package(pkg) => pkg.decl_list.for_each_path(f)?,
263 }
264 }
265 Ok(())
266 }
267}
268
269enum AstItem<'a> {
270 Interface(Interface<'a>),
271 World(World<'a>),
272 Use(ToplevelUse<'a>),
273 Package(PackageFile<'a>),
274}
275
276impl<'a> AstItem<'a> {
277 fn parse(tokens: &mut Tokenizer<'a>, docs: Docs<'a>, depth: usize) -> ParseResult<Self> {
278 let attributes = Attribute::parse_list(tokens)?;
279 match tokens.clone().next()? {
280 Some((_span, Token::Interface)) => {
281 Interface::parse(tokens, docs, attributes).map(Self::Interface)
282 }
283 Some((_span, Token::World)) => World::parse(tokens, docs, attributes).map(Self::World),
284 Some((_span, Token::Use)) => ToplevelUse::parse(tokens, attributes).map(Self::Use),
285 Some((_span, Token::Package)) => {
286 PackageFile::parse_nested(tokens, docs, attributes, depth).map(Self::Package)
287 }
288 other => Err(err_expected(tokens, "`world`, `interface` or `use`", other).into()),
289 }
290 }
291}
292
293#[derive(Debug, Clone)]
294struct PackageName<'a> {
295 docs: Docs<'a>,
296 span: Span,
297 namespace: Id<'a>,
298 name: Id<'a>,
299 version: Option<(Span, Version)>,
300}
301
302impl<'a> PackageName<'a> {
303 fn parse(tokens: &mut Tokenizer<'a>, docs: Docs<'a>) -> ParseResult<Self> {
304 let namespace = parse_id(tokens)?;
305 tokens.expect(Token::Colon)?;
306 let name = parse_id(tokens)?;
307 let version = parse_opt_version(tokens)?;
308 Ok(PackageName {
309 docs,
310 span: Span::new(
311 namespace.span.start(),
312 version
313 .as_ref()
314 .map(|(s, _)| s.end())
315 .unwrap_or(name.span.end()),
316 ),
317 namespace,
318 name,
319 version,
320 })
321 }
322
323 fn package_name(&self) -> crate::PackageName {
324 crate::PackageName {
325 namespace: self.namespace.name.to_string(),
326 name: self.name.name.to_string(),
327 version: self.version.as_ref().map(|(_, v)| v.clone()),
328 }
329 }
330}
331
332struct ToplevelUse<'a> {
333 span: Span,
334 attributes: Vec<Attribute<'a>>,
335 item: UsePath<'a>,
336 as_: Option<Id<'a>>,
337}
338
339impl<'a> ToplevelUse<'a> {
340 fn parse(tokens: &mut Tokenizer<'a>, attributes: Vec<Attribute<'a>>) -> ParseResult<Self> {
341 let span = tokens.expect(Token::Use)?;
342 let item = UsePath::parse(tokens)?;
343 let as_ = if tokens.eat(Token::As)? {
344 Some(parse_id(tokens)?)
345 } else {
346 None
347 };
348 tokens.expect_semicolon()?;
349 Ok(ToplevelUse {
350 span,
351 attributes,
352 item,
353 as_,
354 })
355 }
356}
357
358struct World<'a> {
359 docs: Docs<'a>,
360 attributes: Vec<Attribute<'a>>,
361 name: Id<'a>,
362 items: Vec<WorldItem<'a>>,
363}
364
365impl<'a> World<'a> {
366 fn parse(
367 tokens: &mut Tokenizer<'a>,
368 docs: Docs<'a>,
369 attributes: Vec<Attribute<'a>>,
370 ) -> ParseResult<Self> {
371 Attribute::reject_external_id(&attributes, "world declarations")?;
372 tokens.expect(Token::World)?;
373 let name = parse_id(tokens)?;
374 let items = Self::parse_items(tokens)?;
375 Ok(World {
376 docs,
377 attributes,
378 name,
379 items,
380 })
381 }
382
383 fn parse_items(tokens: &mut Tokenizer<'a>) -> ParseResult<Vec<WorldItem<'a>>> {
384 tokens.expect(Token::LeftBrace)?;
385 let mut items = Vec::new();
386 loop {
387 let docs = parse_docs(tokens)?;
388 if tokens.eat(Token::RightBrace)? {
389 break;
390 }
391 let attributes = Attribute::parse_list(tokens)?;
392 items.push(WorldItem::parse(tokens, docs, attributes)?);
393 }
394 Ok(items)
395 }
396}
397
398enum WorldItem<'a> {
399 Import(Import<'a>),
400 Export(Export<'a>),
401 Use(Use<'a>),
402 Type(TypeDef<'a>),
403 Include(Include<'a>),
404}
405
406impl<'a> WorldItem<'a> {
407 fn parse(
408 tokens: &mut Tokenizer<'a>,
409 docs: Docs<'a>,
410 attributes: Vec<Attribute<'a>>,
411 ) -> ParseResult<WorldItem<'a>> {
412 match tokens.clone().next()? {
413 Some((_span, Token::Import)) => {
414 Import::parse(tokens, docs, attributes).map(WorldItem::Import)
415 }
416 Some((_span, Token::Export)) => {
417 Export::parse(tokens, docs, attributes).map(WorldItem::Export)
418 }
419 Some((_span, Token::Use)) => Use::parse(tokens, attributes).map(WorldItem::Use),
420 Some((_span, Token::Type)) => {
421 TypeDef::parse(tokens, docs, attributes).map(WorldItem::Type)
422 }
423 Some((_span, Token::Flags)) => {
424 TypeDef::parse_flags(tokens, docs, attributes).map(WorldItem::Type)
425 }
426 Some((_span, Token::Resource)) => {
427 TypeDef::parse_resource(tokens, docs, attributes).map(WorldItem::Type)
428 }
429 Some((_span, Token::Record)) => {
430 TypeDef::parse_record(tokens, docs, attributes).map(WorldItem::Type)
431 }
432 Some((_span, Token::Variant)) => {
433 TypeDef::parse_variant(tokens, docs, attributes).map(WorldItem::Type)
434 }
435 Some((_span, Token::Enum)) => {
436 TypeDef::parse_enum(tokens, docs, attributes).map(WorldItem::Type)
437 }
438 Some((_span, Token::Include)) => {
439 Include::parse(tokens, attributes).map(WorldItem::Include)
440 }
441 other => Err(err_expected(
442 tokens,
443 "`import`, `export`, `include`, `use`, or type definition",
444 other,
445 )
446 .into()),
447 }
448 }
449}
450
451struct Import<'a> {
452 docs: Docs<'a>,
453 attributes: Vec<Attribute<'a>>,
454 kind: ExternKind<'a>,
455}
456
457impl<'a> Import<'a> {
458 fn parse(
459 tokens: &mut Tokenizer<'a>,
460 docs: Docs<'a>,
461 attributes: Vec<Attribute<'a>>,
462 ) -> ParseResult<Import<'a>> {
463 tokens.expect(Token::Import)?;
464 let kind = ExternKind::parse(tokens)?;
465 Ok(Import {
466 docs,
467 attributes,
468 kind,
469 })
470 }
471}
472
473struct Export<'a> {
474 docs: Docs<'a>,
475 attributes: Vec<Attribute<'a>>,
476 kind: ExternKind<'a>,
477}
478
479impl<'a> Export<'a> {
480 fn parse(
481 tokens: &mut Tokenizer<'a>,
482 docs: Docs<'a>,
483 attributes: Vec<Attribute<'a>>,
484 ) -> ParseResult<Export<'a>> {
485 tokens.expect(Token::Export)?;
486 let kind = ExternKind::parse(tokens)?;
487 Ok(Export {
488 docs,
489 attributes,
490 kind,
491 })
492 }
493}
494
495enum ExternKind<'a> {
496 Interface(Id<'a>, Vec<InterfaceItem<'a>>),
497 Path(UsePath<'a>),
498 Func(Id<'a>, Func<'a>),
499 NamedPath(Id<'a>, UsePath<'a>),
501}
502
503impl<'a> ExternKind<'a> {
504 fn parse(tokens: &mut Tokenizer<'a>) -> ParseResult<ExternKind<'a>> {
505 let mut clone = tokens.clone();
514 let id = parse_id(&mut clone)?;
515 if clone.eat(Token::Colon)? {
516 if clone.clone().eat(Token::Func)?
519 || clone.clone().eat(Token::Async)?
520 || eat_accessor_token(&mut clone.clone())?.is_some()
521 {
522 *tokens = clone;
523 let ret = ExternKind::Func(id, Func::parse(tokens)?);
524 tokens.expect_semicolon()?;
525 return Ok(ret);
526 }
527
528 if clone.eat(Token::Interface)? {
530 *tokens = clone;
531 return Ok(ExternKind::Interface(id, Interface::parse_items(tokens)?));
532 }
533
534 let mut peek = clone.clone();
545 let is_qualified_path =
546 parse_id(&mut peek).is_ok() && peek.clone().eat(Token::Slash).unwrap_or(false);
547 if !is_qualified_path {
548 *tokens = clone;
549 let path = UsePath::parse(tokens)?;
550 tokens.expect_semicolon()?;
551 return Ok(ExternKind::NamedPath(id, path));
552 }
553 }
554
555 let ret = ExternKind::Path(UsePath::parse(tokens)?);
559 tokens.expect_semicolon()?;
560 Ok(ret)
561 }
562
563 fn span(&self) -> Span {
564 match self {
565 ExternKind::Interface(id, _) => id.span,
566 ExternKind::Path(UsePath::Id(id)) => id.span,
567 ExternKind::Path(UsePath::Package { name, .. }) => name.span,
568 ExternKind::Func(id, _) => id.span,
569 ExternKind::NamedPath(id, _) => id.span,
570 }
571 }
572}
573
574struct Interface<'a> {
575 docs: Docs<'a>,
576 attributes: Vec<Attribute<'a>>,
577 name: Id<'a>,
578 items: Vec<InterfaceItem<'a>>,
579}
580
581impl<'a> Interface<'a> {
582 fn parse(
583 tokens: &mut Tokenizer<'a>,
584 docs: Docs<'a>,
585 attributes: Vec<Attribute<'a>>,
586 ) -> ParseResult<Self> {
587 Attribute::reject_external_id(&attributes, "interface declarations")?;
588 tokens.expect(Token::Interface)?;
589 let name = parse_id(tokens)?;
590 let items = Self::parse_items(tokens)?;
591 Ok(Interface {
592 docs,
593 attributes,
594 name,
595 items,
596 })
597 }
598
599 pub(super) fn parse_items(tokens: &mut Tokenizer<'a>) -> ParseResult<Vec<InterfaceItem<'a>>> {
600 tokens.expect(Token::LeftBrace)?;
601 let mut items = Vec::new();
602 loop {
603 let docs = parse_docs(tokens)?;
604 if tokens.eat(Token::RightBrace)? {
605 break;
606 }
607 let attributes = Attribute::parse_list(tokens)?;
608 items.push(InterfaceItem::parse(tokens, docs, attributes)?);
609 }
610 Ok(items)
611 }
612}
613
614#[derive(Debug)]
615pub enum WorldOrInterface {
616 World,
617 Interface,
618 Unknown,
619}
620
621enum InterfaceItem<'a> {
622 TypeDef(TypeDef<'a>),
623 Func(NamedFunc<'a>),
624 Use(Use<'a>),
625}
626
627struct Use<'a> {
628 attributes: Vec<Attribute<'a>>,
629 from: UsePath<'a>,
630 names: Vec<UseName<'a>>,
631}
632
633#[derive(Debug)]
634enum UsePath<'a> {
635 Id(Id<'a>),
636 Package { id: PackageName<'a>, name: Id<'a> },
637}
638
639impl<'a> UsePath<'a> {
640 fn parse(tokens: &mut Tokenizer<'a>) -> ParseResult<Self> {
641 let id = parse_id(tokens)?;
642 if tokens.eat(Token::Colon)? {
643 let namespace = id;
645 let pkg_name = parse_id(tokens)?;
646 tokens.expect(Token::Slash)?;
647 let name = parse_id(tokens)?;
648 let version = parse_opt_version(tokens)?;
649 Ok(UsePath::Package {
650 id: PackageName {
651 docs: Default::default(),
652 span: Span::new(namespace.span.start(), pkg_name.span.end()),
653 namespace,
654 name: pkg_name,
655 version,
656 },
657 name,
658 })
659 } else {
660 Ok(UsePath::Id(id))
662 }
663 }
664
665 fn name(&self) -> &Id<'a> {
666 match self {
667 UsePath::Id(id) => id,
668 UsePath::Package { name, .. } => name,
669 }
670 }
671}
672
673struct UseName<'a> {
674 name: Id<'a>,
675 as_: Option<Id<'a>>,
676}
677
678impl<'a> Use<'a> {
679 fn parse(tokens: &mut Tokenizer<'a>, attributes: Vec<Attribute<'a>>) -> ParseResult<Self> {
680 tokens.expect(Token::Use)?;
681 let from = UsePath::parse(tokens)?;
682 tokens.expect(Token::Period)?;
683 tokens.expect(Token::LeftBrace)?;
684
685 let mut names = Vec::new();
686 while !tokens.eat(Token::RightBrace)? {
687 let mut name = UseName {
688 name: parse_id(tokens)?,
689 as_: None,
690 };
691 if tokens.eat(Token::As)? {
692 name.as_ = Some(parse_id(tokens)?);
693 }
694 names.push(name);
695 if !tokens.eat(Token::Comma)? {
696 tokens.expect(Token::RightBrace)?;
697 break;
698 }
699 }
700 tokens.expect_semicolon()?;
701 Ok(Use {
702 attributes,
703 from,
704 names,
705 })
706 }
707}
708
709struct Include<'a> {
710 from: UsePath<'a>,
711 attributes: Vec<Attribute<'a>>,
712 names: Vec<IncludeName<'a>>,
713}
714
715struct IncludeName<'a> {
716 name: Id<'a>,
717 as_: Id<'a>,
718}
719
720impl<'a> Include<'a> {
721 fn parse(tokens: &mut Tokenizer<'a>, attributes: Vec<Attribute<'a>>) -> ParseResult<Self> {
722 Attribute::reject_external_id(&attributes, "include statements")?;
723 tokens.expect(Token::Include)?;
724 let from = UsePath::parse(tokens)?;
725
726 let names = if tokens.eat(Token::With)? {
727 parse_list(
728 tokens,
729 Token::LeftBrace,
730 Token::RightBrace,
731 |_docs, tokens| {
732 let name = parse_id(tokens)?;
733 tokens.expect(Token::As)?;
734 let as_ = parse_id(tokens)?;
735 Ok(IncludeName { name, as_ })
736 },
737 )?
738 } else {
739 tokens.expect_semicolon()?;
740 Vec::new()
741 };
742
743 Ok(Include {
744 attributes,
745 from,
746 names,
747 })
748 }
749}
750
751#[derive(Debug, Clone)]
752pub struct Id<'a> {
753 name: &'a str,
754 span: Span,
755}
756
757impl<'a> From<&'a str> for Id<'a> {
758 fn from(s: &'a str) -> Id<'a> {
759 Id {
760 name: s.into(),
761 span: Default::default(),
762 }
763 }
764}
765
766#[derive(Debug, Clone)]
767pub struct Docs<'a> {
768 docs: Vec<Cow<'a, str>>,
769 span: Span,
770}
771
772impl<'a> Default for Docs<'a> {
773 fn default() -> Self {
774 Self {
775 docs: Default::default(),
776 span: Default::default(),
777 }
778 }
779}
780
781struct TypeDef<'a> {
782 docs: Docs<'a>,
783 attributes: Vec<Attribute<'a>>,
784 name: Id<'a>,
785 ty: Type<'a>,
786}
787
788enum Type<'a> {
789 Bool(Span),
790 U8(Span),
791 U16(Span),
792 U32(Span),
793 U64(Span),
794 S8(Span),
795 S16(Span),
796 S32(Span),
797 S64(Span),
798 F32(Span),
799 F64(Span),
800 Char(Span),
801 String(Span),
802 Name(Id<'a>),
803 List(List<'a>),
804 Map(Map<'a>),
805 FixedLengthList(FixedLengthList<'a>),
806 Handle(Handle<'a>),
807 Resource(Resource<'a>),
808 Record(Record<'a>),
809 Flags(Flags<'a>),
810 Variant(Variant<'a>),
811 Tuple(Tuple<'a>),
812 Enum(Enum<'a>),
813 Option(Option_<'a>),
814 Result(Result_<'a>),
815 Future(Future<'a>),
816 Stream(Stream<'a>),
817 ErrorContext(Span),
818}
819
820enum Handle<'a> {
821 Own { resource: Id<'a> },
822 Borrow { resource: Id<'a> },
823}
824
825impl Handle<'_> {
826 fn span(&self) -> Span {
827 match self {
828 Handle::Own { resource } | Handle::Borrow { resource } => resource.span,
829 }
830 }
831}
832
833struct Resource<'a> {
834 span: Span,
835 funcs: Vec<ResourceFunc<'a>>,
836}
837
838enum ResourceFunc<'a> {
839 Method(NamedFunc<'a>),
840 Static(NamedFunc<'a>),
841 Constructor(NamedFunc<'a>),
842}
843
844impl<'a> ResourceFunc<'a> {
845 fn parse(
846 docs: Docs<'a>,
847 attributes: Vec<Attribute<'a>>,
848 tokens: &mut Tokenizer<'a>,
849 ) -> ParseResult<Self> {
850 match tokens.clone().next()? {
851 Some((span, Token::Constructor)) => {
852 tokens.expect(Token::Constructor)?;
853 tokens.expect(Token::LeftParen)?;
854 let params = parse_list_trailer(tokens, Token::RightParen, |_docs, tokens| {
855 let name = parse_id(tokens)?;
856 tokens.expect(Token::Colon)?;
857 let ty = Type::parse(tokens)?;
858 Ok((name, ty))
859 })?;
860 let result = if tokens.eat(Token::RArrow)? {
861 let ty = Type::parse(tokens)?;
862 Some(ty)
863 } else {
864 None
865 };
866 tokens.expect_semicolon()?;
867 Ok(ResourceFunc::Constructor(NamedFunc {
868 docs,
869 attributes,
870 name: Id {
871 span,
872 name: "constructor",
873 },
874 func: Func {
875 span,
876 async_: false,
877 accessor: None,
878 params,
879 result,
880 },
881 }))
882 }
883 Some((_span, Token::Id | Token::ExplicitId)) => {
884 let name = parse_id(tokens)?;
885 tokens.expect(Token::Colon)?;
886 let ctor = if tokens.eat(Token::Static)? {
887 ResourceFunc::Static
888 } else {
889 ResourceFunc::Method
890 };
891 let func = Func::parse(tokens)?;
892 tokens.expect_semicolon()?;
893 Ok(ctor(NamedFunc {
894 docs,
895 attributes,
896 name,
897 func,
898 }))
899 }
900 other => Err(err_expected(tokens, "`constructor` or identifier", other).into()),
901 }
902 }
903
904 fn named_func(&self) -> &NamedFunc<'a> {
905 use ResourceFunc::*;
906 match self {
907 Method(f) | Static(f) | Constructor(f) => f,
908 }
909 }
910}
911
912struct Record<'a> {
913 span: Span,
914 fields: Vec<Field<'a>>,
915}
916
917struct Field<'a> {
918 docs: Docs<'a>,
919 name: Id<'a>,
920 ty: Type<'a>,
921}
922
923struct Flags<'a> {
924 span: Span,
925 flags: Vec<Flag<'a>>,
926}
927
928struct Flag<'a> {
929 docs: Docs<'a>,
930 name: Id<'a>,
931}
932
933struct Variant<'a> {
934 span: Span,
935 cases: Vec<Case<'a>>,
936}
937
938struct Case<'a> {
939 docs: Docs<'a>,
940 name: Id<'a>,
941 ty: Option<Type<'a>>,
942}
943
944struct Enum<'a> {
945 span: Span,
946 cases: Vec<EnumCase<'a>>,
947}
948
949struct EnumCase<'a> {
950 docs: Docs<'a>,
951 name: Id<'a>,
952}
953
954struct Option_<'a> {
955 span: Span,
956 ty: Box<Type<'a>>,
957}
958
959struct List<'a> {
960 span: Span,
961 ty: Box<Type<'a>>,
962}
963
964struct Map<'a> {
965 span: Span,
966 key: Box<Type<'a>>,
967 value: Box<Type<'a>>,
968}
969
970struct FixedLengthList<'a> {
971 span: Span,
972 ty: Box<Type<'a>>,
973 size: u32,
974}
975
976struct Future<'a> {
977 span: Span,
978 ty: Option<Box<Type<'a>>>,
979}
980
981struct Tuple<'a> {
982 span: Span,
983 types: Vec<Type<'a>>,
984}
985
986struct Result_<'a> {
987 span: Span,
988 ok: Option<Box<Type<'a>>>,
989 err: Option<Box<Type<'a>>>,
990}
991
992struct Stream<'a> {
993 span: Span,
994 ty: Option<Box<Type<'a>>>,
995}
996
997struct NamedFunc<'a> {
998 docs: Docs<'a>,
999 attributes: Vec<Attribute<'a>>,
1000 name: Id<'a>,
1001 func: Func<'a>,
1002}
1003
1004type ParamList<'a> = Vec<(Id<'a>, Type<'a>)>;
1005
1006struct Func<'a> {
1007 span: Span,
1008 async_: bool,
1009 accessor: Option<AccessorKind>,
1010 params: ParamList<'a>,
1011 result: Option<Type<'a>>,
1012}
1013
1014impl<'a> Func<'a> {
1015 fn parse(tokens: &mut Tokenizer<'a>) -> ParseResult<Func<'a>> {
1016 fn parse_params<'a>(
1017 tokens: &mut Tokenizer<'a>,
1018 left_paren: bool,
1019 ) -> ParseResult<ParamList<'a>> {
1020 if left_paren {
1021 tokens.expect(Token::LeftParen)?;
1022 };
1023 parse_list_trailer(tokens, Token::RightParen, |_docs, tokens| {
1024 let name = parse_id(tokens)?;
1025 tokens.expect(Token::Colon)?;
1026 let ty = Type::parse(tokens)?;
1027 Ok((name, ty))
1028 })
1029 }
1030
1031 let async_ = tokens.eat(Token::Async)?;
1032 let accessor = if async_ {
1033 None
1034 } else {
1035 eat_accessor_token(tokens)?
1036 };
1037 let (span, accessor) = match accessor {
1038 Some((span, accessor)) => (span, Some(accessor)),
1039 None => (tokens.expect(Token::Func)?, None),
1040 };
1041 let params = parse_params(tokens, true)?;
1042 let result = if tokens.eat(Token::RArrow)? {
1043 let ty = Type::parse(tokens)?;
1044 Some(ty)
1045 } else {
1046 None
1047 };
1048 Ok(Func {
1049 span,
1050 async_,
1051 accessor,
1052 params,
1053 result,
1054 })
1055 }
1056}
1057
1058fn eat_accessor_token(tokens: &mut Tokenizer<'_>) -> ParseResult<Option<(Span, AccessorKind)>> {
1059 let mut clone = tokens.clone();
1060 let (span, accessor) = match clone.next()? {
1061 Some((span, Token::Id)) => match clone.parse_id(span)? {
1062 "get" => (span, AccessorKind::Getter),
1063 "set" => (span, AccessorKind::Setter),
1064 _ => return Ok(None),
1065 },
1066 _ => return Ok(None),
1067 };
1068 if !clone.eat(Token::LeftParen)? {
1069 return Ok(None);
1070 }
1071 tokens.next()?; Ok(Some((span, accessor)))
1073}
1074
1075impl<'a> InterfaceItem<'a> {
1076 fn parse(
1077 tokens: &mut Tokenizer<'a>,
1078 docs: Docs<'a>,
1079 attributes: Vec<Attribute<'a>>,
1080 ) -> ParseResult<InterfaceItem<'a>> {
1081 match tokens.clone().next()? {
1082 Some((_span, Token::Type)) => {
1083 TypeDef::parse(tokens, docs, attributes).map(InterfaceItem::TypeDef)
1084 }
1085 Some((_span, Token::Flags)) => {
1086 TypeDef::parse_flags(tokens, docs, attributes).map(InterfaceItem::TypeDef)
1087 }
1088 Some((_span, Token::Enum)) => {
1089 TypeDef::parse_enum(tokens, docs, attributes).map(InterfaceItem::TypeDef)
1090 }
1091 Some((_span, Token::Variant)) => {
1092 TypeDef::parse_variant(tokens, docs, attributes).map(InterfaceItem::TypeDef)
1093 }
1094 Some((_span, Token::Resource)) => {
1095 TypeDef::parse_resource(tokens, docs, attributes).map(InterfaceItem::TypeDef)
1096 }
1097 Some((_span, Token::Record)) => {
1098 TypeDef::parse_record(tokens, docs, attributes).map(InterfaceItem::TypeDef)
1099 }
1100 Some((_span, Token::Id)) | Some((_span, Token::ExplicitId)) => {
1101 NamedFunc::parse(tokens, docs, attributes).map(InterfaceItem::Func)
1102 }
1103 Some((_span, Token::Use)) => Use::parse(tokens, attributes).map(InterfaceItem::Use),
1104 other => Err(err_expected(tokens, "`type`, `resource` or `func`", other).into()),
1105 }
1106 }
1107}
1108
1109impl<'a> TypeDef<'a> {
1110 fn parse(
1111 tokens: &mut Tokenizer<'a>,
1112 docs: Docs<'a>,
1113 attributes: Vec<Attribute<'a>>,
1114 ) -> ParseResult<Self> {
1115 tokens.expect(Token::Type)?;
1116 let name = parse_id(tokens)?;
1117 tokens.expect(Token::Equals)?;
1118 let ty = Type::parse(tokens)?;
1119 tokens.expect_semicolon()?;
1120 Ok(TypeDef {
1121 docs,
1122 attributes,
1123 name,
1124 ty,
1125 })
1126 }
1127
1128 fn parse_flags(
1129 tokens: &mut Tokenizer<'a>,
1130 docs: Docs<'a>,
1131 attributes: Vec<Attribute<'a>>,
1132 ) -> ParseResult<Self> {
1133 tokens.expect(Token::Flags)?;
1134 let name = parse_id(tokens)?;
1135 let ty = Type::Flags(Flags {
1136 span: name.span,
1137 flags: parse_list(
1138 tokens,
1139 Token::LeftBrace,
1140 Token::RightBrace,
1141 |docs, tokens| {
1142 let name = parse_id(tokens)?;
1143 Ok(Flag { docs, name })
1144 },
1145 )?,
1146 });
1147 Ok(TypeDef {
1148 docs,
1149 attributes,
1150 name,
1151 ty,
1152 })
1153 }
1154
1155 fn parse_resource(
1156 tokens: &mut Tokenizer<'a>,
1157 docs: Docs<'a>,
1158 attributes: Vec<Attribute<'a>>,
1159 ) -> ParseResult<Self> {
1160 tokens.expect(Token::Resource)?;
1161 let name = parse_id(tokens)?;
1162 let mut funcs = Vec::new();
1163 if tokens.eat(Token::LeftBrace)? {
1164 while !tokens.eat(Token::RightBrace)? {
1165 let docs = parse_docs(tokens)?;
1166 let attributes = Attribute::parse_list(tokens)?;
1167 funcs.push(ResourceFunc::parse(docs, attributes, tokens)?);
1168 }
1169 } else {
1170 tokens.expect_semicolon()?;
1171 }
1172 let ty = Type::Resource(Resource {
1173 span: name.span,
1174 funcs,
1175 });
1176 Ok(TypeDef {
1177 docs,
1178 attributes,
1179 name,
1180 ty,
1181 })
1182 }
1183
1184 fn parse_record(
1185 tokens: &mut Tokenizer<'a>,
1186 docs: Docs<'a>,
1187 attributes: Vec<Attribute<'a>>,
1188 ) -> ParseResult<Self> {
1189 tokens.expect(Token::Record)?;
1190 let name = parse_id(tokens)?;
1191 let ty = Type::Record(Record {
1192 span: name.span,
1193 fields: parse_list(
1194 tokens,
1195 Token::LeftBrace,
1196 Token::RightBrace,
1197 |docs, tokens| {
1198 let name = parse_id(tokens)?;
1199 tokens.expect(Token::Colon)?;
1200 let ty = Type::parse(tokens)?;
1201 Ok(Field { docs, name, ty })
1202 },
1203 )?,
1204 });
1205 Ok(TypeDef {
1206 docs,
1207 attributes,
1208 name,
1209 ty,
1210 })
1211 }
1212
1213 fn parse_variant(
1214 tokens: &mut Tokenizer<'a>,
1215 docs: Docs<'a>,
1216 attributes: Vec<Attribute<'a>>,
1217 ) -> ParseResult<Self> {
1218 tokens.expect(Token::Variant)?;
1219 let name = parse_id(tokens)?;
1220 let ty = Type::Variant(Variant {
1221 span: name.span,
1222 cases: parse_list(
1223 tokens,
1224 Token::LeftBrace,
1225 Token::RightBrace,
1226 |docs, tokens| {
1227 let name = parse_id(tokens)?;
1228 let ty = if tokens.eat(Token::LeftParen)? {
1229 let ty = Type::parse(tokens)?;
1230 tokens.expect(Token::RightParen)?;
1231 Some(ty)
1232 } else {
1233 None
1234 };
1235 Ok(Case { docs, name, ty })
1236 },
1237 )?,
1238 });
1239 Ok(TypeDef {
1240 docs,
1241 attributes,
1242 name,
1243 ty,
1244 })
1245 }
1246
1247 fn parse_enum(
1248 tokens: &mut Tokenizer<'a>,
1249 docs: Docs<'a>,
1250 attributes: Vec<Attribute<'a>>,
1251 ) -> ParseResult<Self> {
1252 tokens.expect(Token::Enum)?;
1253 let name = parse_id(tokens)?;
1254 let ty = Type::Enum(Enum {
1255 span: name.span,
1256 cases: parse_list(
1257 tokens,
1258 Token::LeftBrace,
1259 Token::RightBrace,
1260 |docs, tokens| {
1261 let name = parse_id(tokens)?;
1262 Ok(EnumCase { docs, name })
1263 },
1264 )?,
1265 });
1266 Ok(TypeDef {
1267 docs,
1268 attributes,
1269 name,
1270 ty,
1271 })
1272 }
1273}
1274
1275impl<'a> NamedFunc<'a> {
1276 fn parse(
1277 tokens: &mut Tokenizer<'a>,
1278 docs: Docs<'a>,
1279 attributes: Vec<Attribute<'a>>,
1280 ) -> ParseResult<Self> {
1281 let name = parse_id(tokens)?;
1282 tokens.expect(Token::Colon)?;
1283 let func = Func::parse(tokens)?;
1284 tokens.expect_semicolon()?;
1285 Ok(NamedFunc {
1286 docs,
1287 attributes,
1288 name,
1289 func,
1290 })
1291 }
1292}
1293
1294fn parse_id<'a>(tokens: &mut Tokenizer<'a>) -> ParseResult<Id<'a>> {
1295 match tokens.next()? {
1296 Some((span, Token::Id)) => Ok(Id {
1297 name: tokens.parse_id(span)?,
1298 span,
1299 }),
1300 Some((span, Token::ExplicitId)) => Ok(Id {
1301 name: tokens.parse_explicit_id(span)?,
1302 span,
1303 }),
1304 other => Err(err_expected(tokens, "an identifier or string", other)),
1305 }
1306}
1307
1308fn parse_opt_version(tokens: &mut Tokenizer<'_>) -> ParseResult<Option<(Span, Version)>> {
1309 if tokens.eat(Token::At)? {
1310 parse_version(tokens).map(Some)
1311 } else {
1312 Ok(None)
1313 }
1314}
1315
1316fn parse_version(tokens: &mut Tokenizer<'_>) -> ParseResult<(Span, Version)> {
1317 let start = tokens.expect(Token::Integer)?.start();
1318 tokens.expect(Token::Period)?;
1319 tokens.expect(Token::Integer)?;
1320 tokens.expect(Token::Period)?;
1321 let end = tokens.expect(Token::Integer)?.end();
1322 let mut span = Span::new(start, end);
1323 eat_ids(tokens, Token::Minus, &mut span)?;
1324 eat_ids(tokens, Token::Plus, &mut span)?;
1325 let string = tokens.get_span(span);
1326 let version =
1327 Version::parse(string).map_err(|e| ParseError::new_syntax(span, e.to_string()))?;
1328 return Ok((span, version));
1329
1330 fn eat_ids(
1384 tokens: &mut Tokenizer<'_>,
1385 prefix: Token,
1386 end: &mut Span,
1387 ) -> Result<(), lex::Error> {
1388 if !tokens.eat(prefix)? {
1389 return Ok(());
1390 }
1391 loop {
1392 let mut clone = tokens.clone();
1393 match clone.next()? {
1394 Some((span, Token::Id | Token::Integer | Token::Minus)) => {
1395 end.set_end(span.end());
1396 *tokens = clone;
1397 }
1398 Some((_span, Token::Period)) => match clone.next()? {
1399 Some((span, Token::Id | Token::Integer | Token::Minus)) => {
1400 end.set_end(span.end());
1401 *tokens = clone;
1402 }
1403 _ => break Ok(()),
1404 },
1405 _ => break Ok(()),
1406 }
1407 }
1408 }
1409}
1410
1411fn parse_docs<'a>(tokens: &mut Tokenizer<'a>) -> Result<Docs<'a>, lex::Error> {
1412 let mut docs = Docs::default();
1413 let mut clone = tokens.clone();
1414 let mut started = false;
1415 while let Some((span, token)) = clone.next_raw()? {
1416 match token {
1417 Token::Whitespace => {}
1418 Token::Comment => {
1419 let comment = tokens.get_span(span);
1420 if !started {
1421 docs.span.set_start(span.start());
1422 started = true;
1423 }
1424 let trailing_ws = comment
1425 .bytes()
1426 .rev()
1427 .take_while(|ch| ch.is_ascii_whitespace())
1428 .count();
1429 docs.span.set_end(span.end() - (trailing_ws as u32));
1430 docs.docs.push(comment.into());
1431 }
1432 _ => break,
1433 };
1434 *tokens = clone.clone();
1435 }
1436 Ok(docs)
1437}
1438
1439const MAX_TYPE_DEPTH: usize = 100;
1442
1443impl<'a> Type<'a> {
1444 fn parse(tokens: &mut Tokenizer<'a>) -> ParseResult<Self> {
1445 Type::parse_at_depth(tokens, 0)
1446 }
1447
1448 fn parse_at_depth(tokens: &mut Tokenizer<'a>, depth: usize) -> ParseResult<Self> {
1449 let token = tokens.next()?;
1450 if depth >= MAX_TYPE_DEPTH {
1451 let span = match token {
1452 Some((span, _)) => span,
1453 None => tokens.eof_span(),
1454 };
1455 return Err(ParseError::new_syntax(span, "type nesting too deep"));
1456 }
1457 match token {
1458 Some((span, Token::U8)) => Ok(Type::U8(span)),
1459 Some((span, Token::U16)) => Ok(Type::U16(span)),
1460 Some((span, Token::U32)) => Ok(Type::U32(span)),
1461 Some((span, Token::U64)) => Ok(Type::U64(span)),
1462 Some((span, Token::S8)) => Ok(Type::S8(span)),
1463 Some((span, Token::S16)) => Ok(Type::S16(span)),
1464 Some((span, Token::S32)) => Ok(Type::S32(span)),
1465 Some((span, Token::S64)) => Ok(Type::S64(span)),
1466 Some((span, Token::F32)) => Ok(Type::F32(span)),
1467 Some((span, Token::F64)) => Ok(Type::F64(span)),
1468 Some((span, Token::Char)) => Ok(Type::Char(span)),
1469
1470 Some((span, Token::Tuple)) => {
1472 let types = parse_list(
1473 tokens,
1474 Token::LessThan,
1475 Token::GreaterThan,
1476 |_docs, tokens| Type::parse_at_depth(tokens, depth + 1),
1477 )?;
1478 Ok(Type::Tuple(Tuple { span, types }))
1479 }
1480
1481 Some((span, Token::Bool)) => Ok(Type::Bool(span)),
1482 Some((span, Token::String_)) => Ok(Type::String(span)),
1483
1484 Some((span, Token::List)) => {
1487 tokens.expect(Token::LessThan)?;
1488 let ty = Type::parse_at_depth(tokens, depth + 1)?;
1489 let size = if tokens.eat(Token::Comma)? {
1490 let number = tokens.next()?;
1491 if let Some((span, Token::Integer)) = number {
1492 let size: u32 = tokens.get_span(span).parse().map_err(|e| {
1493 ParseError::new_syntax(span, format!("invalid list size: {e}"))
1494 })?;
1495 Some(size)
1496 } else {
1497 return Err(err_expected(tokens, "fixed-length", number).into());
1498 }
1499 } else {
1500 None
1501 };
1502 tokens.expect(Token::GreaterThan)?;
1503 if let Some(size) = size {
1504 Ok(Type::FixedLengthList(FixedLengthList {
1505 span,
1506 ty: Box::new(ty),
1507 size,
1508 }))
1509 } else {
1510 Ok(Type::List(List {
1511 span,
1512 ty: Box::new(ty),
1513 }))
1514 }
1515 }
1516
1517 Some((span, Token::Map)) => {
1519 tokens.expect(Token::LessThan)?;
1520 let key = Type::parse_at_depth(tokens, depth + 1)?;
1521 tokens.expect(Token::Comma)?;
1522 let value = Type::parse_at_depth(tokens, depth + 1)?;
1523 tokens.expect(Token::GreaterThan)?;
1524 Ok(Type::Map(Map {
1525 span,
1526 key: Box::new(key),
1527 value: Box::new(value),
1528 }))
1529 }
1530
1531 Some((span, Token::Option_)) => {
1533 tokens.expect(Token::LessThan)?;
1534 let ty = Type::parse_at_depth(tokens, depth + 1)?;
1535 tokens.expect(Token::GreaterThan)?;
1536 Ok(Type::Option(Option_ {
1537 span,
1538 ty: Box::new(ty),
1539 }))
1540 }
1541
1542 Some((span, Token::Result_)) => {
1547 let mut ok = None;
1548 let mut err = None;
1549
1550 if tokens.eat(Token::LessThan)? {
1551 if tokens.eat(Token::Underscore)? {
1552 tokens.expect(Token::Comma)?;
1553 err = Some(Box::new(Type::parse_at_depth(tokens, depth + 1)?));
1554 } else {
1555 ok = Some(Box::new(Type::parse_at_depth(tokens, depth + 1)?));
1556 if tokens.eat(Token::Comma)? {
1557 err = Some(Box::new(Type::parse_at_depth(tokens, depth + 1)?));
1558 }
1559 };
1560 tokens.expect(Token::GreaterThan)?;
1561 };
1562 Ok(Type::Result(Result_ { span, ok, err }))
1563 }
1564
1565 Some((span, Token::Future)) => {
1568 let mut ty = None;
1569
1570 if tokens.eat(Token::LessThan)? {
1571 ty = Some(Box::new(Type::parse_at_depth(tokens, depth + 1)?));
1572 tokens.expect(Token::GreaterThan)?;
1573 };
1574 Ok(Type::Future(Future { span, ty }))
1575 }
1576
1577 Some((span, Token::Stream)) => {
1580 let mut ty = None;
1581
1582 if tokens.eat(Token::LessThan)? {
1583 ty = Some(Box::new(Type::parse_at_depth(tokens, depth + 1)?));
1584 tokens.expect(Token::GreaterThan)?;
1585 };
1586 Ok(Type::Stream(Stream { span, ty }))
1587 }
1588
1589 Some((span, Token::ErrorContext)) => Ok(Type::ErrorContext(span)),
1591
1592 Some((_span, Token::Own)) => {
1594 tokens.expect(Token::LessThan)?;
1595 let resource = parse_id(tokens)?;
1596 tokens.expect(Token::GreaterThan)?;
1597 Ok(Type::Handle(Handle::Own { resource }))
1598 }
1599
1600 Some((_span, Token::Borrow)) => {
1602 tokens.expect(Token::LessThan)?;
1603 let resource = parse_id(tokens)?;
1604 tokens.expect(Token::GreaterThan)?;
1605 Ok(Type::Handle(Handle::Borrow { resource }))
1606 }
1607
1608 Some((span, Token::Id)) => Ok(Type::Name(Id {
1610 name: tokens.parse_id(span)?.into(),
1611 span,
1612 })),
1613 Some((span, Token::ExplicitId)) => Ok(Type::Name(Id {
1615 name: tokens.parse_explicit_id(span)?.into(),
1616 span,
1617 })),
1618
1619 other => Err(err_expected(tokens, "a type", other).into()),
1620 }
1621 }
1622
1623 fn span(&self) -> Span {
1624 match self {
1625 Type::Bool(span)
1626 | Type::U8(span)
1627 | Type::U16(span)
1628 | Type::U32(span)
1629 | Type::U64(span)
1630 | Type::S8(span)
1631 | Type::S16(span)
1632 | Type::S32(span)
1633 | Type::S64(span)
1634 | Type::F32(span)
1635 | Type::F64(span)
1636 | Type::Char(span)
1637 | Type::String(span)
1638 | Type::ErrorContext(span) => *span,
1639 Type::Name(id) => id.span,
1640 Type::List(l) => l.span,
1641 Type::Map(m) => m.span,
1642 Type::FixedLengthList(l) => l.span,
1643 Type::Handle(h) => h.span(),
1644 Type::Resource(r) => r.span,
1645 Type::Record(r) => r.span,
1646 Type::Flags(f) => f.span,
1647 Type::Variant(v) => v.span,
1648 Type::Tuple(t) => t.span,
1649 Type::Enum(e) => e.span,
1650 Type::Option(o) => o.span,
1651 Type::Result(r) => r.span,
1652 Type::Future(f) => f.span,
1653 Type::Stream(s) => s.span,
1654 }
1655 }
1656}
1657
1658fn parse_list<'a, T>(
1659 tokens: &mut Tokenizer<'a>,
1660 start: Token,
1661 end: Token,
1662 parse: impl FnMut(Docs<'a>, &mut Tokenizer<'a>) -> ParseResult<T>,
1663) -> ParseResult<Vec<T>> {
1664 tokens.expect(start)?;
1665 parse_list_trailer(tokens, end, parse)
1666}
1667
1668fn parse_list_trailer<'a, T>(
1669 tokens: &mut Tokenizer<'a>,
1670 end: Token,
1671 mut parse: impl FnMut(Docs<'a>, &mut Tokenizer<'a>) -> ParseResult<T>,
1672) -> ParseResult<Vec<T>> {
1673 let mut items = Vec::new();
1674 loop {
1675 let docs = parse_docs(tokens)?;
1677
1678 if tokens.eat(end)? {
1680 break;
1681 }
1682
1683 let item = parse(docs, tokens)?;
1684 items.push(item);
1685
1686 if !tokens.eat(Token::Comma)? {
1689 tokens.expect(end)?;
1690 break;
1691 }
1692 }
1693 Ok(items)
1694}
1695
1696fn err_expected(
1697 tokens: &Tokenizer<'_>,
1698 expected: &'static str,
1699 found: Option<(Span, Token)>,
1700) -> ParseError {
1701 match found {
1702 Some((span, token)) => ParseError::new_syntax(
1703 span,
1704 format!("expected {}, found {}", expected, token.describe()),
1705 ),
1706 None => {
1707 ParseError::new_syntax(tokens.eof_span(), format!("expected {expected}, found eof"))
1708 }
1709 }
1710}
1711
1712enum Attribute<'a> {
1713 Since { span: Span, version: Version },
1714 Unstable { span: Span, feature: Id<'a> },
1715 Deprecated { span: Span, version: Version },
1716 ExternalId { span: Span, id: String },
1717}
1718
1719impl<'a> Attribute<'a> {
1720 fn parse_list(tokens: &mut Tokenizer<'a>) -> ParseResult<Vec<Attribute<'a>>> {
1721 let mut ret = Vec::new();
1722 while tokens.eat(Token::At)? {
1723 let id = parse_id(tokens)?;
1724 let attr = match id.name {
1725 "since" => {
1726 tokens.expect(Token::LeftParen)?;
1727 eat_id(tokens, "version")?;
1728 tokens.expect(Token::Equals)?;
1729 let (_span, version) = parse_version(tokens)?;
1730 tokens.expect(Token::RightParen)?;
1731 Attribute::Since {
1732 span: id.span,
1733 version,
1734 }
1735 }
1736 "unstable" => {
1737 tokens.expect(Token::LeftParen)?;
1738 eat_id(tokens, "feature")?;
1739 tokens.expect(Token::Equals)?;
1740 let feature = parse_id(tokens)?;
1741 tokens.expect(Token::RightParen)?;
1742 Attribute::Unstable {
1743 span: id.span,
1744 feature,
1745 }
1746 }
1747 "deprecated" => {
1748 tokens.expect(Token::LeftParen)?;
1749 eat_id(tokens, "version")?;
1750 tokens.expect(Token::Equals)?;
1751 let (_span, version) = parse_version(tokens)?;
1752 tokens.expect(Token::RightParen)?;
1753 Attribute::Deprecated {
1754 span: id.span,
1755 version,
1756 }
1757 }
1758 "external-id" => {
1759 tokens.expect(Token::LeftParen)?;
1760 let span = tokens.expect(Token::StringLiteral)?;
1761 tokens.expect(Token::RightParen)?;
1762 Attribute::ExternalId {
1763 span: id.span,
1764 id: tokens.string_literal(span)?,
1765 }
1766 }
1767 other => {
1768 return Err(ParseError::new_syntax(
1769 id.span,
1770 format!("unknown attribute `{other}`"),
1771 ));
1772 }
1773 };
1774 ret.push(attr);
1775 }
1776 Ok(ret)
1777 }
1778
1779 fn reject_external_id(attrs: &[Attribute<'a>], what: &str) -> ParseResult<()> {
1786 for attr in attrs {
1787 if let Attribute::ExternalId { span, .. } = attr {
1788 return Err(ParseError::new_syntax(
1789 *span,
1790 format!("@external-id is not allowed on {what}"),
1791 ));
1792 }
1793 }
1794 Ok(())
1795 }
1796}
1797
1798fn eat_id(tokens: &mut Tokenizer<'_>, expected: &str) -> ParseResult<Span> {
1799 let id = parse_id(tokens)?;
1800 if id.name != expected {
1801 return Err(ParseError::new_syntax(
1802 id.span,
1803 format!("expected `{expected}`, found `{}`", id.name),
1804 ));
1805 }
1806 Ok(id.span)
1807}
1808
1809#[derive(Clone, Default, Debug, PartialEq, Eq)]
1814pub struct SourceMap {
1815 sources: Vec<Source>,
1816 offset: u32,
1817}
1818
1819#[derive(Clone, Debug, PartialEq, Eq)]
1820struct Source {
1821 offset: u32,
1822 path: String,
1823 contents: String,
1824}
1825
1826impl SourceMap {
1827 pub fn new() -> SourceMap {
1829 SourceMap::default()
1830 }
1831
1832 #[cfg(feature = "std")]
1835 pub fn push_file(&mut self, path: &Path) -> anyhow::Result<()> {
1836 let contents = std::fs::read_to_string(path)
1837 .with_context(|| format!("failed to read file {path:?}"))?;
1838 self.push(path, contents);
1839 Ok(())
1840 }
1841
1842 #[cfg(feature = "std")]
1849 pub fn push_dir(&mut self, path: &Path) -> anyhow::Result<()> {
1850 let cx = || format!("failed to read directory {path:?}");
1851 for entry in path.read_dir().with_context(&cx)? {
1852 let entry = entry.with_context(&cx)?;
1853 let entry_path = entry.path();
1854 let ty = entry.file_type().with_context(&cx)?;
1855 if ty.is_dir() {
1856 continue;
1857 }
1858 if ty.is_symlink() {
1859 if entry_path.is_dir() {
1860 continue;
1861 }
1862 }
1863 let filename = match entry_path.file_name().and_then(|s| s.to_str()) {
1864 Some(name) => name,
1865 None => continue,
1866 };
1867 if !filename.ends_with(".wit") {
1868 continue;
1869 }
1870 self.push_file(&entry_path)?;
1871 }
1872 Ok(())
1873 }
1874
1875 #[cfg(feature = "std")]
1883 pub fn push(&mut self, path: &Path, contents: impl Into<String>) {
1884 self.push_str(&path.display().to_string(), contents);
1885 }
1886
1887 pub fn push_str(&mut self, path: &str, contents: impl Into<String>) {
1895 let mut contents = contents.into();
1896 contents.push('\n');
1902 let new_offset = self.offset + u32::try_from(contents.len()).unwrap();
1903 self.sources.push(Source {
1904 offset: self.offset,
1905 path: path.to_string(),
1906 contents,
1907 });
1908 self.offset = new_offset;
1909 }
1910
1911 pub fn append(&mut self, other: SourceMap) -> u32 {
1917 let base = self.offset;
1918 for mut source in other.sources {
1919 source.offset += base;
1920 self.sources.push(source);
1921 }
1922 self.offset += other.offset;
1923 base
1924 }
1925
1926 pub fn parse(self) -> Result<UnresolvedPackageGroup, (Self, ParseError)> {
1932 match self.parse_inner() {
1933 Ok((main, nested)) => Ok(UnresolvedPackageGroup {
1934 main,
1935 nested,
1936 source_map: self,
1937 }),
1938 Err(e) => Err((self, e)),
1939 }
1940 }
1941
1942 fn parse_inner(&self) -> ParseResult<(UnresolvedPackage, Vec<UnresolvedPackage>)> {
1943 let mut nested = Vec::new();
1944 let mut resolver = Resolver::default();
1945 let mut srcs = self.sources.iter().collect::<Vec<_>>();
1946 srcs.sort_by_key(|src| &src.path);
1947
1948 for src in srcs {
1952 let mut tokens = Tokenizer::new(
1953 &src.contents[..src.contents.len() - 1],
1956 src.offset,
1957 )?;
1958 let mut file = PackageFile::parse(&mut tokens)?;
1959
1960 for item in mem::take(&mut file.decl_list.items) {
1969 match item {
1970 AstItem::Package(nested_pkg) => {
1971 let mut resolve = Resolver::default();
1972 resolve.push(nested_pkg)?;
1973 nested.push(resolve.resolve()?);
1974 }
1975 other => file.decl_list.items.push(other),
1976 }
1977 }
1978
1979 resolver.push(file)?;
1981 }
1982
1983 Ok((resolver.resolve()?, nested))
1984 }
1985
1986 pub(crate) fn highlight_span(&self, span: Span, err: impl fmt::Display) -> Option<String> {
1987 if !span.is_known() {
1988 return None;
1989 }
1990 Some(self.highlight_err(span.start(), Some(span.end()), err))
1991 }
1992
1993 fn highlight_err(&self, start: u32, end: Option<u32>, err: impl fmt::Display) -> String {
1994 let src = self.source_for_offset(start);
1995 let start = src.to_relative_offset(start);
1996 let end = end.map(|end| src.to_relative_offset(end));
1997 let (line, col) = src.linecol(start);
1998 let snippet = src.contents.lines().nth(line).unwrap_or("");
1999 let line = line + 1;
2000 let col = col + 1;
2001
2002 if snippet.len() > 500 {
2006 return format!("{}:{line}:{col}: {err}", src.path);
2007 }
2008 let mut msg = format!(
2009 "\
2010{err}
2011 --> {file}:{line}:{col}
2012 |
2013 {line:4} | {snippet}
2014 | {marker:>0$}",
2015 col,
2016 file = src.path,
2017 marker = "^",
2018 );
2019 if let Some(end) = end {
2020 if let Some(s) = src.contents.get(start..end) {
2021 for _ in s.chars().skip(1) {
2022 msg.push('-');
2023 }
2024 }
2025 }
2026 return msg;
2027 }
2028
2029 pub fn resolve_span(&self, span: Span) -> Option<SpanLocation<'_>> {
2035 if !span.is_known() || span.start() >= self.offset {
2036 return None;
2037 }
2038 let src = self.source_for_offset(span.start());
2039 let len = src.contents.len() - 1;
2042 let start = src.to_relative_offset(span.start()).min(len);
2043 let end = usize::try_from(span.end().saturating_sub(src.offset))
2044 .unwrap()
2045 .clamp(start, len);
2046 Some(SpanLocation {
2047 path: &src.path,
2048 range: start..end,
2049 })
2050 }
2051
2052 pub fn render_location(&self, span: Span) -> String {
2054 if !span.is_known() {
2055 return "<unknown>".to_string();
2056 }
2057 let start = span.start();
2058 let src = self.source_for_offset(start);
2059 let rel_start = src.to_relative_offset(start);
2060 let (line, col) = src.linecol(rel_start);
2061 format!(
2062 "{file}:{line}:{col}",
2063 file = src.path,
2064 line = line + 1,
2065 col = col + 1,
2066 )
2067 }
2068
2069 fn source_for_offset(&self, start: u32) -> &Source {
2070 let i = match self.sources.binary_search_by_key(&start, |src| src.offset) {
2071 Ok(i) => i,
2072 Err(i) => i - 1,
2073 };
2074 &self.sources[i]
2075 }
2076
2077 #[cfg(feature = "std")]
2079 pub fn source_files(&self) -> impl Iterator<Item = &Path> {
2080 self.sources.iter().map(|src| Path::new(&src.path))
2081 }
2082
2083 pub fn source_names(&self) -> impl Iterator<Item = &str> {
2085 self.sources.iter().map(|src| src.path.as_str())
2086 }
2087}
2088
2089#[derive(Clone, Debug, PartialEq, Eq)]
2091pub struct SpanLocation<'a> {
2092 pub path: &'a str,
2094 pub range: core::ops::Range<usize>,
2096}
2097
2098impl Source {
2099 fn to_relative_offset(&self, offset: u32) -> usize {
2100 usize::try_from(offset - self.offset).unwrap()
2101 }
2102
2103 fn linecol(&self, relative_offset: usize) -> (usize, usize) {
2104 let mut cur = 0;
2105 for (i, line) in self.contents.split_terminator('\n').enumerate() {
2109 if cur + line.len() + 1 > relative_offset {
2110 return (i, relative_offset - cur);
2111 }
2112 cur += line.len() + 1;
2113 }
2114 (self.contents.lines().count(), 0)
2115 }
2116}
2117
2118pub enum ParsedUsePath {
2119 Name(String),
2120 Package(crate::PackageName, String),
2121}
2122
2123pub fn parse_use_path(s: &str) -> anyhow::Result<ParsedUsePath> {
2124 let mut tokens = Tokenizer::new(s, 0)?;
2125 let path = UsePath::parse(&mut tokens)?;
2126 if tokens.next()?.is_some() {
2127 anyhow::bail!("trailing tokens in path specifier");
2128 }
2129 Ok(match path {
2130 UsePath::Id(id) => ParsedUsePath::Name(id.name.to_string()),
2131 UsePath::Package { id, name } => {
2132 ParsedUsePath::Package(id.package_name(), name.name.to_string())
2133 }
2134 })
2135}
2136
2137#[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
2138#[cfg_attr(
2139 feature = "serde",
2140 derive(serde_derive::Serialize, serde_derive::Deserialize)
2141)]
2142#[cfg_attr(feature = "serde", serde(into = "String", try_from = "String"))]
2143pub struct ItemName {
2227 pub package: Option<crate::PackageName>,
2228 pub interface: Option<String>,
2229 pub name: String,
2230}
2231impl ItemName {
2232 pub fn instance_name(&self) -> Option<String> {
2251 if self.package.is_none() && self.interface.is_none() {
2252 return None;
2253 }
2254 let mut s = String::new();
2255 if let Some(crate::PackageName {
2256 namespace, name, ..
2257 }) = &self.package
2258 {
2259 s.push_str(&format!("{namespace}:{name}/"));
2260 }
2261 if let Some(name) = &self.interface {
2262 s.push_str(&format!("{name}"));
2263 }
2264 if let Some(crate::PackageName {
2265 version: Some(version),
2266 ..
2267 }) = &self.package
2268 {
2269 s.push_str(&format!("@{version}"));
2270 }
2271 Some(s)
2272 }
2273}
2274impl core::str::FromStr for ItemName {
2275 type Err = anyhow::Error;
2276 fn from_str(s: &str) -> anyhow::Result<ItemName> {
2277 let mut tokens = Tokenizer::new(s, 0)?;
2278
2279 let id = parse_id(&mut tokens)?;
2280 let (package, name) = if tokens.eat(Token::Colon)? {
2281 let name = parse_id(&mut tokens)?;
2282 tokens.expect(Token::Slash)?;
2283 (Some((id, name)), parse_id(&mut tokens)?)
2284 } else {
2285 (None, id)
2286 };
2287 let interface;
2288 let name = if tokens.eat(Token::Period)? {
2289 interface = Some(name.name.to_string());
2290 parse_id(&mut tokens)?
2291 } else {
2292 interface = None;
2293 name
2294 };
2295
2296 let package = package
2297 .map(|(namespace, name)| -> anyhow::Result<crate::PackageName> {
2298 let version = parse_opt_version(&mut tokens)?;
2299 Ok(PackageName {
2300 docs: Docs::default(),
2301 span: Span::new(
2302 namespace.span.start(),
2303 version
2304 .as_ref()
2305 .map(|(s, _)| s.end())
2306 .unwrap_or(name.span.end()),
2307 ),
2308 namespace,
2309 name,
2310 version,
2311 }
2312 .package_name())
2313 })
2314 .transpose()?;
2315
2316 if tokens.next()?.is_some() {
2317 anyhow::bail!("trailing tokens in item name specifier");
2318 }
2319 Ok(ItemName {
2320 package,
2321 interface,
2322 name: name.name.to_string(),
2323 })
2324 }
2325}
2326impl core::convert::TryFrom<String> for ItemName {
2327 type Error = anyhow::Error;
2328 fn try_from(s: String) -> anyhow::Result<ItemName> {
2329 s.parse()
2330 }
2331}
2332impl fmt::Display for ItemName {
2333 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2334 if let Some(crate::PackageName {
2335 namespace, name, ..
2336 }) = &self.package
2337 {
2338 write!(f, "{namespace}:{name}/")?;
2339 }
2340 if let Some(int) = &self.interface {
2341 write!(f, "{int}.")?;
2342 }
2343 write!(f, "{}", self.name)?;
2344 if let Some(crate::PackageName {
2345 version: Some(version),
2346 ..
2347 }) = &self.package
2348 {
2349 write!(f, "@{version}")?;
2350 }
2351 Ok(())
2352 }
2353}
2354impl From<ItemName> for String {
2355 fn from(m: ItemName) -> String {
2356 m.to_string()
2357 }
2358}
2359
2360#[cfg(test)]
2361mod item_name_test {
2362 use super::{ItemName, Version};
2363 use crate::PackageName;
2364 use alloc::borrow::ToOwned;
2365
2366 fn assert_round_trip(s: &str) {
2367 use alloc::string::ToString;
2368 let i = s.parse::<ItemName>().unwrap();
2369 assert_eq!(i.to_string(), s);
2370 }
2371
2372 #[test]
2373 fn bare() {
2374 assert_eq!(
2375 "bare-kebab-name".parse::<ItemName>().unwrap(),
2376 ItemName {
2377 package: None,
2378 interface: None,
2379 name: "bare-kebab-name".to_owned()
2380 }
2381 );
2382 assert_round_trip("bare-kebab-name");
2383 assert!("bare-kebab-name@0.1.0".parse::<ItemName>().is_err());
2385 }
2386 #[test]
2387 fn in_interface() {
2388 assert_eq!(
2389 "foo.bar".parse::<ItemName>().unwrap(),
2390 ItemName {
2391 package: None,
2392 interface: Some("foo".to_owned()),
2393 name: "bar".to_owned()
2394 }
2395 );
2396 assert_round_trip("foo.bar");
2397 assert!("foo.bar@0.1.0".parse::<ItemName>().is_err());
2399 }
2400 #[test]
2401 fn in_package() {
2402 assert_eq!(
2403 "foo:bar/baz.bat".parse::<ItemName>().unwrap(),
2404 ItemName {
2405 package: Some(PackageName {
2406 namespace: "foo".to_owned(),
2407 name: "bar".to_owned(),
2408 version: None
2409 }),
2410 interface: Some("baz".to_owned()),
2411 name: "bat".to_owned()
2412 }
2413 );
2414 assert_round_trip("foo:bar/baz.bat");
2415 assert_eq!(
2416 "foo:bar/baz.bat@0.1.0".parse::<ItemName>().unwrap(),
2417 ItemName {
2418 package: Some(PackageName {
2419 namespace: "foo".to_owned(),
2420 name: "bar".to_owned(),
2421 version: Some(Version::parse("0.1.0").unwrap()),
2422 }),
2423 interface: Some("baz".to_owned()),
2424 name: "bat".to_owned()
2425 }
2426 );
2427 assert_round_trip("foo:bar/baz.bat@0.1.0");
2428 assert_eq!(
2429 "foo:bar/baz".parse::<ItemName>().unwrap(),
2430 ItemName {
2431 package: Some(PackageName {
2432 namespace: "foo".to_owned(),
2433 name: "bar".to_owned(),
2434 version: None
2435 }),
2436 interface: None,
2437 name: "baz".to_owned()
2438 }
2439 );
2440 assert_round_trip("foo:bar/baz@0.1.0");
2441 assert_eq!(
2442 "foo:bar/baz@0.1.0".parse::<ItemName>().unwrap(),
2443 ItemName {
2444 package: Some(PackageName {
2445 namespace: "foo".to_owned(),
2446 name: "bar".to_owned(),
2447 version: Some(Version::parse("0.1.0").unwrap()),
2448 }),
2449 interface: None,
2450 name: "baz".to_owned()
2451 }
2452 );
2453 }
2454}