gluon_base/
kind.rs

1use std::fmt;
2use std::ops::Deref;
3use std::sync::Arc;
4
5use pretty::{DocAllocator, DocBuilder};
6
7use crate::ast::EmptyEnv;
8use crate::symbol::{Symbol, SymbolRef};
9use crate::types::{ToDoc, Walker};
10
11/// Trait for values which contains kinded values which can be referred by name
12pub trait KindEnv {
13    /// Returns the kind of the type `type_name`
14    fn find_kind(&self, type_name: &SymbolRef) -> Option<ArcKind>;
15}
16
17impl<'a, T: ?Sized + KindEnv> KindEnv for &'a T {
18    fn find_kind(&self, id: &SymbolRef) -> Option<ArcKind> {
19        (**self).find_kind(id)
20    }
21}
22
23impl KindEnv for EmptyEnv<Symbol> {
24    fn find_kind(&self, _id: &SymbolRef) -> Option<ArcKind> {
25        None
26    }
27}
28
29/// Kind representation
30///
31/// All types in gluon has a kind. Most types encountered are of the `Type` kind which
32/// includes things like `Int`, `String` and `Option Int`. There are however other types
33/// which are said to be "higher kinded" and these use the `Function` (a -> b) variant.
34/// These types include `Option` and `(->)` which both have the kind `Type -> Type -> Type`
35/// as well as `Functor` which has the kind `Type -> Type -> Type`.
36#[derive(Clone, Debug, Eq, PartialEq, Hash)]
37#[cfg_attr(feature = "serde_derive", derive(DeserializeState, SerializeState))]
38#[cfg_attr(
39    feature = "serde_derive",
40    serde(serialize_state = "crate::serialization::SeSeed")
41)]
42#[cfg_attr(feature = "serde_derive", serde(de_parameters = "S"))]
43#[cfg_attr(feature = "serde_derive", serde(deserialize_state = "S"))]
44#[cfg_attr(
45    feature = "serde_derive",
46    serde(bound(deserialize = "S: AsMut<crate::serialization::NodeMap>"))
47)]
48pub enum Kind {
49    Hole,
50    Error,
51    /// Representation for a kind which is yet to be inferred.
52    Variable(u32),
53    /// The simplest possible kind. All values in a program have this kind.
54    Type,
55    /// Kinds of rows (for polymorphic records).
56    Row,
57    /// Constructor which takes two kinds, taking the first as argument and returning the second.
58    Function(
59        #[cfg_attr(feature = "serde_derive", serde(state))] ArcKind,
60        #[cfg_attr(feature = "serde_derive", serde(state))] ArcKind,
61    ),
62}
63
64impl Default for Kind {
65    fn default() -> Self {
66        Kind::Hole
67    }
68}
69
70impl Kind {
71    pub fn hole() -> ArcKind {
72        ArcKind::new(Kind::Hole)
73    }
74
75    pub fn error() -> ArcKind {
76        ArcKind::new(Kind::Error)
77    }
78
79    pub fn variable(v: u32) -> ArcKind {
80        ArcKind::new(Kind::Variable(v))
81    }
82
83    pub fn typ() -> ArcKind {
84        ArcKind::new(Kind::Type)
85    }
86
87    pub fn row() -> ArcKind {
88        ArcKind::new(Kind::Row)
89    }
90
91    pub fn function(l: ArcKind, r: ArcKind) -> ArcKind {
92        ArcKind::new(Kind::Function(l, r))
93    }
94}
95
96#[derive(PartialEq, Copy, Clone, PartialOrd)]
97enum Prec {
98    /// The kind exists in the top context, no parentheses needed.
99    Top,
100    /// The kind exists in a function argument `Kind -> a`, parentheses are
101    /// needed if the kind is a function `(b -> c) -> a`.
102    Function,
103}
104
105struct DisplayKind<'a>(Prec, &'a Kind);
106
107impl fmt::Display for Kind {
108    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
109        write!(f, "{}", DisplayKind(Prec::Top, self))
110    }
111}
112
113impl<'a, A, B, E> ToDoc<'a, A, B, E> for ArcKind {
114    fn to_doc(&'a self, allocator: &'a A, _: E) -> DocBuilder<'a, A, B>
115    where
116        A: DocAllocator<'a, B>,
117    {
118        allocator.text(self.to_string())
119    }
120}
121
122impl<'a> fmt::Display for DisplayKind<'a> {
123    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
124        match *self.1 {
125            Kind::Hole => "_".fmt(f),
126            Kind::Error => "!".fmt(f),
127            Kind::Variable(i) => i.fmt(f),
128            Kind::Type => "Type".fmt(f),
129            Kind::Row => "Row".fmt(f),
130            Kind::Function(ref arg, ref ret) => match self.0 {
131                Prec::Function => write!(f, "({} -> {})", DisplayKind(Prec::Function, arg), ret),
132                Prec::Top => write!(f, "{} -> {}", DisplayKind(Prec::Function, arg), ret),
133            },
134        }
135    }
136}
137
138/// Reference counted kind type.
139#[derive(Clone, Default, Eq, PartialEq, Hash)]
140pub struct ArcKind(Arc<Kind>);
141
142#[cfg(feature = "serde")]
143impl<'de, S> crate::serde::de::DeserializeState<'de, S> for ArcKind
144where
145    S: AsMut<crate::serialization::NodeMap>,
146{
147    fn deserialize_state<D>(seed: &mut S, deserializer: D) -> Result<ArcKind, D::Error>
148    where
149        D: crate::serde::Deserializer<'de>,
150    {
151        use crate::serde::de::DeserializeSeed;
152        crate::serialization::SharedSeed::new(seed)
153            .deserialize(deserializer)
154            .map(ArcKind)
155    }
156}
157
158impl ArcKind {
159    pub fn new(kind: Kind) -> ArcKind {
160        ArcKind(Arc::new(kind))
161    }
162
163    pub fn make_mut(kind: &mut ArcKind) -> &mut Kind {
164        Arc::make_mut(&mut kind.0)
165    }
166
167    pub fn strong_count(kind: &ArcKind) -> usize {
168        Arc::strong_count(&kind.0)
169    }
170}
171
172impl Deref for ArcKind {
173    type Target = Kind;
174
175    fn deref(&self) -> &Kind {
176        &self.0
177    }
178}
179
180impl From<Kind> for ArcKind {
181    fn from(kind: Kind) -> ArcKind {
182        ArcKind(Arc::new(kind))
183    }
184}
185
186impl fmt::Debug for ArcKind {
187    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
188        self.0.fmt(f)
189    }
190}
191
192impl fmt::Display for ArcKind {
193    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
194        self.0.fmt(f)
195    }
196}
197
198type_cache! { KindCache() () { ArcKind, Kind } row hole error typ }
199
200impl<'a, F: ?Sized> Walker<'a, ArcKind> for F
201where
202    F: FnMut(&ArcKind),
203{
204    fn walk(&mut self, typ: &'a ArcKind) {
205        self(typ);
206        walk_kind(typ, self)
207    }
208}
209
210pub fn walk_kind<'a, F: ?Sized>(k: &'a ArcKind, f: &mut F)
211where
212    F: Walker<'a, ArcKind>,
213{
214    match **k {
215        Kind::Function(ref a, ref r) => {
216            f.walk(a);
217            f.walk(r);
218        }
219        Kind::Hole | Kind::Error | Kind::Variable(_) | Kind::Type | Kind::Row => (),
220    }
221}