kamo/types/
base.rs

1use std::{
2    fmt,
3    hash::{Hash, Hasher},
4    slice::Iter,
5    str::FromStr,
6};
7
8use crate::{
9    mem::{Root, Trace},
10    parser::{Input, ParseError},
11};
12
13use super::{
14    parser::{binary, code, text, TypeCodeError},
15    ArrayType, LambdaType, OptionType, PairType, Parameters, TypeError, TypeVec, UnionType,
16};
17
18/// A type definition.
19///
20/// # Grammar:
21///
22/// The binary representation of a type is a sequence of type codes. The type
23/// codes are defined in the [`code`] module. The grammar of the type code is
24/// defined as follows:
25///
26/// ```text
27/// type             = (filled | option | code::VOID | code::NIL) eof
28/// filled           = any | union | specific
29/// specific         = code::TYPE | code::BOOL | code::CHAR | code::INT
30///                  | code::FLOAT | code::SYMBOL | code::BINARY
31///                  | array | pair | lambda
32/// filled-or-option = filled | option
33/// array            = code::ARRAY filled-or-option fixed
34/// pair             = code::PAIR filled-or-option filled-or-option
35/// option           = code::OPTION filled
36/// union            = code::UNION specific specific+ code::END
37/// lambda           = code::LAMBDA args varg return
38/// args             = (filled-or-option)*
39/// varg             = (code::VARIADIC filled-or-option)?
40/// return           = code::RETURN (code::VOID | filled-or-option)
41/// fixed            = (fixed0 | fixed1 | fixed2 | fixed3 | fixed4)?
42/// fixed0           = code::FIXED0..=code::FIXED0_MAX
43/// fixed1           = code::FIXED1..=code::FIXED1_MAX byte
44/// fixed2           = code::FIXED2..=code::FIXED2_MAX byte byte
45/// fixed3           = code::FIXED3..=code::FIXED3_MAX byte byte byte
46/// fixed4           = code::FIXED4..=code::FIXED4_MAX byte byte byte byte
47/// byte             = 0x00..=0xFF
48/// ```
49#[derive(Clone, Debug, Eq)]
50pub struct Type(TypeVec);
51
52impl Type {
53    /// Creates a new type by parsing the type code.
54    ///
55    /// # Errors
56    ///
57    /// Returns an error if the type code is invalid.
58    #[inline]
59    pub fn new(code: impl AsRef<[u8]>) -> Result<Self, TypeCodeError> {
60        binary::parse(code.as_ref())
61    }
62
63    /// Creates a new type by taking the raw code.
64    ///
65    /// # Safety
66    ///
67    /// The type code is taken as is. It is the responsibility of the caller,
68    /// that the type code is correct.
69    #[must_use]
70    #[inline]
71    pub unsafe fn new_unchecked(code: impl AsRef<[u8]>) -> Self {
72        Self(code.as_ref().into())
73    }
74
75    /// Returns the inner type code which is a sequence of type codes by
76    /// consuming the type.
77    #[must_use]
78    #[inline]
79    pub fn into_inner(self) -> TypeVec {
80        self.0
81    }
82
83    /// Creates a new array type. If the size is not specified, the array is
84    /// dynamic.
85    ///
86    /// # Errors
87    ///
88    /// Returns an error if the element type is not filled or an option or if the
89    /// size is larger than [`ARRAY_MAX`](super::ARRAY_MAX).
90    #[allow(clippy::cast_possible_truncation)]
91    pub fn array(elem: Self, size: Option<usize>) -> Result<Self, TypeError> {
92        let mut code = TypeVec::default();
93        code.push(code::ARRAY);
94
95        if !(elem.is_filled() || elem.is_option()) {
96            return Err(TypeError::ArrayElemNotFilled);
97        }
98        code.extend(elem.0);
99
100        match size {
101            Some(size @ 0x0000_0000_0000..=0x0000_0000_000f) => {
102                code.push(code::FIXED0 | size as u8);
103            }
104            Some(size @ 0x0000_0000_0010..=0x0000_0000_0fff) => {
105                code.push(code::FIXED1 | (size >> 8) as u8);
106                code.push(size as u8);
107            }
108            Some(size @ 0x0000_0000_1000..=0x0000_000f_ffff) => {
109                code.push(code::FIXED2 | (size >> 16) as u8);
110                code.push((size >> 8) as u8);
111                code.push(size as u8);
112            }
113            Some(size @ 0x0000_0010_0000..=0x0000_0fff_ffff) => {
114                code.push(code::FIXED3 | (size >> 24) as u8);
115                code.push((size >> 16) as u8);
116                code.push((size >> 8) as u8);
117                code.push(size as u8);
118            }
119            Some(size @ 0x0000_1000_0000..=0x000f_ffff_ffff) => {
120                code.push(code::FIXED4 | (size >> 32) as u8);
121                code.push((size >> 24) as u8);
122                code.push((size >> 16) as u8);
123                code.push((size >> 8) as u8);
124                code.push(size as u8);
125            }
126            Some(size) => return Err(TypeError::ArraySizeTooLarge(size)),
127            None => {}
128        }
129        Ok(Self(code))
130    }
131
132    /// Returns `true` if the type is an array type.
133    #[must_use]
134    #[inline]
135    pub fn is_array(&self) -> bool {
136        self.0.first() == Some(&code::ARRAY)
137    }
138
139    /// Returns [`ArrayType`] if the type is an array type.
140    ///
141    /// # Panics
142    ///
143    /// Panics if the type is a malformed array type. This is a bug and should be
144    /// reported.
145    #[must_use]
146    pub fn as_array(&self) -> Option<ArrayType> {
147        if self.is_array() {
148            let input = &self.0.as_slice()[1..];
149            let (elem, cursor) = binary::parse_filled_option(input, 0).expect("array elem-type");
150            let (len, _) =
151                binary::parse_fixed(cursor, input.len() - cursor.len()).expect("array size");
152
153            Some(ArrayType { elem, len })
154        } else {
155            None
156        }
157    }
158
159    /// Creates a new lambda type.
160    ///
161    /// # Errors
162    ///
163    /// Returns an error if an parameter type is not filled or an option, if the
164    /// variadic type is not filled or an option or if the return type is not
165    /// filled, an option or `void`.
166    pub fn lambda<I>(params: I, variadic: Option<Self>, ret: Self) -> Result<Self, TypeError>
167    where
168        I: IntoIterator<Item = Self>,
169    {
170        let mut code = TypeVec::default();
171        code.push(code::LAMBDA);
172        for (i, arg) in params.into_iter().enumerate() {
173            if !(arg.is_filled() || arg.is_option()) {
174                return Err(TypeError::ParamNotFilled(i + 1));
175            }
176            code.extend(arg.0);
177        }
178        if let Some(variadic) = variadic {
179            if !(variadic.is_filled() || variadic.is_option()) {
180                return Err(TypeError::VariadicNotFilled);
181            }
182            code.push(code::VARIADIC);
183            code.extend(variadic.0);
184        }
185        code.push(code::RETURN);
186        code.extend(ret.0);
187        Ok(Self(code))
188    }
189
190    /// Returns `true` if the type is a lambda type.
191    #[must_use]
192    #[inline]
193    pub fn is_lambda(&self) -> bool {
194        self.0.first() == Some(&code::LAMBDA)
195    }
196
197    /// Returns [`LambdaType`] if the type is a lambda type.
198    ///
199    /// # Panics
200    ///
201    /// Panics if the type is a malformed lambda type. This is a bug and should
202    /// be reported.
203    #[must_use]
204    pub fn as_lambda(&self) -> Option<LambdaType> {
205        if self.is_lambda() {
206            let code = &self.0.as_slice()[1..];
207            let (params, code) = binary::parse_params(code, 0).expect("lambda parameter types");
208            let (variadic, code) = binary::parse_variadic(code, 0).expect("lambda variadic type");
209            let (ret, _) = binary::parse_return(code, 0).expect("lambda return type");
210
211            Some(LambdaType {
212                params,
213                variadic,
214                result: ret,
215            })
216        } else {
217            None
218        }
219    }
220
221    /// Creates a new option type.
222    ///
223    /// # Errors
224    ///
225    /// Returns an error if the inner type is not filled or if the inner type is
226    /// an option itself.
227    pub fn option(ty: Self) -> Result<Self, TypeError> {
228        let mut code = TypeVec::default();
229
230        if ty.is_option() {
231            return Err(TypeError::NestedOption);
232        }
233        if !ty.is_filled() {
234            return Err(TypeError::OptionNotFilled);
235        }
236        code.push(code::OPTION);
237        code.extend(ty.0);
238        Ok(Self(code))
239    }
240
241    /// Returns `true` if the type is an option type.
242    #[must_use]
243    #[inline]
244    pub fn is_option(&self) -> bool {
245        self.0.first() == Some(&code::OPTION)
246    }
247
248    /// Returns [`OptionType`] if the type is an option type.
249    ///
250    /// # Panics
251    ///
252    /// Panics if the type is a malformed option type. This is a bug and should
253    /// be reported.
254    #[must_use]
255    pub fn as_option(&self) -> Option<OptionType> {
256        if self.is_option() {
257            let code = &self.0.as_slice()[1..];
258            let (some, _) = binary::parse_filled(code, 0).expect("option some-type");
259
260            Some(OptionType { some })
261        } else {
262            None
263        }
264    }
265
266    /// Creates a new pair type.
267    ///
268    /// # Errors
269    ///
270    /// Returns an error if the car or cdr type is not filled or an option.
271    #[allow(clippy::similar_names)]
272    pub fn pair(car: Self, cdr: Self) -> Result<Self, TypeError> {
273        let mut code = TypeVec::default();
274        code.push(code::PAIR);
275        if !(car.is_filled() || car.is_option()) {
276            return Err(TypeError::PairCarNotFilled);
277        }
278        code.extend(car.0);
279        if !(cdr.is_filled() || cdr.is_option()) {
280            return Err(TypeError::PairCdrNotFilled);
281        }
282        code.extend(cdr.0);
283        Ok(Self(code))
284    }
285
286    /// Returns `true` if the type is a pair type.
287    #[must_use]
288    #[inline]
289    pub fn is_pair(&self) -> bool {
290        self.0.first() == Some(&code::PAIR)
291    }
292
293    /// Returns [`PairType`] if the type is a pair type.
294    ///
295    /// # Panics
296    ///
297    /// Panics if the type is a malformed pair type. This is a bug and should be
298    /// reported.
299    #[allow(clippy::similar_names)]
300    #[must_use]
301    pub fn as_pair(&self) -> Option<PairType> {
302        if self.is_pair() {
303            let code = &self.0.as_slice()[1..];
304            let (car, code) = binary::parse_filled_option(code, 0).expect("pair car-type");
305            let (cdr, _) = binary::parse_filled_option(code, 0).expect("pair cdr-type");
306
307            Some(PairType {
308                head: car,
309                tail: cdr,
310            })
311        } else {
312            None
313        }
314    }
315
316    /// Creates a new union type. The member types must be specific and there
317    /// must be at least two members.
318    ///
319    /// # Errors
320    ///
321    /// Returns an error if a member type is not specific or if there are less
322    /// than two members.
323    pub fn union<I>(types: I) -> Result<Self, TypeError>
324    where
325        I: IntoIterator<Item = Self>,
326    {
327        let mut code = TypeVec::default();
328        let mut count = 0;
329
330        code.push(code::UNION);
331        for ty in types {
332            if !ty.is_specific() {
333                return Err(TypeError::UnionNotSpecific(ty));
334            }
335            code.extend(ty.0);
336            count += 1;
337        }
338        if count < 2 {
339            return Err(TypeError::UnionTooFewMembers);
340        }
341        code.push(code::END);
342        Ok(Self(code))
343    }
344
345    /// Returns `true` if the type is a union type.
346    #[allow(clippy::similar_names)]
347    #[must_use]
348    pub fn is_union(&self) -> bool {
349        self.0.first() == Some(&code::UNION)
350    }
351
352    /// Returns [`UnionType`] if the type is a union type.
353    ///
354    /// # Panics
355    ///
356    /// Panics if the type is a malformed union type. This is a bug and should be
357    /// reported.
358    #[must_use]
359    pub fn as_union(&self) -> Option<UnionType> {
360        if self.is_union() {
361            let mut code = &self.0.as_slice()[1..];
362            let mut types = Vec::new();
363            let mut offset = 1;
364
365            loop {
366                assert!(!code.is_empty(), "union not terminated");
367                if code.first() == Some(&code::END) {
368                    break;
369                }
370                match binary::parse_specific(code, offset) {
371                    Ok((ty, rest)) => {
372                        types.push(ty);
373                        offset += code.len() - rest.len();
374                        code = rest;
375                    }
376                    Err(err) => panic!("{err}"),
377                }
378            }
379            assert!(types.len() >= 2, "union with less than 2 members");
380            Some(UnionType { types })
381        } else {
382            None
383        }
384    }
385
386    /// Returns `true` if the type is a specific type.
387    #[must_use]
388    pub fn is_specific(&self) -> bool {
389        matches!(
390            self.0.as_slice(),
391            [code::TYPE
392                | code::BOOL
393                | code::CHAR
394                | code::INT
395                | code::FLOAT
396                | code::BINARY
397                | code::SYMBOL]
398                | [code::ARRAY | code::PAIR | code::LAMBDA, ..]
399        )
400    }
401
402    /// Returns `true` if the type is a filled type.
403    #[must_use]
404    #[inline]
405    pub fn is_filled(&self) -> bool {
406        self.is_specific() || self.is_any() || self.is_union()
407    }
408
409    /// Returns an iterator over the type code.
410    #[inline]
411    pub fn iter(&self) -> Iter<'_, u8> {
412        self.0.iter()
413    }
414
415    /// Returns the type code as a slice.
416    #[must_use]
417    #[inline]
418    pub fn as_slice(&self) -> &[u8] {
419        self.0.as_slice()
420    }
421}
422
423impl<'a> IntoIterator for &'a Type {
424    type IntoIter = std::slice::Iter<'a, u8>;
425    type Item = &'a u8;
426
427    fn into_iter(self) -> Self::IntoIter {
428        self.iter()
429    }
430}
431
432impl Hash for Type {
433    fn hash<H: Hasher>(&self, state: &mut H) {
434        self.0.as_slice().hash(state);
435    }
436}
437
438impl PartialEq<Self> for Type {
439    fn eq(&self, other: &Self) -> bool {
440        if self.0.as_slice() == other.0.as_slice() {
441            return true;
442        }
443
444        if let Some(lhs) = self.as_option() {
445            return &lhs == other;
446        }
447        if let Some(lhs) = self.as_array() {
448            return &lhs == other;
449        }
450        if let Some(lhs) = self.as_pair() {
451            return &lhs == other;
452        }
453        if let Some(lhs) = self.as_lambda() {
454            return &lhs == other;
455        }
456        false
457    }
458}
459
460impl fmt::Display for Type {
461    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
462        match self.0.first().copied() {
463            Some(code::NIL) => write!(f, "nil"),
464            Some(code::VOID) => write!(f, "void"),
465            Some(code::ANY) => write!(f, "any"),
466            Some(code::TYPE) => write!(f, "type"),
467            Some(code::BOOL) => write!(f, "bool"),
468            Some(code::CHAR) => write!(f, "char"),
469            Some(code::INT) => write!(f, "int"),
470            Some(code::FLOAT) => write!(f, "float"),
471            Some(code::SYMBOL) => write!(f, "symbol"),
472            Some(code::BINARY) => write!(f, "binary"),
473            Some(code::ARRAY) => self.as_array().expect("array type").fmt(f),
474            Some(code::PAIR) => self.as_pair().expect("pair type").fmt(f),
475            Some(code::LAMBDA) => self.as_lambda().expect("lambda type").fmt(f),
476            Some(code::OPTION) => self.as_option().expect("option type").fmt(f),
477            Some(code::UNION) => self.as_union().expect("union type").fmt(f),
478            Some(_) | None => Ok(()),
479        }
480    }
481}
482
483impl<'a> Trace<'a> for Type {
484    fn trace(&self, _: &mut Vec<Root<'a>>) {
485        // A type is always traced by the mutator.
486    }
487}
488
489macro_rules! impl_simple {
490    ($($name:ident => $value:expr),+ $(),*) => {
491        impl Type {
492            $(#[must_use] #[inline] pub fn $name() -> Self { $value.clone() })+
493            paste::paste! {
494                $(#[must_use] #[inline] pub fn [<is_ $name>](&self) -> bool { *self == $value })+
495            }
496        }
497    };
498}
499
500impl_simple! {
501    nil     => *code::T_NIL,    void      => *code::T_VOID,
502    any     => *code::T_ANY,    typedef   => *code::T_TYPE,
503    boolean => *code::T_BOOL,   character => *code::T_CHAR,
504    integer => *code::T_INT,    float     => *code::T_FLOAT,
505    string  => *code::T_STRING, symbol    => *code::T_SYMBOL,
506    binary  => *code::T_BINARY, vector    => *code::T_VECTOR,
507    list    => *code::T_LIST,
508}
509
510impl AsRef<Self> for Type {
511    #[inline]
512    fn as_ref(&self) -> &Self {
513        self
514    }
515}
516
517impl FromStr for Type {
518    type Err = ParseError;
519
520    /// Parses a type from the string. User defined types are not supported,
521    /// because they cannot be resolved without an environment.
522    fn from_str(s: &str) -> Result<Self, Self::Err> {
523        let input = Input::new(s);
524        let (ty, _) = text::parse::<0>(None)(input)?;
525
526        Ok(ty)
527    }
528}
529
530impl<'a> From<(&Parameters<'a>, &Self)> for Type {
531    fn from((params, ret): (&Parameters<'a>, &Self)) -> Self {
532        let fixed = params
533            .fixed
534            .iter()
535            .map(|arg| arg.1.clone())
536            .collect::<Vec<_>>();
537        let variadic = params.variadic.as_ref().map(|arg| arg.1.clone());
538        Self::lambda(fixed, variadic, ret.to_owned()).expect("lambda type")
539    }
540}
541
542#[cfg(test)]
543mod tests {
544    use super::*;
545
546    #[test]
547    fn type_create_success() {
548        assert_eq!(Type::new([code::NIL]), Ok(Type::nil()));
549        assert_eq!(Type::new([code::VOID]), Ok(Type::void()));
550        assert_eq!(Type::new([code::ANY]), Ok(Type::any()));
551        assert_eq!(Type::new([code::BOOL]), Ok(Type::boolean()));
552        assert_eq!(Type::new([code::CHAR]), Ok(Type::character()));
553        assert_eq!(Type::new([code::INT]), Ok(Type::integer()));
554        assert_eq!(Type::new([code::FLOAT]), Ok(Type::float()));
555        assert_eq!(Type::new([code::SYMBOL]), Ok(Type::symbol()));
556        assert_eq!(Type::new([code::BINARY]), Ok(Type::binary()));
557        assert_eq!(Type::new([code::ARRAY, code::CHAR]), Ok(Type::string()));
558        assert_eq!(Type::new([code::ARRAY, code::ANY]), Ok(Type::vector()));
559        assert_eq!(
560            Type::new([code::ARRAY, code::INT]),
561            Ok(Type::array(Type::integer(), None).unwrap())
562        );
563        assert_eq!(
564            Type::new([code::PAIR, code::ANY, code::ANY]),
565            Ok(Type::pair(Type::any(), Type::any()).unwrap())
566        );
567        assert_eq!(
568            Type::new([code::LAMBDA, code::ANY, code::ANY, code::RETURN, code::ANY]),
569            Ok(Type::lambda(vec![Type::any(), Type::any()], None, Type::any()).unwrap())
570        );
571        assert_eq!(
572            Type::new([
573                code::OPTION,
574                code::LAMBDA,
575                code::ANY,
576                code::ANY,
577                code::RETURN,
578                code::ANY
579            ]),
580            Ok(Type::option(
581                Type::lambda(vec![Type::any(), Type::any()], None, Type::any()).unwrap()
582            )
583            .unwrap())
584        );
585        assert_eq!(
586            Type::new([
587                code::LAMBDA,
588                code::ANY,
589                code::ANY,
590                code::VARIADIC,
591                code::ANY,
592                code::RETURN,
593                code::ANY
594            ]),
595            Ok(Type::lambda(
596                vec![Type::any(), Type::any()],
597                Some(Type::any()),
598                Type::any()
599            )
600            .unwrap())
601        );
602        assert_eq!(
603            Type::new([code::UNION, code::INT, code::ARRAY, code::CHAR, code::END]),
604            Ok(Type::union(vec![
605                Type::integer(),
606                Type::array(Type::character(), None).unwrap()
607            ])
608            .unwrap())
609        );
610        assert_eq!(
611            Type::new([
612                code::OPTION,
613                code::UNION,
614                code::INT,
615                code::ARRAY,
616                code::CHAR,
617                code::END
618            ]),
619            Ok(Type::option(
620                Type::union(vec![
621                    Type::integer(),
622                    Type::array(Type::character(), None).unwrap()
623                ])
624                .unwrap()
625            )
626            .unwrap())
627        );
628        assert_eq!(
629            Type::new([
630                code::UNION,
631                code::BOOL,
632                code::INT,
633                code::ARRAY,
634                code::CHAR,
635                code::END
636            ]),
637            Ok(Type::union(vec![
638                Type::boolean(),
639                Type::integer(),
640                Type::array(Type::character(), None).unwrap()
641            ])
642            .unwrap())
643        );
644    }
645
646    #[test]
647    fn type_create_failure() {
648        assert_eq!(
649            Type::new([code::ARRAY]),
650            Err(TypeCodeError::ExpectedTypeOrOption(1))
651        );
652        assert_eq!(
653            Type::new([code::ARRAY, code::ARRAY]),
654            Err(TypeCodeError::ExpectedTypeOrOption(2))
655        );
656        assert_eq!(
657            Type::new([code::ARRAY, code::ARRAY, code::ARRAY]),
658            Err(TypeCodeError::ExpectedTypeOrOption(3))
659        );
660        assert_eq!(
661            Type::new([code::PAIR]),
662            Err(TypeCodeError::ExpectedTypeOrOption(1))
663        );
664        assert_eq!(
665            Type::new([code::PAIR, code::ANY]),
666            Err(TypeCodeError::ExpectedTypeOrOption(3))
667        );
668        assert_eq!(
669            Type::new([code::PAIR, code::PAIR, code::ANY]),
670            Err(TypeCodeError::ExpectedTypeOrOption(4))
671        );
672        assert_eq!(
673            Type::new([code::LAMBDA]),
674            Err(TypeCodeError::ExpectedReturn(1))
675        );
676        assert_eq!(
677            Type::new([code::LAMBDA, code::ANY]),
678            Err(TypeCodeError::ExpectedReturn(2))
679        );
680        assert_eq!(
681            Type::new([code::LAMBDA, code::VARIADIC]),
682            Err(TypeCodeError::ExpectedTypeOrOption(2))
683        );
684        assert_eq!(
685            Type::new([code::LAMBDA, code::ANY, code::VARIADIC]),
686            Err(TypeCodeError::ExpectedTypeOrOption(3))
687        );
688        assert_eq!(
689            Type::new([code::UNION]),
690            Err(TypeCodeError::ExpectedSpecificTypeEof(1))
691        );
692        assert_eq!(
693            Type::new([code::UNION, code::END]),
694            Err(TypeCodeError::ExpectedSpecificType(1))
695        );
696        assert_eq!(
697            Type::new([code::UNION, code::OPTION, code::BOOL, code::END]),
698            Err(TypeCodeError::ExpectedSpecificType(1))
699        );
700        assert_eq!(
701            Type::new([code::UNION, code::BOOL, code::END]),
702            Err(TypeCodeError::ExpectedSpecificType(2))
703        );
704        assert_eq!(
705            Type::new([code::UNION, code::BOOL, code::CHAR]),
706            Err(TypeCodeError::ExpectedMemberOrEnd(3))
707        );
708    }
709
710    #[test]
711    fn type_is() {
712        assert!(Type::nil().is_nil());
713        assert!(Type::void().is_void());
714        assert!(Type::any().is_any());
715        assert!(Type::boolean().is_boolean());
716        assert!(Type::character().is_character());
717        assert!(Type::integer().is_integer());
718        assert!(Type::float().is_float());
719        assert!(Type::string().is_string());
720        assert!(Type::symbol().is_symbol());
721        assert!(Type::binary().is_binary());
722        assert!(Type::vector().is_vector());
723        assert!(Type::pair(Type::any(), Type::any()).unwrap().is_pair());
724        assert!(Type::array(Type::any(), None).unwrap().is_array());
725        assert!(Type::lambda(vec![], None, Type::any()).unwrap().is_lambda());
726    }
727
728    #[test]
729    fn type_as_array() {
730        assert_eq!(Type::nil().as_array(), None);
731        assert_eq!(Type::void().as_array(), None);
732        assert_eq!(Type::any().as_array(), None);
733        assert_eq!(Type::boolean().as_array(), None);
734        assert_eq!(Type::character().as_array(), None);
735        assert_eq!(Type::integer().as_array(), None);
736        assert_eq!(Type::float().as_array(), None);
737        assert_eq!(
738            Type::string().as_array(),
739            Some(ArrayType {
740                elem: Type::character(),
741                len: None
742            })
743        );
744        assert_eq!(Type::symbol().as_array(), None);
745        assert_eq!(Type::binary().as_array(), None);
746        assert_eq!(
747            Type::vector().as_array(),
748            Some(ArrayType {
749                elem: Type::any(),
750                len: None
751            })
752        );
753        assert_eq!(
754            Type::pair(Type::any(), Type::any()).unwrap().as_array(),
755            None
756        );
757        assert_eq!(
758            Type::lambda(vec![], None, Type::any()).unwrap().as_array(),
759            None
760        );
761    }
762
763    #[test]
764    fn type_as_pair() {
765        assert_eq!(Type::nil().as_pair(), None);
766        assert_eq!(Type::void().as_pair(), None);
767        assert_eq!(Type::any().as_pair(), None);
768        assert_eq!(Type::boolean().as_pair(), None);
769        assert_eq!(Type::character().as_pair(), None);
770        assert_eq!(Type::integer().as_pair(), None);
771        assert_eq!(Type::float().as_pair(), None);
772        assert_eq!(Type::string().as_pair(), None);
773        assert_eq!(Type::symbol().as_pair(), None);
774        assert_eq!(Type::binary().as_pair(), None);
775        assert_eq!(Type::vector().as_pair(), None);
776        assert_eq!(
777            Type::pair(Type::any(), Type::any()).unwrap().as_pair(),
778            Some(PairType {
779                head: Type::any(),
780                tail: Type::any()
781            })
782        );
783        assert_eq!(
784            Type::lambda(vec![], None, Type::any()).unwrap().as_pair(),
785            None
786        );
787    }
788
789    #[test]
790    fn type_as_lambda() {
791        assert_eq!(Type::nil().as_lambda(), None);
792        assert_eq!(Type::void().as_lambda(), None);
793        assert_eq!(Type::any().as_lambda(), None);
794        assert_eq!(Type::boolean().as_lambda(), None);
795        assert_eq!(Type::character().as_lambda(), None);
796        assert_eq!(Type::integer().as_lambda(), None);
797        assert_eq!(Type::float().as_lambda(), None);
798        assert_eq!(Type::string().as_lambda(), None);
799        assert_eq!(Type::symbol().as_lambda(), None);
800        assert_eq!(Type::binary().as_lambda(), None);
801        assert_eq!(Type::vector().as_lambda(), None);
802        assert_eq!(
803            Type::pair(Type::any(), Type::any()).unwrap().as_lambda(),
804            None
805        );
806        assert_eq!(
807            Type::lambda(vec![], None, Type::any()).unwrap().as_lambda(),
808            Some(LambdaType {
809                params: vec![],
810                variadic: None,
811                result: Type::any()
812            })
813        );
814        assert_eq!(
815            Type::lambda(vec![Type::any()], None, Type::any())
816                .unwrap()
817                .as_lambda(),
818            Some(LambdaType {
819                params: vec![Type::any()],
820                variadic: None,
821                result: Type::any()
822            })
823        );
824        assert_eq!(
825            Type::lambda(vec![Type::any()], Some(Type::any()), Type::any())
826                .unwrap()
827                .as_lambda(),
828            Some(LambdaType {
829                params: vec![Type::any()],
830                variadic: Some(Type::any()),
831                result: Type::any()
832            })
833        );
834        assert_eq!(
835            Type::lambda(vec![Type::any(), Type::any()], None, Type::any())
836                .unwrap()
837                .as_lambda(),
838            Some(LambdaType {
839                params: vec![Type::any(), Type::any()],
840                variadic: None,
841                result: Type::any()
842            })
843        );
844        assert_eq!(
845            Type::lambda(
846                vec![Type::any(), Type::any()],
847                Some(Type::any()),
848                Type::any()
849            )
850            .unwrap()
851            .as_lambda(),
852            Some(LambdaType {
853                params: vec![Type::any(), Type::any()],
854                variadic: Some(Type::any()),
855                result: Type::any()
856            })
857        );
858    }
859
860    #[test]
861    fn type_display() {
862        assert_eq!(format!("{}", Type::nil()), "nil");
863        assert_eq!(format!("{}", Type::void()), "void");
864        assert_eq!(format!("{}", Type::any()), "any");
865        assert_eq!(format!("{}", Type::boolean()), "bool");
866        assert_eq!(format!("{}", Type::character()), "char");
867        assert_eq!(format!("{}", Type::integer()), "int");
868        assert_eq!(format!("{}", Type::float()), "float");
869        assert_eq!(format!("{}", Type::string()), "[char]");
870        assert_eq!(format!("{}", Type::symbol()), "symbol");
871        assert_eq!(format!("{}", Type::binary()), "binary");
872        assert_eq!(format!("{}", Type::vector()), "[any]");
873        assert_eq!(
874            format!("{}", Type::pair(Type::any(), Type::any()).unwrap()),
875            "(any * any)"
876        );
877        assert_eq!(
878            format!("{}", Type::array(Type::any(), None).unwrap()),
879            "[any]"
880        );
881        assert_eq!(
882            format!("{}", Type::lambda(vec![], None, Type::void()).unwrap()),
883            "fn(void -> void)"
884        );
885        assert_eq!(
886            format!("{}", Type::lambda(vec![], None, Type::any()).unwrap()),
887            "fn(void -> any)"
888        );
889        assert_eq!(
890            format!(
891                "{}",
892                Type::lambda(vec![Type::any()], None, Type::any()).unwrap()
893            ),
894            "fn(any -> any)"
895        );
896        assert_eq!(
897            format!(
898                "{}",
899                Type::lambda(vec![Type::any()], Some(Type::any()), Type::any()).unwrap()
900            ),
901            "fn(any, ...any -> any)"
902        );
903        assert_eq!(
904            format!(
905                "{}",
906                Type::lambda(vec![Type::any(), Type::any()], None, Type::any()).unwrap()
907            ),
908            "fn(any, any -> any)"
909        );
910        assert_eq!(
911            format!(
912                "{}",
913                Type::lambda(
914                    vec![Type::any(), Type::any()],
915                    Some(Type::any()),
916                    Type::any()
917                )
918                .unwrap()
919            ),
920            "fn(any, any, ...any -> any)"
921        );
922        assert_eq!(
923            format!(
924                "{}",
925                Type::lambda(
926                    vec![Type::any(), Type::any(), Type::any()],
927                    None,
928                    Type::any()
929                )
930                .unwrap()
931            ),
932            "fn(any, any, any -> any)"
933        );
934        assert_eq!(
935            format!(
936                "{}",
937                Type::lambda(
938                    vec![Type::any(), Type::any(), Type::any()],
939                    Some(Type::any()),
940                    Type::any()
941                )
942                .unwrap()
943            ),
944            "fn(any, any, any, ...any -> any)"
945        );
946        assert_eq!(
947            format!(
948                "{}",
949                Type::lambda(
950                    vec![Type::any(), Type::any()],
951                    None,
952                    Type::lambda(vec![Type::any()], None, Type::any()).unwrap()
953                )
954                .unwrap()
955            ),
956            "fn(any, any -> fn(any -> any))"
957        );
958    }
959
960    lazy_static! {
961        static ref TYPES: [(&'static str, Type); 19] = [
962            ("nil", Type::nil()),
963            ("void", Type::void()),
964            ("any", Type::any()),
965            ("bool", Type::boolean()),
966            ("char", Type::character()),
967            ("binary", Type::binary()),
968            ("int", Type::integer()),
969            ("float", Type::float()),
970            ("symbol", Type::symbol()),
971            ("type", Type::typedef()),
972            // ("", Type::()),
973            (
974                "fn()",
975                Type::lambda(
976                    vec![],
977                    None,
978                    Type::void()
979                )
980                .unwrap()
981            ),
982            (
983                "fn(void -> any)",
984                Type::lambda(
985                    vec![],
986                    None,
987                    Type::any()
988                )
989                .unwrap()
990            ),
991            (
992                "fn(void -> void)",
993                Type::lambda(
994                    vec![],
995                    None,
996                    Type::void()
997                )
998                .unwrap()
999            ),
1000            (
1001                "fn(void -> any)",
1002                Type::lambda(
1003                    vec![],
1004                    None,
1005                    Type::any()
1006                )
1007                .unwrap()
1008            ),
1009            (
1010                "fn(any -> void)",
1011                Type::lambda(
1012                    vec![Type::any()],
1013                    None,
1014                    Type::void()
1015                )
1016                .unwrap()
1017            ),
1018            (
1019                "fn(any -> any)",
1020                Type::lambda(
1021                    vec![Type::any()],
1022                    None,
1023                    Type::any()
1024                )
1025                .unwrap()
1026            ),
1027            (
1028                "fn(...any -> any)",
1029                Type::lambda(
1030                    vec![],
1031                    Some(Type::any()),
1032                    Type::any()
1033                )
1034                .unwrap()
1035            ),
1036            (
1037                "fn(any, any, any, ...any -> any)",
1038                Type::lambda(
1039                    vec![Type::any(), Type::any(), Type::any()],
1040                    Some(Type::any()),
1041                    Type::any()
1042                )
1043                .unwrap()
1044            ),
1045            (
1046                "fn(any, any -> fn(any -> any))",
1047                Type::lambda(
1048                    vec![Type::any(), Type::any()],
1049                    None,
1050                    Type::lambda(vec![Type::any()], None, Type::any()).unwrap()
1051                )
1052                .unwrap()
1053            ),
1054        ];
1055    }
1056
1057    #[test]
1058    fn type_parse() {
1059        for (i, (s, ty)) in TYPES.iter().enumerate() {
1060            assert_eq!(Type::from_str(s), Ok(ty.clone()), "type {} failed", i + 1);
1061        }
1062    }
1063
1064    lazy_static! {
1065        static ref EQUALS: [(&'static str, &'static str); 0] = [];
1066    }
1067
1068    #[test]
1069    fn type_equals() {
1070        for (i, (t1, t2)) in EQUALS.iter().enumerate() {
1071            let t1 = Type::from_str(t1).unwrap_or_else(|_| panic!("{}: type 1", i + 1));
1072            let t2 = Type::from_str(t2).unwrap_or_else(|_| panic!("{}: type 2", i + 1));
1073            assert!(t1 == t2, "type {} failed", i + 1);
1074        }
1075    }
1076}