1use crate::ast::error::ParseError;
2use crate::{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)? || clone.clone().eat(Token::Async)? {
517 *tokens = clone;
518 let ret = ExternKind::Func(id, Func::parse(tokens)?);
519 tokens.expect_semicolon()?;
520 return Ok(ret);
521 }
522
523 if clone.eat(Token::Interface)? {
525 *tokens = clone;
526 return Ok(ExternKind::Interface(id, Interface::parse_items(tokens)?));
527 }
528
529 let mut peek = clone.clone();
540 let is_qualified_path =
541 parse_id(&mut peek).is_ok() && peek.clone().eat(Token::Slash).unwrap_or(false);
542 if !is_qualified_path {
543 *tokens = clone;
544 let path = UsePath::parse(tokens)?;
545 tokens.expect_semicolon()?;
546 return Ok(ExternKind::NamedPath(id, path));
547 }
548 }
549
550 let ret = ExternKind::Path(UsePath::parse(tokens)?);
554 tokens.expect_semicolon()?;
555 Ok(ret)
556 }
557
558 fn span(&self) -> Span {
559 match self {
560 ExternKind::Interface(id, _) => id.span,
561 ExternKind::Path(UsePath::Id(id)) => id.span,
562 ExternKind::Path(UsePath::Package { name, .. }) => name.span,
563 ExternKind::Func(id, _) => id.span,
564 ExternKind::NamedPath(id, _) => id.span,
565 }
566 }
567}
568
569struct Interface<'a> {
570 docs: Docs<'a>,
571 attributes: Vec<Attribute<'a>>,
572 name: Id<'a>,
573 items: Vec<InterfaceItem<'a>>,
574}
575
576impl<'a> Interface<'a> {
577 fn parse(
578 tokens: &mut Tokenizer<'a>,
579 docs: Docs<'a>,
580 attributes: Vec<Attribute<'a>>,
581 ) -> ParseResult<Self> {
582 tokens.expect(Token::Interface)?;
583 let name = parse_id(tokens)?;
584 let items = Self::parse_items(tokens)?;
585 Ok(Interface {
586 docs,
587 attributes,
588 name,
589 items,
590 })
591 }
592
593 pub(super) fn parse_items(tokens: &mut Tokenizer<'a>) -> ParseResult<Vec<InterfaceItem<'a>>> {
594 tokens.expect(Token::LeftBrace)?;
595 let mut items = Vec::new();
596 loop {
597 let docs = parse_docs(tokens)?;
598 if tokens.eat(Token::RightBrace)? {
599 break;
600 }
601 let attributes = Attribute::parse_list(tokens)?;
602 items.push(InterfaceItem::parse(tokens, docs, attributes)?);
603 }
604 Ok(items)
605 }
606}
607
608#[derive(Debug)]
609pub enum WorldOrInterface {
610 World,
611 Interface,
612 Unknown,
613}
614
615enum InterfaceItem<'a> {
616 TypeDef(TypeDef<'a>),
617 Func(NamedFunc<'a>),
618 Use(Use<'a>),
619}
620
621struct Use<'a> {
622 attributes: Vec<Attribute<'a>>,
623 from: UsePath<'a>,
624 names: Vec<UseName<'a>>,
625}
626
627#[derive(Debug)]
628enum UsePath<'a> {
629 Id(Id<'a>),
630 Package { id: PackageName<'a>, name: Id<'a> },
631}
632
633impl<'a> UsePath<'a> {
634 fn parse(tokens: &mut Tokenizer<'a>) -> ParseResult<Self> {
635 let id = parse_id(tokens)?;
636 if tokens.eat(Token::Colon)? {
637 let namespace = id;
639 let pkg_name = parse_id(tokens)?;
640 tokens.expect(Token::Slash)?;
641 let name = parse_id(tokens)?;
642 let version = parse_opt_version(tokens)?;
643 Ok(UsePath::Package {
644 id: PackageName {
645 docs: Default::default(),
646 span: Span::new(namespace.span.start(), pkg_name.span.end()),
647 namespace,
648 name: pkg_name,
649 version,
650 },
651 name,
652 })
653 } else {
654 Ok(UsePath::Id(id))
656 }
657 }
658
659 fn name(&self) -> &Id<'a> {
660 match self {
661 UsePath::Id(id) => id,
662 UsePath::Package { name, .. } => name,
663 }
664 }
665}
666
667struct UseName<'a> {
668 name: Id<'a>,
669 as_: Option<Id<'a>>,
670}
671
672impl<'a> Use<'a> {
673 fn parse(tokens: &mut Tokenizer<'a>, attributes: Vec<Attribute<'a>>) -> ParseResult<Self> {
674 tokens.expect(Token::Use)?;
675 let from = UsePath::parse(tokens)?;
676 tokens.expect(Token::Period)?;
677 tokens.expect(Token::LeftBrace)?;
678
679 let mut names = Vec::new();
680 while !tokens.eat(Token::RightBrace)? {
681 let mut name = UseName {
682 name: parse_id(tokens)?,
683 as_: None,
684 };
685 if tokens.eat(Token::As)? {
686 name.as_ = Some(parse_id(tokens)?);
687 }
688 names.push(name);
689 if !tokens.eat(Token::Comma)? {
690 tokens.expect(Token::RightBrace)?;
691 break;
692 }
693 }
694 tokens.expect_semicolon()?;
695 Ok(Use {
696 attributes,
697 from,
698 names,
699 })
700 }
701}
702
703struct Include<'a> {
704 from: UsePath<'a>,
705 attributes: Vec<Attribute<'a>>,
706 names: Vec<IncludeName<'a>>,
707}
708
709struct IncludeName<'a> {
710 name: Id<'a>,
711 as_: Id<'a>,
712}
713
714impl<'a> Include<'a> {
715 fn parse(tokens: &mut Tokenizer<'a>, attributes: Vec<Attribute<'a>>) -> ParseResult<Self> {
716 tokens.expect(Token::Include)?;
717 let from = UsePath::parse(tokens)?;
718
719 let names = if tokens.eat(Token::With)? {
720 parse_list(
721 tokens,
722 Token::LeftBrace,
723 Token::RightBrace,
724 |_docs, tokens| {
725 let name = parse_id(tokens)?;
726 tokens.expect(Token::As)?;
727 let as_ = parse_id(tokens)?;
728 Ok(IncludeName { name, as_ })
729 },
730 )?
731 } else {
732 tokens.expect_semicolon()?;
733 Vec::new()
734 };
735
736 Ok(Include {
737 attributes,
738 from,
739 names,
740 })
741 }
742}
743
744#[derive(Debug, Clone)]
745pub struct Id<'a> {
746 name: &'a str,
747 span: Span,
748}
749
750impl<'a> From<&'a str> for Id<'a> {
751 fn from(s: &'a str) -> Id<'a> {
752 Id {
753 name: s.into(),
754 span: Default::default(),
755 }
756 }
757}
758
759#[derive(Debug, Clone)]
760pub struct Docs<'a> {
761 docs: Vec<Cow<'a, str>>,
762 span: Span,
763}
764
765impl<'a> Default for Docs<'a> {
766 fn default() -> Self {
767 Self {
768 docs: Default::default(),
769 span: Default::default(),
770 }
771 }
772}
773
774struct TypeDef<'a> {
775 docs: Docs<'a>,
776 attributes: Vec<Attribute<'a>>,
777 name: Id<'a>,
778 ty: Type<'a>,
779}
780
781enum Type<'a> {
782 Bool(Span),
783 U8(Span),
784 U16(Span),
785 U32(Span),
786 U64(Span),
787 S8(Span),
788 S16(Span),
789 S32(Span),
790 S64(Span),
791 F32(Span),
792 F64(Span),
793 Char(Span),
794 String(Span),
795 Name(Id<'a>),
796 List(List<'a>),
797 Map(Map<'a>),
798 FixedLengthList(FixedLengthList<'a>),
799 Handle(Handle<'a>),
800 Resource(Resource<'a>),
801 Record(Record<'a>),
802 Flags(Flags<'a>),
803 Variant(Variant<'a>),
804 Tuple(Tuple<'a>),
805 Enum(Enum<'a>),
806 Option(Option_<'a>),
807 Result(Result_<'a>),
808 Future(Future<'a>),
809 Stream(Stream<'a>),
810 ErrorContext(Span),
811}
812
813enum Handle<'a> {
814 Own { resource: Id<'a> },
815 Borrow { resource: Id<'a> },
816}
817
818impl Handle<'_> {
819 fn span(&self) -> Span {
820 match self {
821 Handle::Own { resource } | Handle::Borrow { resource } => resource.span,
822 }
823 }
824}
825
826struct Resource<'a> {
827 span: Span,
828 funcs: Vec<ResourceFunc<'a>>,
829}
830
831enum ResourceFunc<'a> {
832 Method(NamedFunc<'a>),
833 Static(NamedFunc<'a>),
834 Constructor(NamedFunc<'a>),
835}
836
837impl<'a> ResourceFunc<'a> {
838 fn parse(
839 docs: Docs<'a>,
840 attributes: Vec<Attribute<'a>>,
841 tokens: &mut Tokenizer<'a>,
842 ) -> ParseResult<Self> {
843 match tokens.clone().next()? {
844 Some((span, Token::Constructor)) => {
845 tokens.expect(Token::Constructor)?;
846 tokens.expect(Token::LeftParen)?;
847 let params = parse_list_trailer(tokens, Token::RightParen, |_docs, tokens| {
848 let name = parse_id(tokens)?;
849 tokens.expect(Token::Colon)?;
850 let ty = Type::parse(tokens)?;
851 Ok((name, ty))
852 })?;
853 let result = if tokens.eat(Token::RArrow)? {
854 let ty = Type::parse(tokens)?;
855 Some(ty)
856 } else {
857 None
858 };
859 tokens.expect_semicolon()?;
860 Ok(ResourceFunc::Constructor(NamedFunc {
861 docs,
862 attributes,
863 name: Id {
864 span,
865 name: "constructor",
866 },
867 func: Func {
868 span,
869 async_: false,
870 params,
871 result,
872 },
873 }))
874 }
875 Some((_span, Token::Id | Token::ExplicitId)) => {
876 let name = parse_id(tokens)?;
877 tokens.expect(Token::Colon)?;
878 let ctor = if tokens.eat(Token::Static)? {
879 ResourceFunc::Static
880 } else {
881 ResourceFunc::Method
882 };
883 let func = Func::parse(tokens)?;
884 tokens.expect_semicolon()?;
885 Ok(ctor(NamedFunc {
886 docs,
887 attributes,
888 name,
889 func,
890 }))
891 }
892 other => Err(err_expected(tokens, "`constructor` or identifier", other).into()),
893 }
894 }
895
896 fn named_func(&self) -> &NamedFunc<'a> {
897 use ResourceFunc::*;
898 match self {
899 Method(f) | Static(f) | Constructor(f) => f,
900 }
901 }
902}
903
904struct Record<'a> {
905 span: Span,
906 fields: Vec<Field<'a>>,
907}
908
909struct Field<'a> {
910 docs: Docs<'a>,
911 name: Id<'a>,
912 ty: Type<'a>,
913}
914
915struct Flags<'a> {
916 span: Span,
917 flags: Vec<Flag<'a>>,
918}
919
920struct Flag<'a> {
921 docs: Docs<'a>,
922 name: Id<'a>,
923}
924
925struct Variant<'a> {
926 span: Span,
927 cases: Vec<Case<'a>>,
928}
929
930struct Case<'a> {
931 docs: Docs<'a>,
932 name: Id<'a>,
933 ty: Option<Type<'a>>,
934}
935
936struct Enum<'a> {
937 span: Span,
938 cases: Vec<EnumCase<'a>>,
939}
940
941struct EnumCase<'a> {
942 docs: Docs<'a>,
943 name: Id<'a>,
944}
945
946struct Option_<'a> {
947 span: Span,
948 ty: Box<Type<'a>>,
949}
950
951struct List<'a> {
952 span: Span,
953 ty: Box<Type<'a>>,
954}
955
956struct Map<'a> {
957 span: Span,
958 key: Box<Type<'a>>,
959 value: Box<Type<'a>>,
960}
961
962struct FixedLengthList<'a> {
963 span: Span,
964 ty: Box<Type<'a>>,
965 size: u32,
966}
967
968struct Future<'a> {
969 span: Span,
970 ty: Option<Box<Type<'a>>>,
971}
972
973struct Tuple<'a> {
974 span: Span,
975 types: Vec<Type<'a>>,
976}
977
978struct Result_<'a> {
979 span: Span,
980 ok: Option<Box<Type<'a>>>,
981 err: Option<Box<Type<'a>>>,
982}
983
984struct Stream<'a> {
985 span: Span,
986 ty: Option<Box<Type<'a>>>,
987}
988
989struct NamedFunc<'a> {
990 docs: Docs<'a>,
991 attributes: Vec<Attribute<'a>>,
992 name: Id<'a>,
993 func: Func<'a>,
994}
995
996type ParamList<'a> = Vec<(Id<'a>, Type<'a>)>;
997
998struct Func<'a> {
999 span: Span,
1000 async_: bool,
1001 params: ParamList<'a>,
1002 result: Option<Type<'a>>,
1003}
1004
1005impl<'a> Func<'a> {
1006 fn parse(tokens: &mut Tokenizer<'a>) -> ParseResult<Func<'a>> {
1007 fn parse_params<'a>(
1008 tokens: &mut Tokenizer<'a>,
1009 left_paren: bool,
1010 ) -> ParseResult<ParamList<'a>> {
1011 if left_paren {
1012 tokens.expect(Token::LeftParen)?;
1013 };
1014 parse_list_trailer(tokens, Token::RightParen, |_docs, tokens| {
1015 let name = parse_id(tokens)?;
1016 tokens.expect(Token::Colon)?;
1017 let ty = Type::parse(tokens)?;
1018 Ok((name, ty))
1019 })
1020 }
1021
1022 let async_ = tokens.eat(Token::Async)?;
1023 let span = tokens.expect(Token::Func)?;
1024 let params = parse_params(tokens, true)?;
1025 let result = if tokens.eat(Token::RArrow)? {
1026 let ty = Type::parse(tokens)?;
1027 Some(ty)
1028 } else {
1029 None
1030 };
1031 Ok(Func {
1032 span,
1033 async_,
1034 params,
1035 result,
1036 })
1037 }
1038}
1039
1040impl<'a> InterfaceItem<'a> {
1041 fn parse(
1042 tokens: &mut Tokenizer<'a>,
1043 docs: Docs<'a>,
1044 attributes: Vec<Attribute<'a>>,
1045 ) -> ParseResult<InterfaceItem<'a>> {
1046 match tokens.clone().next()? {
1047 Some((_span, Token::Type)) => {
1048 TypeDef::parse(tokens, docs, attributes).map(InterfaceItem::TypeDef)
1049 }
1050 Some((_span, Token::Flags)) => {
1051 TypeDef::parse_flags(tokens, docs, attributes).map(InterfaceItem::TypeDef)
1052 }
1053 Some((_span, Token::Enum)) => {
1054 TypeDef::parse_enum(tokens, docs, attributes).map(InterfaceItem::TypeDef)
1055 }
1056 Some((_span, Token::Variant)) => {
1057 TypeDef::parse_variant(tokens, docs, attributes).map(InterfaceItem::TypeDef)
1058 }
1059 Some((_span, Token::Resource)) => {
1060 TypeDef::parse_resource(tokens, docs, attributes).map(InterfaceItem::TypeDef)
1061 }
1062 Some((_span, Token::Record)) => {
1063 TypeDef::parse_record(tokens, docs, attributes).map(InterfaceItem::TypeDef)
1064 }
1065 Some((_span, Token::Id)) | Some((_span, Token::ExplicitId)) => {
1066 NamedFunc::parse(tokens, docs, attributes).map(InterfaceItem::Func)
1067 }
1068 Some((_span, Token::Use)) => Use::parse(tokens, attributes).map(InterfaceItem::Use),
1069 other => Err(err_expected(tokens, "`type`, `resource` or `func`", other).into()),
1070 }
1071 }
1072}
1073
1074impl<'a> TypeDef<'a> {
1075 fn parse(
1076 tokens: &mut Tokenizer<'a>,
1077 docs: Docs<'a>,
1078 attributes: Vec<Attribute<'a>>,
1079 ) -> ParseResult<Self> {
1080 tokens.expect(Token::Type)?;
1081 let name = parse_id(tokens)?;
1082 tokens.expect(Token::Equals)?;
1083 let ty = Type::parse(tokens)?;
1084 tokens.expect_semicolon()?;
1085 Ok(TypeDef {
1086 docs,
1087 attributes,
1088 name,
1089 ty,
1090 })
1091 }
1092
1093 fn parse_flags(
1094 tokens: &mut Tokenizer<'a>,
1095 docs: Docs<'a>,
1096 attributes: Vec<Attribute<'a>>,
1097 ) -> ParseResult<Self> {
1098 tokens.expect(Token::Flags)?;
1099 let name = parse_id(tokens)?;
1100 let ty = Type::Flags(Flags {
1101 span: name.span,
1102 flags: parse_list(
1103 tokens,
1104 Token::LeftBrace,
1105 Token::RightBrace,
1106 |docs, tokens| {
1107 let name = parse_id(tokens)?;
1108 Ok(Flag { docs, name })
1109 },
1110 )?,
1111 });
1112 Ok(TypeDef {
1113 docs,
1114 attributes,
1115 name,
1116 ty,
1117 })
1118 }
1119
1120 fn parse_resource(
1121 tokens: &mut Tokenizer<'a>,
1122 docs: Docs<'a>,
1123 attributes: Vec<Attribute<'a>>,
1124 ) -> ParseResult<Self> {
1125 tokens.expect(Token::Resource)?;
1126 let name = parse_id(tokens)?;
1127 let mut funcs = Vec::new();
1128 if tokens.eat(Token::LeftBrace)? {
1129 while !tokens.eat(Token::RightBrace)? {
1130 let docs = parse_docs(tokens)?;
1131 let attributes = Attribute::parse_list(tokens)?;
1132 funcs.push(ResourceFunc::parse(docs, attributes, tokens)?);
1133 }
1134 } else {
1135 tokens.expect_semicolon()?;
1136 }
1137 let ty = Type::Resource(Resource {
1138 span: name.span,
1139 funcs,
1140 });
1141 Ok(TypeDef {
1142 docs,
1143 attributes,
1144 name,
1145 ty,
1146 })
1147 }
1148
1149 fn parse_record(
1150 tokens: &mut Tokenizer<'a>,
1151 docs: Docs<'a>,
1152 attributes: Vec<Attribute<'a>>,
1153 ) -> ParseResult<Self> {
1154 tokens.expect(Token::Record)?;
1155 let name = parse_id(tokens)?;
1156 let ty = Type::Record(Record {
1157 span: name.span,
1158 fields: parse_list(
1159 tokens,
1160 Token::LeftBrace,
1161 Token::RightBrace,
1162 |docs, tokens| {
1163 let name = parse_id(tokens)?;
1164 tokens.expect(Token::Colon)?;
1165 let ty = Type::parse(tokens)?;
1166 Ok(Field { docs, name, ty })
1167 },
1168 )?,
1169 });
1170 Ok(TypeDef {
1171 docs,
1172 attributes,
1173 name,
1174 ty,
1175 })
1176 }
1177
1178 fn parse_variant(
1179 tokens: &mut Tokenizer<'a>,
1180 docs: Docs<'a>,
1181 attributes: Vec<Attribute<'a>>,
1182 ) -> ParseResult<Self> {
1183 tokens.expect(Token::Variant)?;
1184 let name = parse_id(tokens)?;
1185 let ty = Type::Variant(Variant {
1186 span: name.span,
1187 cases: parse_list(
1188 tokens,
1189 Token::LeftBrace,
1190 Token::RightBrace,
1191 |docs, tokens| {
1192 let name = parse_id(tokens)?;
1193 let ty = if tokens.eat(Token::LeftParen)? {
1194 let ty = Type::parse(tokens)?;
1195 tokens.expect(Token::RightParen)?;
1196 Some(ty)
1197 } else {
1198 None
1199 };
1200 Ok(Case { docs, name, ty })
1201 },
1202 )?,
1203 });
1204 Ok(TypeDef {
1205 docs,
1206 attributes,
1207 name,
1208 ty,
1209 })
1210 }
1211
1212 fn parse_enum(
1213 tokens: &mut Tokenizer<'a>,
1214 docs: Docs<'a>,
1215 attributes: Vec<Attribute<'a>>,
1216 ) -> ParseResult<Self> {
1217 tokens.expect(Token::Enum)?;
1218 let name = parse_id(tokens)?;
1219 let ty = Type::Enum(Enum {
1220 span: name.span,
1221 cases: parse_list(
1222 tokens,
1223 Token::LeftBrace,
1224 Token::RightBrace,
1225 |docs, tokens| {
1226 let name = parse_id(tokens)?;
1227 Ok(EnumCase { docs, name })
1228 },
1229 )?,
1230 });
1231 Ok(TypeDef {
1232 docs,
1233 attributes,
1234 name,
1235 ty,
1236 })
1237 }
1238}
1239
1240impl<'a> NamedFunc<'a> {
1241 fn parse(
1242 tokens: &mut Tokenizer<'a>,
1243 docs: Docs<'a>,
1244 attributes: Vec<Attribute<'a>>,
1245 ) -> ParseResult<Self> {
1246 let name = parse_id(tokens)?;
1247 tokens.expect(Token::Colon)?;
1248 let func = Func::parse(tokens)?;
1249 tokens.expect_semicolon()?;
1250 Ok(NamedFunc {
1251 docs,
1252 attributes,
1253 name,
1254 func,
1255 })
1256 }
1257}
1258
1259fn parse_id<'a>(tokens: &mut Tokenizer<'a>) -> ParseResult<Id<'a>> {
1260 match tokens.next()? {
1261 Some((span, Token::Id)) => Ok(Id {
1262 name: tokens.parse_id(span)?,
1263 span,
1264 }),
1265 Some((span, Token::ExplicitId)) => Ok(Id {
1266 name: tokens.parse_explicit_id(span)?,
1267 span,
1268 }),
1269 other => Err(err_expected(tokens, "an identifier or string", other)),
1270 }
1271}
1272
1273fn parse_opt_version(tokens: &mut Tokenizer<'_>) -> ParseResult<Option<(Span, Version)>> {
1274 if tokens.eat(Token::At)? {
1275 parse_version(tokens).map(Some)
1276 } else {
1277 Ok(None)
1278 }
1279}
1280
1281fn parse_version(tokens: &mut Tokenizer<'_>) -> ParseResult<(Span, Version)> {
1282 let start = tokens.expect(Token::Integer)?.start();
1283 tokens.expect(Token::Period)?;
1284 tokens.expect(Token::Integer)?;
1285 tokens.expect(Token::Period)?;
1286 let end = tokens.expect(Token::Integer)?.end();
1287 let mut span = Span::new(start, end);
1288 eat_ids(tokens, Token::Minus, &mut span)?;
1289 eat_ids(tokens, Token::Plus, &mut span)?;
1290 let string = tokens.get_span(span);
1291 let version =
1292 Version::parse(string).map_err(|e| ParseError::new_syntax(span, e.to_string()))?;
1293 return Ok((span, version));
1294
1295 fn eat_ids(
1349 tokens: &mut Tokenizer<'_>,
1350 prefix: Token,
1351 end: &mut Span,
1352 ) -> Result<(), lex::Error> {
1353 if !tokens.eat(prefix)? {
1354 return Ok(());
1355 }
1356 loop {
1357 let mut clone = tokens.clone();
1358 match clone.next()? {
1359 Some((span, Token::Id | Token::Integer | Token::Minus)) => {
1360 end.set_end(span.end());
1361 *tokens = clone;
1362 }
1363 Some((_span, Token::Period)) => match clone.next()? {
1364 Some((span, Token::Id | Token::Integer | Token::Minus)) => {
1365 end.set_end(span.end());
1366 *tokens = clone;
1367 }
1368 _ => break Ok(()),
1369 },
1370 _ => break Ok(()),
1371 }
1372 }
1373 }
1374}
1375
1376fn parse_docs<'a>(tokens: &mut Tokenizer<'a>) -> Result<Docs<'a>, lex::Error> {
1377 let mut docs = Docs::default();
1378 let mut clone = tokens.clone();
1379 let mut started = false;
1380 while let Some((span, token)) = clone.next_raw()? {
1381 match token {
1382 Token::Whitespace => {}
1383 Token::Comment => {
1384 let comment = tokens.get_span(span);
1385 if !started {
1386 docs.span.set_start(span.start());
1387 started = true;
1388 }
1389 let trailing_ws = comment
1390 .bytes()
1391 .rev()
1392 .take_while(|ch| ch.is_ascii_whitespace())
1393 .count();
1394 docs.span.set_end(span.end() - (trailing_ws as u32));
1395 docs.docs.push(comment.into());
1396 }
1397 _ => break,
1398 };
1399 *tokens = clone.clone();
1400 }
1401 Ok(docs)
1402}
1403
1404const MAX_TYPE_DEPTH: usize = 100;
1407
1408impl<'a> Type<'a> {
1409 fn parse(tokens: &mut Tokenizer<'a>) -> ParseResult<Self> {
1410 Type::parse_at_depth(tokens, 0)
1411 }
1412
1413 fn parse_at_depth(tokens: &mut Tokenizer<'a>, depth: usize) -> ParseResult<Self> {
1414 let token = tokens.next()?;
1415 if depth >= MAX_TYPE_DEPTH {
1416 let span = match token {
1417 Some((span, _)) => span,
1418 None => tokens.eof_span(),
1419 };
1420 return Err(ParseError::new_syntax(span, "type nesting too deep"));
1421 }
1422 match token {
1423 Some((span, Token::U8)) => Ok(Type::U8(span)),
1424 Some((span, Token::U16)) => Ok(Type::U16(span)),
1425 Some((span, Token::U32)) => Ok(Type::U32(span)),
1426 Some((span, Token::U64)) => Ok(Type::U64(span)),
1427 Some((span, Token::S8)) => Ok(Type::S8(span)),
1428 Some((span, Token::S16)) => Ok(Type::S16(span)),
1429 Some((span, Token::S32)) => Ok(Type::S32(span)),
1430 Some((span, Token::S64)) => Ok(Type::S64(span)),
1431 Some((span, Token::F32)) => Ok(Type::F32(span)),
1432 Some((span, Token::F64)) => Ok(Type::F64(span)),
1433 Some((span, Token::Char)) => Ok(Type::Char(span)),
1434
1435 Some((span, Token::Tuple)) => {
1437 let types = parse_list(
1438 tokens,
1439 Token::LessThan,
1440 Token::GreaterThan,
1441 |_docs, tokens| Type::parse_at_depth(tokens, depth + 1),
1442 )?;
1443 Ok(Type::Tuple(Tuple { span, types }))
1444 }
1445
1446 Some((span, Token::Bool)) => Ok(Type::Bool(span)),
1447 Some((span, Token::String_)) => Ok(Type::String(span)),
1448
1449 Some((span, Token::List)) => {
1452 tokens.expect(Token::LessThan)?;
1453 let ty = Type::parse_at_depth(tokens, depth + 1)?;
1454 let size = if tokens.eat(Token::Comma)? {
1455 let number = tokens.next()?;
1456 if let Some((span, Token::Integer)) = number {
1457 let size: u32 = tokens.get_span(span).parse().map_err(|e| {
1458 ParseError::new_syntax(span, format!("invalid list size: {e}"))
1459 })?;
1460 Some(size)
1461 } else {
1462 return Err(err_expected(tokens, "fixed-length", number).into());
1463 }
1464 } else {
1465 None
1466 };
1467 tokens.expect(Token::GreaterThan)?;
1468 if let Some(size) = size {
1469 Ok(Type::FixedLengthList(FixedLengthList {
1470 span,
1471 ty: Box::new(ty),
1472 size,
1473 }))
1474 } else {
1475 Ok(Type::List(List {
1476 span,
1477 ty: Box::new(ty),
1478 }))
1479 }
1480 }
1481
1482 Some((span, Token::Map)) => {
1484 tokens.expect(Token::LessThan)?;
1485 let key = Type::parse_at_depth(tokens, depth + 1)?;
1486 tokens.expect(Token::Comma)?;
1487 let value = Type::parse_at_depth(tokens, depth + 1)?;
1488 tokens.expect(Token::GreaterThan)?;
1489 Ok(Type::Map(Map {
1490 span,
1491 key: Box::new(key),
1492 value: Box::new(value),
1493 }))
1494 }
1495
1496 Some((span, Token::Option_)) => {
1498 tokens.expect(Token::LessThan)?;
1499 let ty = Type::parse_at_depth(tokens, depth + 1)?;
1500 tokens.expect(Token::GreaterThan)?;
1501 Ok(Type::Option(Option_ {
1502 span,
1503 ty: Box::new(ty),
1504 }))
1505 }
1506
1507 Some((span, Token::Result_)) => {
1512 let mut ok = None;
1513 let mut err = None;
1514
1515 if tokens.eat(Token::LessThan)? {
1516 if tokens.eat(Token::Underscore)? {
1517 tokens.expect(Token::Comma)?;
1518 err = Some(Box::new(Type::parse_at_depth(tokens, depth + 1)?));
1519 } else {
1520 ok = Some(Box::new(Type::parse_at_depth(tokens, depth + 1)?));
1521 if tokens.eat(Token::Comma)? {
1522 err = Some(Box::new(Type::parse_at_depth(tokens, depth + 1)?));
1523 }
1524 };
1525 tokens.expect(Token::GreaterThan)?;
1526 };
1527 Ok(Type::Result(Result_ { span, ok, err }))
1528 }
1529
1530 Some((span, Token::Future)) => {
1533 let mut ty = None;
1534
1535 if tokens.eat(Token::LessThan)? {
1536 ty = Some(Box::new(Type::parse_at_depth(tokens, depth + 1)?));
1537 tokens.expect(Token::GreaterThan)?;
1538 };
1539 Ok(Type::Future(Future { span, ty }))
1540 }
1541
1542 Some((span, Token::Stream)) => {
1545 let mut ty = None;
1546
1547 if tokens.eat(Token::LessThan)? {
1548 ty = Some(Box::new(Type::parse_at_depth(tokens, depth + 1)?));
1549 tokens.expect(Token::GreaterThan)?;
1550 };
1551 Ok(Type::Stream(Stream { span, ty }))
1552 }
1553
1554 Some((span, Token::ErrorContext)) => Ok(Type::ErrorContext(span)),
1556
1557 Some((_span, Token::Own)) => {
1559 tokens.expect(Token::LessThan)?;
1560 let resource = parse_id(tokens)?;
1561 tokens.expect(Token::GreaterThan)?;
1562 Ok(Type::Handle(Handle::Own { resource }))
1563 }
1564
1565 Some((_span, Token::Borrow)) => {
1567 tokens.expect(Token::LessThan)?;
1568 let resource = parse_id(tokens)?;
1569 tokens.expect(Token::GreaterThan)?;
1570 Ok(Type::Handle(Handle::Borrow { resource }))
1571 }
1572
1573 Some((span, Token::Id)) => Ok(Type::Name(Id {
1575 name: tokens.parse_id(span)?.into(),
1576 span,
1577 })),
1578 Some((span, Token::ExplicitId)) => Ok(Type::Name(Id {
1580 name: tokens.parse_explicit_id(span)?.into(),
1581 span,
1582 })),
1583
1584 other => Err(err_expected(tokens, "a type", other).into()),
1585 }
1586 }
1587
1588 fn span(&self) -> Span {
1589 match self {
1590 Type::Bool(span)
1591 | Type::U8(span)
1592 | Type::U16(span)
1593 | Type::U32(span)
1594 | Type::U64(span)
1595 | Type::S8(span)
1596 | Type::S16(span)
1597 | Type::S32(span)
1598 | Type::S64(span)
1599 | Type::F32(span)
1600 | Type::F64(span)
1601 | Type::Char(span)
1602 | Type::String(span)
1603 | Type::ErrorContext(span) => *span,
1604 Type::Name(id) => id.span,
1605 Type::List(l) => l.span,
1606 Type::Map(m) => m.span,
1607 Type::FixedLengthList(l) => l.span,
1608 Type::Handle(h) => h.span(),
1609 Type::Resource(r) => r.span,
1610 Type::Record(r) => r.span,
1611 Type::Flags(f) => f.span,
1612 Type::Variant(v) => v.span,
1613 Type::Tuple(t) => t.span,
1614 Type::Enum(e) => e.span,
1615 Type::Option(o) => o.span,
1616 Type::Result(r) => r.span,
1617 Type::Future(f) => f.span,
1618 Type::Stream(s) => s.span,
1619 }
1620 }
1621}
1622
1623fn parse_list<'a, T>(
1624 tokens: &mut Tokenizer<'a>,
1625 start: Token,
1626 end: Token,
1627 parse: impl FnMut(Docs<'a>, &mut Tokenizer<'a>) -> ParseResult<T>,
1628) -> ParseResult<Vec<T>> {
1629 tokens.expect(start)?;
1630 parse_list_trailer(tokens, end, parse)
1631}
1632
1633fn parse_list_trailer<'a, T>(
1634 tokens: &mut Tokenizer<'a>,
1635 end: Token,
1636 mut parse: impl FnMut(Docs<'a>, &mut Tokenizer<'a>) -> ParseResult<T>,
1637) -> ParseResult<Vec<T>> {
1638 let mut items = Vec::new();
1639 loop {
1640 let docs = parse_docs(tokens)?;
1642
1643 if tokens.eat(end)? {
1645 break;
1646 }
1647
1648 let item = parse(docs, tokens)?;
1649 items.push(item);
1650
1651 if !tokens.eat(Token::Comma)? {
1654 tokens.expect(end)?;
1655 break;
1656 }
1657 }
1658 Ok(items)
1659}
1660
1661fn err_expected(
1662 tokens: &Tokenizer<'_>,
1663 expected: &'static str,
1664 found: Option<(Span, Token)>,
1665) -> ParseError {
1666 match found {
1667 Some((span, token)) => ParseError::new_syntax(
1668 span,
1669 format!("expected {}, found {}", expected, token.describe()),
1670 ),
1671 None => {
1672 ParseError::new_syntax(tokens.eof_span(), format!("expected {expected}, found eof"))
1673 }
1674 }
1675}
1676
1677enum Attribute<'a> {
1678 Since { span: Span, version: Version },
1679 Unstable { span: Span, feature: Id<'a> },
1680 Deprecated { span: Span, version: Version },
1681 ExternalId { span: Span, id: String },
1682}
1683
1684impl<'a> Attribute<'a> {
1685 fn parse_list(tokens: &mut Tokenizer<'a>) -> ParseResult<Vec<Attribute<'a>>> {
1686 let mut ret = Vec::new();
1687 while tokens.eat(Token::At)? {
1688 let id = parse_id(tokens)?;
1689 let attr = match id.name {
1690 "since" => {
1691 tokens.expect(Token::LeftParen)?;
1692 eat_id(tokens, "version")?;
1693 tokens.expect(Token::Equals)?;
1694 let (_span, version) = parse_version(tokens)?;
1695 tokens.expect(Token::RightParen)?;
1696 Attribute::Since {
1697 span: id.span,
1698 version,
1699 }
1700 }
1701 "unstable" => {
1702 tokens.expect(Token::LeftParen)?;
1703 eat_id(tokens, "feature")?;
1704 tokens.expect(Token::Equals)?;
1705 let feature = parse_id(tokens)?;
1706 tokens.expect(Token::RightParen)?;
1707 Attribute::Unstable {
1708 span: id.span,
1709 feature,
1710 }
1711 }
1712 "deprecated" => {
1713 tokens.expect(Token::LeftParen)?;
1714 eat_id(tokens, "version")?;
1715 tokens.expect(Token::Equals)?;
1716 let (_span, version) = parse_version(tokens)?;
1717 tokens.expect(Token::RightParen)?;
1718 Attribute::Deprecated {
1719 span: id.span,
1720 version,
1721 }
1722 }
1723 "external-id" => {
1724 tokens.expect(Token::LeftParen)?;
1725 let span = tokens.expect(Token::StringLiteral)?;
1726 tokens.expect(Token::RightParen)?;
1727 Attribute::ExternalId {
1728 span: id.span,
1729 id: tokens.string_literal(span)?,
1730 }
1731 }
1732 other => {
1733 return Err(ParseError::new_syntax(
1734 id.span,
1735 format!("unknown attribute `{other}`"),
1736 ));
1737 }
1738 };
1739 ret.push(attr);
1740 }
1741 Ok(ret)
1742 }
1743}
1744
1745fn eat_id(tokens: &mut Tokenizer<'_>, expected: &str) -> ParseResult<Span> {
1746 let id = parse_id(tokens)?;
1747 if id.name != expected {
1748 return Err(ParseError::new_syntax(
1749 id.span,
1750 format!("expected `{expected}`, found `{}`", id.name),
1751 ));
1752 }
1753 Ok(id.span)
1754}
1755
1756#[derive(Clone, Default, Debug, PartialEq, Eq)]
1761pub struct SourceMap {
1762 sources: Vec<Source>,
1763 offset: u32,
1764}
1765
1766#[derive(Clone, Debug, PartialEq, Eq)]
1767struct Source {
1768 offset: u32,
1769 path: String,
1770 contents: String,
1771}
1772
1773impl SourceMap {
1774 pub fn new() -> SourceMap {
1776 SourceMap::default()
1777 }
1778
1779 #[cfg(feature = "std")]
1782 pub fn push_file(&mut self, path: &Path) -> anyhow::Result<()> {
1783 let contents = std::fs::read_to_string(path)
1784 .with_context(|| format!("failed to read file {path:?}"))?;
1785 self.push(path, contents);
1786 Ok(())
1787 }
1788
1789 #[cfg(feature = "std")]
1796 pub fn push_dir(&mut self, path: &Path) -> anyhow::Result<()> {
1797 let cx = || format!("failed to read directory {path:?}");
1798 for entry in path.read_dir().with_context(&cx)? {
1799 let entry = entry.with_context(&cx)?;
1800 let entry_path = entry.path();
1801 let ty = entry.file_type().with_context(&cx)?;
1802 if ty.is_dir() {
1803 continue;
1804 }
1805 if ty.is_symlink() {
1806 if entry_path.is_dir() {
1807 continue;
1808 }
1809 }
1810 let filename = match entry_path.file_name().and_then(|s| s.to_str()) {
1811 Some(name) => name,
1812 None => continue,
1813 };
1814 if !filename.ends_with(".wit") {
1815 continue;
1816 }
1817 self.push_file(&entry_path)?;
1818 }
1819 Ok(())
1820 }
1821
1822 #[cfg(feature = "std")]
1830 pub fn push(&mut self, path: &Path, contents: impl Into<String>) {
1831 self.push_str(&path.display().to_string(), contents);
1832 }
1833
1834 pub fn push_str(&mut self, path: &str, contents: impl Into<String>) {
1842 let mut contents = contents.into();
1843 contents.push('\n');
1849 let new_offset = self.offset + u32::try_from(contents.len()).unwrap();
1850 self.sources.push(Source {
1851 offset: self.offset,
1852 path: path.to_string(),
1853 contents,
1854 });
1855 self.offset = new_offset;
1856 }
1857
1858 pub fn append(&mut self, other: SourceMap) -> u32 {
1864 let base = self.offset;
1865 for mut source in other.sources {
1866 source.offset += base;
1867 self.sources.push(source);
1868 }
1869 self.offset += other.offset;
1870 base
1871 }
1872
1873 pub fn parse(self) -> Result<UnresolvedPackageGroup, (Self, ParseError)> {
1879 match self.parse_inner() {
1880 Ok((main, nested)) => Ok(UnresolvedPackageGroup {
1881 main,
1882 nested,
1883 source_map: self,
1884 }),
1885 Err(e) => Err((self, e)),
1886 }
1887 }
1888
1889 fn parse_inner(&self) -> ParseResult<(UnresolvedPackage, Vec<UnresolvedPackage>)> {
1890 let mut nested = Vec::new();
1891 let mut resolver = Resolver::default();
1892 let mut srcs = self.sources.iter().collect::<Vec<_>>();
1893 srcs.sort_by_key(|src| &src.path);
1894
1895 for src in srcs {
1899 let mut tokens = Tokenizer::new(
1900 &src.contents[..src.contents.len() - 1],
1903 src.offset,
1904 )?;
1905 let mut file = PackageFile::parse(&mut tokens)?;
1906
1907 for item in mem::take(&mut file.decl_list.items) {
1916 match item {
1917 AstItem::Package(nested_pkg) => {
1918 let mut resolve = Resolver::default();
1919 resolve.push(nested_pkg)?;
1920 nested.push(resolve.resolve()?);
1921 }
1922 other => file.decl_list.items.push(other),
1923 }
1924 }
1925
1926 resolver.push(file)?;
1928 }
1929
1930 Ok((resolver.resolve()?, nested))
1931 }
1932
1933 pub(crate) fn highlight_span(&self, span: Span, err: impl fmt::Display) -> Option<String> {
1934 if !span.is_known() {
1935 return None;
1936 }
1937 Some(self.highlight_err(span.start(), Some(span.end()), err))
1938 }
1939
1940 fn highlight_err(&self, start: u32, end: Option<u32>, err: impl fmt::Display) -> String {
1941 let src = self.source_for_offset(start);
1942 let start = src.to_relative_offset(start);
1943 let end = end.map(|end| src.to_relative_offset(end));
1944 let (line, col) = src.linecol(start);
1945 let snippet = src.contents.lines().nth(line).unwrap_or("");
1946 let line = line + 1;
1947 let col = col + 1;
1948
1949 if snippet.len() > 500 {
1953 return format!("{}:{line}:{col}: {err}", src.path);
1954 }
1955 let mut msg = format!(
1956 "\
1957{err}
1958 --> {file}:{line}:{col}
1959 |
1960 {line:4} | {snippet}
1961 | {marker:>0$}",
1962 col,
1963 file = src.path,
1964 marker = "^",
1965 );
1966 if let Some(end) = end {
1967 if let Some(s) = src.contents.get(start..end) {
1968 for _ in s.chars().skip(1) {
1969 msg.push('-');
1970 }
1971 }
1972 }
1973 return msg;
1974 }
1975
1976 pub fn resolve_span(&self, span: Span) -> Option<SpanLocation<'_>> {
1982 if !span.is_known() || span.start() >= self.offset {
1983 return None;
1984 }
1985 let src = self.source_for_offset(span.start());
1986 let len = src.contents.len() - 1;
1989 let start = src.to_relative_offset(span.start()).min(len);
1990 let end = usize::try_from(span.end().saturating_sub(src.offset))
1991 .unwrap()
1992 .clamp(start, len);
1993 Some(SpanLocation {
1994 path: &src.path,
1995 range: start..end,
1996 })
1997 }
1998
1999 pub fn render_location(&self, span: Span) -> String {
2001 if !span.is_known() {
2002 return "<unknown>".to_string();
2003 }
2004 let start = span.start();
2005 let src = self.source_for_offset(start);
2006 let rel_start = src.to_relative_offset(start);
2007 let (line, col) = src.linecol(rel_start);
2008 format!(
2009 "{file}:{line}:{col}",
2010 file = src.path,
2011 line = line + 1,
2012 col = col + 1,
2013 )
2014 }
2015
2016 fn source_for_offset(&self, start: u32) -> &Source {
2017 let i = match self.sources.binary_search_by_key(&start, |src| src.offset) {
2018 Ok(i) => i,
2019 Err(i) => i - 1,
2020 };
2021 &self.sources[i]
2022 }
2023
2024 #[cfg(feature = "std")]
2026 pub fn source_files(&self) -> impl Iterator<Item = &Path> {
2027 self.sources.iter().map(|src| Path::new(&src.path))
2028 }
2029
2030 pub fn source_names(&self) -> impl Iterator<Item = &str> {
2032 self.sources.iter().map(|src| src.path.as_str())
2033 }
2034}
2035
2036#[derive(Clone, Debug, PartialEq, Eq)]
2038pub struct SpanLocation<'a> {
2039 pub path: &'a str,
2041 pub range: core::ops::Range<usize>,
2043}
2044
2045impl Source {
2046 fn to_relative_offset(&self, offset: u32) -> usize {
2047 usize::try_from(offset - self.offset).unwrap()
2048 }
2049
2050 fn linecol(&self, relative_offset: usize) -> (usize, usize) {
2051 let mut cur = 0;
2052 for (i, line) in self.contents.split_terminator('\n').enumerate() {
2056 if cur + line.len() + 1 > relative_offset {
2057 return (i, relative_offset - cur);
2058 }
2059 cur += line.len() + 1;
2060 }
2061 (self.contents.lines().count(), 0)
2062 }
2063}
2064
2065pub enum ParsedUsePath {
2066 Name(String),
2067 Package(crate::PackageName, String),
2068}
2069
2070pub fn parse_use_path(s: &str) -> anyhow::Result<ParsedUsePath> {
2071 let mut tokens = Tokenizer::new(s, 0)?;
2072 let path = UsePath::parse(&mut tokens)?;
2073 if tokens.next()?.is_some() {
2074 anyhow::bail!("trailing tokens in path specifier");
2075 }
2076 Ok(match path {
2077 UsePath::Id(id) => ParsedUsePath::Name(id.name.to_string()),
2078 UsePath::Package { id, name } => {
2079 ParsedUsePath::Package(id.package_name(), name.name.to_string())
2080 }
2081 })
2082}
2083
2084#[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
2085#[cfg_attr(
2086 feature = "serde",
2087 derive(serde_derive::Serialize, serde_derive::Deserialize)
2088)]
2089#[cfg_attr(feature = "serde", serde(into = "String", try_from = "String"))]
2090pub struct ItemName {
2174 pub package: Option<crate::PackageName>,
2175 pub interface: Option<String>,
2176 pub name: String,
2177}
2178impl ItemName {
2179 pub fn instance_name(&self) -> Option<String> {
2198 if self.package.is_none() && self.interface.is_none() {
2199 return None;
2200 }
2201 let mut s = String::new();
2202 if let Some(crate::PackageName {
2203 namespace, name, ..
2204 }) = &self.package
2205 {
2206 s.push_str(&format!("{namespace}:{name}/"));
2207 }
2208 if let Some(name) = &self.interface {
2209 s.push_str(&format!("{name}"));
2210 }
2211 if let Some(crate::PackageName {
2212 version: Some(version),
2213 ..
2214 }) = &self.package
2215 {
2216 s.push_str(&format!("@{version}"));
2217 }
2218 Some(s)
2219 }
2220}
2221impl core::str::FromStr for ItemName {
2222 type Err = anyhow::Error;
2223 fn from_str(s: &str) -> anyhow::Result<ItemName> {
2224 let mut tokens = Tokenizer::new(s, 0)?;
2225
2226 let id = parse_id(&mut tokens)?;
2227 let (package, name) = if tokens.eat(Token::Colon)? {
2228 let name = parse_id(&mut tokens)?;
2229 tokens.expect(Token::Slash)?;
2230 (Some((id, name)), parse_id(&mut tokens)?)
2231 } else {
2232 (None, id)
2233 };
2234 let interface;
2235 let name = if tokens.eat(Token::Period)? {
2236 interface = Some(name.name.to_string());
2237 parse_id(&mut tokens)?
2238 } else {
2239 interface = None;
2240 name
2241 };
2242
2243 let package = package
2244 .map(|(namespace, name)| -> anyhow::Result<crate::PackageName> {
2245 let version = parse_opt_version(&mut tokens)?;
2246 Ok(PackageName {
2247 docs: Docs::default(),
2248 span: Span::new(
2249 namespace.span.start(),
2250 version
2251 .as_ref()
2252 .map(|(s, _)| s.end())
2253 .unwrap_or(name.span.end()),
2254 ),
2255 namespace,
2256 name,
2257 version,
2258 }
2259 .package_name())
2260 })
2261 .transpose()?;
2262
2263 if tokens.next()?.is_some() {
2264 anyhow::bail!("trailing tokens in item name specifier");
2265 }
2266 Ok(ItemName {
2267 package,
2268 interface,
2269 name: name.name.to_string(),
2270 })
2271 }
2272}
2273impl core::convert::TryFrom<String> for ItemName {
2274 type Error = anyhow::Error;
2275 fn try_from(s: String) -> anyhow::Result<ItemName> {
2276 s.parse()
2277 }
2278}
2279impl fmt::Display for ItemName {
2280 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2281 if let Some(crate::PackageName {
2282 namespace, name, ..
2283 }) = &self.package
2284 {
2285 write!(f, "{namespace}:{name}/")?;
2286 }
2287 if let Some(int) = &self.interface {
2288 write!(f, "{int}.")?;
2289 }
2290 write!(f, "{}", self.name)?;
2291 if let Some(crate::PackageName {
2292 version: Some(version),
2293 ..
2294 }) = &self.package
2295 {
2296 write!(f, "@{version}")?;
2297 }
2298 Ok(())
2299 }
2300}
2301impl From<ItemName> for String {
2302 fn from(m: ItemName) -> String {
2303 m.to_string()
2304 }
2305}
2306
2307#[cfg(test)]
2308mod item_name_test {
2309 use super::{ItemName, Version};
2310 use crate::PackageName;
2311 use alloc::borrow::ToOwned;
2312
2313 fn assert_round_trip(s: &str) {
2314 use alloc::string::ToString;
2315 let i = s.parse::<ItemName>().unwrap();
2316 assert_eq!(i.to_string(), s);
2317 }
2318
2319 #[test]
2320 fn bare() {
2321 assert_eq!(
2322 "bare-kebab-name".parse::<ItemName>().unwrap(),
2323 ItemName {
2324 package: None,
2325 interface: None,
2326 name: "bare-kebab-name".to_owned()
2327 }
2328 );
2329 assert_round_trip("bare-kebab-name");
2330 assert!("bare-kebab-name@0.1.0".parse::<ItemName>().is_err());
2332 }
2333 #[test]
2334 fn in_interface() {
2335 assert_eq!(
2336 "foo.bar".parse::<ItemName>().unwrap(),
2337 ItemName {
2338 package: None,
2339 interface: Some("foo".to_owned()),
2340 name: "bar".to_owned()
2341 }
2342 );
2343 assert_round_trip("foo.bar");
2344 assert!("foo.bar@0.1.0".parse::<ItemName>().is_err());
2346 }
2347 #[test]
2348 fn in_package() {
2349 assert_eq!(
2350 "foo:bar/baz.bat".parse::<ItemName>().unwrap(),
2351 ItemName {
2352 package: Some(PackageName {
2353 namespace: "foo".to_owned(),
2354 name: "bar".to_owned(),
2355 version: None
2356 }),
2357 interface: Some("baz".to_owned()),
2358 name: "bat".to_owned()
2359 }
2360 );
2361 assert_round_trip("foo:bar/baz.bat");
2362 assert_eq!(
2363 "foo:bar/baz.bat@0.1.0".parse::<ItemName>().unwrap(),
2364 ItemName {
2365 package: Some(PackageName {
2366 namespace: "foo".to_owned(),
2367 name: "bar".to_owned(),
2368 version: Some(Version::parse("0.1.0").unwrap()),
2369 }),
2370 interface: Some("baz".to_owned()),
2371 name: "bat".to_owned()
2372 }
2373 );
2374 assert_round_trip("foo:bar/baz.bat@0.1.0");
2375 assert_eq!(
2376 "foo:bar/baz".parse::<ItemName>().unwrap(),
2377 ItemName {
2378 package: Some(PackageName {
2379 namespace: "foo".to_owned(),
2380 name: "bar".to_owned(),
2381 version: None
2382 }),
2383 interface: None,
2384 name: "baz".to_owned()
2385 }
2386 );
2387 assert_round_trip("foo:bar/baz@0.1.0");
2388 assert_eq!(
2389 "foo:bar/baz@0.1.0".parse::<ItemName>().unwrap(),
2390 ItemName {
2391 package: Some(PackageName {
2392 namespace: "foo".to_owned(),
2393 name: "bar".to_owned(),
2394 version: Some(Version::parse("0.1.0").unwrap()),
2395 }),
2396 interface: None,
2397 name: "baz".to_owned()
2398 }
2399 );
2400 }
2401}