1use super::{
2 parse_delimited, parse_optional, parse_optional_payload, parse_token, DocComment, Error, Ident,
3 Lookahead, PackagePath, Parse, ParseResult, Peek,
4};
5use crate::lexer::{Lexer, Token};
6use miette::SourceSpan;
7use serde::Serialize;
8
9#[derive(Debug, Clone, Serialize)]
11#[serde(rename_all = "camelCase")]
12pub enum TypeStatement<'a> {
13 Interface(InterfaceDecl<'a>),
15 World(WorldDecl<'a>),
17 Type(TypeDecl<'a>),
19}
20
21impl<'a> Parse<'a> for TypeStatement<'a> {
22 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
23 let mut lookahead = Lookahead::new(lexer);
24 if InterfaceDecl::peek(&mut lookahead) {
25 Ok(Self::Interface(Parse::parse(lexer)?))
26 } else if WorldDecl::peek(&mut lookahead) {
27 Ok(Self::World(Parse::parse(lexer)?))
28 } else if TypeDecl::peek(&mut lookahead) {
29 Ok(Self::Type(Parse::parse(lexer)?))
30 } else {
31 Err(lookahead.error())
32 }
33 }
34}
35
36impl Peek for TypeStatement<'_> {
37 fn peek(lookahead: &mut Lookahead) -> bool {
38 lookahead.peek(Token::InterfaceKeyword)
39 || lookahead.peek(Token::WorldKeyword)
40 || TypeDecl::peek(lookahead)
41 }
42}
43
44#[derive(Debug, Clone, Serialize)]
49#[serde(rename_all = "camelCase")]
50pub enum TypeDecl<'a> {
51 Variant(VariantDecl<'a>),
53 Record(RecordDecl<'a>),
55 Flags(FlagsDecl<'a>),
57 Enum(EnumDecl<'a>),
59 Alias(TypeAlias<'a>),
61}
62
63impl TypeDecl<'_> {
64 pub fn id(&self) -> &Ident<'_> {
66 match self {
67 Self::Variant(variant) => &variant.id,
68 Self::Record(record) => &record.id,
69 Self::Flags(flags) => &flags.id,
70 Self::Enum(e) => &e.id,
71 Self::Alias(alias) => &alias.id,
72 }
73 }
74}
75
76impl<'a> Parse<'a> for TypeDecl<'a> {
77 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
78 let mut lookahead = Lookahead::new(lexer);
79 if lookahead.peek(Token::VariantKeyword) {
80 Ok(Self::Variant(Parse::parse(lexer)?))
81 } else if lookahead.peek(Token::RecordKeyword) {
82 Ok(Self::Record(Parse::parse(lexer)?))
83 } else if lookahead.peek(Token::FlagsKeyword) {
84 Ok(Self::Flags(Parse::parse(lexer)?))
85 } else if lookahead.peek(Token::EnumKeyword) {
86 Ok(Self::Enum(Parse::parse(lexer)?))
87 } else if lookahead.peek(Token::TypeKeyword) {
88 Ok(Self::Alias(Parse::parse(lexer)?))
89 } else {
90 Err(lookahead.error())
91 }
92 }
93}
94
95impl Peek for TypeDecl<'_> {
96 fn peek(lookahead: &mut Lookahead) -> bool {
97 lookahead.peek(Token::VariantKeyword)
98 || lookahead.peek(Token::RecordKeyword)
99 || lookahead.peek(Token::FlagsKeyword)
100 || lookahead.peek(Token::EnumKeyword)
101 || lookahead.peek(Token::TypeKeyword)
102 }
103}
104
105#[derive(Debug, Clone, Serialize)]
107#[serde(rename_all = "camelCase")]
108pub struct ResourceDecl<'a> {
109 pub docs: Vec<DocComment<'a>>,
111 pub id: Ident<'a>,
113 pub methods: Vec<ResourceMethod<'a>>,
115}
116
117impl<'a> Parse<'a> for ResourceDecl<'a> {
118 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
119 let docs = Parse::parse(lexer)?;
120 parse_token(lexer, Token::ResourceKeyword)?;
121 let id = Ident::parse(lexer)?;
122 let mut lookahead = Lookahead::new(lexer);
123 let methods = if lookahead.peek(Token::Semicolon) {
124 lexer.next();
125 Default::default()
126 } else if lookahead.peek(Token::OpenBrace) {
127 parse_token(lexer, Token::OpenBrace)?;
128 let methods = parse_delimited(lexer, Token::CloseBrace, false)?;
129 parse_token(lexer, Token::CloseBrace)?;
130 methods
131 } else {
132 return Err(lookahead.error());
133 };
134
135 Ok(Self { docs, id, methods })
136 }
137}
138
139#[derive(Debug, Clone, Serialize)]
141#[serde(rename_all = "camelCase")]
142pub struct VariantDecl<'a> {
143 pub docs: Vec<DocComment<'a>>,
145 pub id: Ident<'a>,
147 pub cases: Vec<VariantCase<'a>>,
149}
150
151impl<'a> Parse<'a> for VariantDecl<'a> {
152 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
153 let docs = Parse::parse(lexer)?;
154 parse_token(lexer, Token::VariantKeyword)?;
155 let id = Ident::parse(lexer)?;
156 parse_token(lexer, Token::OpenBrace)?;
157 let cases = parse_delimited(lexer, Token::CloseBrace, true)?;
158 let close = parse_token(lexer, Token::CloseBrace)?;
159
160 if cases.is_empty() {
161 return Err(Error::EmptyType {
162 ty: "variant",
163 kind: "case",
164 span: close,
165 });
166 }
167
168 Ok(Self { docs, id, cases })
169 }
170}
171
172#[derive(Debug, Clone, Serialize)]
174#[serde(rename_all = "camelCase")]
175pub struct VariantCase<'a> {
176 pub docs: Vec<DocComment<'a>>,
178 pub id: Ident<'a>,
180 pub ty: Option<Type<'a>>,
182}
183
184impl<'a> Parse<'a> for VariantCase<'a> {
185 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
186 let docs = Parse::parse(lexer)?;
187 let id = Ident::parse(lexer)?;
188 let ty = parse_optional(lexer, Token::OpenParen, |lexer| {
189 let ty = Parse::parse(lexer)?;
190 parse_token(lexer, Token::CloseParen)?;
191 Ok(ty)
192 })?;
193 Ok(Self { docs, id, ty })
194 }
195}
196
197impl Peek for VariantCase<'_> {
198 fn peek(lookahead: &mut Lookahead) -> bool {
199 lookahead.peek(Token::Ident)
200 }
201}
202
203#[derive(Debug, Clone, Serialize)]
205#[serde(rename_all = "camelCase")]
206pub struct RecordDecl<'a> {
207 pub docs: Vec<DocComment<'a>>,
209 pub id: Ident<'a>,
211 pub fields: Vec<Field<'a>>,
213}
214
215impl<'a> Parse<'a> for RecordDecl<'a> {
216 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
217 let docs = Parse::parse(lexer)?;
218 parse_token(lexer, Token::RecordKeyword)?;
219 let id = Ident::parse(lexer)?;
220 parse_token(lexer, Token::OpenBrace)?;
221 let fields = parse_delimited(lexer, Token::CloseBrace, true)?;
222 let close = parse_token(lexer, Token::CloseBrace)?;
223
224 if fields.is_empty() {
225 return Err(Error::EmptyType {
226 ty: "record",
227 kind: "field",
228 span: close,
229 });
230 }
231
232 Ok(Self { docs, id, fields })
233 }
234}
235
236#[derive(Debug, Clone, Serialize)]
238#[serde(rename_all = "camelCase")]
239pub struct Field<'a> {
240 pub docs: Vec<DocComment<'a>>,
242 pub id: Ident<'a>,
244 pub ty: Type<'a>,
246}
247
248impl<'a> Parse<'a> for Field<'a> {
249 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
250 let docs = Parse::parse(lexer)?;
251 let named: NamedType = Parse::parse(lexer)?;
252 Ok(Self {
253 docs,
254 id: named.id,
255 ty: named.ty,
256 })
257 }
258}
259
260impl Peek for Field<'_> {
261 fn peek(lookahead: &mut Lookahead) -> bool {
262 NamedType::peek(lookahead)
263 }
264}
265
266#[derive(Debug, Clone, Serialize)]
268#[serde(rename_all = "camelCase")]
269pub struct FlagsDecl<'a> {
270 pub docs: Vec<DocComment<'a>>,
272 pub id: Ident<'a>,
274 pub flags: Vec<Flag<'a>>,
276}
277
278impl<'a> Parse<'a> for FlagsDecl<'a> {
279 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
280 let docs = Parse::parse(lexer)?;
281 parse_token(lexer, Token::FlagsKeyword)?;
282 let id = Ident::parse(lexer)?;
283 parse_token(lexer, Token::OpenBrace)?;
284 let flags = parse_delimited(lexer, Token::CloseBrace, true)?;
285 let close = parse_token(lexer, Token::CloseBrace)?;
286
287 if flags.is_empty() {
288 return Err(Error::EmptyType {
289 ty: "flags",
290 kind: "flag",
291 span: close,
292 });
293 }
294
295 Ok(Self { docs, id, flags })
296 }
297}
298
299#[derive(Debug, Clone, Serialize)]
301#[serde(rename_all = "camelCase")]
302pub struct Flag<'a> {
303 pub docs: Vec<DocComment<'a>>,
305 pub id: Ident<'a>,
307}
308
309impl<'a> Parse<'a> for Flag<'a> {
310 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
311 let docs = Parse::parse(lexer)?;
312 let id = Ident::parse(lexer)?;
313 Ok(Self { docs, id })
314 }
315}
316
317impl Peek for Flag<'_> {
318 fn peek(lookahead: &mut Lookahead) -> bool {
319 lookahead.peek(Token::Ident)
320 }
321}
322
323#[derive(Debug, Clone, Serialize)]
325#[serde(rename_all = "camelCase")]
326pub struct EnumDecl<'a> {
327 pub docs: Vec<DocComment<'a>>,
329 pub id: Ident<'a>,
331 pub cases: Vec<EnumCase<'a>>,
333}
334
335impl<'a> Parse<'a> for EnumDecl<'a> {
336 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
337 let docs = Parse::parse(lexer)?;
338 parse_token(lexer, Token::EnumKeyword)?;
339 let id = Ident::parse(lexer)?;
340 parse_token(lexer, Token::OpenBrace)?;
341 let cases = parse_delimited(lexer, Token::CloseBrace, true)?;
342 let close = parse_token(lexer, Token::CloseBrace)?;
343
344 if cases.is_empty() {
345 return Err(Error::EmptyType {
346 ty: "enum",
347 kind: "case",
348 span: close,
349 });
350 }
351
352 Ok(Self { docs, id, cases })
353 }
354}
355
356#[derive(Debug, Clone, Serialize)]
358#[serde(rename_all = "camelCase")]
359pub struct EnumCase<'a> {
360 pub docs: Vec<DocComment<'a>>,
362 pub id: Ident<'a>,
364}
365
366impl<'a> Parse<'a> for EnumCase<'a> {
367 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
368 let docs = Parse::parse(lexer)?;
369 let id = Ident::parse(lexer)?;
370 Ok(Self { docs, id })
371 }
372}
373
374impl Peek for EnumCase<'_> {
375 fn peek(lookahead: &mut Lookahead) -> bool {
376 lookahead.peek(Token::Ident)
377 }
378}
379
380#[derive(Debug, Clone, Serialize)]
382#[serde(rename_all = "camelCase")]
383pub enum ResourceMethod<'a> {
384 Constructor(Constructor<'a>),
386 Method(Method<'a>),
388}
389
390impl<'a> Parse<'a> for ResourceMethod<'a> {
391 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
392 let mut lookahead = Lookahead::new(lexer);
393 if lookahead.peek(Token::ConstructorKeyword) {
394 Ok(Self::Constructor(Parse::parse(lexer)?))
395 } else if Ident::peek(&mut lookahead) {
396 Ok(Self::Method(Parse::parse(lexer)?))
397 } else {
398 Err(lookahead.error())
399 }
400 }
401}
402
403impl Peek for ResourceMethod<'_> {
404 fn peek(lookahead: &mut Lookahead) -> bool {
405 lookahead.peek(Token::ConstructorKeyword) || Ident::peek(lookahead)
406 }
407}
408
409#[derive(Debug, Clone, Serialize)]
411#[serde(rename_all = "camelCase")]
412pub struct Constructor<'a> {
413 pub docs: Vec<DocComment<'a>>,
415 pub span: SourceSpan,
417 pub params: Vec<NamedType<'a>>,
419}
420
421impl<'a> Parse<'a> for Constructor<'a> {
422 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
423 let docs = Parse::parse(lexer)?;
424 let span = parse_token(lexer, Token::ConstructorKeyword)?;
425 parse_token(lexer, Token::OpenParen)?;
426 let params = parse_delimited(lexer, Token::CloseParen, true)?;
427 parse_token(lexer, Token::CloseParen)?;
428 parse_token(lexer, Token::Semicolon)?;
429 Ok(Self { docs, span, params })
430 }
431}
432
433#[derive(Debug, Clone, Serialize)]
435#[serde(rename_all = "camelCase")]
436pub struct Method<'a> {
437 pub docs: Vec<DocComment<'a>>,
439 pub id: Ident<'a>,
441 pub is_static: bool,
443 pub ty: FuncType<'a>,
445}
446
447impl<'a> Parse<'a> for Method<'a> {
448 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
449 let docs = Parse::parse(lexer)?;
450 let id = Ident::parse(lexer)?;
451 parse_token(lexer, Token::Colon)?;
452 let is_static = lexer
453 .peek()
454 .map(|(r, _)| matches!(r, Ok(Token::StaticKeyword)))
455 .unwrap_or(false);
456
457 if is_static {
458 lexer.next();
459 }
460
461 let ty = Parse::parse(lexer)?;
462 parse_token(lexer, Token::Semicolon)?;
463 Ok(Self {
464 docs,
465 id,
466 is_static,
467 ty,
468 })
469 }
470}
471
472#[derive(Debug, Clone, Serialize)]
474#[serde(rename_all = "camelCase")]
475pub enum FuncTypeRef<'a> {
476 Func(FuncType<'a>),
478 Ident(Ident<'a>),
480}
481
482impl<'a> Parse<'a> for FuncTypeRef<'a> {
483 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
484 let mut lookahead = Lookahead::new(lexer);
485 if lookahead.peek(Token::AsyncKeyword) || lookahead.peek(Token::FuncKeyword) {
486 Ok(Self::Func(Parse::parse(lexer)?))
487 } else if Ident::peek(&mut lookahead) {
488 Ok(Self::Ident(Parse::parse(lexer)?))
489 } else {
490 Err(lookahead.error())
491 }
492 }
493}
494
495#[derive(Debug, Clone, Serialize)]
497#[serde(rename_all = "camelCase")]
498pub struct FuncType<'a> {
499 pub is_async: bool,
501 pub params: Vec<NamedType<'a>>,
503 pub results: ResultList<'a>,
505}
506
507impl<'a> Parse<'a> for FuncType<'a> {
508 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
509 let is_async = parse_optional(lexer, Token::AsyncKeyword, |_| Ok(()))?.is_some();
510 parse_token(lexer, Token::FuncKeyword)?;
511 parse_token(lexer, Token::OpenParen)?;
512 let params = parse_delimited(lexer, Token::CloseParen, true)?;
513 parse_token(lexer, Token::CloseParen)?;
514 let results =
515 parse_optional(lexer, Token::Arrow, Parse::parse)?.unwrap_or(ResultList::Empty);
516
517 Ok(Self {
518 is_async,
519 params,
520 results,
521 })
522 }
523}
524
525impl Peek for FuncType<'_> {
526 fn peek(lookahead: &mut Lookahead) -> bool {
527 lookahead.peek(Token::AsyncKeyword) || lookahead.peek(Token::FuncKeyword)
528 }
529}
530
531#[derive(Debug, Clone, Serialize)]
533#[serde(rename_all = "camelCase")]
534pub enum ResultList<'a> {
535 Empty,
537 Scalar(Type<'a>),
539}
540
541impl<'a> Parse<'a> for ResultList<'a> {
542 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
543 let mut lookahead = Lookahead::new(lexer);
544 if Type::peek(&mut lookahead) {
545 Ok(Self::Scalar(Parse::parse(lexer)?))
546 } else {
547 Ok(Self::Empty)
548 }
549 }
550}
551
552#[derive(Debug, Clone, Serialize)]
554#[serde(rename_all = "camelCase")]
555pub struct NamedType<'a> {
556 pub id: Ident<'a>,
558 pub ty: Type<'a>,
560}
561
562impl<'a> Parse<'a> for NamedType<'a> {
563 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
564 let id = Ident::parse(lexer)?;
565 parse_token(lexer, Token::Colon)?;
566 let ty = Parse::parse(lexer)?;
567 Ok(Self { id, ty })
568 }
569}
570
571impl Peek for NamedType<'_> {
572 fn peek(lookahead: &mut Lookahead) -> bool {
573 Ident::peek(lookahead)
574 }
575}
576
577#[derive(Debug, Clone, Serialize)]
579#[serde(rename_all = "camelCase")]
580pub struct TypeAlias<'a> {
581 pub docs: Vec<DocComment<'a>>,
583 pub id: Ident<'a>,
585 pub kind: TypeAliasKind<'a>,
587}
588
589impl<'a> Parse<'a> for TypeAlias<'a> {
590 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
591 let docs = Parse::parse(lexer)?;
592 parse_token(lexer, Token::TypeKeyword)?;
593 let id = Ident::parse(lexer)?;
594 parse_token(lexer, Token::Equals)?;
595 let kind = Parse::parse(lexer)?;
596 parse_token(lexer, Token::Semicolon)?;
597 Ok(Self { docs, id, kind })
598 }
599}
600
601#[derive(Debug, Clone, Serialize)]
603#[serde(rename_all = "camelCase")]
604pub enum TypeAliasKind<'a> {
605 Func(FuncType<'a>),
607 Type(Type<'a>),
609}
610
611impl<'a> Parse<'a> for TypeAliasKind<'a> {
612 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
613 let mut lookahead = Lookahead::new(lexer);
614 if lookahead.peek(Token::AsyncKeyword) || lookahead.peek(Token::FuncKeyword) {
615 Ok(Self::Func(Parse::parse(lexer)?))
616 } else if Type::peek(&mut lookahead) {
617 Ok(Self::Type(Parse::parse(lexer)?))
618 } else {
619 Err(lookahead.error())
620 }
621 }
622}
623
624#[derive(Debug, Clone, Serialize)]
626#[serde(rename_all = "camelCase")]
627pub enum Type<'a> {
628 U8(SourceSpan),
630 S8(SourceSpan),
632 U16(SourceSpan),
634 S16(SourceSpan),
636 U32(SourceSpan),
638 S32(SourceSpan),
640 U64(SourceSpan),
642 S64(SourceSpan),
644 F32(SourceSpan),
646 F64(SourceSpan),
648 Char(SourceSpan),
650 Bool(SourceSpan),
652 String(SourceSpan),
654 Tuple(Vec<Type<'a>>, SourceSpan),
656 List(Box<Type<'a>>, SourceSpan),
658 Option(Box<Type<'a>>, SourceSpan),
660 Result {
662 ok: Option<Box<Type<'a>>>,
664 err: Option<Box<Type<'a>>>,
666 span: SourceSpan,
668 },
669 Borrow(Ident<'a>, SourceSpan),
671 Stream(Option<Box<Type<'a>>>, SourceSpan),
673 Future(Option<Box<Type<'a>>>, SourceSpan),
675 ErrorContext(SourceSpan),
677 Ident(Ident<'a>),
679}
680
681impl Type<'_> {
682 pub fn span(&self) -> SourceSpan {
684 match self {
685 Self::U8(span)
686 | Self::S8(span)
687 | Self::U16(span)
688 | Self::S16(span)
689 | Self::U32(span)
690 | Self::S32(span)
691 | Self::U64(span)
692 | Self::S64(span)
693 | Self::F32(span)
694 | Self::F64(span)
695 | Self::Char(span)
696 | Self::Bool(span)
697 | Self::String(span)
698 | Self::Tuple(_, span)
699 | Self::List(_, span)
700 | Self::Option(_, span)
701 | Self::Result { span, .. }
702 | Self::Borrow(_, span)
703 | Self::Stream(_, span)
704 | Self::Future(_, span)
705 | Self::ErrorContext(span) => *span,
706 Self::Ident(ident) => ident.span,
707 }
708 }
709}
710
711impl<'a> Parse<'a> for Type<'a> {
712 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
713 let mut lookahead = Lookahead::new(lexer);
714 if lookahead.peek(Token::U8Keyword) {
715 Ok(Self::U8(lexer.next().unwrap().1))
716 } else if lookahead.peek(Token::S8Keyword) {
717 Ok(Self::S8(lexer.next().unwrap().1))
718 } else if lookahead.peek(Token::U16Keyword) {
719 Ok(Self::U16(lexer.next().unwrap().1))
720 } else if lookahead.peek(Token::S16Keyword) {
721 Ok(Self::S16(lexer.next().unwrap().1))
722 } else if lookahead.peek(Token::U32Keyword) {
723 Ok(Self::U32(lexer.next().unwrap().1))
724 } else if lookahead.peek(Token::S32Keyword) {
725 Ok(Self::S32(lexer.next().unwrap().1))
726 } else if lookahead.peek(Token::U64Keyword) {
727 Ok(Self::U64(lexer.next().unwrap().1))
728 } else if lookahead.peek(Token::S64Keyword) {
729 Ok(Self::S64(lexer.next().unwrap().1))
730 } else if lookahead.peek(Token::F32Keyword) {
731 Ok(Self::F32(lexer.next().unwrap().1))
732 } else if lookahead.peek(Token::F64Keyword) {
733 Ok(Self::F64(lexer.next().unwrap().1))
734 } else if lookahead.peek(Token::CharKeyword) {
735 Ok(Self::Char(lexer.next().unwrap().1))
736 } else if lookahead.peek(Token::BoolKeyword) {
737 Ok(Self::Bool(lexer.next().unwrap().1))
738 } else if lookahead.peek(Token::StringKeyword) {
739 Ok(Self::String(lexer.next().unwrap().1))
740 } else if lookahead.peek(Token::TupleKeyword) {
741 let span = lexer.next().unwrap().1;
742 parse_token(lexer, Token::OpenAngle)?;
743
744 let mut lookahead = Lookahead::new(lexer);
746 if !Type::peek(&mut lookahead) {
747 return Err(lookahead.error());
748 }
749
750 let types = parse_delimited(lexer, Token::CloseAngle, true)?;
751 assert!(!types.is_empty());
752 let close = parse_token(lexer, Token::CloseAngle)?;
753 Ok(Self::Tuple(
754 types,
755 SourceSpan::new(
756 span.offset().into(),
757 (close.offset() + close.len()) - span.offset(),
758 ),
759 ))
760 } else if lookahead.peek(Token::ListKeyword) {
761 let span = lexer.next().unwrap().1;
762 parse_token(lexer, Token::OpenAngle)?;
763 let ty = Box::new(Parse::parse(lexer)?);
764 let close = parse_token(lexer, Token::CloseAngle)?;
765 Ok(Self::List(
766 ty,
767 SourceSpan::new(
768 span.offset().into(),
769 (close.offset() + close.len()) - span.offset(),
770 ),
771 ))
772 } else if lookahead.peek(Token::OptionKeyword) {
773 let span = lexer.next().unwrap().1;
774 parse_token(lexer, Token::OpenAngle)?;
775 let ty = Box::new(Parse::parse(lexer)?);
776 let close = parse_token(lexer, Token::CloseAngle)?;
777 Ok(Self::Option(
778 ty,
779 SourceSpan::new(
780 span.offset().into(),
781 (close.offset() + close.len()) - span.offset(),
782 ),
783 ))
784 } else if lookahead.peek(Token::ResultKeyword) {
785 let mut span = lexer.next().unwrap().1;
786
787 let parse = |lexer: &mut Lexer<'a>| {
788 let mut lookahead = Lookahead::new(lexer);
789 let ok = if lookahead.peek(Token::Underscore) {
790 lexer.next();
791 None
792 } else if Type::peek(&mut lookahead) {
793 Some(Box::new(Parse::parse(lexer)?))
794 } else {
795 return Err(lookahead.error());
796 };
797
798 let err = parse_optional(lexer, Token::Comma, |lexer| {
799 let mut lookahead = Lookahead::new(lexer);
800 if lookahead.peek(Token::Underscore) {
801 lexer.next();
802 Ok(None)
803 } else if Type::peek(&mut lookahead) {
804 Ok(Some(Box::new(Parse::parse(lexer)?)))
805 } else {
806 Err(lookahead.error())
807 }
808 })?
809 .unwrap_or(None);
810
811 let close = parse_token(lexer, Token::CloseAngle)?;
812 span = SourceSpan::new(
813 span.offset().into(),
814 (close.offset() + close.len()) - span.offset(),
815 );
816 Ok((ok, err))
817 };
818
819 let (ok, err) = match parse_optional(lexer, Token::OpenAngle, parse)? {
820 Some((ok, err)) => (ok, err),
821 None => (None, None),
822 };
823 Ok(Self::Result { ok, err, span })
824 } else if lookahead.peek(Token::BorrowKeyword) {
825 let span = lexer.next().unwrap().1;
826 parse_token(lexer, Token::OpenAngle)?;
827 let id = Parse::parse(lexer)?;
828 let close = parse_token(lexer, Token::CloseAngle)?;
829 Ok(Self::Borrow(
830 id,
831 SourceSpan::new(
832 span.offset().into(),
833 (close.offset() + close.len()) - span.offset(),
834 ),
835 ))
836 } else if lookahead.peek(Token::StreamKeyword) {
837 parse_optional_payload(lexer, Self::Stream)
838 } else if lookahead.peek(Token::FutureKeyword) {
839 parse_optional_payload(lexer, Self::Future)
840 } else if lookahead.peek(Token::ErrorContextKeyword) {
841 Ok(Self::ErrorContext(lexer.next().unwrap().1))
842 } else if Ident::peek(&mut lookahead) {
843 Ok(Self::Ident(Parse::parse(lexer)?))
844 } else {
845 Err(lookahead.error())
846 }
847 }
848}
849
850impl Peek for Type<'_> {
851 fn peek(lookahead: &mut Lookahead) -> bool {
852 lookahead.peek(Token::U8Keyword)
853 || lookahead.peek(Token::S8Keyword)
854 || lookahead.peek(Token::U16Keyword)
855 || lookahead.peek(Token::S16Keyword)
856 || lookahead.peek(Token::U32Keyword)
857 || lookahead.peek(Token::S32Keyword)
858 || lookahead.peek(Token::U64Keyword)
859 || lookahead.peek(Token::S64Keyword)
860 || lookahead.peek(Token::F32Keyword)
861 || lookahead.peek(Token::F64Keyword)
862 || lookahead.peek(Token::CharKeyword)
863 || lookahead.peek(Token::BoolKeyword)
864 || lookahead.peek(Token::StringKeyword)
865 || lookahead.peek(Token::TupleKeyword)
866 || lookahead.peek(Token::ListKeyword)
867 || lookahead.peek(Token::OptionKeyword)
868 || lookahead.peek(Token::ResultKeyword)
869 || lookahead.peek(Token::BorrowKeyword)
870 || lookahead.peek(Token::StreamKeyword)
871 || lookahead.peek(Token::FutureKeyword)
872 || lookahead.peek(Token::ErrorContextKeyword)
873 || Ident::peek(lookahead)
874 }
875}
876
877#[derive(Debug, Clone, Serialize)]
882#[serde(rename_all = "camelCase")]
883pub enum ItemTypeDecl<'a> {
884 Resource(ResourceDecl<'a>),
886 Variant(VariantDecl<'a>),
888 Record(RecordDecl<'a>),
890 Flags(FlagsDecl<'a>),
892 Enum(EnumDecl<'a>),
894 Alias(TypeAlias<'a>),
896}
897
898impl<'a> Parse<'a> for ItemTypeDecl<'a> {
899 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
900 let mut lookahead = Lookahead::new(lexer);
901 if lookahead.peek(Token::ResourceKeyword) {
902 Ok(Self::Resource(Parse::parse(lexer)?))
903 } else if lookahead.peek(Token::VariantKeyword) {
904 Ok(Self::Variant(Parse::parse(lexer)?))
905 } else if lookahead.peek(Token::RecordKeyword) {
906 Ok(Self::Record(Parse::parse(lexer)?))
907 } else if lookahead.peek(Token::FlagsKeyword) {
908 Ok(Self::Flags(Parse::parse(lexer)?))
909 } else if lookahead.peek(Token::EnumKeyword) {
910 Ok(Self::Enum(Parse::parse(lexer)?))
911 } else if lookahead.peek(Token::TypeKeyword) {
912 Ok(Self::Alias(Parse::parse(lexer)?))
913 } else {
914 Err(lookahead.error())
915 }
916 }
917}
918
919impl Peek for ItemTypeDecl<'_> {
920 fn peek(lookahead: &mut Lookahead) -> bool {
921 lookahead.peek(Token::ResourceKeyword)
922 || lookahead.peek(Token::VariantKeyword)
923 || lookahead.peek(Token::RecordKeyword)
924 || lookahead.peek(Token::FlagsKeyword)
925 || lookahead.peek(Token::EnumKeyword)
926 || lookahead.peek(Token::TypeKeyword)
927 }
928}
929
930impl ItemTypeDecl<'_> {
931 pub fn id(&self) -> &Ident<'_> {
933 match self {
934 Self::Resource(resource) => &resource.id,
935 Self::Variant(variant) => &variant.id,
936 Self::Record(record) => &record.id,
937 Self::Flags(flags) => &flags.id,
938 Self::Enum(e) => &e.id,
939 Self::Alias(alias) => &alias.id,
940 }
941 }
942}
943
944#[derive(Debug, Clone, Serialize)]
946#[serde(rename_all = "camelCase")]
947pub struct InterfaceDecl<'a> {
948 pub docs: Vec<DocComment<'a>>,
950 pub id: Ident<'a>,
952 pub items: Vec<InterfaceItem<'a>>,
954}
955
956impl<'a> Parse<'a> for InterfaceDecl<'a> {
957 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
958 let docs = Parse::parse(lexer)?;
959 parse_token(lexer, Token::InterfaceKeyword)?;
960 let id = Ident::parse(lexer)?;
961 parse_token(lexer, Token::OpenBrace)?;
962 let items = parse_delimited(lexer, Token::CloseBrace, false)?;
963 parse_token(lexer, Token::CloseBrace)?;
964 Ok(Self { docs, id, items })
965 }
966}
967
968impl Peek for InterfaceDecl<'_> {
969 fn peek(lookahead: &mut Lookahead) -> bool {
970 lookahead.peek(Token::InterfaceKeyword)
971 }
972}
973
974#[derive(Debug, Clone, Serialize)]
976#[serde(rename_all = "camelCase")]
977pub enum InterfaceItem<'a> {
978 Use(Box<Use<'a>>),
980 Type(ItemTypeDecl<'a>),
982 Export(InterfaceExport<'a>),
984}
985
986impl<'a> Parse<'a> for InterfaceItem<'a> {
987 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
988 let mut lookahead = Lookahead::new(lexer);
989 if Use::peek(&mut lookahead) {
990 Ok(Self::Use(Box::new(Parse::parse(lexer)?)))
991 } else if InterfaceExport::peek(&mut lookahead) {
992 Ok(Self::Export(Parse::parse(lexer)?))
993 } else if ItemTypeDecl::peek(&mut lookahead) {
994 Ok(Self::Type(Parse::parse(lexer)?))
995 } else {
996 Err(lookahead.error())
997 }
998 }
999}
1000
1001impl Peek for InterfaceItem<'_> {
1002 fn peek(lookahead: &mut Lookahead) -> bool {
1003 Use::peek(lookahead) || InterfaceExport::peek(lookahead) || ItemTypeDecl::peek(lookahead)
1004 }
1005}
1006
1007#[derive(Debug, Clone, Serialize)]
1009#[serde(rename_all = "camelCase")]
1010pub struct Use<'a> {
1011 pub docs: Vec<DocComment<'a>>,
1013 pub path: UsePath<'a>,
1015 pub items: Vec<UseItem<'a>>,
1017}
1018
1019impl<'a> Parse<'a> for Use<'a> {
1020 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
1021 let docs = Parse::parse(lexer)?;
1022 parse_token(lexer, Token::UseKeyword)?;
1023 let path = Parse::parse(lexer)?;
1024 parse_token(lexer, Token::Dot)?;
1025 parse_token(lexer, Token::OpenBrace)?;
1026 let items = parse_delimited(lexer, Token::CloseBrace, true)?;
1027 parse_token(lexer, Token::CloseBrace)?;
1028 parse_token(lexer, Token::Semicolon)?;
1029 Ok(Self { docs, path, items })
1030 }
1031}
1032
1033impl Peek for Use<'_> {
1034 fn peek(lookahead: &mut Lookahead) -> bool {
1035 lookahead.peek(Token::UseKeyword)
1036 }
1037}
1038
1039#[derive(Debug, Clone, Serialize)]
1041#[serde(rename_all = "camelCase")]
1042pub enum UsePath<'a> {
1043 Package(PackagePath<'a>),
1045 Ident(Ident<'a>),
1047}
1048
1049impl<'a> Parse<'a> for UsePath<'a> {
1050 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
1051 let mut lookahead = Lookahead::new(lexer);
1052 if PackagePath::peek(&mut lookahead) {
1053 Ok(Self::Package(Parse::parse(lexer)?))
1054 } else if Ident::peek(&mut lookahead) {
1055 Ok(Self::Ident(Parse::parse(lexer)?))
1056 } else {
1057 Err(lookahead.error())
1058 }
1059 }
1060}
1061
1062impl Peek for UsePath<'_> {
1063 fn peek(lookahead: &mut Lookahead) -> bool {
1064 PackagePath::peek(lookahead) | Ident::peek(lookahead)
1065 }
1066}
1067
1068#[derive(Debug, Clone, Serialize)]
1070#[serde(rename_all = "camelCase")]
1071pub struct UseItem<'a> {
1072 pub id: Ident<'a>,
1074 pub as_id: Option<Ident<'a>>,
1076}
1077
1078impl<'a> Parse<'a> for UseItem<'a> {
1079 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
1080 let id = Ident::parse(lexer)?;
1081 let as_id = parse_optional(lexer, Token::AsKeyword, Ident::parse)?;
1082 Ok(Self { id, as_id })
1083 }
1084}
1085
1086impl Peek for UseItem<'_> {
1087 fn peek(lookahead: &mut Lookahead) -> bool {
1088 Ident::peek(lookahead)
1089 }
1090}
1091
1092#[derive(Debug, Clone, Serialize)]
1094#[serde(rename_all = "camelCase")]
1095pub struct InterfaceExport<'a> {
1096 pub docs: Vec<DocComment<'a>>,
1098 pub id: Ident<'a>,
1100 pub ty: FuncTypeRef<'a>,
1102}
1103
1104impl<'a> Parse<'a> for InterfaceExport<'a> {
1105 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
1106 let docs = Parse::parse(lexer)?;
1107 let id = Ident::parse(lexer)?;
1108 parse_token(lexer, Token::Colon)?;
1109 let ty = Parse::parse(lexer)?;
1110 parse_token(lexer, Token::Semicolon)?;
1111 Ok(Self { docs, id, ty })
1112 }
1113}
1114
1115impl Peek for InterfaceExport<'_> {
1116 fn peek(lookahead: &mut Lookahead) -> bool {
1117 Ident::peek(lookahead)
1118 }
1119}
1120
1121#[derive(Debug, Clone, Serialize)]
1123#[serde(rename_all = "camelCase")]
1124pub struct WorldDecl<'a> {
1125 pub docs: Vec<DocComment<'a>>,
1127 pub id: Ident<'a>,
1129 pub items: Vec<WorldItem<'a>>,
1131}
1132
1133impl<'a> Parse<'a> for WorldDecl<'a> {
1134 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
1135 let docs = Parse::parse(lexer)?;
1136 parse_token(lexer, Token::WorldKeyword)?;
1137 let id = Ident::parse(lexer)?;
1138 parse_token(lexer, Token::OpenBrace)?;
1139 let items = parse_delimited(lexer, Token::CloseBrace, false)?;
1140 parse_token(lexer, Token::CloseBrace)?;
1141 Ok(Self { docs, id, items })
1142 }
1143}
1144
1145impl Peek for WorldDecl<'_> {
1146 fn peek(lookahead: &mut Lookahead) -> bool {
1147 lookahead.peek(Token::WorldKeyword)
1148 }
1149}
1150
1151#[derive(Debug, Clone, Serialize)]
1153#[serde(rename_all = "camelCase")]
1154pub enum WorldItem<'a> {
1155 Use(Use<'a>),
1157 Type(ItemTypeDecl<'a>),
1159 Import(WorldImport<'a>),
1161 Export(WorldExport<'a>),
1163 Include(WorldInclude<'a>),
1165}
1166
1167impl<'a> Parse<'a> for WorldItem<'a> {
1168 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
1169 let mut lookahead = Lookahead::new(lexer);
1170 if Use::peek(&mut lookahead) {
1171 Ok(Self::Use(Parse::parse(lexer)?))
1172 } else if WorldImport::peek(&mut lookahead) {
1173 Ok(Self::Import(Parse::parse(lexer)?))
1174 } else if WorldExport::peek(&mut lookahead) {
1175 Ok(Self::Export(Parse::parse(lexer)?))
1176 } else if WorldInclude::peek(&mut lookahead) {
1177 Ok(Self::Include(Parse::parse(lexer)?))
1178 } else if ItemTypeDecl::peek(&mut lookahead) {
1179 Ok(Self::Type(Parse::parse(lexer)?))
1180 } else {
1181 Err(lookahead.error())
1182 }
1183 }
1184}
1185
1186impl Peek for WorldItem<'_> {
1187 fn peek(lookahead: &mut Lookahead) -> bool {
1188 Use::peek(lookahead)
1189 || WorldImport::peek(lookahead)
1190 || WorldExport::peek(lookahead)
1191 || WorldInclude::peek(lookahead)
1192 || ItemTypeDecl::peek(lookahead)
1193 }
1194}
1195
1196#[derive(Debug, Clone, Serialize)]
1198#[serde(rename_all = "camelCase")]
1199pub struct WorldImport<'a> {
1200 pub docs: Vec<DocComment<'a>>,
1202 pub path: WorldItemPath<'a>,
1204}
1205
1206impl<'a> Parse<'a> for WorldImport<'a> {
1207 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
1208 let docs = Parse::parse(lexer)?;
1209 parse_token(lexer, Token::ImportKeyword)?;
1210 let path = Parse::parse(lexer)?;
1211 parse_token(lexer, Token::Semicolon)?;
1212 Ok(Self { docs, path })
1213 }
1214}
1215
1216impl Peek for WorldImport<'_> {
1217 fn peek(lookahead: &mut Lookahead) -> bool {
1218 lookahead.peek(Token::ImportKeyword)
1219 }
1220}
1221
1222#[derive(Debug, Clone, Serialize)]
1224#[serde(rename_all = "camelCase")]
1225pub struct WorldExport<'a> {
1226 pub docs: Vec<DocComment<'a>>,
1228 pub path: WorldItemPath<'a>,
1230}
1231
1232impl<'a> Parse<'a> for WorldExport<'a> {
1233 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
1234 let docs = Parse::parse(lexer)?;
1235 parse_token(lexer, Token::ExportKeyword)?;
1236 let path = Parse::parse(lexer)?;
1237 parse_token(lexer, Token::Semicolon)?;
1238 Ok(Self { docs, path })
1239 }
1240}
1241
1242impl Peek for WorldExport<'_> {
1243 fn peek(lookahead: &mut Lookahead) -> bool {
1244 lookahead.peek(Token::ExportKeyword)
1245 }
1246}
1247
1248#[derive(Debug, Clone, Serialize)]
1250#[serde(rename_all = "camelCase")]
1251pub enum WorldItemPath<'a> {
1252 Named(NamedWorldItem<'a>),
1254 Package(PackagePath<'a>),
1256 Ident(Ident<'a>),
1258}
1259
1260impl<'a> Parse<'a> for WorldItemPath<'a> {
1261 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
1262 let mut lookahead = Lookahead::new(lexer);
1263 if PackagePath::peek(&mut lookahead) {
1264 Ok(Self::Package(Parse::parse(lexer)?))
1265 } else if Ident::peek(&mut lookahead) {
1266 if let Some((Ok(Token::Colon), _)) = lexer.peek2() {
1268 Ok(Self::Named(Parse::parse(lexer)?))
1269 } else {
1270 Ok(Self::Ident(Parse::parse(lexer)?))
1271 }
1272 } else {
1273 Err(lookahead.error())
1274 }
1275 }
1276}
1277
1278#[derive(Debug, Clone, Serialize)]
1280#[serde(rename_all = "camelCase")]
1281pub struct NamedWorldItem<'a> {
1282 pub id: Ident<'a>,
1284 pub ty: ExternType<'a>,
1286}
1287
1288impl<'a> Parse<'a> for NamedWorldItem<'a> {
1289 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
1290 let id = Ident::parse(lexer)?;
1291 parse_token(lexer, Token::Colon)?;
1292 let ty = Parse::parse(lexer)?;
1293 Ok(Self { id, ty })
1294 }
1295}
1296
1297#[derive(Debug, Clone, Serialize)]
1299#[serde(rename_all = "camelCase")]
1300pub enum ExternType<'a> {
1301 Ident(Ident<'a>),
1303 Func(FuncType<'a>),
1305 Interface(InlineInterface<'a>),
1307}
1308
1309impl<'a> Parse<'a> for ExternType<'a> {
1310 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
1311 let mut lookahead = Lookahead::new(lexer);
1312 if Ident::peek(&mut lookahead) {
1313 Ok(Self::Ident(Parse::parse(lexer)?))
1314 } else if FuncType::peek(&mut lookahead) {
1315 Ok(Self::Func(Parse::parse(lexer)?))
1316 } else if InlineInterface::peek(&mut lookahead) {
1317 Ok(Self::Interface(Parse::parse(lexer)?))
1318 } else {
1319 Err(lookahead.error())
1320 }
1321 }
1322}
1323
1324#[derive(Debug, Clone, Serialize)]
1326#[serde(rename_all = "camelCase")]
1327pub struct InlineInterface<'a> {
1328 pub items: Vec<InterfaceItem<'a>>,
1330}
1331
1332impl<'a> Parse<'a> for InlineInterface<'a> {
1333 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
1334 parse_token(lexer, Token::InterfaceKeyword)?;
1335 parse_token(lexer, Token::OpenBrace)?;
1336 let items = parse_delimited(lexer, Token::CloseBrace, false)?;
1337 parse_token(lexer, Token::CloseBrace)?;
1338 Ok(Self { items })
1339 }
1340}
1341
1342impl Peek for InlineInterface<'_> {
1343 fn peek(lookahead: &mut Lookahead) -> bool {
1344 lookahead.peek(Token::InterfaceKeyword)
1345 }
1346}
1347
1348#[derive(Debug, Clone, Serialize)]
1350#[serde(rename_all = "camelCase")]
1351pub struct WorldInclude<'a> {
1352 pub docs: Vec<DocComment<'a>>,
1354 pub world: WorldRef<'a>,
1356 pub with: Vec<WorldIncludeItem<'a>>,
1358}
1359
1360impl<'a> Parse<'a> for WorldInclude<'a> {
1361 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
1362 let docs = Parse::parse(lexer)?;
1363 parse_token(lexer, Token::IncludeKeyword)?;
1364 let world = Parse::parse(lexer)?;
1365 let with = parse_optional(lexer, Token::WithKeyword, |lexer| {
1366 parse_token(lexer, Token::OpenBrace)?;
1367 let items = parse_delimited(lexer, Token::CloseBrace, true)?;
1368 parse_token(lexer, Token::CloseBrace)?;
1369 Ok(items)
1370 })?
1371 .unwrap_or_default();
1372 parse_token(lexer, Token::Semicolon)?;
1373 Ok(Self { docs, world, with })
1374 }
1375}
1376
1377impl Peek for WorldInclude<'_> {
1378 fn peek(lookahead: &mut Lookahead) -> bool {
1379 lookahead.peek(Token::IncludeKeyword)
1380 }
1381}
1382
1383#[derive(Debug, Clone, Serialize)]
1385#[serde(rename_all = "camelCase")]
1386pub enum WorldRef<'a> {
1387 Ident(Ident<'a>),
1389 Package(PackagePath<'a>),
1391}
1392
1393impl<'a> WorldRef<'a> {
1394 pub fn name(&self) -> &'a str {
1396 match self {
1397 Self::Ident(id) => id.string,
1398 Self::Package(path) => path.string,
1399 }
1400 }
1401
1402 pub fn span(&self) -> SourceSpan {
1404 match self {
1405 Self::Ident(id) => id.span,
1406 Self::Package(path) => path.span,
1407 }
1408 }
1409}
1410
1411impl<'a> Parse<'a> for WorldRef<'a> {
1412 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
1413 let mut lookahead = Lookahead::new(lexer);
1414 if PackagePath::peek(&mut lookahead) {
1415 Ok(Self::Package(Parse::parse(lexer)?))
1416 } else if Ident::peek(&mut lookahead) {
1417 Ok(Self::Ident(Parse::parse(lexer)?))
1418 } else {
1419 Err(lookahead.error())
1420 }
1421 }
1422}
1423
1424#[derive(Debug, Clone, Serialize)]
1426#[serde(rename_all = "camelCase")]
1427pub struct WorldIncludeItem<'a> {
1428 pub from: Ident<'a>,
1430 pub to: Ident<'a>,
1432}
1433
1434impl<'a> Parse<'a> for WorldIncludeItem<'a> {
1435 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
1436 let from = Ident::parse(lexer)?;
1437 parse_token(lexer, Token::AsKeyword)?;
1438 let to = Ident::parse(lexer)?;
1439 Ok(Self { from, to })
1440 }
1441}
1442
1443impl Peek for WorldIncludeItem<'_> {
1444 fn peek(lookahead: &mut Lookahead) -> bool {
1445 Ident::peek(lookahead)
1446 }
1447}
1448
1449#[cfg(test)]
1450mod test {
1451 use crate::ast::test::roundtrip;
1452
1453 #[test]
1454 fn resource_roundtrip() {
1455 roundtrip(
1456 r#"package foo:bar;
1457interface i { resource foo-bar {
1458 /** A constructor */
1459 constructor(foo: u8, bar: u8);
1460 /// A method
1461 foo: func() -> string;
1462 /// A method
1463 set-foo: func(foo: string);
1464 /// A static method
1465 id: static func() -> u32;
1466}}"#,
1467 r#"package foo:bar;
1468
1469interface i {
1470 resource foo-bar {
1471 /// A constructor
1472 constructor(foo: u8, bar: u8);
1473
1474 /// A method
1475 foo: func() -> string;
1476
1477 /// A method
1478 set-foo: func(foo: string);
1479
1480 /// A static method
1481 id: static func() -> u32;
1482 }
1483}
1484"#,
1485 )
1486 .unwrap();
1487 }
1488
1489 #[test]
1490 fn variant_roundtrip() {
1491 roundtrip(
1492 r#"package foo:bar;
1493variant foo {
1494 foo,
1495 bar(u32),
1496 baz(bar),
1497 qux(tuple<u8, u16, u32>)
1498}"#,
1499 r#"package foo:bar;
1500
1501variant foo {
1502 foo,
1503 bar(u32),
1504 baz(bar),
1505 qux(tuple<u8, u16, u32>),
1506}
1507"#,
1508 )
1509 .unwrap();
1510 }
1511
1512 #[test]
1513 fn record_roundtrip() {
1514 roundtrip(
1515 r#"package foo:bar;
1516record foo-bar2-baz {
1517 foo: foo,
1518 bar-qux: list<string>,
1519 // A comment
1520 jam: borrow<foo>,
1521}"#,
1522 r#"package foo:bar;
1523
1524record foo-bar2-baz {
1525 foo: foo,
1526 bar-qux: list<string>,
1527 jam: borrow<foo>,
1528}
1529"#,
1530 )
1531 .unwrap();
1532 }
1533
1534 #[test]
1535 fn flags_roundtrip() {
1536 roundtrip(
1537 r#"package foo:bar;
1538flags %flags {
1539 foo, bar, baz
1540}"#,
1541 r#"package foo:bar;
1542
1543flags %flags {
1544 foo,
1545 bar,
1546 baz,
1547}
1548"#,
1549 )
1550 .unwrap();
1551 }
1552
1553 #[test]
1554 fn enum_roundtrip() {
1555 roundtrip(
1556 r#"package foo:bar; enum foo {
1557 foo, bar, baz
1558}"#,
1559 r#"package foo:bar;
1560
1561enum foo {
1562 foo,
1563 bar,
1564 baz,
1565}
1566"#,
1567 )
1568 .unwrap();
1569 }
1570
1571 #[test]
1572 fn func_type_alias_roundtrip() {
1573 roundtrip(
1574 r#"package foo:bar; type x = func(a: /* comment */ string) -> string;"#,
1575 "package foo:bar;\n\ntype x = func(a: string) -> string;\n",
1576 )
1577 .unwrap();
1578 }
1579
1580 #[test]
1581 fn type_alias_roundtrip() {
1582 roundtrip(
1583 r#"package foo:bar; type x = tuple<u8, s8, u16, s16, u32, s32, u64, s64, f32, f64, char, bool, string, tuple<string, list<u8>>, option<list<bool>>, result, result<string>, result<_, string>, result<u8, u8>, borrow<y>, y>;"#,
1584 "package foo:bar;\n\ntype x = tuple<u8, s8, u16, s16, u32, s32, u64, s64, f32, f64, char, bool, string, tuple<string, list<u8>>, option<list<bool>>, result, result<string>, result<_, string>, result<u8, u8>, borrow<y>, y>;\n",
1585 )
1586 .unwrap();
1587 }
1588
1589 #[test]
1590 fn stream_future_error_context_roundtrip() {
1591 roundtrip(
1593 "package foo:bar; type a = stream;",
1594 "package foo:bar;\n\ntype a = stream;\n",
1595 )
1596 .unwrap();
1597
1598 roundtrip(
1600 "package foo:bar; type b = stream<u8>;",
1601 "package foo:bar;\n\ntype b = stream<u8>;\n",
1602 )
1603 .unwrap();
1604
1605 roundtrip(
1607 "package foo:bar; type c = future;",
1608 "package foo:bar;\n\ntype c = future;\n",
1609 )
1610 .unwrap();
1611
1612 roundtrip(
1614 "package foo:bar; type d = future<string>;",
1615 "package foo:bar;\n\ntype d = future<string>;\n",
1616 )
1617 .unwrap();
1618
1619 roundtrip(
1621 "package foo:bar; type e = error-context;",
1622 "package foo:bar;\n\ntype e = error-context;\n",
1623 )
1624 .unwrap();
1625
1626 roundtrip(
1628 "package foo:bar; type f = stream<stream<u8>>;",
1629 "package foo:bar;\n\ntype f = stream<stream<u8>>;\n",
1630 )
1631 .unwrap();
1632
1633 roundtrip(
1635 "package foo:bar; type g = future<option<u32>>;",
1636 "package foo:bar;\n\ntype g = future<option<u32>>;\n",
1637 )
1638 .unwrap();
1639 }
1640
1641 #[test]
1642 fn async_func_roundtrip() {
1643 roundtrip(
1645 "package foo:bar; type x = async func() -> string;",
1646 "package foo:bar;\n\ntype x = async func() -> string;\n",
1647 )
1648 .unwrap();
1649
1650 roundtrip(
1652 "package foo:bar; type y = async func(a: u32, b: string) -> stream<u8>;",
1653 "package foo:bar;\n\ntype y = async func(a: u32, b: string) -> stream<u8>;\n",
1654 )
1655 .unwrap();
1656
1657 roundtrip(
1659 "package foo:bar; type z = async func();",
1660 "package foo:bar;\n\ntype z = async func();\n",
1661 )
1662 .unwrap();
1663
1664 roundtrip(
1666 "package foo:bar; type w = func() -> u32;",
1667 "package foo:bar;\n\ntype w = func() -> u32;\n",
1668 )
1669 .unwrap();
1670
1671 roundtrip(
1673 "package foo:bar; interface i { do-work: async func(input: string) -> future<u32>; }",
1674 "package foo:bar;\n\ninterface i {\n do-work: async func(input: string) -> future<u32>;\n}\n",
1675 )
1676 .unwrap();
1677
1678 roundtrip(
1680 "package foo:bar; world w { import run: async func(); export process: async func(data: list<u8>) -> stream<u8>; }",
1681 "package foo:bar;\n\nworld w {\n import run: async func();\n\n export process: async func(data: list<u8>) -> stream<u8>;\n}\n",
1682 )
1683 .unwrap();
1684 }
1685
1686 #[test]
1687 fn interface_roundtrip() {
1688 roundtrip(
1689 r#"package foo:bar;
1690
1691interface foo {
1692 /// Type t
1693 type t = list<string>;
1694
1695 /// Use x and y
1696 use foo.{ x, y, };
1697
1698 /// Function a
1699 a: func(a: string, b: string) -> string;
1700
1701 // not a doc comment
1702 type x = func() -> list<string>;
1703
1704 /// Function b
1705 b: x;
1706}
1707 "#,
1708 r#"package foo:bar;
1709
1710interface foo {
1711 /// Type t
1712 type t = list<string>;
1713
1714 /// Use x and y
1715 use foo.{ x, y };
1716
1717 /// Function a
1718 a: func(a: string, b: string) -> string;
1719
1720 type x = func() -> list<string>;
1721
1722 /// Function b
1723 b: x;
1724}
1725"#,
1726 )
1727 .unwrap();
1728 }
1729
1730 #[test]
1731 fn world_roundtrip() {
1732 roundtrip(
1733 r#"package foo:bar;
1734
1735world foo {
1736 /// Type t
1737 type t = list<string>;
1738
1739 // not a doc comment
1740 type x = func() -> list<string>;
1741
1742 use foo.{ y, };
1743
1744 /// Import with function type.
1745 import a: func(a: string, b: string) -> string;
1746
1747 /// Import with identifier.
1748 import b: x;
1749
1750 /// Import with inline interface.
1751 import c: interface {
1752 /// Function a
1753 a: func(a: string, b: string) -> string;
1754 };
1755
1756 /// Import with package path
1757 import foo:bar/baz@1.0.0;
1758
1759 /// Export with function type.
1760 export a: func(a: string, b: string) -> string;
1761
1762 /// Export with identifier.
1763 export b: x;
1764
1765 /// Export with inline interface.
1766 export c: interface {
1767 /// Function a
1768 a: func(a: string, b: string) -> string;
1769 };
1770
1771 /// Export with package path
1772 export foo:bar/baz@1.0.0;
1773
1774 /// Include world from package path with 2 renames.
1775 include foo:bar/baz with { a as a1, b as b1 };
1776
1777 /// Include world from package path with 1 rename.
1778 include foo:bar/baz with {foo as foo1};
1779
1780 /// Include world from package path (spacing).
1781 include foo:bar/baz with { foo as foo1 };
1782
1783 /// Include world from package path newline delimited renaming.
1784 include foo:bar/baz with {
1785 foo as foo1,
1786 bar as bar1
1787 };
1788
1789 /// Include local world.
1790 include foo-bar;
1791
1792 /// Include local world with renaming.
1793 include foo-bar with { foo as bar };
1794}"#,
1795 r#"package foo:bar;
1796
1797world foo {
1798 /// Type t
1799 type t = list<string>;
1800
1801 type x = func() -> list<string>;
1802
1803 use foo.{ y };
1804
1805 /// Import with function type.
1806 import a: func(a: string, b: string) -> string;
1807
1808 /// Import with identifier.
1809 import b: x;
1810
1811 /// Import with inline interface.
1812 import c: interface {
1813 /// Function a
1814 a: func(a: string, b: string) -> string;
1815 };
1816
1817 /// Import with package path
1818 import foo:bar/baz@1.0.0;
1819
1820 /// Export with function type.
1821 export a: func(a: string, b: string) -> string;
1822
1823 /// Export with identifier.
1824 export b: x;
1825
1826 /// Export with inline interface.
1827 export c: interface {
1828 /// Function a
1829 a: func(a: string, b: string) -> string;
1830 };
1831
1832 /// Export with package path
1833 export foo:bar/baz@1.0.0;
1834
1835 /// Include world from package path with 2 renames.
1836 include foo:bar/baz with {
1837 a as a1,
1838 b as b1,
1839 };
1840
1841 /// Include world from package path with 1 rename.
1842 include foo:bar/baz with {
1843 foo as foo1,
1844 };
1845
1846 /// Include world from package path (spacing).
1847 include foo:bar/baz with {
1848 foo as foo1,
1849 };
1850
1851 /// Include world from package path newline delimited renaming.
1852 include foo:bar/baz with {
1853 foo as foo1,
1854 bar as bar1,
1855 };
1856
1857 /// Include local world.
1858 include foo-bar;
1859
1860 /// Include local world with renaming.
1861 include foo-bar with {
1862 foo as bar,
1863 };
1864}
1865"#,
1866 )
1867 .unwrap();
1868 }
1869}