Skip to main content

graphix_compiler/typ/
mod.rs

1use crate::{env::Env, expr::ModPath, format_with_flags, PrintFlag, PRINT_FLAGS};
2use anyhow::{anyhow, bail, Result};
3use arcstr::ArcStr;
4use enumflags2::BitFlags;
5use fxhash::FxHashSet;
6use netidx::{publisher::Typ, utils::Either};
7use poolshark::local::LPooled;
8use std::{
9    cmp::{Eq, PartialEq},
10    fmt::Debug,
11    iter,
12};
13use triomphe::Arc;
14
15mod cast;
16mod contains;
17mod fntyp;
18mod matches;
19mod normalize;
20mod print;
21mod setops;
22mod tval;
23mod tvar;
24
25pub use fntyp::{FnArgType, FnType};
26pub use tval::TVal;
27pub use tvar::TVar;
28
29struct AndAc(bool);
30
31impl FromIterator<bool> for AndAc {
32    fn from_iter<T: IntoIterator<Item = bool>>(iter: T) -> Self {
33        AndAc(iter.into_iter().all(|b| b))
34    }
35}
36
37atomic_id!(AbstractId);
38
39#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
40pub enum Type {
41    Bottom,
42    Any,
43    Primitive(BitFlags<Typ>),
44    Ref { scope: ModPath, name: ModPath, params: Arc<[Type]> },
45    Fn(Arc<FnType>),
46    Set(Arc<[Type]>),
47    TVar(TVar),
48    Error(Arc<Type>),
49    Array(Arc<Type>),
50    ByRef(Arc<Type>),
51    Tuple(Arc<[Type]>),
52    Struct(Arc<[(ArcStr, Type)]>),
53    Variant(ArcStr, Arc<[Type]>),
54    Map { key: Arc<Type>, value: Arc<Type> },
55    Abstract { id: AbstractId, params: Arc<[Type]> },
56}
57
58impl Default for Type {
59    fn default() -> Self {
60        Self::Bottom
61    }
62}
63
64impl Type {
65    pub fn empty_tvar() -> Self {
66        Type::TVar(TVar::default())
67    }
68
69    fn iter_prims(&self) -> impl Iterator<Item = Self> {
70        match self {
71            Self::Primitive(p) => {
72                Either::Left(p.iter().map(|t| Type::Primitive(t.into())))
73            }
74            t => Either::Right(iter::once(t.clone())),
75        }
76    }
77
78    pub fn is_defined(&self) -> bool {
79        match self {
80            Self::Bottom
81            | Self::Any
82            | Self::Primitive(_)
83            | Self::Fn(_)
84            | Self::Set(_)
85            | Self::Error(_)
86            | Self::Array(_)
87            | Self::ByRef(_)
88            | Self::Tuple(_)
89            | Self::Struct(_)
90            | Self::Variant(_, _)
91            | Self::Ref { .. }
92            | Self::Map { .. }
93            | Self::Abstract { .. } => true,
94            Self::TVar(tv) => tv.read().typ.read().is_some(),
95        }
96    }
97
98    pub fn lookup_ref<'a>(&'a self, env: &'a Env) -> Result<&'a Type> {
99        match self {
100            Self::Ref { scope, name, params } => {
101                let def = env
102                    .lookup_typedef(scope, name)
103                    .ok_or_else(|| anyhow!("undefined type {name} in {scope}"))?;
104                if def.params.len() != params.len() {
105                    bail!("{} expects {} type parameters", name, def.params.len());
106                }
107                def.typ.unbind_tvars();
108                for ((tv, ct), arg) in def.params.iter().zip(params.iter()) {
109                    if let Some(ct) = ct {
110                        ct.check_contains(env, arg)?;
111                    }
112                    if !tv.would_cycle(arg) {
113                        match arg {
114                            Type::TVar(arg_tv) => match &*arg_tv.read().typ.read() {
115                                None => *tv.read().typ.write() = Some(arg.clone()),
116                                Some(t) => *tv.read().typ.write() = Some(t.clone()),
117                            },
118                            _ => {
119                                *tv.read().typ.write() = Some(arg.clone());
120                            }
121                        }
122                    }
123                }
124                Ok(&def.typ)
125            }
126            t => Ok(t),
127        }
128    }
129
130    pub fn any() -> Self {
131        Self::Any
132    }
133
134    pub fn boolean() -> Self {
135        Self::Primitive(Typ::Bool.into())
136    }
137
138    pub fn number() -> Self {
139        Self::Primitive(Typ::number())
140    }
141
142    pub fn int() -> Self {
143        Self::Primitive(Typ::integer())
144    }
145
146    pub fn uint() -> Self {
147        Self::Primitive(Typ::unsigned_integer())
148    }
149
150    fn strip_error_int(&self, env: &Env, hist: &mut FxHashSet<usize>) -> Option<Type> {
151        match self {
152            Type::Error(t) => match t.strip_error_int(env, hist) {
153                Some(t) => Some(t),
154                None => Some((**t).clone()),
155            },
156            Type::TVar(tv) => {
157                tv.read().typ.read().as_ref().and_then(|t| t.strip_error_int(env, hist))
158            }
159            Type::Primitive(p) => {
160                if *p == BitFlags::from(Typ::Error) {
161                    Some(Type::Any)
162                } else {
163                    None
164                }
165            }
166            Type::Ref { .. } => {
167                let t = self.lookup_ref(env).ok()?;
168                let addr = t as *const Type as usize;
169                if hist.insert(addr) {
170                    t.strip_error_int(env, hist)
171                } else {
172                    None
173                }
174            }
175            Type::Set(s) => {
176                let r = Self::flatten_set(
177                    s.iter().filter_map(|t| t.strip_error_int(env, hist)),
178                );
179                match r {
180                    Type::Primitive(p) if p.is_empty() => None,
181                    t => Some(t),
182                }
183            }
184            Type::Array(_)
185            | Type::Map { .. }
186            | Type::ByRef(_)
187            | Type::Tuple(_)
188            | Type::Struct(_)
189            | Type::Variant(_, _)
190            | Type::Fn(_)
191            | Type::Any
192            | Type::Bottom
193            | Type::Abstract { .. } => None,
194        }
195    }
196
197    /// remove the outer error type and return the inner payload, fail if self
198    /// isn't an error or contains non error types
199    pub fn strip_error(&self, env: &Env) -> Option<Self> {
200        self.strip_error_int(env, &mut LPooled::take())
201    }
202
203    pub fn is_bot(&self) -> bool {
204        match self {
205            Type::Bottom => true,
206            Type::Any
207            | Type::Abstract { .. }
208            | Type::TVar(_)
209            | Type::Primitive(_)
210            | Type::Ref { .. }
211            | Type::Fn(_)
212            | Type::Error(_)
213            | Type::Array(_)
214            | Type::ByRef(_)
215            | Type::Tuple(_)
216            | Type::Struct(_)
217            | Type::Variant(_, _)
218            | Type::Set(_)
219            | Type::Map { .. } => false,
220        }
221    }
222
223    pub fn with_deref<R, F: FnOnce(Option<&Self>) -> R>(&self, f: F) -> R {
224        match self {
225            Self::Bottom
226            | Self::Abstract { .. }
227            | Self::Any
228            | Self::Primitive(_)
229            | Self::Fn(_)
230            | Self::Set(_)
231            | Self::Error(_)
232            | Self::Array(_)
233            | Self::ByRef(_)
234            | Self::Tuple(_)
235            | Self::Struct(_)
236            | Self::Variant(_, _)
237            | Self::Ref { .. }
238            | Self::Map { .. } => f(Some(self)),
239            Self::TVar(tv) => match tv.read().typ.read().as_ref() {
240                Some(t) => t.with_deref(f),
241                None => f(None),
242            },
243        }
244    }
245
246    pub fn scope_refs(&self, scope: &ModPath) -> Type {
247        match self {
248            Type::Bottom => Type::Bottom,
249            Type::Any => Type::Any,
250            Type::Primitive(s) => Type::Primitive(*s),
251            Type::Abstract { id, params } => Type::Abstract {
252                id: *id,
253                params: Arc::from_iter(params.iter().map(|t| t.scope_refs(scope))),
254            },
255            Type::Error(t0) => Type::Error(Arc::new(t0.scope_refs(scope))),
256            Type::Array(t0) => Type::Array(Arc::new(t0.scope_refs(scope))),
257            Type::Map { key, value } => {
258                let key = Arc::new(key.scope_refs(scope));
259                let value = Arc::new(value.scope_refs(scope));
260                Type::Map { key, value }
261            }
262            Type::ByRef(t) => Type::ByRef(Arc::new(t.scope_refs(scope))),
263            Type::Tuple(ts) => {
264                let i = ts.iter().map(|t| t.scope_refs(scope));
265                Type::Tuple(Arc::from_iter(i))
266            }
267            Type::Variant(tag, ts) => {
268                let i = ts.iter().map(|t| t.scope_refs(scope));
269                Type::Variant(tag.clone(), Arc::from_iter(i))
270            }
271            Type::Struct(ts) => {
272                let i = ts.iter().map(|(n, t)| (n.clone(), t.scope_refs(scope)));
273                Type::Struct(Arc::from_iter(i))
274            }
275            Type::TVar(tv) => match tv.read().typ.read().as_ref() {
276                None => Type::TVar(TVar::empty_named(tv.name.clone())),
277                Some(typ) => {
278                    let typ = typ.scope_refs(scope);
279                    Type::TVar(TVar::named(tv.name.clone(), typ))
280                }
281            },
282            Type::Ref { scope: _, name, params } => {
283                let params = Arc::from_iter(params.iter().map(|t| t.scope_refs(scope)));
284                Type::Ref { scope: scope.clone(), name: name.clone(), params }
285            }
286            Type::Set(ts) => {
287                Type::Set(Arc::from_iter(ts.iter().map(|t| t.scope_refs(scope))))
288            }
289            Type::Fn(f) => Type::Fn(Arc::new(f.scope_refs(scope))),
290        }
291    }
292}