purescript_waterslide/
purs_type.rs

1use std::fmt::{Display, Formatter};
2use purs_constructor::*;
3
4/// The representation for a Purescript data type declaration. The `PursType` for a Rust struct and
5/// enum can be obtained by deriving the `AsPursType` trait.
6#[derive(Clone, Debug, PartialEq)]
7pub enum PursType {
8    /// A purescript record
9    Struct(PursConstructor, Vec<(String, PursConstructor)>),
10    /// A purescript type constructor with arguments
11    TupleStruct(PursConstructor, Vec<PursConstructor>),
12    /// A purescript data type with multiple constructors
13    Enum(PursConstructor, Vec<PursConstructor>),
14}
15
16impl Display for PursType {
17    fn fmt(&self, f: &mut Formatter) -> ::std::fmt::Result {
18        use PursType::*;
19
20        match *self {
21            Struct(ref type_, ref fields) => {
22                write!(f, "data {} ", type_.name)?;
23
24                for param in &type_.parameters {
25                    write!(f, "{} ", &param.name)?;
26                }
27
28                write!(f, "= {} {{ ", type_.name)?;
29
30                for (idx, &(ref name, ref constructor)) in fields.iter().enumerate() {
31                    write!(f, "{} :: {}", name, constructor)?;
32                    if idx < (fields.len() - 1) {
33                        write!(f, ",")?;
34                    }
35                    write!(f, " ")?;
36                }
37                write!(f, "}}")
38            }
39            TupleStruct(ref type_, ref fields) => {
40                write!(f, "data {} ", type_.name)?;
41
42                for param in &type_.parameters {
43                    write!(f, "{} ", &param.name)?;
44                }
45
46                write!(f, "= {}", type_.name)?;
47
48                for field in fields.iter() {
49                    if field.parameters.is_empty() {
50                        write!(f, " {}", field)?;
51                    } else {
52                        write!(f, " ({})", field)?;
53                    }
54                }
55                Ok(())
56            }
57            Enum(ref type_, ref constructors) => {
58                write!(f, "data {} ", type_.name)?;
59
60                for param in &type_.parameters {
61                    write!(f, "{} ", &param.name)?;
62                }
63
64                write!(f, "= ")?;
65
66                for (idx, constructor) in constructors.iter().enumerate() {
67                    write!(f, "{}", constructor)?;
68                    if idx < constructors.len() - 1 {
69                        write!(f, " | ")?;
70                    }
71                }
72                Ok(())
73            }
74        }
75    }
76}
77
78/// Struct and enums that implement that trait can be part of generated modules. `AsPursType` is
79/// required to produce a data type *definition*, whereas `AsPursConstructor` and its corresponding
80/// struct `PursConstructor` are necessary to *use* a type in definitions.
81pub trait AsPursType: AsPursConstructor {
82    /// Statically procudes a PursType instance
83    fn as_purs_type() -> PursType;
84}