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 tokens.expect(Token::World)?;
372 let name = parse_id(tokens)?;
373 let items = Self::parse_items(tokens)?;
374 Ok(World {
375 docs,
376 attributes,
377 name,
378 items,
379 })
380 }
381
382 fn parse_items(tokens: &mut Tokenizer<'a>) -> ParseResult<Vec<WorldItem<'a>>> {
383 tokens.expect(Token::LeftBrace)?;
384 let mut items = Vec::new();
385 loop {
386 let docs = parse_docs(tokens)?;
387 if tokens.eat(Token::RightBrace)? {
388 break;
389 }
390 let attributes = Attribute::parse_list(tokens)?;
391 items.push(WorldItem::parse(tokens, docs, attributes)?);
392 }
393 Ok(items)
394 }
395}
396
397enum WorldItem<'a> {
398 Import(Import<'a>),
399 Export(Export<'a>),
400 Use(Use<'a>),
401 Type(TypeDef<'a>),
402 Include(Include<'a>),
403}
404
405impl<'a> WorldItem<'a> {
406 fn parse(
407 tokens: &mut Tokenizer<'a>,
408 docs: Docs<'a>,
409 attributes: Vec<Attribute<'a>>,
410 ) -> ParseResult<WorldItem<'a>> {
411 match tokens.clone().next()? {
412 Some((_span, Token::Import)) => {
413 Import::parse(tokens, docs, attributes).map(WorldItem::Import)
414 }
415 Some((_span, Token::Export)) => {
416 Export::parse(tokens, docs, attributes).map(WorldItem::Export)
417 }
418 Some((_span, Token::Use)) => Use::parse(tokens, attributes).map(WorldItem::Use),
419 Some((_span, Token::Type)) => {
420 TypeDef::parse(tokens, docs, attributes).map(WorldItem::Type)
421 }
422 Some((_span, Token::Flags)) => {
423 TypeDef::parse_flags(tokens, docs, attributes).map(WorldItem::Type)
424 }
425 Some((_span, Token::Resource)) => {
426 TypeDef::parse_resource(tokens, docs, attributes).map(WorldItem::Type)
427 }
428 Some((_span, Token::Record)) => {
429 TypeDef::parse_record(tokens, docs, attributes).map(WorldItem::Type)
430 }
431 Some((_span, Token::Variant)) => {
432 TypeDef::parse_variant(tokens, docs, attributes).map(WorldItem::Type)
433 }
434 Some((_span, Token::Enum)) => {
435 TypeDef::parse_enum(tokens, docs, attributes).map(WorldItem::Type)
436 }
437 Some((_span, Token::Include)) => {
438 Include::parse(tokens, attributes).map(WorldItem::Include)
439 }
440 other => Err(err_expected(
441 tokens,
442 "`import`, `export`, `include`, `use`, or type definition",
443 other,
444 )
445 .into()),
446 }
447 }
448}
449
450struct Import<'a> {
451 docs: Docs<'a>,
452 attributes: Vec<Attribute<'a>>,
453 kind: ExternKind<'a>,
454}
455
456impl<'a> Import<'a> {
457 fn parse(
458 tokens: &mut Tokenizer<'a>,
459 docs: Docs<'a>,
460 attributes: Vec<Attribute<'a>>,
461 ) -> ParseResult<Import<'a>> {
462 tokens.expect(Token::Import)?;
463 let kind = ExternKind::parse(tokens)?;
464 Ok(Import {
465 docs,
466 attributes,
467 kind,
468 })
469 }
470}
471
472struct Export<'a> {
473 docs: Docs<'a>,
474 attributes: Vec<Attribute<'a>>,
475 kind: ExternKind<'a>,
476}
477
478impl<'a> Export<'a> {
479 fn parse(
480 tokens: &mut Tokenizer<'a>,
481 docs: Docs<'a>,
482 attributes: Vec<Attribute<'a>>,
483 ) -> ParseResult<Export<'a>> {
484 tokens.expect(Token::Export)?;
485 let kind = ExternKind::parse(tokens)?;
486 Ok(Export {
487 docs,
488 attributes,
489 kind,
490 })
491 }
492}
493
494enum ExternKind<'a> {
495 Interface(Id<'a>, Vec<InterfaceItem<'a>>),
496 Path(UsePath<'a>),
497 Func(Id<'a>, Func<'a>),
498 NamedPath(Id<'a>, UsePath<'a>),
500}
501
502impl<'a> ExternKind<'a> {
503 fn parse(tokens: &mut Tokenizer<'a>) -> ParseResult<ExternKind<'a>> {
504 let mut clone = tokens.clone();
513 let id = parse_id(&mut clone)?;
514 if clone.eat(Token::Colon)? {
515 if clone.clone().eat(Token::Func)?
518 || clone.clone().eat(Token::Async)?
519 || eat_accessor_token(&mut clone.clone())?.is_some()
520 {
521 *tokens = clone;
522 let ret = ExternKind::Func(id, Func::parse(tokens)?);
523 tokens.expect_semicolon()?;
524 return Ok(ret);
525 }
526
527 if clone.eat(Token::Interface)? {
529 *tokens = clone;
530 return Ok(ExternKind::Interface(id, Interface::parse_items(tokens)?));
531 }
532
533 let mut peek = clone.clone();
544 let is_qualified_path =
545 parse_id(&mut peek).is_ok() && peek.clone().eat(Token::Slash).unwrap_or(false);
546 if !is_qualified_path {
547 *tokens = clone;
548 let path = UsePath::parse(tokens)?;
549 tokens.expect_semicolon()?;
550 return Ok(ExternKind::NamedPath(id, path));
551 }
552 }
553
554 let ret = ExternKind::Path(UsePath::parse(tokens)?);
558 tokens.expect_semicolon()?;
559 Ok(ret)
560 }
561
562 fn span(&self) -> Span {
563 match self {
564 ExternKind::Interface(id, _) => id.span,
565 ExternKind::Path(UsePath::Id(id)) => id.span,
566 ExternKind::Path(UsePath::Package { name, .. }) => name.span,
567 ExternKind::Func(id, _) => id.span,
568 ExternKind::NamedPath(id, _) => id.span,
569 }
570 }
571}
572
573struct Interface<'a> {
574 docs: Docs<'a>,
575 attributes: Vec<Attribute<'a>>,
576 name: Id<'a>,
577 items: Vec<InterfaceItem<'a>>,
578}
579
580impl<'a> Interface<'a> {
581 fn parse(
582 tokens: &mut Tokenizer<'a>,
583 docs: Docs<'a>,
584 attributes: Vec<Attribute<'a>>,
585 ) -> ParseResult<Self> {
586 tokens.expect(Token::Interface)?;
587 let name = parse_id(tokens)?;
588 let items = Self::parse_items(tokens)?;
589 Ok(Interface {
590 docs,
591 attributes,
592 name,
593 items,
594 })
595 }
596
597 pub(super) fn parse_items(tokens: &mut Tokenizer<'a>) -> ParseResult<Vec<InterfaceItem<'a>>> {
598 tokens.expect(Token::LeftBrace)?;
599 let mut items = Vec::new();
600 loop {
601 let docs = parse_docs(tokens)?;
602 if tokens.eat(Token::RightBrace)? {
603 break;
604 }
605 let attributes = Attribute::parse_list(tokens)?;
606 items.push(InterfaceItem::parse(tokens, docs, attributes)?);
607 }
608 Ok(items)
609 }
610}
611
612#[derive(Debug)]
613pub enum WorldOrInterface {
614 World,
615 Interface,
616 Unknown,
617}
618
619enum InterfaceItem<'a> {
620 TypeDef(TypeDef<'a>),
621 Func(NamedFunc<'a>),
622 Use(Use<'a>),
623}
624
625struct Use<'a> {
626 attributes: Vec<Attribute<'a>>,
627 from: UsePath<'a>,
628 names: Vec<UseName<'a>>,
629}
630
631#[derive(Debug)]
632enum UsePath<'a> {
633 Id(Id<'a>),
634 Package { id: PackageName<'a>, name: Id<'a> },
635}
636
637impl<'a> UsePath<'a> {
638 fn parse(tokens: &mut Tokenizer<'a>) -> ParseResult<Self> {
639 let id = parse_id(tokens)?;
640 if tokens.eat(Token::Colon)? {
641 let namespace = id;
643 let pkg_name = parse_id(tokens)?;
644 tokens.expect(Token::Slash)?;
645 let name = parse_id(tokens)?;
646 let version = parse_opt_version(tokens)?;
647 Ok(UsePath::Package {
648 id: PackageName {
649 docs: Default::default(),
650 span: Span::new(namespace.span.start(), pkg_name.span.end()),
651 namespace,
652 name: pkg_name,
653 version,
654 },
655 name,
656 })
657 } else {
658 Ok(UsePath::Id(id))
660 }
661 }
662
663 fn name(&self) -> &Id<'a> {
664 match self {
665 UsePath::Id(id) => id,
666 UsePath::Package { name, .. } => name,
667 }
668 }
669}
670
671struct UseName<'a> {
672 name: Id<'a>,
673 as_: Option<Id<'a>>,
674}
675
676impl<'a> Use<'a> {
677 fn parse(tokens: &mut Tokenizer<'a>, attributes: Vec<Attribute<'a>>) -> ParseResult<Self> {
678 tokens.expect(Token::Use)?;
679 let from = UsePath::parse(tokens)?;
680 tokens.expect(Token::Period)?;
681 tokens.expect(Token::LeftBrace)?;
682
683 let mut names = Vec::new();
684 while !tokens.eat(Token::RightBrace)? {
685 let mut name = UseName {
686 name: parse_id(tokens)?,
687 as_: None,
688 };
689 if tokens.eat(Token::As)? {
690 name.as_ = Some(parse_id(tokens)?);
691 }
692 names.push(name);
693 if !tokens.eat(Token::Comma)? {
694 tokens.expect(Token::RightBrace)?;
695 break;
696 }
697 }
698 tokens.expect_semicolon()?;
699 Ok(Use {
700 attributes,
701 from,
702 names,
703 })
704 }
705}
706
707struct Include<'a> {
708 from: UsePath<'a>,
709 attributes: Vec<Attribute<'a>>,
710 names: Vec<IncludeName<'a>>,
711}
712
713struct IncludeName<'a> {
714 name: Id<'a>,
715 as_: Id<'a>,
716}
717
718impl<'a> Include<'a> {
719 fn parse(tokens: &mut Tokenizer<'a>, attributes: Vec<Attribute<'a>>) -> ParseResult<Self> {
720 tokens.expect(Token::Include)?;
721 let from = UsePath::parse(tokens)?;
722
723 let names = if tokens.eat(Token::With)? {
724 parse_list(
725 tokens,
726 Token::LeftBrace,
727 Token::RightBrace,
728 |_docs, tokens| {
729 let name = parse_id(tokens)?;
730 tokens.expect(Token::As)?;
731 let as_ = parse_id(tokens)?;
732 Ok(IncludeName { name, as_ })
733 },
734 )?
735 } else {
736 tokens.expect_semicolon()?;
737 Vec::new()
738 };
739
740 Ok(Include {
741 attributes,
742 from,
743 names,
744 })
745 }
746}
747
748#[derive(Debug, Clone)]
749pub struct Id<'a> {
750 name: &'a str,
751 span: Span,
752}
753
754impl<'a> From<&'a str> for Id<'a> {
755 fn from(s: &'a str) -> Id<'a> {
756 Id {
757 name: s.into(),
758 span: Default::default(),
759 }
760 }
761}
762
763#[derive(Debug, Clone)]
764pub struct Docs<'a> {
765 docs: Vec<Cow<'a, str>>,
766 span: Span,
767}
768
769impl<'a> Default for Docs<'a> {
770 fn default() -> Self {
771 Self {
772 docs: Default::default(),
773 span: Default::default(),
774 }
775 }
776}
777
778struct TypeDef<'a> {
779 docs: Docs<'a>,
780 attributes: Vec<Attribute<'a>>,
781 name: Id<'a>,
782 ty: Type<'a>,
783}
784
785enum Type<'a> {
786 Bool(Span),
787 U8(Span),
788 U16(Span),
789 U32(Span),
790 U64(Span),
791 S8(Span),
792 S16(Span),
793 S32(Span),
794 S64(Span),
795 F32(Span),
796 F64(Span),
797 Char(Span),
798 String(Span),
799 Name(Id<'a>),
800 List(List<'a>),
801 Map(Map<'a>),
802 FixedLengthList(FixedLengthList<'a>),
803 Handle(Handle<'a>),
804 Resource(Resource<'a>),
805 Record(Record<'a>),
806 Flags(Flags<'a>),
807 Variant(Variant<'a>),
808 Tuple(Tuple<'a>),
809 Enum(Enum<'a>),
810 Option(Option_<'a>),
811 Result(Result_<'a>),
812 Future(Future<'a>),
813 Stream(Stream<'a>),
814 ErrorContext(Span),
815}
816
817enum Handle<'a> {
818 Own { resource: Id<'a> },
819 Borrow { resource: Id<'a> },
820}
821
822impl Handle<'_> {
823 fn span(&self) -> Span {
824 match self {
825 Handle::Own { resource } | Handle::Borrow { resource } => resource.span,
826 }
827 }
828}
829
830struct Resource<'a> {
831 span: Span,
832 funcs: Vec<ResourceFunc<'a>>,
833}
834
835enum ResourceFunc<'a> {
836 Method(NamedFunc<'a>),
837 Static(NamedFunc<'a>),
838 Constructor(NamedFunc<'a>),
839}
840
841impl<'a> ResourceFunc<'a> {
842 fn parse(
843 docs: Docs<'a>,
844 attributes: Vec<Attribute<'a>>,
845 tokens: &mut Tokenizer<'a>,
846 ) -> ParseResult<Self> {
847 match tokens.clone().next()? {
848 Some((span, Token::Constructor)) => {
849 tokens.expect(Token::Constructor)?;
850 tokens.expect(Token::LeftParen)?;
851 let params = parse_list_trailer(tokens, Token::RightParen, |_docs, tokens| {
852 let name = parse_id(tokens)?;
853 tokens.expect(Token::Colon)?;
854 let ty = Type::parse(tokens)?;
855 Ok((name, ty))
856 })?;
857 let result = if tokens.eat(Token::RArrow)? {
858 let ty = Type::parse(tokens)?;
859 Some(ty)
860 } else {
861 None
862 };
863 tokens.expect_semicolon()?;
864 Ok(ResourceFunc::Constructor(NamedFunc {
865 docs,
866 attributes,
867 name: Id {
868 span,
869 name: "constructor",
870 },
871 func: Func {
872 span,
873 async_: false,
874 accessor: None,
875 params,
876 result,
877 },
878 }))
879 }
880 Some((_span, Token::Id | Token::ExplicitId)) => {
881 let name = parse_id(tokens)?;
882 tokens.expect(Token::Colon)?;
883 let ctor = if tokens.eat(Token::Static)? {
884 ResourceFunc::Static
885 } else {
886 ResourceFunc::Method
887 };
888 let func = Func::parse(tokens)?;
889 tokens.expect_semicolon()?;
890 Ok(ctor(NamedFunc {
891 docs,
892 attributes,
893 name,
894 func,
895 }))
896 }
897 other => Err(err_expected(tokens, "`constructor` or identifier", other).into()),
898 }
899 }
900
901 fn named_func(&self) -> &NamedFunc<'a> {
902 use ResourceFunc::*;
903 match self {
904 Method(f) | Static(f) | Constructor(f) => f,
905 }
906 }
907}
908
909struct Record<'a> {
910 span: Span,
911 fields: Vec<Field<'a>>,
912}
913
914struct Field<'a> {
915 docs: Docs<'a>,
916 name: Id<'a>,
917 ty: Type<'a>,
918}
919
920struct Flags<'a> {
921 span: Span,
922 flags: Vec<Flag<'a>>,
923}
924
925struct Flag<'a> {
926 docs: Docs<'a>,
927 name: Id<'a>,
928}
929
930struct Variant<'a> {
931 span: Span,
932 cases: Vec<Case<'a>>,
933}
934
935struct Case<'a> {
936 docs: Docs<'a>,
937 name: Id<'a>,
938 ty: Option<Type<'a>>,
939}
940
941struct Enum<'a> {
942 span: Span,
943 cases: Vec<EnumCase<'a>>,
944}
945
946struct EnumCase<'a> {
947 docs: Docs<'a>,
948 name: Id<'a>,
949}
950
951struct Option_<'a> {
952 span: Span,
953 ty: Box<Type<'a>>,
954}
955
956struct List<'a> {
957 span: Span,
958 ty: Box<Type<'a>>,
959}
960
961struct Map<'a> {
962 span: Span,
963 key: Box<Type<'a>>,
964 value: Box<Type<'a>>,
965}
966
967struct FixedLengthList<'a> {
968 span: Span,
969 ty: Box<Type<'a>>,
970 size: u32,
971}
972
973struct Future<'a> {
974 span: Span,
975 ty: Option<Box<Type<'a>>>,
976}
977
978struct Tuple<'a> {
979 span: Span,
980 types: Vec<Type<'a>>,
981}
982
983struct Result_<'a> {
984 span: Span,
985 ok: Option<Box<Type<'a>>>,
986 err: Option<Box<Type<'a>>>,
987}
988
989struct Stream<'a> {
990 span: Span,
991 ty: Option<Box<Type<'a>>>,
992}
993
994struct NamedFunc<'a> {
995 docs: Docs<'a>,
996 attributes: Vec<Attribute<'a>>,
997 name: Id<'a>,
998 func: Func<'a>,
999}
1000
1001type ParamList<'a> = Vec<(Id<'a>, Type<'a>)>;
1002
1003struct Func<'a> {
1004 span: Span,
1005 async_: bool,
1006 accessor: Option<AccessorKind>,
1007 params: ParamList<'a>,
1008 result: Option<Type<'a>>,
1009}
1010
1011impl<'a> Func<'a> {
1012 fn parse(tokens: &mut Tokenizer<'a>) -> ParseResult<Func<'a>> {
1013 fn parse_params<'a>(
1014 tokens: &mut Tokenizer<'a>,
1015 left_paren: bool,
1016 ) -> ParseResult<ParamList<'a>> {
1017 if left_paren {
1018 tokens.expect(Token::LeftParen)?;
1019 };
1020 parse_list_trailer(tokens, Token::RightParen, |_docs, tokens| {
1021 let name = parse_id(tokens)?;
1022 tokens.expect(Token::Colon)?;
1023 let ty = Type::parse(tokens)?;
1024 Ok((name, ty))
1025 })
1026 }
1027
1028 let async_ = tokens.eat(Token::Async)?;
1029 let accessor = if async_ {
1030 None
1031 } else {
1032 eat_accessor_token(tokens)?
1033 };
1034 let (span, accessor) = match accessor {
1035 Some((span, accessor)) => (span, Some(accessor)),
1036 None => (tokens.expect(Token::Func)?, None),
1037 };
1038 let params = parse_params(tokens, true)?;
1039 let result = if tokens.eat(Token::RArrow)? {
1040 let ty = Type::parse(tokens)?;
1041 Some(ty)
1042 } else {
1043 None
1044 };
1045 Ok(Func {
1046 span,
1047 async_,
1048 accessor,
1049 params,
1050 result,
1051 })
1052 }
1053}
1054
1055fn eat_accessor_token(tokens: &mut Tokenizer<'_>) -> ParseResult<Option<(Span, AccessorKind)>> {
1056 let mut clone = tokens.clone();
1057 let (span, accessor) = match clone.next()? {
1058 Some((span, Token::Id)) => match clone.parse_id(span)? {
1059 "get" => (span, AccessorKind::Getter),
1060 "set" => (span, AccessorKind::Setter),
1061 _ => return Ok(None),
1062 },
1063 _ => return Ok(None),
1064 };
1065 if !clone.eat(Token::LeftParen)? {
1066 return Ok(None);
1067 }
1068 tokens.next()?; Ok(Some((span, accessor)))
1070}
1071
1072impl<'a> InterfaceItem<'a> {
1073 fn parse(
1074 tokens: &mut Tokenizer<'a>,
1075 docs: Docs<'a>,
1076 attributes: Vec<Attribute<'a>>,
1077 ) -> ParseResult<InterfaceItem<'a>> {
1078 match tokens.clone().next()? {
1079 Some((_span, Token::Type)) => {
1080 TypeDef::parse(tokens, docs, attributes).map(InterfaceItem::TypeDef)
1081 }
1082 Some((_span, Token::Flags)) => {
1083 TypeDef::parse_flags(tokens, docs, attributes).map(InterfaceItem::TypeDef)
1084 }
1085 Some((_span, Token::Enum)) => {
1086 TypeDef::parse_enum(tokens, docs, attributes).map(InterfaceItem::TypeDef)
1087 }
1088 Some((_span, Token::Variant)) => {
1089 TypeDef::parse_variant(tokens, docs, attributes).map(InterfaceItem::TypeDef)
1090 }
1091 Some((_span, Token::Resource)) => {
1092 TypeDef::parse_resource(tokens, docs, attributes).map(InterfaceItem::TypeDef)
1093 }
1094 Some((_span, Token::Record)) => {
1095 TypeDef::parse_record(tokens, docs, attributes).map(InterfaceItem::TypeDef)
1096 }
1097 Some((_span, Token::Id)) | Some((_span, Token::ExplicitId)) => {
1098 NamedFunc::parse(tokens, docs, attributes).map(InterfaceItem::Func)
1099 }
1100 Some((_span, Token::Use)) => Use::parse(tokens, attributes).map(InterfaceItem::Use),
1101 other => Err(err_expected(tokens, "`type`, `resource` or `func`", other).into()),
1102 }
1103 }
1104}
1105
1106impl<'a> TypeDef<'a> {
1107 fn parse(
1108 tokens: &mut Tokenizer<'a>,
1109 docs: Docs<'a>,
1110 attributes: Vec<Attribute<'a>>,
1111 ) -> ParseResult<Self> {
1112 tokens.expect(Token::Type)?;
1113 let name = parse_id(tokens)?;
1114 tokens.expect(Token::Equals)?;
1115 let ty = Type::parse(tokens)?;
1116 tokens.expect_semicolon()?;
1117 Ok(TypeDef {
1118 docs,
1119 attributes,
1120 name,
1121 ty,
1122 })
1123 }
1124
1125 fn parse_flags(
1126 tokens: &mut Tokenizer<'a>,
1127 docs: Docs<'a>,
1128 attributes: Vec<Attribute<'a>>,
1129 ) -> ParseResult<Self> {
1130 tokens.expect(Token::Flags)?;
1131 let name = parse_id(tokens)?;
1132 let ty = Type::Flags(Flags {
1133 span: name.span,
1134 flags: parse_list(
1135 tokens,
1136 Token::LeftBrace,
1137 Token::RightBrace,
1138 |docs, tokens| {
1139 let name = parse_id(tokens)?;
1140 Ok(Flag { docs, name })
1141 },
1142 )?,
1143 });
1144 Ok(TypeDef {
1145 docs,
1146 attributes,
1147 name,
1148 ty,
1149 })
1150 }
1151
1152 fn parse_resource(
1153 tokens: &mut Tokenizer<'a>,
1154 docs: Docs<'a>,
1155 attributes: Vec<Attribute<'a>>,
1156 ) -> ParseResult<Self> {
1157 tokens.expect(Token::Resource)?;
1158 let name = parse_id(tokens)?;
1159 let mut funcs = Vec::new();
1160 if tokens.eat(Token::LeftBrace)? {
1161 while !tokens.eat(Token::RightBrace)? {
1162 let docs = parse_docs(tokens)?;
1163 let attributes = Attribute::parse_list(tokens)?;
1164 funcs.push(ResourceFunc::parse(docs, attributes, tokens)?);
1165 }
1166 } else {
1167 tokens.expect_semicolon()?;
1168 }
1169 let ty = Type::Resource(Resource {
1170 span: name.span,
1171 funcs,
1172 });
1173 Ok(TypeDef {
1174 docs,
1175 attributes,
1176 name,
1177 ty,
1178 })
1179 }
1180
1181 fn parse_record(
1182 tokens: &mut Tokenizer<'a>,
1183 docs: Docs<'a>,
1184 attributes: Vec<Attribute<'a>>,
1185 ) -> ParseResult<Self> {
1186 tokens.expect(Token::Record)?;
1187 let name = parse_id(tokens)?;
1188 let ty = Type::Record(Record {
1189 span: name.span,
1190 fields: parse_list(
1191 tokens,
1192 Token::LeftBrace,
1193 Token::RightBrace,
1194 |docs, tokens| {
1195 let name = parse_id(tokens)?;
1196 tokens.expect(Token::Colon)?;
1197 let ty = Type::parse(tokens)?;
1198 Ok(Field { docs, name, ty })
1199 },
1200 )?,
1201 });
1202 Ok(TypeDef {
1203 docs,
1204 attributes,
1205 name,
1206 ty,
1207 })
1208 }
1209
1210 fn parse_variant(
1211 tokens: &mut Tokenizer<'a>,
1212 docs: Docs<'a>,
1213 attributes: Vec<Attribute<'a>>,
1214 ) -> ParseResult<Self> {
1215 tokens.expect(Token::Variant)?;
1216 let name = parse_id(tokens)?;
1217 let ty = Type::Variant(Variant {
1218 span: name.span,
1219 cases: parse_list(
1220 tokens,
1221 Token::LeftBrace,
1222 Token::RightBrace,
1223 |docs, tokens| {
1224 let name = parse_id(tokens)?;
1225 let ty = if tokens.eat(Token::LeftParen)? {
1226 let ty = Type::parse(tokens)?;
1227 tokens.expect(Token::RightParen)?;
1228 Some(ty)
1229 } else {
1230 None
1231 };
1232 Ok(Case { docs, name, ty })
1233 },
1234 )?,
1235 });
1236 Ok(TypeDef {
1237 docs,
1238 attributes,
1239 name,
1240 ty,
1241 })
1242 }
1243
1244 fn parse_enum(
1245 tokens: &mut Tokenizer<'a>,
1246 docs: Docs<'a>,
1247 attributes: Vec<Attribute<'a>>,
1248 ) -> ParseResult<Self> {
1249 tokens.expect(Token::Enum)?;
1250 let name = parse_id(tokens)?;
1251 let ty = Type::Enum(Enum {
1252 span: name.span,
1253 cases: parse_list(
1254 tokens,
1255 Token::LeftBrace,
1256 Token::RightBrace,
1257 |docs, tokens| {
1258 let name = parse_id(tokens)?;
1259 Ok(EnumCase { docs, name })
1260 },
1261 )?,
1262 });
1263 Ok(TypeDef {
1264 docs,
1265 attributes,
1266 name,
1267 ty,
1268 })
1269 }
1270}
1271
1272impl<'a> NamedFunc<'a> {
1273 fn parse(
1274 tokens: &mut Tokenizer<'a>,
1275 docs: Docs<'a>,
1276 attributes: Vec<Attribute<'a>>,
1277 ) -> ParseResult<Self> {
1278 let name = parse_id(tokens)?;
1279 tokens.expect(Token::Colon)?;
1280 let func = Func::parse(tokens)?;
1281 tokens.expect_semicolon()?;
1282 Ok(NamedFunc {
1283 docs,
1284 attributes,
1285 name,
1286 func,
1287 })
1288 }
1289}
1290
1291fn parse_id<'a>(tokens: &mut Tokenizer<'a>) -> ParseResult<Id<'a>> {
1292 match tokens.next()? {
1293 Some((span, Token::Id)) => Ok(Id {
1294 name: tokens.parse_id(span)?,
1295 span,
1296 }),
1297 Some((span, Token::ExplicitId)) => Ok(Id {
1298 name: tokens.parse_explicit_id(span)?,
1299 span,
1300 }),
1301 other => Err(err_expected(tokens, "an identifier or string", other)),
1302 }
1303}
1304
1305fn parse_opt_version(tokens: &mut Tokenizer<'_>) -> ParseResult<Option<(Span, Version)>> {
1306 if tokens.eat(Token::At)? {
1307 parse_version(tokens).map(Some)
1308 } else {
1309 Ok(None)
1310 }
1311}
1312
1313fn parse_version(tokens: &mut Tokenizer<'_>) -> ParseResult<(Span, Version)> {
1314 let start = tokens.expect(Token::Integer)?.start();
1315 tokens.expect(Token::Period)?;
1316 tokens.expect(Token::Integer)?;
1317 tokens.expect(Token::Period)?;
1318 let end = tokens.expect(Token::Integer)?.end();
1319 let mut span = Span::new(start, end);
1320 eat_ids(tokens, Token::Minus, &mut span)?;
1321 eat_ids(tokens, Token::Plus, &mut span)?;
1322 let string = tokens.get_span(span);
1323 let version =
1324 Version::parse(string).map_err(|e| ParseError::new_syntax(span, e.to_string()))?;
1325 return Ok((span, version));
1326
1327 fn eat_ids(
1381 tokens: &mut Tokenizer<'_>,
1382 prefix: Token,
1383 end: &mut Span,
1384 ) -> Result<(), lex::Error> {
1385 if !tokens.eat(prefix)? {
1386 return Ok(());
1387 }
1388 loop {
1389 let mut clone = tokens.clone();
1390 match clone.next()? {
1391 Some((span, Token::Id | Token::Integer | Token::Minus)) => {
1392 end.set_end(span.end());
1393 *tokens = clone;
1394 }
1395 Some((_span, Token::Period)) => match clone.next()? {
1396 Some((span, Token::Id | Token::Integer | Token::Minus)) => {
1397 end.set_end(span.end());
1398 *tokens = clone;
1399 }
1400 _ => break Ok(()),
1401 },
1402 _ => break Ok(()),
1403 }
1404 }
1405 }
1406}
1407
1408fn parse_docs<'a>(tokens: &mut Tokenizer<'a>) -> Result<Docs<'a>, lex::Error> {
1409 let mut docs = Docs::default();
1410 let mut clone = tokens.clone();
1411 let mut started = false;
1412 while let Some((span, token)) = clone.next_raw()? {
1413 match token {
1414 Token::Whitespace => {}
1415 Token::Comment => {
1416 let comment = tokens.get_span(span);
1417 if !started {
1418 docs.span.set_start(span.start());
1419 started = true;
1420 }
1421 let trailing_ws = comment
1422 .bytes()
1423 .rev()
1424 .take_while(|ch| ch.is_ascii_whitespace())
1425 .count();
1426 docs.span.set_end(span.end() - (trailing_ws as u32));
1427 docs.docs.push(comment.into());
1428 }
1429 _ => break,
1430 };
1431 *tokens = clone.clone();
1432 }
1433 Ok(docs)
1434}
1435
1436const MAX_TYPE_DEPTH: usize = 100;
1439
1440impl<'a> Type<'a> {
1441 fn parse(tokens: &mut Tokenizer<'a>) -> ParseResult<Self> {
1442 Type::parse_at_depth(tokens, 0)
1443 }
1444
1445 fn parse_at_depth(tokens: &mut Tokenizer<'a>, depth: usize) -> ParseResult<Self> {
1446 let token = tokens.next()?;
1447 if depth >= MAX_TYPE_DEPTH {
1448 let span = match token {
1449 Some((span, _)) => span,
1450 None => tokens.eof_span(),
1451 };
1452 return Err(ParseError::new_syntax(span, "type nesting too deep"));
1453 }
1454 match token {
1455 Some((span, Token::U8)) => Ok(Type::U8(span)),
1456 Some((span, Token::U16)) => Ok(Type::U16(span)),
1457 Some((span, Token::U32)) => Ok(Type::U32(span)),
1458 Some((span, Token::U64)) => Ok(Type::U64(span)),
1459 Some((span, Token::S8)) => Ok(Type::S8(span)),
1460 Some((span, Token::S16)) => Ok(Type::S16(span)),
1461 Some((span, Token::S32)) => Ok(Type::S32(span)),
1462 Some((span, Token::S64)) => Ok(Type::S64(span)),
1463 Some((span, Token::F32)) => Ok(Type::F32(span)),
1464 Some((span, Token::F64)) => Ok(Type::F64(span)),
1465 Some((span, Token::Char)) => Ok(Type::Char(span)),
1466
1467 Some((span, Token::Tuple)) => {
1469 let types = parse_list(
1470 tokens,
1471 Token::LessThan,
1472 Token::GreaterThan,
1473 |_docs, tokens| Type::parse_at_depth(tokens, depth + 1),
1474 )?;
1475 Ok(Type::Tuple(Tuple { span, types }))
1476 }
1477
1478 Some((span, Token::Bool)) => Ok(Type::Bool(span)),
1479 Some((span, Token::String_)) => Ok(Type::String(span)),
1480
1481 Some((span, Token::List)) => {
1484 tokens.expect(Token::LessThan)?;
1485 let ty = Type::parse_at_depth(tokens, depth + 1)?;
1486 let size = if tokens.eat(Token::Comma)? {
1487 let number = tokens.next()?;
1488 if let Some((span, Token::Integer)) = number {
1489 let size: u32 = tokens.get_span(span).parse().map_err(|e| {
1490 ParseError::new_syntax(span, format!("invalid list size: {e}"))
1491 })?;
1492 Some(size)
1493 } else {
1494 return Err(err_expected(tokens, "fixed-length", number).into());
1495 }
1496 } else {
1497 None
1498 };
1499 tokens.expect(Token::GreaterThan)?;
1500 if let Some(size) = size {
1501 Ok(Type::FixedLengthList(FixedLengthList {
1502 span,
1503 ty: Box::new(ty),
1504 size,
1505 }))
1506 } else {
1507 Ok(Type::List(List {
1508 span,
1509 ty: Box::new(ty),
1510 }))
1511 }
1512 }
1513
1514 Some((span, Token::Map)) => {
1516 tokens.expect(Token::LessThan)?;
1517 let key = Type::parse_at_depth(tokens, depth + 1)?;
1518 tokens.expect(Token::Comma)?;
1519 let value = Type::parse_at_depth(tokens, depth + 1)?;
1520 tokens.expect(Token::GreaterThan)?;
1521 Ok(Type::Map(Map {
1522 span,
1523 key: Box::new(key),
1524 value: Box::new(value),
1525 }))
1526 }
1527
1528 Some((span, Token::Option_)) => {
1530 tokens.expect(Token::LessThan)?;
1531 let ty = Type::parse_at_depth(tokens, depth + 1)?;
1532 tokens.expect(Token::GreaterThan)?;
1533 Ok(Type::Option(Option_ {
1534 span,
1535 ty: Box::new(ty),
1536 }))
1537 }
1538
1539 Some((span, Token::Result_)) => {
1544 let mut ok = None;
1545 let mut err = None;
1546
1547 if tokens.eat(Token::LessThan)? {
1548 if tokens.eat(Token::Underscore)? {
1549 tokens.expect(Token::Comma)?;
1550 err = Some(Box::new(Type::parse_at_depth(tokens, depth + 1)?));
1551 } else {
1552 ok = Some(Box::new(Type::parse_at_depth(tokens, depth + 1)?));
1553 if tokens.eat(Token::Comma)? {
1554 err = Some(Box::new(Type::parse_at_depth(tokens, depth + 1)?));
1555 }
1556 };
1557 tokens.expect(Token::GreaterThan)?;
1558 };
1559 Ok(Type::Result(Result_ { span, ok, err }))
1560 }
1561
1562 Some((span, Token::Future)) => {
1565 let mut ty = None;
1566
1567 if tokens.eat(Token::LessThan)? {
1568 ty = Some(Box::new(Type::parse_at_depth(tokens, depth + 1)?));
1569 tokens.expect(Token::GreaterThan)?;
1570 };
1571 Ok(Type::Future(Future { span, ty }))
1572 }
1573
1574 Some((span, Token::Stream)) => {
1577 let mut ty = None;
1578
1579 if tokens.eat(Token::LessThan)? {
1580 ty = Some(Box::new(Type::parse_at_depth(tokens, depth + 1)?));
1581 tokens.expect(Token::GreaterThan)?;
1582 };
1583 Ok(Type::Stream(Stream { span, ty }))
1584 }
1585
1586 Some((span, Token::ErrorContext)) => Ok(Type::ErrorContext(span)),
1588
1589 Some((_span, Token::Own)) => {
1591 tokens.expect(Token::LessThan)?;
1592 let resource = parse_id(tokens)?;
1593 tokens.expect(Token::GreaterThan)?;
1594 Ok(Type::Handle(Handle::Own { resource }))
1595 }
1596
1597 Some((_span, Token::Borrow)) => {
1599 tokens.expect(Token::LessThan)?;
1600 let resource = parse_id(tokens)?;
1601 tokens.expect(Token::GreaterThan)?;
1602 Ok(Type::Handle(Handle::Borrow { resource }))
1603 }
1604
1605 Some((span, Token::Id)) => Ok(Type::Name(Id {
1607 name: tokens.parse_id(span)?.into(),
1608 span,
1609 })),
1610 Some((span, Token::ExplicitId)) => Ok(Type::Name(Id {
1612 name: tokens.parse_explicit_id(span)?.into(),
1613 span,
1614 })),
1615
1616 other => Err(err_expected(tokens, "a type", other).into()),
1617 }
1618 }
1619
1620 fn span(&self) -> Span {
1621 match self {
1622 Type::Bool(span)
1623 | Type::U8(span)
1624 | Type::U16(span)
1625 | Type::U32(span)
1626 | Type::U64(span)
1627 | Type::S8(span)
1628 | Type::S16(span)
1629 | Type::S32(span)
1630 | Type::S64(span)
1631 | Type::F32(span)
1632 | Type::F64(span)
1633 | Type::Char(span)
1634 | Type::String(span)
1635 | Type::ErrorContext(span) => *span,
1636 Type::Name(id) => id.span,
1637 Type::List(l) => l.span,
1638 Type::Map(m) => m.span,
1639 Type::FixedLengthList(l) => l.span,
1640 Type::Handle(h) => h.span(),
1641 Type::Resource(r) => r.span,
1642 Type::Record(r) => r.span,
1643 Type::Flags(f) => f.span,
1644 Type::Variant(v) => v.span,
1645 Type::Tuple(t) => t.span,
1646 Type::Enum(e) => e.span,
1647 Type::Option(o) => o.span,
1648 Type::Result(r) => r.span,
1649 Type::Future(f) => f.span,
1650 Type::Stream(s) => s.span,
1651 }
1652 }
1653}
1654
1655fn parse_list<'a, T>(
1656 tokens: &mut Tokenizer<'a>,
1657 start: Token,
1658 end: Token,
1659 parse: impl FnMut(Docs<'a>, &mut Tokenizer<'a>) -> ParseResult<T>,
1660) -> ParseResult<Vec<T>> {
1661 tokens.expect(start)?;
1662 parse_list_trailer(tokens, end, parse)
1663}
1664
1665fn parse_list_trailer<'a, T>(
1666 tokens: &mut Tokenizer<'a>,
1667 end: Token,
1668 mut parse: impl FnMut(Docs<'a>, &mut Tokenizer<'a>) -> ParseResult<T>,
1669) -> ParseResult<Vec<T>> {
1670 let mut items = Vec::new();
1671 loop {
1672 let docs = parse_docs(tokens)?;
1674
1675 if tokens.eat(end)? {
1677 break;
1678 }
1679
1680 let item = parse(docs, tokens)?;
1681 items.push(item);
1682
1683 if !tokens.eat(Token::Comma)? {
1686 tokens.expect(end)?;
1687 break;
1688 }
1689 }
1690 Ok(items)
1691}
1692
1693fn err_expected(
1694 tokens: &Tokenizer<'_>,
1695 expected: &'static str,
1696 found: Option<(Span, Token)>,
1697) -> ParseError {
1698 match found {
1699 Some((span, token)) => ParseError::new_syntax(
1700 span,
1701 format!("expected {}, found {}", expected, token.describe()),
1702 ),
1703 None => {
1704 ParseError::new_syntax(tokens.eof_span(), format!("expected {expected}, found eof"))
1705 }
1706 }
1707}
1708
1709enum Attribute<'a> {
1710 Since { span: Span, version: Version },
1711 Unstable { span: Span, feature: Id<'a> },
1712 Deprecated { span: Span, version: Version },
1713 ExternalId { span: Span, id: String },
1714}
1715
1716impl<'a> Attribute<'a> {
1717 fn parse_list(tokens: &mut Tokenizer<'a>) -> ParseResult<Vec<Attribute<'a>>> {
1718 let mut ret = Vec::new();
1719 while tokens.eat(Token::At)? {
1720 let id = parse_id(tokens)?;
1721 let attr = match id.name {
1722 "since" => {
1723 tokens.expect(Token::LeftParen)?;
1724 eat_id(tokens, "version")?;
1725 tokens.expect(Token::Equals)?;
1726 let (_span, version) = parse_version(tokens)?;
1727 tokens.expect(Token::RightParen)?;
1728 Attribute::Since {
1729 span: id.span,
1730 version,
1731 }
1732 }
1733 "unstable" => {
1734 tokens.expect(Token::LeftParen)?;
1735 eat_id(tokens, "feature")?;
1736 tokens.expect(Token::Equals)?;
1737 let feature = parse_id(tokens)?;
1738 tokens.expect(Token::RightParen)?;
1739 Attribute::Unstable {
1740 span: id.span,
1741 feature,
1742 }
1743 }
1744 "deprecated" => {
1745 tokens.expect(Token::LeftParen)?;
1746 eat_id(tokens, "version")?;
1747 tokens.expect(Token::Equals)?;
1748 let (_span, version) = parse_version(tokens)?;
1749 tokens.expect(Token::RightParen)?;
1750 Attribute::Deprecated {
1751 span: id.span,
1752 version,
1753 }
1754 }
1755 "external-id" => {
1756 tokens.expect(Token::LeftParen)?;
1757 let span = tokens.expect(Token::StringLiteral)?;
1758 tokens.expect(Token::RightParen)?;
1759 Attribute::ExternalId {
1760 span: id.span,
1761 id: tokens.string_literal(span)?,
1762 }
1763 }
1764 other => {
1765 return Err(ParseError::new_syntax(
1766 id.span,
1767 format!("unknown attribute `{other}`"),
1768 ));
1769 }
1770 };
1771 ret.push(attr);
1772 }
1773 Ok(ret)
1774 }
1775}
1776
1777fn eat_id(tokens: &mut Tokenizer<'_>, expected: &str) -> ParseResult<Span> {
1778 let id = parse_id(tokens)?;
1779 if id.name != expected {
1780 return Err(ParseError::new_syntax(
1781 id.span,
1782 format!("expected `{expected}`, found `{}`", id.name),
1783 ));
1784 }
1785 Ok(id.span)
1786}
1787
1788#[derive(Clone, Default, Debug, PartialEq, Eq)]
1793pub struct SourceMap {
1794 sources: Vec<Source>,
1795 offset: u32,
1796}
1797
1798#[derive(Clone, Debug, PartialEq, Eq)]
1799struct Source {
1800 offset: u32,
1801 path: String,
1802 contents: String,
1803}
1804
1805impl SourceMap {
1806 pub fn new() -> SourceMap {
1808 SourceMap::default()
1809 }
1810
1811 #[cfg(feature = "std")]
1814 pub fn push_file(&mut self, path: &Path) -> anyhow::Result<()> {
1815 let contents = std::fs::read_to_string(path)
1816 .with_context(|| format!("failed to read file {path:?}"))?;
1817 self.push(path, contents);
1818 Ok(())
1819 }
1820
1821 #[cfg(feature = "std")]
1828 pub fn push_dir(&mut self, path: &Path) -> anyhow::Result<()> {
1829 let cx = || format!("failed to read directory {path:?}");
1830 for entry in path.read_dir().with_context(&cx)? {
1831 let entry = entry.with_context(&cx)?;
1832 let entry_path = entry.path();
1833 let ty = entry.file_type().with_context(&cx)?;
1834 if ty.is_dir() {
1835 continue;
1836 }
1837 if ty.is_symlink() {
1838 if entry_path.is_dir() {
1839 continue;
1840 }
1841 }
1842 let filename = match entry_path.file_name().and_then(|s| s.to_str()) {
1843 Some(name) => name,
1844 None => continue,
1845 };
1846 if !filename.ends_with(".wit") {
1847 continue;
1848 }
1849 self.push_file(&entry_path)?;
1850 }
1851 Ok(())
1852 }
1853
1854 #[cfg(feature = "std")]
1862 pub fn push(&mut self, path: &Path, contents: impl Into<String>) {
1863 self.push_str(&path.display().to_string(), contents);
1864 }
1865
1866 pub fn push_str(&mut self, path: &str, contents: impl Into<String>) {
1874 let mut contents = contents.into();
1875 contents.push('\n');
1881 let new_offset = self.offset + u32::try_from(contents.len()).unwrap();
1882 self.sources.push(Source {
1883 offset: self.offset,
1884 path: path.to_string(),
1885 contents,
1886 });
1887 self.offset = new_offset;
1888 }
1889
1890 pub fn append(&mut self, other: SourceMap) -> u32 {
1896 let base = self.offset;
1897 for mut source in other.sources {
1898 source.offset += base;
1899 self.sources.push(source);
1900 }
1901 self.offset += other.offset;
1902 base
1903 }
1904
1905 pub fn parse(self) -> Result<UnresolvedPackageGroup, (Self, ParseError)> {
1911 match self.parse_inner() {
1912 Ok((main, nested)) => Ok(UnresolvedPackageGroup {
1913 main,
1914 nested,
1915 source_map: self,
1916 }),
1917 Err(e) => Err((self, e)),
1918 }
1919 }
1920
1921 fn parse_inner(&self) -> ParseResult<(UnresolvedPackage, Vec<UnresolvedPackage>)> {
1922 let mut nested = Vec::new();
1923 let mut resolver = Resolver::default();
1924 let mut srcs = self.sources.iter().collect::<Vec<_>>();
1925 srcs.sort_by_key(|src| &src.path);
1926
1927 for src in srcs {
1931 let mut tokens = Tokenizer::new(
1932 &src.contents[..src.contents.len() - 1],
1935 src.offset,
1936 )?;
1937 let mut file = PackageFile::parse(&mut tokens)?;
1938
1939 for item in mem::take(&mut file.decl_list.items) {
1948 match item {
1949 AstItem::Package(nested_pkg) => {
1950 let mut resolve = Resolver::default();
1951 resolve.push(nested_pkg)?;
1952 nested.push(resolve.resolve()?);
1953 }
1954 other => file.decl_list.items.push(other),
1955 }
1956 }
1957
1958 resolver.push(file)?;
1960 }
1961
1962 Ok((resolver.resolve()?, nested))
1963 }
1964
1965 pub(crate) fn highlight_span(&self, span: Span, err: impl fmt::Display) -> Option<String> {
1966 if !span.is_known() {
1967 return None;
1968 }
1969 Some(self.highlight_err(span.start(), Some(span.end()), err))
1970 }
1971
1972 fn highlight_err(&self, start: u32, end: Option<u32>, err: impl fmt::Display) -> String {
1973 let src = self.source_for_offset(start);
1974 let start = src.to_relative_offset(start);
1975 let end = end.map(|end| src.to_relative_offset(end));
1976 let (line, col) = src.linecol(start);
1977 let snippet = src.contents.lines().nth(line).unwrap_or("");
1978 let line = line + 1;
1979 let col = col + 1;
1980
1981 if snippet.len() > 500 {
1985 return format!("{}:{line}:{col}: {err}", src.path);
1986 }
1987 let mut msg = format!(
1988 "\
1989{err}
1990 --> {file}:{line}:{col}
1991 |
1992 {line:4} | {snippet}
1993 | {marker:>0$}",
1994 col,
1995 file = src.path,
1996 marker = "^",
1997 );
1998 if let Some(end) = end {
1999 if let Some(s) = src.contents.get(start..end) {
2000 for _ in s.chars().skip(1) {
2001 msg.push('-');
2002 }
2003 }
2004 }
2005 return msg;
2006 }
2007
2008 pub fn resolve_span(&self, span: Span) -> Option<SpanLocation<'_>> {
2014 if !span.is_known() || span.start() >= self.offset {
2015 return None;
2016 }
2017 let src = self.source_for_offset(span.start());
2018 let len = src.contents.len() - 1;
2021 let start = src.to_relative_offset(span.start()).min(len);
2022 let end = usize::try_from(span.end().saturating_sub(src.offset))
2023 .unwrap()
2024 .clamp(start, len);
2025 Some(SpanLocation {
2026 path: &src.path,
2027 range: start..end,
2028 })
2029 }
2030
2031 pub fn render_location(&self, span: Span) -> String {
2033 if !span.is_known() {
2034 return "<unknown>".to_string();
2035 }
2036 let start = span.start();
2037 let src = self.source_for_offset(start);
2038 let rel_start = src.to_relative_offset(start);
2039 let (line, col) = src.linecol(rel_start);
2040 format!(
2041 "{file}:{line}:{col}",
2042 file = src.path,
2043 line = line + 1,
2044 col = col + 1,
2045 )
2046 }
2047
2048 fn source_for_offset(&self, start: u32) -> &Source {
2049 let i = match self.sources.binary_search_by_key(&start, |src| src.offset) {
2050 Ok(i) => i,
2051 Err(i) => i - 1,
2052 };
2053 &self.sources[i]
2054 }
2055
2056 #[cfg(feature = "std")]
2058 pub fn source_files(&self) -> impl Iterator<Item = &Path> {
2059 self.sources.iter().map(|src| Path::new(&src.path))
2060 }
2061
2062 pub fn source_names(&self) -> impl Iterator<Item = &str> {
2064 self.sources.iter().map(|src| src.path.as_str())
2065 }
2066}
2067
2068#[derive(Clone, Debug, PartialEq, Eq)]
2070pub struct SpanLocation<'a> {
2071 pub path: &'a str,
2073 pub range: core::ops::Range<usize>,
2075}
2076
2077impl Source {
2078 fn to_relative_offset(&self, offset: u32) -> usize {
2079 usize::try_from(offset - self.offset).unwrap()
2080 }
2081
2082 fn linecol(&self, relative_offset: usize) -> (usize, usize) {
2083 let mut cur = 0;
2084 for (i, line) in self.contents.split_terminator('\n').enumerate() {
2088 if cur + line.len() + 1 > relative_offset {
2089 return (i, relative_offset - cur);
2090 }
2091 cur += line.len() + 1;
2092 }
2093 (self.contents.lines().count(), 0)
2094 }
2095}
2096
2097pub enum ParsedUsePath {
2098 Name(String),
2099 Package(crate::PackageName, String),
2100}
2101
2102pub fn parse_use_path(s: &str) -> anyhow::Result<ParsedUsePath> {
2103 let mut tokens = Tokenizer::new(s, 0)?;
2104 let path = UsePath::parse(&mut tokens)?;
2105 if tokens.next()?.is_some() {
2106 anyhow::bail!("trailing tokens in path specifier");
2107 }
2108 Ok(match path {
2109 UsePath::Id(id) => ParsedUsePath::Name(id.name.to_string()),
2110 UsePath::Package { id, name } => {
2111 ParsedUsePath::Package(id.package_name(), name.name.to_string())
2112 }
2113 })
2114}
2115
2116#[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
2117#[cfg_attr(
2118 feature = "serde",
2119 derive(serde_derive::Serialize, serde_derive::Deserialize)
2120)]
2121#[cfg_attr(feature = "serde", serde(into = "String", try_from = "String"))]
2122pub struct ItemName {
2206 pub package: Option<crate::PackageName>,
2207 pub interface: Option<String>,
2208 pub name: String,
2209}
2210impl ItemName {
2211 pub fn instance_name(&self) -> Option<String> {
2230 if self.package.is_none() && self.interface.is_none() {
2231 return None;
2232 }
2233 let mut s = String::new();
2234 if let Some(crate::PackageName {
2235 namespace, name, ..
2236 }) = &self.package
2237 {
2238 s.push_str(&format!("{namespace}:{name}/"));
2239 }
2240 if let Some(name) = &self.interface {
2241 s.push_str(&format!("{name}"));
2242 }
2243 if let Some(crate::PackageName {
2244 version: Some(version),
2245 ..
2246 }) = &self.package
2247 {
2248 s.push_str(&format!("@{version}"));
2249 }
2250 Some(s)
2251 }
2252}
2253impl core::str::FromStr for ItemName {
2254 type Err = anyhow::Error;
2255 fn from_str(s: &str) -> anyhow::Result<ItemName> {
2256 let mut tokens = Tokenizer::new(s, 0)?;
2257
2258 let id = parse_id(&mut tokens)?;
2259 let (package, name) = if tokens.eat(Token::Colon)? {
2260 let name = parse_id(&mut tokens)?;
2261 tokens.expect(Token::Slash)?;
2262 (Some((id, name)), parse_id(&mut tokens)?)
2263 } else {
2264 (None, id)
2265 };
2266 let interface;
2267 let name = if tokens.eat(Token::Period)? {
2268 interface = Some(name.name.to_string());
2269 parse_id(&mut tokens)?
2270 } else {
2271 interface = None;
2272 name
2273 };
2274
2275 let package = package
2276 .map(|(namespace, name)| -> anyhow::Result<crate::PackageName> {
2277 let version = parse_opt_version(&mut tokens)?;
2278 Ok(PackageName {
2279 docs: Docs::default(),
2280 span: Span::new(
2281 namespace.span.start(),
2282 version
2283 .as_ref()
2284 .map(|(s, _)| s.end())
2285 .unwrap_or(name.span.end()),
2286 ),
2287 namespace,
2288 name,
2289 version,
2290 }
2291 .package_name())
2292 })
2293 .transpose()?;
2294
2295 if tokens.next()?.is_some() {
2296 anyhow::bail!("trailing tokens in item name specifier");
2297 }
2298 Ok(ItemName {
2299 package,
2300 interface,
2301 name: name.name.to_string(),
2302 })
2303 }
2304}
2305impl core::convert::TryFrom<String> for ItemName {
2306 type Error = anyhow::Error;
2307 fn try_from(s: String) -> anyhow::Result<ItemName> {
2308 s.parse()
2309 }
2310}
2311impl fmt::Display for ItemName {
2312 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2313 if let Some(crate::PackageName {
2314 namespace, name, ..
2315 }) = &self.package
2316 {
2317 write!(f, "{namespace}:{name}/")?;
2318 }
2319 if let Some(int) = &self.interface {
2320 write!(f, "{int}.")?;
2321 }
2322 write!(f, "{}", self.name)?;
2323 if let Some(crate::PackageName {
2324 version: Some(version),
2325 ..
2326 }) = &self.package
2327 {
2328 write!(f, "@{version}")?;
2329 }
2330 Ok(())
2331 }
2332}
2333impl From<ItemName> for String {
2334 fn from(m: ItemName) -> String {
2335 m.to_string()
2336 }
2337}
2338
2339#[cfg(test)]
2340mod item_name_test {
2341 use super::{ItemName, Version};
2342 use crate::PackageName;
2343 use alloc::borrow::ToOwned;
2344
2345 fn assert_round_trip(s: &str) {
2346 use alloc::string::ToString;
2347 let i = s.parse::<ItemName>().unwrap();
2348 assert_eq!(i.to_string(), s);
2349 }
2350
2351 #[test]
2352 fn bare() {
2353 assert_eq!(
2354 "bare-kebab-name".parse::<ItemName>().unwrap(),
2355 ItemName {
2356 package: None,
2357 interface: None,
2358 name: "bare-kebab-name".to_owned()
2359 }
2360 );
2361 assert_round_trip("bare-kebab-name");
2362 assert!("bare-kebab-name@0.1.0".parse::<ItemName>().is_err());
2364 }
2365 #[test]
2366 fn in_interface() {
2367 assert_eq!(
2368 "foo.bar".parse::<ItemName>().unwrap(),
2369 ItemName {
2370 package: None,
2371 interface: Some("foo".to_owned()),
2372 name: "bar".to_owned()
2373 }
2374 );
2375 assert_round_trip("foo.bar");
2376 assert!("foo.bar@0.1.0".parse::<ItemName>().is_err());
2378 }
2379 #[test]
2380 fn in_package() {
2381 assert_eq!(
2382 "foo:bar/baz.bat".parse::<ItemName>().unwrap(),
2383 ItemName {
2384 package: Some(PackageName {
2385 namespace: "foo".to_owned(),
2386 name: "bar".to_owned(),
2387 version: None
2388 }),
2389 interface: Some("baz".to_owned()),
2390 name: "bat".to_owned()
2391 }
2392 );
2393 assert_round_trip("foo:bar/baz.bat");
2394 assert_eq!(
2395 "foo:bar/baz.bat@0.1.0".parse::<ItemName>().unwrap(),
2396 ItemName {
2397 package: Some(PackageName {
2398 namespace: "foo".to_owned(),
2399 name: "bar".to_owned(),
2400 version: Some(Version::parse("0.1.0").unwrap()),
2401 }),
2402 interface: Some("baz".to_owned()),
2403 name: "bat".to_owned()
2404 }
2405 );
2406 assert_round_trip("foo:bar/baz.bat@0.1.0");
2407 assert_eq!(
2408 "foo:bar/baz".parse::<ItemName>().unwrap(),
2409 ItemName {
2410 package: Some(PackageName {
2411 namespace: "foo".to_owned(),
2412 name: "bar".to_owned(),
2413 version: None
2414 }),
2415 interface: None,
2416 name: "baz".to_owned()
2417 }
2418 );
2419 assert_round_trip("foo:bar/baz@0.1.0");
2420 assert_eq!(
2421 "foo:bar/baz@0.1.0".parse::<ItemName>().unwrap(),
2422 ItemName {
2423 package: Some(PackageName {
2424 namespace: "foo".to_owned(),
2425 name: "bar".to_owned(),
2426 version: Some(Version::parse("0.1.0").unwrap()),
2427 }),
2428 interface: None,
2429 name: "baz".to_owned()
2430 }
2431 );
2432 }
2433}