1use super::{
2 parse_delimited, parse_optional, parse_token, DocComment, Error, Ident, Lookahead, PackagePath,
3 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::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 params: Vec<NamedType<'a>>,
501 pub results: ResultList<'a>,
503}
504
505impl<'a> Parse<'a> for FuncType<'a> {
506 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
507 parse_token(lexer, Token::FuncKeyword)?;
508 parse_token(lexer, Token::OpenParen)?;
509 let params = parse_delimited(lexer, Token::CloseParen, true)?;
510 parse_token(lexer, Token::CloseParen)?;
511 let results =
512 parse_optional(lexer, Token::Arrow, Parse::parse)?.unwrap_or(ResultList::Empty);
513
514 Ok(Self { params, results })
515 }
516}
517
518impl Peek for FuncType<'_> {
519 fn peek(lookahead: &mut Lookahead) -> bool {
520 lookahead.peek(Token::FuncKeyword)
521 }
522}
523
524#[derive(Debug, Clone, Serialize)]
526#[serde(rename_all = "camelCase")]
527pub enum ResultList<'a> {
528 Empty,
530 Scalar(Type<'a>),
532 Named(Vec<NamedType<'a>>),
534}
535
536impl<'a> Parse<'a> for ResultList<'a> {
537 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
538 let mut lookahead = Lookahead::new(lexer);
539 if lookahead.peek(Token::OpenParen) {
540 parse_token(lexer, Token::OpenParen)?;
541 let results = parse_delimited(lexer, Token::CloseParen, true)?;
542 parse_token(lexer, Token::CloseParen)?;
543 Ok(Self::Named(results))
544 } else 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::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 Ident(Ident<'a>),
673}
674
675impl<'a> Type<'a> {
676 pub fn span(&self) -> SourceSpan {
678 match self {
679 Self::U8(span)
680 | Self::S8(span)
681 | Self::U16(span)
682 | Self::S16(span)
683 | Self::U32(span)
684 | Self::S32(span)
685 | Self::U64(span)
686 | Self::S64(span)
687 | Self::F32(span)
688 | Self::F64(span)
689 | Self::Char(span)
690 | Self::Bool(span)
691 | Self::String(span)
692 | Self::Tuple(_, span)
693 | Self::List(_, span)
694 | Self::Option(_, span)
695 | Self::Result { span, .. }
696 | Self::Borrow(_, span) => *span,
697 Self::Ident(ident) => ident.span,
698 }
699 }
700}
701
702impl<'a> Parse<'a> for Type<'a> {
703 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
704 let mut lookahead = Lookahead::new(lexer);
705 if lookahead.peek(Token::U8Keyword) {
706 Ok(Self::U8(lexer.next().unwrap().1))
707 } else if lookahead.peek(Token::S8Keyword) {
708 Ok(Self::S8(lexer.next().unwrap().1))
709 } else if lookahead.peek(Token::U16Keyword) {
710 Ok(Self::U16(lexer.next().unwrap().1))
711 } else if lookahead.peek(Token::S16Keyword) {
712 Ok(Self::S16(lexer.next().unwrap().1))
713 } else if lookahead.peek(Token::U32Keyword) {
714 Ok(Self::U32(lexer.next().unwrap().1))
715 } else if lookahead.peek(Token::S32Keyword) {
716 Ok(Self::S32(lexer.next().unwrap().1))
717 } else if lookahead.peek(Token::U64Keyword) {
718 Ok(Self::U64(lexer.next().unwrap().1))
719 } else if lookahead.peek(Token::S64Keyword) {
720 Ok(Self::S64(lexer.next().unwrap().1))
721 } else if lookahead.peek(Token::F32Keyword) {
722 Ok(Self::F32(lexer.next().unwrap().1))
723 } else if lookahead.peek(Token::F64Keyword) {
724 Ok(Self::F64(lexer.next().unwrap().1))
725 } else if lookahead.peek(Token::CharKeyword) {
726 Ok(Self::Char(lexer.next().unwrap().1))
727 } else if lookahead.peek(Token::BoolKeyword) {
728 Ok(Self::Bool(lexer.next().unwrap().1))
729 } else if lookahead.peek(Token::StringKeyword) {
730 Ok(Self::String(lexer.next().unwrap().1))
731 } else if lookahead.peek(Token::TupleKeyword) {
732 let span = lexer.next().unwrap().1;
733 parse_token(lexer, Token::OpenAngle)?;
734
735 let mut lookahead = Lookahead::new(lexer);
737 if !Type::peek(&mut lookahead) {
738 return Err(lookahead.error());
739 }
740
741 let types = parse_delimited(lexer, Token::CloseAngle, true)?;
742 assert!(!types.is_empty());
743 let close = parse_token(lexer, Token::CloseAngle)?;
744 Ok(Self::Tuple(
745 types,
746 SourceSpan::new(
747 span.offset().into(),
748 (close.offset() + close.len()) - span.offset(),
749 ),
750 ))
751 } else if lookahead.peek(Token::ListKeyword) {
752 let span = lexer.next().unwrap().1;
753 parse_token(lexer, Token::OpenAngle)?;
754 let ty = Box::new(Parse::parse(lexer)?);
755 let close = parse_token(lexer, Token::CloseAngle)?;
756 Ok(Self::List(
757 ty,
758 SourceSpan::new(
759 span.offset().into(),
760 (close.offset() + close.len()) - span.offset(),
761 ),
762 ))
763 } else if lookahead.peek(Token::OptionKeyword) {
764 let span = lexer.next().unwrap().1;
765 parse_token(lexer, Token::OpenAngle)?;
766 let ty = Box::new(Parse::parse(lexer)?);
767 let close = parse_token(lexer, Token::CloseAngle)?;
768 Ok(Self::Option(
769 ty,
770 SourceSpan::new(
771 span.offset().into(),
772 (close.offset() + close.len()) - span.offset(),
773 ),
774 ))
775 } else if lookahead.peek(Token::ResultKeyword) {
776 let mut span = lexer.next().unwrap().1;
777
778 let parse = |lexer: &mut Lexer<'a>| {
779 let mut lookahead = Lookahead::new(lexer);
780 let ok = if lookahead.peek(Token::Underscore) {
781 lexer.next();
782 None
783 } else if Type::peek(&mut lookahead) {
784 Some(Box::new(Parse::parse(lexer)?))
785 } else {
786 return Err(lookahead.error());
787 };
788
789 let err = parse_optional(lexer, Token::Comma, |lexer| {
790 let mut lookahead = Lookahead::new(lexer);
791 if lookahead.peek(Token::Underscore) {
792 lexer.next();
793 Ok(None)
794 } else if Type::peek(&mut lookahead) {
795 Ok(Some(Box::new(Parse::parse(lexer)?)))
796 } else {
797 return Err(lookahead.error());
798 }
799 })?
800 .unwrap_or(None);
801
802 let close = parse_token(lexer, Token::CloseAngle)?;
803 span = SourceSpan::new(
804 span.offset().into(),
805 (close.offset() + close.len()) - span.offset(),
806 );
807 Ok((ok, err))
808 };
809
810 let (ok, err) = match parse_optional(lexer, Token::OpenAngle, parse)? {
811 Some((ok, err)) => (ok, err),
812 None => (None, None),
813 };
814 Ok(Self::Result { ok, err, span })
815 } else if lookahead.peek(Token::BorrowKeyword) {
816 let span = lexer.next().unwrap().1;
817 parse_token(lexer, Token::OpenAngle)?;
818 let id = Parse::parse(lexer)?;
819 let close = parse_token(lexer, Token::CloseAngle)?;
820 Ok(Self::Borrow(
821 id,
822 SourceSpan::new(
823 span.offset().into(),
824 (close.offset() + close.len()) - span.offset(),
825 ),
826 ))
827 } else if Ident::peek(&mut lookahead) {
828 Ok(Self::Ident(Parse::parse(lexer)?))
829 } else {
830 Err(lookahead.error())
831 }
832 }
833}
834
835impl Peek for Type<'_> {
836 fn peek(lookahead: &mut Lookahead) -> bool {
837 lookahead.peek(Token::U8Keyword)
838 || lookahead.peek(Token::S8Keyword)
839 || lookahead.peek(Token::U16Keyword)
840 || lookahead.peek(Token::S16Keyword)
841 || lookahead.peek(Token::U32Keyword)
842 || lookahead.peek(Token::S32Keyword)
843 || lookahead.peek(Token::U64Keyword)
844 || lookahead.peek(Token::S64Keyword)
845 || lookahead.peek(Token::F32Keyword)
846 || lookahead.peek(Token::F64Keyword)
847 || lookahead.peek(Token::CharKeyword)
848 || lookahead.peek(Token::BoolKeyword)
849 || lookahead.peek(Token::StringKeyword)
850 || lookahead.peek(Token::TupleKeyword)
851 || lookahead.peek(Token::ListKeyword)
852 || lookahead.peek(Token::OptionKeyword)
853 || lookahead.peek(Token::ResultKeyword)
854 || lookahead.peek(Token::BorrowKeyword)
855 || Ident::peek(lookahead)
856 }
857}
858
859#[derive(Debug, Clone, Serialize)]
864#[serde(rename_all = "camelCase")]
865pub enum ItemTypeDecl<'a> {
866 Resource(ResourceDecl<'a>),
868 Variant(VariantDecl<'a>),
870 Record(RecordDecl<'a>),
872 Flags(FlagsDecl<'a>),
874 Enum(EnumDecl<'a>),
876 Alias(TypeAlias<'a>),
878}
879
880impl<'a> Parse<'a> for ItemTypeDecl<'a> {
881 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
882 let mut lookahead = Lookahead::new(lexer);
883 if lookahead.peek(Token::ResourceKeyword) {
884 Ok(Self::Resource(Parse::parse(lexer)?))
885 } else if lookahead.peek(Token::VariantKeyword) {
886 Ok(Self::Variant(Parse::parse(lexer)?))
887 } else if lookahead.peek(Token::RecordKeyword) {
888 Ok(Self::Record(Parse::parse(lexer)?))
889 } else if lookahead.peek(Token::FlagsKeyword) {
890 Ok(Self::Flags(Parse::parse(lexer)?))
891 } else if lookahead.peek(Token::EnumKeyword) {
892 Ok(Self::Enum(Parse::parse(lexer)?))
893 } else if lookahead.peek(Token::TypeKeyword) {
894 Ok(Self::Alias(Parse::parse(lexer)?))
895 } else {
896 Err(lookahead.error())
897 }
898 }
899}
900
901impl Peek for ItemTypeDecl<'_> {
902 fn peek(lookahead: &mut Lookahead) -> bool {
903 lookahead.peek(Token::ResourceKeyword)
904 || lookahead.peek(Token::VariantKeyword)
905 || lookahead.peek(Token::RecordKeyword)
906 || lookahead.peek(Token::FlagsKeyword)
907 || lookahead.peek(Token::EnumKeyword)
908 || lookahead.peek(Token::TypeKeyword)
909 }
910}
911
912impl ItemTypeDecl<'_> {
913 pub fn id(&self) -> &Ident {
915 match self {
916 Self::Resource(resource) => &resource.id,
917 Self::Variant(variant) => &variant.id,
918 Self::Record(record) => &record.id,
919 Self::Flags(flags) => &flags.id,
920 Self::Enum(e) => &e.id,
921 Self::Alias(alias) => &alias.id,
922 }
923 }
924}
925
926#[derive(Debug, Clone, Serialize)]
928#[serde(rename_all = "camelCase")]
929pub struct InterfaceDecl<'a> {
930 pub docs: Vec<DocComment<'a>>,
932 pub id: Ident<'a>,
934 pub items: Vec<InterfaceItem<'a>>,
936}
937
938impl<'a> Parse<'a> for InterfaceDecl<'a> {
939 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
940 let docs = Parse::parse(lexer)?;
941 parse_token(lexer, Token::InterfaceKeyword)?;
942 let id = Ident::parse(lexer)?;
943 parse_token(lexer, Token::OpenBrace)?;
944 let items = parse_delimited(lexer, Token::CloseBrace, false)?;
945 parse_token(lexer, Token::CloseBrace)?;
946 Ok(Self { docs, id, items })
947 }
948}
949
950impl Peek for InterfaceDecl<'_> {
951 fn peek(lookahead: &mut Lookahead) -> bool {
952 lookahead.peek(Token::InterfaceKeyword)
953 }
954}
955
956#[derive(Debug, Clone, Serialize)]
958#[serde(rename_all = "camelCase")]
959pub enum InterfaceItem<'a> {
960 Use(Box<Use<'a>>),
962 Type(ItemTypeDecl<'a>),
964 Export(InterfaceExport<'a>),
966}
967
968impl<'a> Parse<'a> for InterfaceItem<'a> {
969 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
970 let mut lookahead = Lookahead::new(lexer);
971 if Use::peek(&mut lookahead) {
972 Ok(Self::Use(Box::new(Parse::parse(lexer)?)))
973 } else if InterfaceExport::peek(&mut lookahead) {
974 Ok(Self::Export(Parse::parse(lexer)?))
975 } else if ItemTypeDecl::peek(&mut lookahead) {
976 Ok(Self::Type(Parse::parse(lexer)?))
977 } else {
978 Err(lookahead.error())
979 }
980 }
981}
982
983impl Peek for InterfaceItem<'_> {
984 fn peek(lookahead: &mut Lookahead) -> bool {
985 Use::peek(lookahead) || InterfaceExport::peek(lookahead) || ItemTypeDecl::peek(lookahead)
986 }
987}
988
989#[derive(Debug, Clone, Serialize)]
991#[serde(rename_all = "camelCase")]
992pub struct Use<'a> {
993 pub docs: Vec<DocComment<'a>>,
995 pub path: UsePath<'a>,
997 pub items: Vec<UseItem<'a>>,
999}
1000
1001impl<'a> Parse<'a> for Use<'a> {
1002 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
1003 let docs = Parse::parse(lexer)?;
1004 parse_token(lexer, Token::UseKeyword)?;
1005 let path = Parse::parse(lexer)?;
1006 parse_token(lexer, Token::Dot)?;
1007 parse_token(lexer, Token::OpenBrace)?;
1008 let items = parse_delimited(lexer, Token::CloseBrace, true)?;
1009 parse_token(lexer, Token::CloseBrace)?;
1010 parse_token(lexer, Token::Semicolon)?;
1011 Ok(Self { docs, path, items })
1012 }
1013}
1014
1015impl Peek for Use<'_> {
1016 fn peek(lookahead: &mut Lookahead) -> bool {
1017 lookahead.peek(Token::UseKeyword)
1018 }
1019}
1020
1021#[derive(Debug, Clone, Serialize)]
1023#[serde(rename_all = "camelCase")]
1024pub enum UsePath<'a> {
1025 Package(PackagePath<'a>),
1027 Ident(Ident<'a>),
1029}
1030
1031impl<'a> Parse<'a> for UsePath<'a> {
1032 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
1033 let mut lookahead = Lookahead::new(lexer);
1034 if PackagePath::peek(&mut lookahead) {
1035 Ok(Self::Package(Parse::parse(lexer)?))
1036 } else if Ident::peek(&mut lookahead) {
1037 Ok(Self::Ident(Parse::parse(lexer)?))
1038 } else {
1039 Err(lookahead.error())
1040 }
1041 }
1042}
1043
1044impl Peek for UsePath<'_> {
1045 fn peek(lookahead: &mut Lookahead) -> bool {
1046 PackagePath::peek(lookahead) | Ident::peek(lookahead)
1047 }
1048}
1049
1050#[derive(Debug, Clone, Serialize)]
1052#[serde(rename_all = "camelCase")]
1053pub struct UseItem<'a> {
1054 pub id: Ident<'a>,
1056 pub as_id: Option<Ident<'a>>,
1058}
1059
1060impl<'a> Parse<'a> for UseItem<'a> {
1061 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
1062 let id = Ident::parse(lexer)?;
1063 let as_id = parse_optional(lexer, Token::AsKeyword, Ident::parse)?;
1064 Ok(Self { id, as_id })
1065 }
1066}
1067
1068impl Peek for UseItem<'_> {
1069 fn peek(lookahead: &mut Lookahead) -> bool {
1070 Ident::peek(lookahead)
1071 }
1072}
1073
1074#[derive(Debug, Clone, Serialize)]
1076#[serde(rename_all = "camelCase")]
1077pub struct InterfaceExport<'a> {
1078 pub docs: Vec<DocComment<'a>>,
1080 pub id: Ident<'a>,
1082 pub ty: FuncTypeRef<'a>,
1084}
1085
1086impl<'a> Parse<'a> for InterfaceExport<'a> {
1087 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
1088 let docs = Parse::parse(lexer)?;
1089 let id = Ident::parse(lexer)?;
1090 parse_token(lexer, Token::Colon)?;
1091 let ty = Parse::parse(lexer)?;
1092 parse_token(lexer, Token::Semicolon)?;
1093 Ok(Self { docs, id, ty })
1094 }
1095}
1096
1097impl Peek for InterfaceExport<'_> {
1098 fn peek(lookahead: &mut Lookahead) -> bool {
1099 Ident::peek(lookahead)
1100 }
1101}
1102
1103#[derive(Debug, Clone, Serialize)]
1105#[serde(rename_all = "camelCase")]
1106pub struct WorldDecl<'a> {
1107 pub docs: Vec<DocComment<'a>>,
1109 pub id: Ident<'a>,
1111 pub items: Vec<WorldItem<'a>>,
1113}
1114
1115impl<'a> Parse<'a> for WorldDecl<'a> {
1116 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
1117 let docs = Parse::parse(lexer)?;
1118 parse_token(lexer, Token::WorldKeyword)?;
1119 let id = Ident::parse(lexer)?;
1120 parse_token(lexer, Token::OpenBrace)?;
1121 let items = parse_delimited(lexer, Token::CloseBrace, false)?;
1122 parse_token(lexer, Token::CloseBrace)?;
1123 Ok(Self { docs, id, items })
1124 }
1125}
1126
1127impl Peek for WorldDecl<'_> {
1128 fn peek(lookahead: &mut Lookahead) -> bool {
1129 lookahead.peek(Token::WorldKeyword)
1130 }
1131}
1132
1133#[derive(Debug, Clone, Serialize)]
1135#[serde(rename_all = "camelCase")]
1136pub enum WorldItem<'a> {
1137 Use(Use<'a>),
1139 Type(ItemTypeDecl<'a>),
1141 Import(WorldImport<'a>),
1143 Export(WorldExport<'a>),
1145 Include(WorldInclude<'a>),
1147}
1148
1149impl<'a> Parse<'a> for WorldItem<'a> {
1150 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
1151 let mut lookahead = Lookahead::new(lexer);
1152 if Use::peek(&mut lookahead) {
1153 Ok(Self::Use(Parse::parse(lexer)?))
1154 } else if WorldImport::peek(&mut lookahead) {
1155 Ok(Self::Import(Parse::parse(lexer)?))
1156 } else if WorldExport::peek(&mut lookahead) {
1157 Ok(Self::Export(Parse::parse(lexer)?))
1158 } else if WorldInclude::peek(&mut lookahead) {
1159 Ok(Self::Include(Parse::parse(lexer)?))
1160 } else if ItemTypeDecl::peek(&mut lookahead) {
1161 Ok(Self::Type(Parse::parse(lexer)?))
1162 } else {
1163 Err(lookahead.error())
1164 }
1165 }
1166}
1167
1168impl Peek for WorldItem<'_> {
1169 fn peek(lookahead: &mut Lookahead) -> bool {
1170 Use::peek(lookahead)
1171 || WorldImport::peek(lookahead)
1172 || WorldExport::peek(lookahead)
1173 || WorldInclude::peek(lookahead)
1174 || ItemTypeDecl::peek(lookahead)
1175 }
1176}
1177
1178#[derive(Debug, Clone, Serialize)]
1180#[serde(rename_all = "camelCase")]
1181pub struct WorldImport<'a> {
1182 pub docs: Vec<DocComment<'a>>,
1184 pub path: WorldItemPath<'a>,
1186}
1187
1188impl<'a> Parse<'a> for WorldImport<'a> {
1189 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
1190 let docs = Parse::parse(lexer)?;
1191 parse_token(lexer, Token::ImportKeyword)?;
1192 let path = Parse::parse(lexer)?;
1193 parse_token(lexer, Token::Semicolon)?;
1194 Ok(Self { docs, path })
1195 }
1196}
1197
1198impl Peek for WorldImport<'_> {
1199 fn peek(lookahead: &mut Lookahead) -> bool {
1200 lookahead.peek(Token::ImportKeyword)
1201 }
1202}
1203
1204#[derive(Debug, Clone, Serialize)]
1206#[serde(rename_all = "camelCase")]
1207pub struct WorldExport<'a> {
1208 pub docs: Vec<DocComment<'a>>,
1210 pub path: WorldItemPath<'a>,
1212}
1213
1214impl<'a> Parse<'a> for WorldExport<'a> {
1215 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
1216 let docs = Parse::parse(lexer)?;
1217 parse_token(lexer, Token::ExportKeyword)?;
1218 let path = Parse::parse(lexer)?;
1219 parse_token(lexer, Token::Semicolon)?;
1220 Ok(Self { docs, path })
1221 }
1222}
1223
1224impl Peek for WorldExport<'_> {
1225 fn peek(lookahead: &mut Lookahead) -> bool {
1226 lookahead.peek(Token::ExportKeyword)
1227 }
1228}
1229
1230#[derive(Debug, Clone, Serialize)]
1232#[serde(rename_all = "camelCase")]
1233pub enum WorldItemPath<'a> {
1234 Named(NamedWorldItem<'a>),
1236 Package(PackagePath<'a>),
1238 Ident(Ident<'a>),
1240}
1241
1242impl<'a> Parse<'a> for WorldItemPath<'a> {
1243 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
1244 let mut lookahead = Lookahead::new(lexer);
1245 if PackagePath::peek(&mut lookahead) {
1246 Ok(Self::Package(Parse::parse(lexer)?))
1247 } else if Ident::peek(&mut lookahead) {
1248 if let Some((Ok(Token::Colon), _)) = lexer.peek2() {
1250 Ok(Self::Named(Parse::parse(lexer)?))
1251 } else {
1252 Ok(Self::Ident(Parse::parse(lexer)?))
1253 }
1254 } else {
1255 Err(lookahead.error())
1256 }
1257 }
1258}
1259
1260#[derive(Debug, Clone, Serialize)]
1262#[serde(rename_all = "camelCase")]
1263pub struct NamedWorldItem<'a> {
1264 pub id: Ident<'a>,
1266 pub ty: ExternType<'a>,
1268}
1269
1270impl<'a> Parse<'a> for NamedWorldItem<'a> {
1271 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
1272 let id = Ident::parse(lexer)?;
1273 parse_token(lexer, Token::Colon)?;
1274 let ty = Parse::parse(lexer)?;
1275 Ok(Self { id, ty })
1276 }
1277}
1278
1279#[derive(Debug, Clone, Serialize)]
1281#[serde(rename_all = "camelCase")]
1282pub enum ExternType<'a> {
1283 Ident(Ident<'a>),
1285 Func(FuncType<'a>),
1287 Interface(InlineInterface<'a>),
1289}
1290
1291impl<'a> Parse<'a> for ExternType<'a> {
1292 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
1293 let mut lookahead = Lookahead::new(lexer);
1294 if Ident::peek(&mut lookahead) {
1295 Ok(Self::Ident(Parse::parse(lexer)?))
1296 } else if FuncType::peek(&mut lookahead) {
1297 Ok(Self::Func(Parse::parse(lexer)?))
1298 } else if InlineInterface::peek(&mut lookahead) {
1299 Ok(Self::Interface(Parse::parse(lexer)?))
1300 } else {
1301 Err(lookahead.error())
1302 }
1303 }
1304}
1305
1306#[derive(Debug, Clone, Serialize)]
1308#[serde(rename_all = "camelCase")]
1309pub struct InlineInterface<'a> {
1310 pub items: Vec<InterfaceItem<'a>>,
1312}
1313
1314impl<'a> Parse<'a> for InlineInterface<'a> {
1315 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
1316 parse_token(lexer, Token::InterfaceKeyword)?;
1317 parse_token(lexer, Token::OpenBrace)?;
1318 let items = parse_delimited(lexer, Token::CloseBrace, false)?;
1319 parse_token(lexer, Token::CloseBrace)?;
1320 Ok(Self { items })
1321 }
1322}
1323
1324impl Peek for InlineInterface<'_> {
1325 fn peek(lookahead: &mut Lookahead) -> bool {
1326 lookahead.peek(Token::InterfaceKeyword)
1327 }
1328}
1329
1330#[derive(Debug, Clone, Serialize)]
1332#[serde(rename_all = "camelCase")]
1333pub struct WorldInclude<'a> {
1334 pub docs: Vec<DocComment<'a>>,
1336 pub world: WorldRef<'a>,
1338 pub with: Vec<WorldIncludeItem<'a>>,
1340}
1341
1342impl<'a> Parse<'a> for WorldInclude<'a> {
1343 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
1344 let docs = Parse::parse(lexer)?;
1345 parse_token(lexer, Token::IncludeKeyword)?;
1346 let world = Parse::parse(lexer)?;
1347 let with = parse_optional(lexer, Token::WithKeyword, |lexer| {
1348 parse_token(lexer, Token::OpenBrace)?;
1349 let items = parse_delimited(lexer, Token::CloseBrace, true)?;
1350 parse_token(lexer, Token::CloseBrace)?;
1351 Ok(items)
1352 })?
1353 .unwrap_or_default();
1354 parse_token(lexer, Token::Semicolon)?;
1355 Ok(Self { docs, world, with })
1356 }
1357}
1358
1359impl Peek for WorldInclude<'_> {
1360 fn peek(lookahead: &mut Lookahead) -> bool {
1361 lookahead.peek(Token::IncludeKeyword)
1362 }
1363}
1364
1365#[derive(Debug, Clone, Serialize)]
1367#[serde(rename_all = "camelCase")]
1368pub enum WorldRef<'a> {
1369 Ident(Ident<'a>),
1371 Package(PackagePath<'a>),
1373}
1374
1375impl<'a> WorldRef<'a> {
1376 pub fn name(&self) -> &'a str {
1378 match self {
1379 Self::Ident(id) => id.string,
1380 Self::Package(path) => path.string,
1381 }
1382 }
1383
1384 pub fn span(&self) -> SourceSpan {
1386 match self {
1387 Self::Ident(id) => id.span,
1388 Self::Package(path) => path.span,
1389 }
1390 }
1391}
1392
1393impl<'a> Parse<'a> for WorldRef<'a> {
1394 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
1395 let mut lookahead = Lookahead::new(lexer);
1396 if PackagePath::peek(&mut lookahead) {
1397 Ok(Self::Package(Parse::parse(lexer)?))
1398 } else if Ident::peek(&mut lookahead) {
1399 Ok(Self::Ident(Parse::parse(lexer)?))
1400 } else {
1401 Err(lookahead.error())
1402 }
1403 }
1404}
1405
1406#[derive(Debug, Clone, Serialize)]
1408#[serde(rename_all = "camelCase")]
1409pub struct WorldIncludeItem<'a> {
1410 pub from: Ident<'a>,
1412 pub to: Ident<'a>,
1414}
1415
1416impl<'a> Parse<'a> for WorldIncludeItem<'a> {
1417 fn parse(lexer: &mut Lexer<'a>) -> ParseResult<Self> {
1418 let from = Ident::parse(lexer)?;
1419 parse_token(lexer, Token::AsKeyword)?;
1420 let to = Ident::parse(lexer)?;
1421 Ok(Self { from, to })
1422 }
1423}
1424
1425impl Peek for WorldIncludeItem<'_> {
1426 fn peek(lookahead: &mut Lookahead) -> bool {
1427 Ident::peek(lookahead)
1428 }
1429}
1430
1431#[cfg(test)]
1432mod test {
1433 use crate::ast::test::roundtrip;
1434
1435 #[test]
1436 fn resource_roundtrip() {
1437 roundtrip(
1438 r#"package foo:bar;
1439interface i { resource foo-bar {
1440 /** A constructor */
1441 constructor(foo: u8, bar: u8);
1442 /// A method
1443 foo: func() -> string;
1444 /// A method
1445 set-foo: func(foo: string);
1446 /// A static method
1447 id: static func() -> u32;
1448}}"#,
1449 r#"package foo:bar;
1450
1451interface i {
1452 resource foo-bar {
1453 /// A constructor
1454 constructor(foo: u8, bar: u8);
1455
1456 /// A method
1457 foo: func() -> string;
1458
1459 /// A method
1460 set-foo: func(foo: string);
1461
1462 /// A static method
1463 id: static func() -> u32;
1464 }
1465}
1466"#,
1467 )
1468 .unwrap();
1469 }
1470
1471 #[test]
1472 fn variant_roundtrip() {
1473 roundtrip(
1474 r#"package foo:bar;
1475variant foo {
1476 foo,
1477 bar(u32),
1478 baz(bar),
1479 qux(tuple<u8, u16, u32>)
1480}"#,
1481 r#"package foo:bar;
1482
1483variant foo {
1484 foo,
1485 bar(u32),
1486 baz(bar),
1487 qux(tuple<u8, u16, u32>),
1488}
1489"#,
1490 )
1491 .unwrap();
1492 }
1493
1494 #[test]
1495 fn record_roundtrip() {
1496 roundtrip(
1497 r#"package foo:bar;
1498record foo-bar2-baz {
1499 foo: foo,
1500 bar-qux: list<string>,
1501 // A comment
1502 jam: borrow<foo>,
1503}"#,
1504 r#"package foo:bar;
1505
1506record foo-bar2-baz {
1507 foo: foo,
1508 bar-qux: list<string>,
1509 jam: borrow<foo>,
1510}
1511"#,
1512 )
1513 .unwrap();
1514 }
1515
1516 #[test]
1517 fn flags_roundtrip() {
1518 roundtrip(
1519 r#"package foo:bar;
1520flags %flags {
1521 foo, bar, baz
1522}"#,
1523 r#"package foo:bar;
1524
1525flags %flags {
1526 foo,
1527 bar,
1528 baz,
1529}
1530"#,
1531 )
1532 .unwrap();
1533 }
1534
1535 #[test]
1536 fn enum_roundtrip() {
1537 roundtrip(
1538 r#"package foo:bar; enum foo {
1539 foo, bar, baz
1540}"#,
1541 r#"package foo:bar;
1542
1543enum foo {
1544 foo,
1545 bar,
1546 baz,
1547}
1548"#,
1549 )
1550 .unwrap();
1551 }
1552
1553 #[test]
1554 fn func_type_alias_roundtrip() {
1555 roundtrip(
1556 r#"package foo:bar; type x = func(a: /* comment */ string) -> string;"#,
1557 "package foo:bar;\n\ntype x = func(a: string) -> string;\n",
1558 )
1559 .unwrap();
1560 }
1561
1562 #[test]
1563 fn type_alias_roundtrip() {
1564 roundtrip(
1565 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>;"#,
1566 "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",
1567 )
1568 .unwrap();
1569 }
1570
1571 #[test]
1572 fn interface_roundtrip() {
1573 roundtrip(
1574 r#"package foo:bar;
1575
1576interface foo {
1577 /// Type t
1578 type t = list<string>;
1579
1580 /// Use x and y
1581 use foo.{ x, y, };
1582
1583 /// Function a
1584 a: func(a: string, b: string) -> string;
1585
1586 // not a doc comment
1587 type x = func() -> list<string>;
1588
1589 /// Function b
1590 b: x;
1591}
1592 "#,
1593 r#"package foo:bar;
1594
1595interface foo {
1596 /// Type t
1597 type t = list<string>;
1598
1599 /// Use x and y
1600 use foo.{ x, y };
1601
1602 /// Function a
1603 a: func(a: string, b: string) -> string;
1604
1605 type x = func() -> list<string>;
1606
1607 /// Function b
1608 b: x;
1609}
1610"#,
1611 )
1612 .unwrap();
1613 }
1614
1615 #[test]
1616 fn world_roundtrip() {
1617 roundtrip(
1618 r#"package foo:bar;
1619
1620world foo {
1621 /// Type t
1622 type t = list<string>;
1623
1624 // not a doc comment
1625 type x = func() -> list<string>;
1626
1627 use foo.{ y, };
1628
1629 /// Import with function type.
1630 import a: func(a: string, b: string) -> string;
1631
1632 /// Import with identifier.
1633 import b: x;
1634
1635 /// Import with inline interface.
1636 import c: interface {
1637 /// Function a
1638 a: func(a: string, b: string) -> string;
1639 };
1640
1641 /// Import with package path
1642 import foo:bar/baz@1.0.0;
1643
1644 /// Export with function type.
1645 export a: func(a: string, b: string) -> string;
1646
1647 /// Export with identifier.
1648 export b: x;
1649
1650 /// Export with inline interface.
1651 export c: interface {
1652 /// Function a
1653 a: func(a: string, b: string) -> string;
1654 };
1655
1656 /// Export with package path
1657 export foo:bar/baz@1.0.0;
1658
1659 /// Include world from package path with 2 renames.
1660 include foo:bar/baz with { a as a1, b as b1 };
1661
1662 /// Include world from package path with 1 rename.
1663 include foo:bar/baz with {foo as foo1};
1664
1665 /// Include world from package path (spacing).
1666 include foo:bar/baz with { foo as foo1 };
1667
1668 /// Include world from package path newline delimited renaming.
1669 include foo:bar/baz with {
1670 foo as foo1,
1671 bar as bar1
1672 };
1673
1674 /// Include local world.
1675 include foo-bar;
1676
1677 /// Include local world with renaming.
1678 include foo-bar with { foo as bar };
1679}"#,
1680 r#"package foo:bar;
1681
1682world foo {
1683 /// Type t
1684 type t = list<string>;
1685
1686 type x = func() -> list<string>;
1687
1688 use foo.{ y };
1689
1690 /// Import with function type.
1691 import a: func(a: string, b: string) -> string;
1692
1693 /// Import with identifier.
1694 import b: x;
1695
1696 /// Import with inline interface.
1697 import c: interface {
1698 /// Function a
1699 a: func(a: string, b: string) -> string;
1700 };
1701
1702 /// Import with package path
1703 import foo:bar/baz@1.0.0;
1704
1705 /// Export with function type.
1706 export a: func(a: string, b: string) -> string;
1707
1708 /// Export with identifier.
1709 export b: x;
1710
1711 /// Export with inline interface.
1712 export c: interface {
1713 /// Function a
1714 a: func(a: string, b: string) -> string;
1715 };
1716
1717 /// Export with package path
1718 export foo:bar/baz@1.0.0;
1719
1720 /// Include world from package path with 2 renames.
1721 include foo:bar/baz with {
1722 a as a1,
1723 b as b1,
1724 };
1725
1726 /// Include world from package path with 1 rename.
1727 include foo:bar/baz with {
1728 foo as foo1,
1729 };
1730
1731 /// Include world from package path (spacing).
1732 include foo:bar/baz with {
1733 foo as foo1,
1734 };
1735
1736 /// Include world from package path newline delimited renaming.
1737 include foo:bar/baz with {
1738 foo as foo1,
1739 bar as bar1,
1740 };
1741
1742 /// Include local world.
1743 include foo-bar;
1744
1745 /// Include local world with renaming.
1746 include foo-bar with {
1747 foo as bar,
1748 };
1749}
1750"#,
1751 )
1752 .unwrap();
1753 }
1754}