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