1use crate::parser::errors::RibParseError;
16use crate::rib_source_span::GetSourcePosition;
17use crate::wit_type::{TypeResult, WitType};
18use crate::{InferredNumber, InferredType, TypeInternal};
19use combine::parser::char;
20use combine::parser::char::{char, spaces, string};
21use combine::{attempt, between, choice, optional, sep_by, Parser};
22use combine::{parser, ParseError};
23use std::fmt::Display;
24use std::ops::Deref;
25
26#[derive(Debug, Hash, Clone, Eq, PartialEq, Ord, PartialOrd)]
35pub enum TypeName {
36 Bool,
37 S8,
38 U8,
39 S16,
40 U16,
41 S32,
42 U32,
43 S64,
44 U64,
45 F32,
46 F64,
47 Chr,
48 Str,
49 List(Box<TypeName>),
50 Tuple(Vec<TypeName>),
51 Option(Box<TypeName>),
52 Result {
53 ok: Option<Box<TypeName>>,
54 error: Option<Box<TypeName>>,
55 },
56 Record(Vec<(String, Box<TypeName>)>),
57 Flags(Vec<String>),
58 Enum(Vec<String>),
59 Variant {
60 cases: Vec<(String, Option<Box<TypeName>>)>,
61 },
62}
63
64impl Display for TypeName {
65 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
66 match self {
67 TypeName::Bool => write!(f, "bool"),
68 TypeName::S8 => write!(f, "s8"),
69 TypeName::U8 => write!(f, "u8"),
70 TypeName::S16 => write!(f, "s16"),
71 TypeName::U16 => write!(f, "u16"),
72 TypeName::S32 => write!(f, "s32"),
73 TypeName::U32 => write!(f, "u32"),
74 TypeName::S64 => write!(f, "s64"),
75 TypeName::U64 => write!(f, "u64"),
76 TypeName::F32 => write!(f, "f32"),
77 TypeName::F64 => write!(f, "f64"),
78 TypeName::Chr => write!(f, "char"),
79 TypeName::Str => write!(f, "string"),
80 TypeName::List(inner_type) => write!(f, "list<{inner_type}>"),
81 TypeName::Tuple(inner_types) => {
82 write!(f, "tuple<")?;
83 for (i, inner_type) in inner_types.iter().enumerate() {
84 if i > 0 {
85 write!(f, ", ")?;
86 }
87 write!(f, "{inner_type}")?;
88 }
89 write!(f, ">")
90 }
91 TypeName::Option(inner_type) => write!(f, "option<{inner_type}>"),
92 TypeName::Result { ok, error } => match (ok, error) {
94 (Some(ok), Some(error)) => {
95 write!(f, "result<{ok}, {error}>")
96 }
97 (Some(ok), None) => {
98 write!(f, "result<{ok}>")
99 }
100 (None, Some(error)) => {
101 write!(f, "result<_, {error}>")
102 }
103 (None, None) => {
104 write!(f, "result")
105 }
106 },
107 TypeName::Record(fields) => {
108 write!(f, "record {{ ")?;
109 for (i, (field, typ)) in fields.iter().enumerate() {
110 if i > 0 {
111 write!(f, ", ")?;
112 }
113 write!(f, "{field}: {typ}")?;
114 }
115 write!(f, " }}")
116 }
117 TypeName::Flags(flags) => {
118 write!(f, "flags<")?;
119 for (i, flag) in flags.iter().enumerate() {
120 if i > 0 {
121 write!(f, ", ")?;
122 }
123 write!(f, "{flag}")?;
124 }
125 write!(f, ">")
126 }
127 TypeName::Enum(cases) => {
128 write!(f, "enum {{ ")?;
129 for (i, case) in cases.iter().enumerate() {
130 if i > 0 {
131 write!(f, ", ")?;
132 }
133 write!(f, "{case}")?;
134 }
135 write!(f, " }}")
136 }
137 TypeName::Variant { cases } => {
138 write!(f, "variant {{")?;
139 for (i, (case, typ)) in cases.iter().enumerate() {
140 if i > 0 {
141 write!(f, ", ")?;
142 }
143 write!(f, "{case}")?;
144 if let Some(typ) = typ {
145 write!(f, "({typ})")?;
146 }
147 }
148 write!(f, " }}")
149 }
150 }
151 }
152}
153
154impl From<&InferredNumber> for TypeName {
155 fn from(value: &InferredNumber) -> Self {
156 match value {
157 InferredNumber::S8 => TypeName::S8,
158 InferredNumber::U8 => TypeName::U8,
159 InferredNumber::S16 => TypeName::S16,
160 InferredNumber::U16 => TypeName::U16,
161 InferredNumber::S32 => TypeName::S32,
162 InferredNumber::U32 => TypeName::U32,
163 InferredNumber::S64 => TypeName::S64,
164 InferredNumber::U64 => TypeName::U64,
165 InferredNumber::F32 => TypeName::F32,
166 InferredNumber::F64 => TypeName::F64,
167 }
168 }
169}
170
171impl TryFrom<WitType> for TypeName {
172 type Error = String;
173 fn try_from(analysed_type: WitType) -> Result<Self, Self::Error> {
174 match analysed_type {
175 WitType::Bool(_) => Ok(TypeName::Bool),
176 WitType::S8(_) => Ok(TypeName::S8),
177 WitType::U8(_) => Ok(TypeName::U8),
178 WitType::S16(_) => Ok(TypeName::S16),
179 WitType::U16(_) => Ok(TypeName::U16),
180 WitType::S32(_) => Ok(TypeName::S32),
181 WitType::U32(_) => Ok(TypeName::U32),
182 WitType::S64(_) => Ok(TypeName::S64),
183 WitType::U64(_) => Ok(TypeName::U64),
184 WitType::F32(_) => Ok(TypeName::F32),
185 WitType::F64(_) => Ok(TypeName::F64),
186 WitType::Chr(_) => Ok(TypeName::Chr),
187 WitType::Str(_) => Ok(TypeName::Str),
188 WitType::List(inner_type) => Ok(TypeName::List(Box::new(
189 inner_type.inner.deref().clone().try_into()?,
190 ))),
191 WitType::Tuple(inner_type) => Ok(TypeName::Tuple(
192 inner_type
193 .items
194 .into_iter()
195 .map(|x| x.try_into())
196 .collect::<Result<_, _>>()?,
197 )),
198 WitType::Option(type_option) => Ok(TypeName::Option(Box::new(
199 type_option.inner.deref().clone().try_into()?,
200 ))),
201 WitType::Result(TypeResult { ok, err, .. }) => match (ok, err) {
202 (Some(ok), Some(err)) => Ok(TypeName::Result {
203 ok: Some(Box::new(ok.deref().clone().try_into()?)),
204 error: Some(Box::new(err.deref().clone().try_into()?)),
205 }),
206 (Some(ok), None) => Ok(TypeName::Result {
207 ok: Some(Box::new(ok.deref().clone().try_into()?)),
208 error: None,
209 }),
210 (None, Some(err)) => Ok(TypeName::Result {
211 ok: None,
212 error: Some(Box::new(err.deref().clone().try_into()?)),
213 }),
214 (None, None) => Ok(TypeName::Result {
215 ok: None,
216 error: None,
217 }),
218 },
219 WitType::Record(type_record) => {
220 let mut fields = vec![];
221 for field in type_record.fields {
222 let name = field.name.clone();
223 let typ = field.typ.clone();
224 let type_name = typ.try_into()?;
225 fields.push((name, Box::new(type_name)));
226 }
227
228 Ok(TypeName::Record(fields))
229 }
230 WitType::Flags(flags) => Ok(TypeName::Flags(flags.names)),
231 WitType::Enum(cases) => Ok(TypeName::Enum(cases.cases)),
232 WitType::Variant(cases) => {
233 let mut variant_cases = vec![];
234 for case in cases.cases {
235 let name = case.name.clone();
236 let typ = case.typ.clone();
237 match typ {
238 Some(typ) => {
239 let type_name = typ.try_into()?;
240 variant_cases.push((name, Some(Box::new(type_name))));
241 }
242 None => {
243 variant_cases.push((name, None));
244 }
245 }
246 }
247 Ok(TypeName::Variant {
248 cases: variant_cases,
249 })
250 }
251 WitType::Handle(type_handle) => {
252 Err(format!("Handle type not supported: {type_handle:?}"))
253 }
254 }
255 }
256}
257
258impl From<&TypeName> for InferredType {
259 fn from(type_name: &TypeName) -> Self {
260 match type_name {
261 TypeName::Bool => InferredType::bool(),
262 TypeName::S8 => InferredType::s8(),
263 TypeName::U8 => InferredType::u8(),
264 TypeName::S16 => InferredType::s16(),
265 TypeName::U16 => InferredType::u16(),
266 TypeName::S32 => InferredType::s32(),
267 TypeName::U32 => InferredType::u32(),
268 TypeName::S64 => InferredType::s64(),
269 TypeName::U64 => InferredType::u64(),
270 TypeName::F32 => InferredType::f32(),
271 TypeName::F64 => InferredType::f64(),
272 TypeName::Chr => InferredType::char(),
273 TypeName::Str => InferredType::string(),
274 TypeName::List(inner_type) => InferredType::list(inner_type.deref().into()),
275 TypeName::Tuple(inner_types) => {
276 InferredType::tuple(inner_types.iter().map(|t| t.into()).collect())
277 }
278 TypeName::Option(type_name) => InferredType::option(type_name.deref().into()),
279 TypeName::Result { ok, error } => InferredType::result(
280 ok.as_deref().map(|x| x.into()),
281 error.as_deref().map(|x| x.into()),
282 ),
283 TypeName::Record(fields) => InferredType::record(
284 fields
285 .iter()
286 .map(|(field, typ)| (field.clone(), typ.deref().into()))
287 .collect(),
288 ),
289 TypeName::Flags(flags) => InferredType::flags(flags.clone()),
290 TypeName::Enum(cases) => InferredType::enum_(cases.clone()),
291 TypeName::Variant { cases } => InferredType::from_variant_cases(
292 cases
293 .iter()
294 .map(|(case_name, typ)| (case_name.clone(), typ.as_deref().map(|x| x.into())))
295 .collect(),
296 ),
297 }
298 }
299}
300
301impl TryFrom<InferredType> for TypeName {
302 type Error = String;
303
304 fn try_from(value: InferredType) -> Result<Self, Self::Error> {
305 match value.inner.deref() {
306 TypeInternal::Bool => Ok(TypeName::Bool),
307 TypeInternal::S8 => Ok(TypeName::S8),
308 TypeInternal::U8 => Ok(TypeName::U8),
309 TypeInternal::S16 => Ok(TypeName::S16),
310 TypeInternal::U16 => Ok(TypeName::U16),
311 TypeInternal::S32 => Ok(TypeName::S32),
312 TypeInternal::U32 => Ok(TypeName::U32),
313 TypeInternal::S64 => Ok(TypeName::S64),
314 TypeInternal::U64 => Ok(TypeName::U64),
315 TypeInternal::F32 => Ok(TypeName::F32),
316 TypeInternal::F64 => Ok(TypeName::F64),
317 TypeInternal::Chr => Ok(TypeName::Chr),
318 TypeInternal::Str => Ok(TypeName::Str),
319 TypeInternal::List(inferred_type) => {
320 let verified = inferred_type.clone().try_into()?;
321 Ok(TypeName::List(Box::new(verified)))
322 }
323 TypeInternal::Tuple(inferred_types) => {
324 let mut verified_types = vec![];
325 for typ in inferred_types {
326 let verified = typ.clone().try_into()?;
327 verified_types.push(verified);
328 }
329 Ok(TypeName::Tuple(verified_types))
330 }
331 TypeInternal::Record(name_and_types) => {
332 let mut fields = vec![];
333 for (field, typ) in name_and_types {
334 fields.push((field.clone(), Box::new(typ.clone().try_into()?)));
335 }
336 Ok(TypeName::Record(fields))
337 }
338 TypeInternal::Flags(flags) => Ok(TypeName::Flags(flags.clone())),
339 TypeInternal::Enum(enums) => Ok(TypeName::Enum(enums.clone())),
340 TypeInternal::Option(inferred_type) => {
341 let result = inferred_type.clone().try_into()?;
342 Ok(TypeName::Option(Box::new(result)))
343 }
344 TypeInternal::Result { ok, error } => {
345 let ok_unified = ok.as_ref().map(|ok| ok.clone().try_into()).transpose()?;
346 let err_unified = error
347 .as_ref()
348 .map(|err| err.clone().try_into())
349 .transpose()?;
350 Ok(TypeName::Result {
351 ok: ok_unified.map(Box::new),
352 error: err_unified.map(Box::new),
353 })
354 }
355 TypeInternal::Variant(variant) => {
356 let mut cases = vec![];
357 for (case, typ) in variant {
358 let verified = typ.clone().map(TypeName::try_from).transpose()?;
359 cases.push((case.clone(), verified.map(Box::new)));
360 }
361 Ok(TypeName::Variant { cases })
362 }
363 TypeInternal::Resource { .. } => {
364 Err("Cannot convert a resource type to a type name".to_string())
365 }
366 TypeInternal::AllOf(_) => {
367 Err("Cannot convert a all of type to a type name".to_string())
368 }
369 TypeInternal::Unknown => {
370 Err("Cannot convert an unknown type to a type name".to_string())
371 }
372 TypeInternal::Sequence(_) => {
373 Err("Cannot convert a sequence type to a type name".to_string())
374 }
375 TypeInternal::Instance { .. } => {
376 Err("Cannot convert an instance type to a type name".to_string())
377 }
378 TypeInternal::Range { .. } => {
379 Err("Cannot convert a range type to a type name".to_string())
380 }
381 }
382 }
383}
384
385pub fn parse_basic_type<Input>() -> impl Parser<Input, Output = TypeName>
386where
387 Input: combine::Stream<Token = char>,
388 RibParseError: Into<
389 <Input::Error as ParseError<Input::Token, Input::Range, Input::Position>>::StreamError,
390 >,
391 Input::Position: GetSourcePosition,
392{
393 choice((
394 attempt(string("bool").map(|_| TypeName::Bool)),
395 attempt(string("s8").map(|_| TypeName::S8)),
396 attempt(string("u8").map(|_| TypeName::U8)),
397 attempt(string("s16").map(|_| TypeName::S16)),
398 attempt(string("u16").map(|_| TypeName::U16)),
399 attempt(string("s32").map(|_| TypeName::S32)),
400 attempt(string("u32").map(|_| TypeName::U32)),
401 attempt(string("s64").map(|_| TypeName::S64)),
402 attempt(string("u64").map(|_| TypeName::U64)),
403 attempt(string("f32").map(|_| TypeName::F32)),
404 attempt(string("f64").map(|_| TypeName::F64)),
405 attempt(string("char").map(|_| TypeName::Chr)),
406 attempt(string("string").map(|_| TypeName::Str)),
407 ))
408 .skip(spaces().silent())
409}
410
411pub fn parse_list_type<Input>() -> impl Parser<Input, Output = TypeName>
412where
413 Input: combine::Stream<Token = char>,
414 RibParseError: Into<
415 <Input::Error as ParseError<Input::Token, Input::Range, Input::Position>>::StreamError,
416 >,
417 Input::Position: GetSourcePosition,
418{
419 string("list")
420 .skip(spaces().silent())
421 .with(between(
422 char('<').skip(spaces().silent().silent()),
423 char('>').skip(spaces().silent().silent()),
424 type_name(),
425 ))
426 .map(|inner_type| TypeName::List(Box::new(inner_type)))
427}
428
429pub fn parse_option_type<Input>() -> impl Parser<Input, Output = TypeName>
430where
431 Input: combine::Stream<Token = char>,
432 RibParseError: Into<
433 <Input::Error as ParseError<Input::Token, Input::Range, Input::Position>>::StreamError,
434 >,
435 Input::Position: GetSourcePosition,
436{
437 string("option")
438 .skip(spaces().silent())
439 .with(between(
440 char('<').skip(spaces().silent().silent()),
441 char('>').skip(spaces().silent().silent()),
442 type_name(),
443 ))
444 .map(|inner_type| TypeName::Option(Box::new(inner_type)))
445}
446
447enum ResultSuccess {
448 NoType,
449 WithType(TypeName),
450}
451
452pub fn parse_result_type<Input>() -> impl Parser<Input, Output = TypeName>
454where
455 Input: combine::Stream<Token = char>,
456 RibParseError: Into<
457 <Input::Error as ParseError<Input::Token, Input::Range, Input::Position>>::StreamError,
458 >,
459 Input::Position: GetSourcePosition,
460{
461 string("result")
462 .skip(spaces().silent())
463 .with(optional(between(
464 char('<').skip(spaces().silent()),
465 char('>').skip(spaces().silent()),
466 (
467 choice!(
468 string("_")
469 .skip(spaces().silent())
470 .map(|_| ResultSuccess::NoType),
471 type_name()
472 .skip(spaces().silent())
473 .map(ResultSuccess::WithType)
474 ),
475 optional(
476 char(',')
477 .skip(spaces().silent())
478 .with(type_name().skip(spaces().silent())),
479 ),
480 ),
481 )))
482 .map(|result| match result {
483 None => TypeName::Result {
484 ok: None,
485 error: None,
486 },
487 Some((ResultSuccess::NoType, None)) => TypeName::Result {
488 ok: None,
489 error: None,
490 },
491 Some((ResultSuccess::NoType, Some(error))) => TypeName::Result {
492 ok: None,
493 error: Some(Box::new(error)),
494 },
495 Some((ResultSuccess::WithType(ok), None)) => TypeName::Result {
496 ok: Some(Box::new(ok)),
497 error: None,
498 },
499 Some((ResultSuccess::WithType(ok), Some(error))) => TypeName::Result {
500 ok: Some(Box::new(ok)),
501 error: Some(Box::new(error)),
502 },
503 })
504}
505
506pub fn parse_tuple_type<Input>() -> impl Parser<Input, Output = TypeName>
507where
508 Input: combine::Stream<Token = char>,
509 RibParseError: Into<
510 <Input::Error as ParseError<Input::Token, Input::Range, Input::Position>>::StreamError,
511 >,
512 Input::Position: GetSourcePosition,
513{
514 string("tuple")
515 .skip(spaces().silent())
516 .with(between(
517 char('<').skip(spaces().silent()),
518 char('>').skip(spaces().silent()),
519 sep_by(type_name(), char(',').skip(spaces().silent())),
520 ))
521 .map(TypeName::Tuple)
522}
523
524pub fn type_name_<Input>() -> impl Parser<Input, Output = TypeName>
525where
526 Input: combine::Stream<Token = char>,
527 RibParseError: Into<
528 <Input::Error as ParseError<Input::Token, Input::Range, Input::Position>>::StreamError,
529 >,
530 Input::Position: GetSourcePosition,
531{
532 spaces().silent().with(choice((
533 attempt(parse_basic_type()),
534 attempt(parse_list_type()),
535 attempt(parse_tuple_type()),
536 attempt(parse_option_type()),
537 attempt(parse_result_type()),
538 )))
539}
540
541parser! {
542 pub fn type_name[Input]()(Input) -> TypeName
543 where [Input: combine::Stream<Token = char>, RibParseError: Into<<Input::Error as ParseError<Input::Token, Input::Range, Input::Position>>::StreamError>, Input::Position: GetSourcePosition]
544 {
545 type_name_()
546 }
547}
548
549#[cfg(test)]
550mod type_name_tests {
551 use combine::stream::position;
552 use combine::EasyParser;
553 use test_r::test;
554
555 use super::*;
556
557 fn parse_and_compare(input: &str, expected: TypeName) {
558 let written = format!("{expected}");
559 let result1 = type_name()
560 .easy_parse(position::Stream::new(input))
561 .map(|x| x.0);
562 let result2 = type_name()
563 .easy_parse(position::Stream::new(written.as_str()))
564 .map(|x| x.0);
565 assert_eq!(result1, Ok(expected.clone()));
566 assert_eq!(result2, Ok(expected));
567 }
568
569 #[test]
570 fn test_basic_types() {
571 parse_and_compare("bool", TypeName::Bool);
572 parse_and_compare("s8", TypeName::S8);
573 parse_and_compare("u8", TypeName::U8);
574 parse_and_compare("s16", TypeName::S16);
575 parse_and_compare("u16", TypeName::U16);
576 parse_and_compare("s32", TypeName::S32);
577 parse_and_compare("u32", TypeName::U32);
578 parse_and_compare("s64", TypeName::S64);
579 parse_and_compare("u64", TypeName::U64);
580 parse_and_compare("f32", TypeName::F32);
581 parse_and_compare("f64", TypeName::F64);
582 parse_and_compare("char", TypeName::Chr);
583 parse_and_compare("string", TypeName::Str);
584 }
585
586 #[test]
587 fn test_list_type_name() {
588 parse_and_compare("list<u8>", TypeName::List(Box::new(TypeName::U8)));
589 parse_and_compare(
590 "list<list<f32>>",
591 TypeName::List(Box::new(TypeName::List(Box::new(TypeName::F32)))),
592 );
593 }
594
595 #[test]
596 fn test_tuple_type_name() {
597 parse_and_compare(
598 "tuple<u8, u16>",
599 TypeName::Tuple(vec![TypeName::U8, TypeName::U16]),
600 );
601 parse_and_compare(
602 "tuple<s32, list<u8>>",
603 TypeName::Tuple(vec![TypeName::S32, TypeName::List(Box::new(TypeName::U8))]),
604 );
605 parse_and_compare(
606 "tuple<tuple<s8, s16>, u32>",
607 TypeName::Tuple(vec![
608 TypeName::Tuple(vec![TypeName::S8, TypeName::S16]),
609 TypeName::U32,
610 ]),
611 );
612 }
613
614 #[test]
615 fn test_option_type_name() {
616 parse_and_compare("option<u8>", TypeName::Option(Box::new(TypeName::U8)));
617 parse_and_compare(
618 "option<list<f32>>",
619 TypeName::Option(Box::new(TypeName::List(Box::new(TypeName::F32)))),
620 );
621 }
622
623 #[test]
624 fn test_nested_types() {
625 parse_and_compare(
626 "list<tuple<u8, s8>>",
627 TypeName::List(Box::new(TypeName::Tuple(vec![TypeName::U8, TypeName::S8]))),
628 );
629 parse_and_compare(
630 "tuple<list<u16>, list<f64>>",
631 TypeName::Tuple(vec![
632 TypeName::List(Box::new(TypeName::U16)),
633 TypeName::List(Box::new(TypeName::F64)),
634 ]),
635 );
636 }
637
638 #[test]
639 fn test_spaces_around_types() {
640 parse_and_compare(" u8 ", TypeName::U8);
641 parse_and_compare("list< u8 >", TypeName::List(Box::new(TypeName::U8)));
642 parse_and_compare(
643 "tuple< s32 , list< u8 > >",
644 TypeName::Tuple(vec![TypeName::S32, TypeName::List(Box::new(TypeName::U8))]),
645 );
646 }
647}