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