ryna/
types.rs

1use std::collections::HashMap;
2use std::collections::HashSet;
3
4use colored::Colorize;
5use rustc_hash::FxHashSet;
6use serde::{Serialize, Deserialize};
7use malachite::Integer;
8
9use crate::annotations::Annotation;
10use crate::context::RynaContext;
11use crate::html_ext::HTMLColorable;
12use crate::id_mapper::IdMapper;
13use crate::interfaces::InterfaceConstraint;
14use crate::ryna_error;
15use crate::object::Object;
16use crate::parser::Location;
17use crate::patterns::Pattern;
18
19/*
20                                                  ╒══════════════════╕
21    ============================================= │  IMPLEMENTATION  │ =============================================
22                                                  ╘══════════════════╛
23*/
24
25pub type ParsingFunction = fn(&RynaContext, &TypeTemplate, &String) -> Result<Object, String>;
26
27#[derive(Clone, Serialize, Deserialize, Debug)]
28pub struct TypeTemplate {
29    pub id: usize,
30    pub name: String,
31    pub params: Vec<String>,
32
33    pub location: Location,
34    pub annotations: Vec<Annotation>,
35    pub attributes: Vec<(String, Type)>,
36
37    pub alias: Option<Type>,
38    pub patterns: Vec<Pattern>,
39
40    #[serde(skip)]
41    pub parser: Option<ParsingFunction>
42}
43
44impl TypeTemplate {
45    pub fn is_nominal(&self) -> bool {
46        self.alias.is_none()
47    }
48
49    pub fn is_structural(&self) -> bool {
50        self.alias.is_some()
51    }
52
53    pub fn needs_destructor(&self, templates: &[Type], ctx: &RynaContext) -> bool {
54        match self.id {
55            INT_ID |
56            FLOAT_ID |
57            STR_ID |
58            BOOL_ID |
59            FILE_ID |
60            PTR_ID |
61            LIB_ID |
62            LIB_FUNC_ID => false,
63
64            _ => {
65                // Check if the attributes have destructors
66                let subs = templates.iter().cloned().enumerate().collect::<HashMap<_, _>>();
67                let sub_attrs = self.attributes.iter().map(|t| t.1.sub_templates(&subs)).collect::<Vec<_>>();
68
69                sub_attrs.iter().any(|i| i.needs_destructor(ctx))
70            }
71        }
72    }
73
74    pub fn destructor_dependencies(&self, templates: &[Type], ctx: &RynaContext, set: &mut FxHashSet<Type>) {
75        match self.id {
76            INT_ID |
77            FLOAT_ID |
78            STR_ID |
79            BOOL_ID |
80            FILE_ID |
81            PTR_ID |
82            LIB_ID |
83            LIB_FUNC_ID => { },
84
85            _ => {
86                // Else, add the attributes' dependencies
87                let subs = templates.iter().cloned().enumerate().collect::<HashMap<_, _>>();
88                let sub_attrs = self.attributes.iter().map(|t| t.1.sub_templates(&subs)).collect::<Vec<_>>();
89
90                sub_attrs.iter().for_each(|i| i.destructor_dependencies_rec(ctx, set));
91            }
92        }
93    }
94}
95
96#[allow(clippy::derived_hash_with_manual_eq)]
97#[derive(Clone, Hash, Debug, Serialize, Deserialize)]
98pub enum Type {
99    // Empty type (also called void)
100    Empty,
101
102    // Type to infer later
103    InferenceMarker,
104
105    // Type to substitute in interfaces
106    SelfType,
107
108    // Simple types
109    Basic(usize),
110
111    // References
112    Ref(Box<Type>),
113    MutRef(Box<Type>),
114
115    // Algebraic types
116    Or(Vec<Type>),
117    And(Vec<Type>),
118
119    // Parametric types
120    Wildcard,
121    TemplateParam(usize, Vec<InterfaceConstraint>),
122    TemplateParamStr(String, Vec<InterfaceConstraint>),
123    Template(usize, Vec<Type>),
124
125    // Function type
126    Function(Box<Type>, Box<Type>)
127}
128
129impl PartialEq for Type {
130    fn eq(&self, b: &Self) -> bool {
131        return match (self, b) {
132            (Type::SelfType, Type::SelfType) |
133            (Type::Empty, Type::Empty) |
134            (Type::InferenceMarker, Type::InferenceMarker) |
135            (Type::Wildcard, Type::Wildcard) => true,
136            (Type::Basic(id_a), Type::Basic(id_b)) => id_a == id_b,
137            (Type::Ref(ta), Type::Ref(tb)) => ta == tb,
138            (Type::MutRef(ta), Type::MutRef(tb)) => ta == tb,
139            (Type::Or(va), Type::Or(vb)) => va.iter().all(|i| vb.contains(i)) && vb.iter().all(|i| va.contains(i)),
140            (Type::And(va), Type::And(vb)) => va == vb,
141            (Type::And(va), b) => va.len() == 1 && va[0] == *b,
142            (a, Type::And(vb)) => vb.len() == 1 && vb[0] == *a,
143            (Type::TemplateParam(id_a, v_a), Type::TemplateParam(id_b, v_b)) => id_a == id_b && v_a == v_b,
144            (Type::TemplateParamStr(n_a, v_a), Type::TemplateParamStr(n_b, v_b)) => n_a == n_b && v_a == v_b,
145            (Type::Template(id_a, va), Type::Template(id_b, vb)) => id_a == id_b && va == vb,
146            (Type::Function(fa, ta), Type::Function(fb, tb)) => fa == fb && ta == tb,
147            
148            _ => false
149        }
150    }
151}
152
153impl Eq for Type {}
154
155impl Type {
156    pub fn is_const_ref(&self) -> bool {
157        matches!(
158            self,
159            Type::Ref(_)
160        )
161    }
162
163    pub fn is_mut_ref(&self) -> bool {
164        matches!(
165            self,
166            Type::MutRef(_)
167        )
168    }
169
170    pub fn is_ref(&self) -> bool {
171        matches!(
172            self,
173            Type::Ref(_) | Type::MutRef(_)
174        )
175    }
176
177    pub fn to_ref(self) -> Type {
178        Type::Ref(Box::new(self))
179    }
180
181    pub fn to_mut(self) -> Type {
182        Type::MutRef(Box::new(self))
183    }
184
185    pub fn or(self, other: Type) -> Type {
186        Type::Or(vec!(self, other))
187    }
188
189    pub fn deref_type(&self) -> &Type {
190        match self {
191            Type::Ref(t) | Type::MutRef(t) => t,
192            _ => self
193        }
194    }
195
196    pub fn needs_destructor_rec(&self, ctx: &RynaContext, check_self: bool) -> bool {
197        // The type must implement the destroyable interface
198        if *self.deref_type() != Type::Wildcard && check_self && ctx.implements_destroyable(self) {
199            return true;
200        }
201
202        match self {
203            Type::Empty |
204            Type::InferenceMarker |
205            Type::SelfType |
206            Type::Wildcard |
207            Type::TemplateParam(..) |
208            Type::TemplateParamStr(..) => false,
209
210            Type::Ref(t) |
211            Type::MutRef(t) => t.needs_destructor_rec(ctx, true),
212
213            Type::Or(vec) |
214            Type::And(vec) => vec.iter().any(|i| i.needs_destructor_rec(ctx, true)),
215
216            Type::Basic(id) => ctx.type_templates[*id].needs_destructor(&[], ctx),
217
218            Type::Template(ARR_ID, vec) |
219            Type::Template(ARR_IT_ID, vec) => vec.iter().any(|i| i.needs_destructor_rec(ctx, true)),
220
221            Type::Template(id, vec) => ctx.type_templates[*id].needs_destructor(vec, ctx) || vec.iter().any(|i| i.needs_destructor_rec(ctx, true)),
222
223            Type::Function(a, b) => a.needs_destructor_rec(ctx, true) || b.needs_destructor_rec(ctx, true),
224        }
225    }
226
227    pub fn needs_destructor(&self, ctx: &RynaContext) -> bool {
228        self.needs_destructor_rec(ctx, true)
229    }
230
231    // A type that needs a generated destructor cannot implement Destroyable
232    pub fn cannot_have_destructor(&self, ctx: &RynaContext) -> bool {
233        self.needs_destructor_rec(ctx, false)
234    }
235
236    // A type that implements Destroyable but it must not
237    pub fn has_invalid_destructor(&self, ctx: &RynaContext) -> bool {
238        self.cannot_have_destructor(ctx) && ctx.implements_destroyable(self)
239    }
240
241    pub fn destructor_dependencies_rec(&self, ctx: &RynaContext, set: &mut FxHashSet<Type>) {
242        // Add this type if it needs a destructor
243        if self.needs_destructor(ctx) {
244            set.insert(self.clone());
245        }
246
247        match self {
248            Type::Empty |
249            Type::InferenceMarker |
250            Type::SelfType |
251            Type::Wildcard |
252            Type::TemplateParam(..) |
253            Type::TemplateParamStr(..) => { },
254
255            Type::Ref(t) |
256            Type::MutRef(t) => t.destructor_dependencies_rec(ctx, set),
257
258            Type::Or(vec) |
259            Type::And(vec) => vec.iter().for_each(|i| i.destructor_dependencies_rec(ctx, set)),
260
261            Type::Basic(id) => ctx.type_templates[*id].destructor_dependencies(&[], ctx, set),
262
263            Type::Template(ARR_IT_ID, vec) => {
264                ctx.type_templates[ARR_IT_ID].destructor_dependencies(&vec, ctx, set);                 
265                ctx.type_templates[ARR_ID].destructor_dependencies(&[vec[0].clone()], ctx, set);                 
266            },
267
268            Type::Template(id, vec) => {
269                ctx.type_templates[*id].destructor_dependencies(vec, ctx, set); 
270                vec.iter().for_each(|i| i.destructor_dependencies_rec(ctx, set));
271            },
272
273            Type::Function(a, b) => {
274                a.destructor_dependencies_rec(ctx, set);
275                b.destructor_dependencies_rec(ctx, set);
276            },
277        }
278    }
279
280    pub fn destructor_dependencies(&self, ctx: &RynaContext) -> FxHashSet<Type> {
281        let mut res = FxHashSet::default();
282
283        self.destructor_dependencies_rec(ctx, &mut res);
284        res.remove(self);
285
286        res
287    }
288
289    pub fn get_name(&self, ctx: &RynaContext) -> String {
290        return match self {
291            Type::Empty => "()".into(),
292            Type::SelfType => format!("{}", "Self".green()),
293            Type::InferenceMarker => "[Inferred]".into(),
294
295            Type::Basic(id) => ctx.type_templates[*id].name.clone().cyan().to_string(),
296            Type::Ref(t) => {
297                let needs_parens = matches!(**t, Type::Or(_) | Type::Function(..));
298
299                format!(
300                    "{}{}{}{}", 
301                    "&".magenta(), 
302                    if needs_parens { "(" } else { "" },
303                    t.get_name(ctx),
304                    if needs_parens { ")" } else { "" }
305                )
306            },
307
308            Type::MutRef(t) => {
309                let needs_parens = matches!(**t, Type::Or(_) | Type::Function(..));
310
311                format!(
312                    "{}{}{}{}", 
313                    "@".magenta(), 
314                    if needs_parens { "(" } else { "" },
315                    t.get_name(ctx),
316                    if needs_parens { ")" } else { "" }
317                )
318            },
319
320            Type::Or(v) => v.iter().map(|i| i.get_name(ctx)).collect::<Vec<_>>().join(" | "),
321            Type::And(v) => format!("({})", v.iter().map(|i| i.get_name(ctx)).collect::<Vec<_>>().join(", ")),
322
323            Type::Wildcard => "*".cyan().to_string(),
324
325            Type::TemplateParam(id, v) => {
326                if !v.is_empty() {
327                    format!(
328                        "{} [{}]", 
329                        format!("'T_{}", id).green(), 
330                        v.iter().map(|i| i.get_name(ctx)).collect::<Vec<_>>().join(", ")
331                    )
332
333                } else {
334                    format!("'T_{}", id).green().to_string()
335                }
336            },
337            Type::TemplateParamStr(name, v) => {
338                if !v.is_empty() {
339                    format!(
340                        "{} [{}]", 
341                        format!("'{}", name).green(), 
342                        v.iter().map(|i| i.get_name(ctx)).collect::<Vec<_>>().join(", ")
343                    )
344                    
345                } else {
346                    format!("'{}", name).green().to_string()
347                }   
348            },
349            Type::Template(id, v) => format!("{}<{}>", ctx.type_templates[*id].name.cyan().to_string().clone(), 
350                                                       v.iter().map(|i| i.get_name(ctx)).collect::<Vec<_>>().join(", ")),
351            Type::Function(from, to) => format!("{} => {}", from.get_name(ctx), to.get_name(ctx))
352        }
353    }
354
355    pub fn get_name_html(&self, ctx: &RynaContext) -> String {
356        return match self {
357            Type::Empty => "()".into(),
358            Type::SelfType => format!("{}", "Self".html_cyan()),
359            Type::InferenceMarker => "[Inferred]".into(),
360
361            Type::Basic(id) => ctx.type_templates[*id].name.clone().html_green().to_string(),
362            Type::Ref(t) => format!("{}{}", "&".html_magenta(), t.get_name_html(ctx)),
363            Type::MutRef(t) => format!("{}{}", "@".html_magenta(), t.get_name_html(ctx)),
364            Type::Or(v) => v.iter().map(|i| i.get_name_html(ctx)).collect::<Vec<_>>().join(" | "),
365            Type::And(v) => format!("({})", v.iter().map(|i| i.get_name_html(ctx)).collect::<Vec<_>>().join(", ")),
366
367            Type::Wildcard => "*".html_cyan().to_string(),
368
369            Type::TemplateParam(id, v) => {
370                if !v.is_empty() {
371                    format!(
372                        "{} [{}]", 
373                        format!("'T_{}", id).html_blue(), 
374                        v.iter().map(|i| i.get_name_html(ctx)).collect::<Vec<_>>().join(", ")
375                    )
376
377                } else {
378                    format!("'T_{}", id).html_blue().to_string()
379                }
380            },
381            Type::TemplateParamStr(name, v) => {
382                if !v.is_empty() {
383                    format!(
384                        "{} [{}]", 
385                        format!("'{}", name).html_blue(), 
386                        v.iter().map(|i| i.get_name_html(ctx)).collect::<Vec<_>>().join(", ")
387                    )
388                    
389                } else {
390                    format!("'{}", name).html_blue().to_string()
391                }   
392            },
393            Type::Template(id, v) => format!("{}&lt;{}&gt;", ctx.type_templates[*id].name.html_green().to_string().clone(), 
394                                                       v.iter().map(|i| i.get_name_html(ctx)).collect::<Vec<_>>().join(", ")),
395            Type::Function(from, to) => format!("{} => {}", from.get_name_html(ctx), to.get_name_html(ctx))
396        }
397    }
398
399    pub fn get_name_plain(&self, ctx: &RynaContext) -> String {
400        return match self {
401            Type::Empty => "()".into(),
402            Type::SelfType => "Self".to_string(),
403            Type::InferenceMarker => "[Inferred]".into(),
404
405            Type::Basic(id) => ctx.type_templates[*id].name.clone().to_string(),
406            Type::Ref(t) => format!("{}{}", "&", t.get_name_plain(ctx)),
407            Type::MutRef(t) => format!("{}{}", "@", t.get_name_plain(ctx)),
408            Type::Or(v) => v.iter().map(|i| i.get_name_plain(ctx)).collect::<Vec<_>>().join(" | "),
409            Type::And(v) => format!("({})", v.iter().map(|i| i.get_name_plain(ctx)).collect::<Vec<_>>().join(", ")),
410
411            Type::Wildcard => "*".to_string(),
412
413            Type::TemplateParam(id, v) => {
414                if !v.is_empty() {
415                    format!(
416                        "T_{} [{}]", 
417                        id, 
418                        v.iter().map(|i| i.get_name_plain(ctx)).collect::<Vec<_>>().join(", ")
419                    )
420
421                } else {
422                    format!("'T_{}", id).to_string()
423                }
424            },
425            Type::TemplateParamStr(name, v) => {
426                if !v.is_empty() {
427                    format!(
428                        "'{} [{}]", 
429                        name, 
430                        v.iter().map(|i| i.get_name_plain(ctx)).collect::<Vec<_>>().join(", ")
431                    )
432                    
433                } else {
434                    format!("'{}", name).to_string()
435                }   
436            },
437            Type::Template(id, v) => format!("{}<{}>", ctx.type_templates[*id].name.to_string().clone(), 
438                                                       v.iter().map(|i| i.get_name_plain(ctx)).collect::<Vec<_>>().join(", ")),
439            Type::Function(from, to) => format!("{} => {}", from.get_name_plain(ctx), to.get_name_plain(ctx))
440        }
441    }
442
443    pub fn has_templates(&self) -> bool {
444        return match self {
445            Type::Wildcard |
446            Type::Empty |
447            Type::Basic(_) => false,
448
449            Type::Ref(a) |
450            Type::MutRef(a) => a.has_templates(),
451
452            Type::Template(_, a) |
453            Type::Or(a) |
454            Type::And(a) => a.iter().any(Type::has_templates),
455
456            Type::TemplateParam(..) => true,
457            
458            Type::Function(a, b) => a.has_templates() || b.has_templates(),
459
460            _ => unimplemented!()
461        };
462    }
463
464    pub fn has_self(&self) -> bool {
465        return match self {
466            Type::SelfType => true,
467
468            Type::Wildcard |
469            Type::Empty |
470            Type::Basic(_) => false,
471
472            Type::Ref(a) |
473            Type::MutRef(a) => a.has_self(),
474
475            Type::Template(_, a) |
476            Type::Or(a) |
477            Type::And(a) => a.iter().any(Type::has_self),
478
479            Type::TemplateParamStr(_, c) |
480            Type::TemplateParam(_, c) => c.iter().flat_map(|i| &i.args).any(Type::has_self),
481
482            Type::Function(a, b) => a.has_self() || b.has_self(),
483
484            e => unimplemented!("{e:?}")
485        };
486    }
487
488    pub fn template_dependencies(&self, templates: &mut HashSet<usize>) {
489        return match self {
490            Type::Wildcard |
491            Type::Empty  |
492            Type::InferenceMarker  |
493            Type::SelfType  |
494            Type::Basic(..)  |
495            Type::TemplateParamStr(..) => {}
496
497            Type::Ref(t) |
498            Type::MutRef(t) => t.template_dependencies(templates),
499
500            Type::Template(_, ts) |
501            Type::Or(ts) |
502            Type::And(ts) => ts.iter().for_each(|i| i.template_dependencies(templates)),
503
504            Type::TemplateParam(id, cs) => {
505                templates.insert(*id);
506
507                for c in cs {
508                    for t in &c.args {
509                        t.template_dependencies(templates);
510                    }
511                }
512            },
513
514            Type::Function(a, b) => {
515                a.template_dependencies(templates);
516                b.template_dependencies(templates);
517            },
518        };
519    }
520
521    pub fn type_dependencies(&self) -> Vec<usize> {
522        return match self {
523            Type::Wildcard |
524            Type::Empty  |
525            Type::InferenceMarker  |
526            Type::SelfType  |
527            Type::TemplateParamStr(..) => vec!(),
528
529            Type::Basic(id) => vec!(*id),
530
531            Type::Ref(a) |
532            Type::MutRef(a) => a.type_dependencies(),
533
534            Type::Or(ts) |
535            Type::And(ts) => ts.iter().flat_map(|t| t.type_dependencies()).collect(),
536
537            Type::Function(a, b) => {
538                let mut res = a.type_dependencies();
539                res.append(&mut b.type_dependencies());
540
541                res
542            }
543
544            Type::TemplateParam(_, v) => {
545                v.iter().flat_map(|i| i.args.clone()).flat_map(|i| i.type_dependencies()).collect()
546            }
547
548            Type::Template(id, ts) => {
549                let mut res = vec!(*id);
550                res.append(&mut ts.iter().flat_map(|t| t.type_dependencies()).collect());
551
552                res
553            }
554        };
555    }
556
557    pub fn interface_dependencies(&self) -> Vec<usize> {
558        return match self {
559            Type::Wildcard |
560            Type::Empty  |
561            Type::InferenceMarker  |
562            Type::SelfType  |
563            Type::Basic(..) |
564            Type::TemplateParamStr(..) => vec!(),
565
566            Type::Ref(a) |
567            Type::MutRef(a) => a.interface_dependencies(),
568
569            Type::Or(ts) |
570            Type::And(ts) => ts.iter().flat_map(|t| t.interface_dependencies()).collect(),
571
572            Type::Function(a, b) => {
573                let mut res = a.interface_dependencies();
574                res.append(&mut b.interface_dependencies());
575
576                res
577            }
578
579            Type::TemplateParam(_, v) => {
580                let mut res = v.iter().map(|i| i.id).collect::<Vec<_>>();
581
582                for i in v {
583                    res.extend(i.args.iter().flat_map(|i| i.interface_dependencies()));
584                }
585
586                res
587            },
588
589            Type::Template(_, ts) => {
590                let mut res = vec!();
591                res.append(&mut ts.iter().flat_map(|t| t.interface_dependencies()).collect());
592
593                res
594            }
595        };
596    }
597
598    pub fn bindable_to(&self, other: &Type, ctx: &RynaContext) -> bool {
599        self.template_bindable_to(other, &mut HashMap::new(), &mut HashMap::new(), ctx)
600    }
601
602    pub fn bindable_to_subtitutions(&self, other: &Type, ctx: &RynaContext) -> (bool, HashMap<usize, Type>) {
603        let mut assignments = HashMap::new();
604        let res = self.template_bindable_to(other, &mut assignments, &mut HashMap::new(), ctx);
605
606        (res, assignments)
607    }
608
609    pub fn bindable_to_template(&self, other: &Type, templates: &[Type], ctx: &RynaContext) -> bool {
610        return self.template_bindable_to(other, &mut templates.iter().cloned().enumerate().collect(), &mut HashMap::new(), ctx);
611    }
612
613    pub fn template_bindable_to(&self, other: &Type, t_assignments: &mut HashMap<usize, Type>, t_deps: &mut HashMap<usize, HashSet<usize>>, ctx: &RynaContext) -> bool {
614        return match (self, other) {
615            (_, Type::Wildcard) => true,
616
617            (a, b) if a == b => true,
618
619            (_, Type::Empty) => false,
620
621            (Type::Ref(ta), Type::Ref(tb)) => ta.template_bindable_to(tb, t_assignments, t_deps, ctx),
622            (Type::MutRef(ta), Type::MutRef(tb)) => ta.template_bindable_to(tb, t_assignments, t_deps, ctx),
623
624            (Type::Basic(id), b) if ctx.type_templates[*id].is_structural() => {
625                let alias = ctx.type_templates[*id].alias.as_ref().unwrap();
626                return alias.template_bindable_to(b, t_assignments, t_deps, ctx);
627            },
628
629            (a, Type::Basic(id)) if ctx.type_templates[*id].is_structural() => {
630                let alias = ctx.type_templates[*id].alias.as_ref().unwrap();
631                return a.template_bindable_to(alias, t_assignments, t_deps, ctx);
632            },
633
634            (Type::Template(id, v), b) if ctx.type_templates[*id].is_structural() => {
635                let alias = ctx.type_templates[*id].alias.as_ref().unwrap();
636                let sub_alias = alias.sub_templates(&v.iter().cloned().enumerate().collect());
637
638                return sub_alias.template_bindable_to(b, t_assignments, t_deps, ctx);
639            },
640
641            (a, Type::Template(id, v)) if ctx.type_templates[*id].is_structural() => {
642                let alias = ctx.type_templates[*id].alias.as_ref().unwrap();
643                let sub_alias = alias.sub_templates(&v.iter().cloned().enumerate().collect());   
644
645                return a.template_bindable_to(&sub_alias, t_assignments, t_deps, ctx);
646            },
647
648            (Type::TemplateParam(id, cs), b) |
649            (b, Type::TemplateParam(id, cs)) => {
650                if let Some(t) = t_assignments.get(id).cloned() {    
651                    // More specific type
652                    if b.template_bindable_to(&t, t_assignments, t_deps, ctx) {
653                        t_assignments.insert(*id, b.clone());
654    
655                        return true;
656                    } 
657                    
658                    false
659                
660                } else {
661                    for c in cs {
662                        if !ctx.implements_interface(b, c, t_assignments, t_deps) {
663                            return false;
664                        }
665                    }
666
667                    t_assignments.insert(*id, b.clone());
668
669                    return b.template_cyclic_reference_check(*id, t_deps);
670                }
671            },
672
673            (Type::Or(v), b) => v.iter().all(|i| i.template_bindable_to(b, t_assignments, t_deps, ctx)),
674
675            (a, Type::Or(v)) => {
676                let mut t_assignments_cpy = t_assignments.clone();
677                let mut t_deps_cpy = t_deps.clone();
678
679                for i in v {
680                    if a.template_bindable_to(i, &mut t_assignments_cpy, &mut t_deps_cpy, ctx) {
681                        *t_assignments = t_assignments_cpy;
682                        *t_deps = t_deps_cpy;
683    
684                        return true;
685                    }
686                }
687
688                return false;
689            },
690
691            (Type::And(va), Type::And(vb)) => va.len() == vb.len() && va.iter().zip(vb).all(|(i, j)| i.template_bindable_to(j, t_assignments, t_deps, ctx)),
692            (Type::And(va), b) => va.len() == 1 && va[0].template_bindable_to(b, t_assignments, t_deps, ctx),
693            (a, Type::And(vb)) => vb.len() == 1 && a.template_bindable_to(&vb[0], t_assignments, t_deps, ctx),
694                        
695            (Type::Template(id_a, va), Type::Template(id_b, vb)) => id_a == id_b && va.len() == vb.len() && 
696                                                                    va.iter().zip(vb).all(|(i, j)| i.template_bindable_to(j, t_assignments, t_deps, ctx)),
697
698            (Type::Function(fa, ta), Type::Function(fb, tb)) => fa.template_bindable_to(fb, t_assignments, t_deps, ctx) && ta.template_bindable_to(tb, t_assignments, t_deps, ctx),
699
700            _ => false
701        }
702    }
703
704    fn template_cyclic_reference_check(&self, t_id: usize, t_deps: &mut HashMap<usize, HashSet<usize>>) -> bool {
705        return match self {
706            Type::Ref(t) => t.template_cyclic_reference_check(t_id, t_deps),
707            Type::MutRef(t) => t.template_cyclic_reference_check(t_id, t_deps),
708
709            Type::Or(v) => v.iter().all(|i| i.template_cyclic_reference_check(t_id, t_deps)),
710            Type::And(v) => v.iter().all(|i| i.template_cyclic_reference_check(t_id, t_deps)),
711            
712            Type::TemplateParam(id, _) => {
713                t_deps.entry(t_id).or_default().insert(*id);
714
715                t_id != *id && !t_deps.entry(*id).or_default().contains(&t_id)
716            },
717            
718            Type::Template(_, v) => v.iter().all(|i| i.template_cyclic_reference_check(t_id, t_deps)),
719
720            Type::Function(f, t) => f.template_cyclic_reference_check(t_id, t_deps) && t.template_cyclic_reference_check(t_id, t_deps),
721
722            _ => true
723        }
724    }
725
726    pub fn compile_templates(&mut self, templates: &Vec<String>) {
727        return match self {
728            Type::Ref(t) => t.compile_templates(templates),
729            Type::MutRef(t) => t.compile_templates(templates),
730
731            Type::Or(v) => v.iter_mut().for_each(|i| i.compile_templates(templates)),
732            Type::And(v) => v.iter_mut().for_each(|i| i.compile_templates(templates)),
733            
734            Type::TemplateParamStr(name, v) => {
735                v.iter_mut().for_each(|i| {
736                    i.args.iter_mut().for_each(|j| j.compile_templates(templates));
737                });
738                
739                if let Some(idx) = templates.iter().position(|i| i == name) {
740                    *self = Type::TemplateParam(idx, v.clone());
741                }
742            },
743            
744            Type::Template(_, v) => v.iter_mut().for_each(|i| i.compile_templates(templates)),
745
746            Type::Function(f, t) => {
747                f.compile_templates(templates); 
748                t.compile_templates(templates)
749            },
750
751            _ => { }
752        }
753    }
754
755    pub fn offset_templates(&mut self, offset: usize) {
756        return match self {
757            Type::Ref(t) => t.offset_templates(offset),
758            Type::MutRef(t) => t.offset_templates(offset),
759
760            Type::Or(v) => v.iter_mut().for_each(|i| i.offset_templates(offset)),
761            Type::And(v) => v.iter_mut().for_each(|i| i.offset_templates(offset)),
762            
763            Type::TemplateParam(id, v) => {
764                *id += offset;
765
766                v.iter_mut().for_each(|i| {
767                    i.args.iter_mut().for_each(|j| j.offset_templates(offset));
768                });
769            },
770            
771            Type::Template(_, v) => v.iter_mut().for_each(|i| i.offset_templates(offset)),
772
773            Type::Function(f, t) => {
774                f.offset_templates(offset); 
775                t.offset_templates(offset)
776            },
777
778            _ => { }
779        }
780    }
781
782    pub fn max_template(&self) -> i32 {
783        return match self {
784            Type::Ref(t) => t.max_template(),
785            Type::MutRef(t) => t.max_template(),
786
787            Type::Or(v) => v.iter().map(|i| i.max_template()).max().unwrap_or(-1),
788            Type::And(v) => v.iter().map(|i| i.max_template()).max().unwrap_or(-1),
789            
790            Type::TemplateParam(id, v) => {
791                v.iter().flat_map(|i| {
792                    i.args.iter().map(|j| j.max_template())
793                }).max().unwrap_or(-1).max(*id as i32)
794            },
795            
796            Type::Template(_, v) => v.iter().map(|i| i.max_template()).max().unwrap_or(-1),
797
798            Type::Function(f, t) => {
799                f.max_template().max(t.max_template())
800            },
801
802            _ => -1
803        }
804    }
805
806    pub fn sub_templates(&self, args: &HashMap<usize, Type>) -> Type {
807        self.sub_templates_rec(args, 100)
808    }
809
810    pub fn sub_templates_rec(&self, args: &HashMap<usize, Type>, rec: i32) -> Type {
811        return match self {
812            Type::Ref(t) => Type::Ref(Box::new(t.sub_templates_rec(args, rec))),
813            Type::MutRef(t) => Type::MutRef(Box::new(t.sub_templates_rec(args, rec))),
814            Type::Or(t) => Type::Or(t.iter().map(|i| i.sub_templates_rec(args, rec)).collect()),
815            Type::And(t) => Type::And(t.iter().map(|i| i.sub_templates_rec(args, rec)).collect()),
816            Type::Function(f, t) => Type::Function(Box::new(f.sub_templates_rec(args, rec)), Box::new(t.sub_templates_rec(args, rec))),
817            Type::TemplateParam(id, v) => {
818                let res = args.get(id).cloned().unwrap_or_else(||
819                    Type::TemplateParam(*id, v.iter().map(|i| {
820                        let mapped_args = i.args.iter().map(|j| j.sub_templates_rec(args, rec)).collect();
821                        InterfaceConstraint::new(i.id, mapped_args)
822                    }).collect())
823                );
824
825                let mut templates = HashSet::new();
826                res.template_dependencies(&mut templates);
827                
828                if templates.contains(id) { // Edge case
829                    res
830
831                } else if rec > 0 {
832                    res.sub_templates_rec(args, rec - 1)
833                    
834                } else {
835                    ryna_error!("Exceeded type recursion limit (100)"); // TODO: return a compiler error
836                }
837            },
838            Type::Template(id, t) => Type::Template(*id, t.iter().map(|i| i.sub_templates_rec(args, rec)).collect()),
839            _ => self.clone()
840        };
841    }
842
843    pub fn sub_self(&self, sub: &Type) -> Type {
844        return match self {
845            Type::SelfType => sub.clone(),
846            Type::Ref(t) => Type::Ref(Box::new(t.sub_self(sub))),
847            Type::MutRef(t) => Type::MutRef(Box::new(t.sub_self(sub))),
848            Type::Or(t) => Type::Or(t.iter().map(|i| i.sub_self(sub)).collect()),
849            Type::And(t) => Type::And(t.iter().map(|i| i.sub_self(sub)).collect()),
850            Type::Function(f, t) => Type::Function(Box::new(f.sub_self(sub)), Box::new(t.sub_self(sub))),
851            Type::TemplateParam(id, v) => {
852                Type::TemplateParam(*id, v.iter().map(|i| {
853                    let mapped_args = i.args.iter().map(|j| j.sub_self(sub)).collect();
854                    InterfaceConstraint::new(i.id, mapped_args)
855                }).collect())
856            }
857            Type::Template(id, t) => Type::Template(*id, t.iter().map(|i| i.sub_self(sub)).collect()),
858            _ => self.clone()
859        };
860    }
861
862    pub fn map_type(&self, ctx: &mut RynaContext, other_ctx: &RynaContext, id_mapper: &mut IdMapper, l: &Location) -> Type {
863        self.map_basic_types(&mut |id| ctx.map_ryna_class(other_ctx, id, id_mapper, l))
864            .map_interfaces(&mut |id| ctx.map_ryna_interface(other_ctx, id, id_mapper, l))
865    }
866
867    pub fn map_basic_types(&self, mapping: &mut impl FnMut(usize) -> Result<usize, String>) -> Type {
868        return match self {
869            Type::Basic(id) => Type::Basic(mapping(*id).unwrap()),
870            
871            Type::Ref(t) => Type::Ref(Box::new(t.map_basic_types(mapping))),
872            Type::MutRef(t) => Type::MutRef(Box::new(t.map_basic_types(mapping))),
873            Type::Or(t) => Type::Or(t.iter().map(|i| i.map_basic_types(mapping)).collect()),
874            Type::And(t) => Type::And(t.iter().map(|i| i.map_basic_types(mapping)).collect()),
875            Type::Function(f, t) => Type::Function(Box::new(f.map_basic_types(mapping)), Box::new(t.map_basic_types(mapping))),
876            Type::TemplateParam(id, v) => {
877                Type::TemplateParam(*id, v.iter().map(|i| {
878                    let mapped_args = i.args.iter().map(|j| j.map_basic_types(mapping)).collect();
879                    InterfaceConstraint::new(i.id, mapped_args)
880                }).collect())
881            }
882            Type::Template(id, t) => Type::Template(mapping(*id).unwrap(), t.iter().map(|i| i.map_basic_types(mapping)).collect()),
883
884            _ => self.clone()
885        };
886    }
887
888    pub fn map_interfaces(&self, mapping: &mut impl FnMut(usize) -> Result<usize, String>) -> Type {
889        return match self {            
890            Type::Ref(t) => Type::Ref(Box::new(t.map_interfaces(mapping))),
891            Type::MutRef(t) => Type::MutRef(Box::new(t.map_interfaces(mapping))),
892            Type::Or(t) => Type::Or(t.iter().map(|i| i.map_interfaces(mapping)).collect()),
893            Type::And(t) => Type::And(t.iter().map(|i| i.map_interfaces(mapping)).collect()),
894            Type::Function(f, t) => Type::Function(Box::new(f.map_interfaces(mapping)), Box::new(t.map_interfaces(mapping))),
895            Type::TemplateParam(id, v) => {
896                Type::TemplateParam(*id, v.iter().map(|i| {
897                    let mapped_args = i.args.iter().map(|j| j.map_interfaces(mapping)).collect();
898                    InterfaceConstraint::new(mapping(i.id).unwrap(), mapped_args)
899                }).collect())
900            }
901            Type::Template(id, t) => Type::Template(*id, t.iter().map(|i| i.map_interfaces(mapping)).collect()),
902
903            _ => self.clone()
904        };
905    }
906}
907
908/*
909                                                  ╒══════════════════╕
910    ============================================= │  STANDARD TYPES  │ =============================================
911                                                  ╘══════════════════╛
912*/
913
914// Constants for common types
915pub const INT_ID: usize = 0;
916pub const FLOAT_ID: usize = 1;
917pub const STR_ID: usize = 2;
918pub const BOOL_ID: usize = 3;
919pub const ARR_ID: usize = 4;
920pub const ARR_IT_ID: usize = 5;
921pub const FILE_ID: usize = 6;
922pub const PTR_ID: usize = 7;
923pub const LIB_ID: usize = 8;
924pub const LIB_FUNC_ID: usize = 9;
925
926pub const INT: Type = Type::Basic(INT_ID);
927pub const FLOAT: Type = Type::Basic(FLOAT_ID);
928pub const STR: Type = Type::Basic(STR_ID);
929pub const BOOL: Type = Type::Basic(BOOL_ID);
930pub const FILE: Type = Type::Basic(FILE_ID);
931pub const PTR: Type = Type::Basic(PTR_ID);
932pub const LIB: Type = Type::Basic(LIB_ID);
933pub const LIB_FUNC: Type = Type::Basic(LIB_FUNC_ID);
934
935#[macro_export]
936macro_rules! ARR_OF { ($t: expr) => { Type::Template($crate::types::ARR_ID, vec!($t)) }; }
937
938#[macro_export]
939macro_rules! ARR_IT_OF { ($t: expr, $t2: expr) => { Type::Template($crate::types::ARR_IT_ID, vec!($t, $t2)) }; }
940
941pub const T_0: Type = Type::TemplateParam(0, vec!());
942pub const T_1: Type = Type::TemplateParam(1, vec!());
943pub const T_2: Type = Type::TemplateParam(2, vec!());
944
945// Standard context
946pub fn standard_types(ctx: &mut RynaContext) {
947    ctx.define_type(Location::none(), vec!(), "Int".into(), vec!(), vec!(), None, vec!(), Some(|_, _, s| s.parse::<Integer>().map(Object::new).map_err(|_| "Invalid Int format".into()))).unwrap();
948    ctx.define_type(Location::none(), vec!(), "Float".into(), vec!(), vec!(), None, vec!(), Some(|_, _, s| s.parse::<f64>().map(Object::new).map_err(|_| "Invalid float format".to_string()))).unwrap();
949    ctx.define_type(Location::none(), vec!(), "String".into(), vec!(), vec!(), None, vec!(), None).unwrap();
950
951    ctx.define_type(Location::none(), vec!(), "Bool".into(), vec!(), vec!(), None, vec!(), Some(|_, _, s| 
952        if s == "true" || s == "false" {
953            Ok(Object::new(s.starts_with('t')))
954
955        } else {
956            Err(format!("Unable to parse bool from {}", s))
957        }
958    )).unwrap();
959
960    ctx.define_type(Location::none(), vec!(), "Array".into(), vec!("Inner".into()), vec!(), None, vec!(), None).unwrap();
961    ctx.define_type(Location::none(), vec!(), "ArrayIterator".into(), vec!("Inner".into(), "Elem".into()), vec!(), None, vec!(), None).unwrap();
962
963    ctx.define_type(Location::none(), vec!(), "File".into(), vec!(), vec!(), None, vec!(), None).unwrap();
964    
965    ctx.define_type(Location::none(), vec!(), "Pointer".into(), vec!(), vec!(), None, vec!(), None).unwrap();
966
967    ctx.define_type(Location::none(), vec!(), "Library".into(), vec!(), vec!(), None, vec!(), None).unwrap();
968    ctx.define_type(Location::none(), vec!(), "LibraryFunction".into(), vec!(), vec!(), None, vec!(), None).unwrap();
969}
970
971/*
972                                                  ╒═════════╕
973    ============================================= │  TESTS  │ =============================================
974                                                  ╘═════════╛
975*/
976
977#[cfg(test)]
978mod tests {
979    use crate::{context::standard_ctx, types::*};
980
981    #[test]
982    fn basic_type_binding() {
983        let ctx = standard_ctx();
984
985        let number_t = TypeTemplate {
986            id: 0,
987            name: "Int".into(),
988            params: vec!(),
989            location: Location::none(),
990            annotations: vec!(),
991            attributes: vec!(),
992            alias: None,
993            patterns: vec!(),
994            parser: None
995        };
996
997        let string_t = TypeTemplate {
998            id: 1,
999            name: "String".into(),
1000            params: vec!(),
1001            location: Location::none(),
1002            annotations: vec!(),
1003            attributes: vec!(),
1004            alias: None,
1005            patterns: vec!(),
1006            parser: None
1007        };
1008
1009        let bool_t = TypeTemplate {
1010            id: 2,
1011            name: "Bool".into(),
1012            params: vec!(),
1013            location: Location::none(),
1014            annotations: vec!(),
1015            attributes: vec!(),
1016            alias: None,
1017            patterns: vec!(),
1018            parser: None
1019        };
1020
1021        let vector_t = TypeTemplate {
1022            id: 3,
1023            name: "Vector".into(),
1024            params: vec!("T".into()),
1025            location: Location::none(),
1026            annotations: vec!(),
1027            attributes: vec!(),
1028            alias: None,
1029            patterns: vec!(),
1030            parser: None
1031        };
1032
1033        let number = Type::Basic(number_t.id);
1034        let string = Type::Basic(string_t.id);
1035        let boolean = Type::Basic(bool_t.id);
1036
1037        assert!(number.bindable_to(&number, &ctx));
1038        assert!(string.bindable_to(&string, &ctx));
1039        assert!(!number.bindable_to(&string, &ctx));
1040
1041        let number_ref = Type::Ref(Box::new(number.clone()));
1042        let number_mut = Type::MutRef(Box::new(number.clone()));
1043
1044        assert!(number_ref.bindable_to(&number_ref, &ctx));
1045        assert!(number_mut.bindable_to(&number_mut, &ctx));
1046        assert!(!number_mut.bindable_to(&number_ref, &ctx));
1047        assert!(!number_ref.bindable_to(&number_mut, &ctx));
1048
1049        let string_or_number = Type::Or(vec!(string.clone(), number.clone()));
1050        let number_or_string = Type::Or(vec!(number.clone(), string.clone()));
1051
1052        assert!(string_or_number.bindable_to(&string_or_number, &ctx));
1053        assert!(number_or_string.bindable_to(&number_or_string, &ctx));
1054        assert!(string_or_number.bindable_to(&number_or_string, &ctx));
1055        assert!(number_or_string.bindable_to(&string_or_number, &ctx));
1056
1057        assert!(number.bindable_to(&string_or_number, &ctx));
1058        assert!(string.bindable_to(&string_or_number, &ctx));
1059        assert!(!boolean.bindable_to(&string_or_number, &ctx));
1060
1061        assert!(!string_or_number.bindable_to(&string, &ctx));
1062
1063        let string_and_number = Type::And(vec!(string.clone(), number.clone()));
1064
1065        assert!(string_and_number.bindable_to(&string_and_number, &ctx));
1066        assert!(!string_or_number.bindable_to(&string_and_number, &ctx));
1067        assert!(!string.bindable_to(&string_and_number, &ctx));
1068        assert!(!number.bindable_to(&string_and_number, &ctx));
1069
1070        let wildcard = Type::Wildcard;
1071
1072        assert!(number.bindable_to(&wildcard, &ctx));
1073        assert!(string.bindable_to(&wildcard, &ctx));
1074        assert!(boolean.bindable_to(&wildcard, &ctx));
1075        assert!(number_or_string.bindable_to(&wildcard, &ctx));
1076        assert!(string_and_number.bindable_to(&wildcard, &ctx));
1077        assert!(wildcard.bindable_to(&wildcard, &ctx));
1078
1079        let empty = Type::Empty;
1080
1081        assert!(!number.bindable_to(&empty, &ctx));
1082        assert!(!string.bindable_to(&empty, &ctx));
1083        assert!(!boolean.bindable_to(&empty, &ctx));
1084        assert!(!number_or_string.bindable_to(&empty, &ctx));
1085        assert!(!string_and_number.bindable_to(&empty, &ctx));
1086        assert!(empty.bindable_to(&empty, &ctx));
1087
1088        let vector_number = Type::Template(vector_t.id, vec!(number.clone()));
1089        let vector_string = Type::Template(vector_t.id, vec!(string));
1090        let vector_number_or_string = Type::Template(vector_t.id, vec!(number_or_string.clone()));
1091
1092        assert!(vector_number.bindable_to(&vector_number, &ctx));
1093        assert!(vector_number.bindable_to(&vector_number_or_string, &ctx));
1094        assert!(!vector_number.bindable_to(&vector_string, &ctx));
1095
1096        let f_number_number = Type::Function(Box::new(number.clone()), Box::new(number.clone()));
1097        let f_number_or_string_number = Type::Function(Box::new(number_or_string.clone()), Box::new(number.clone()));
1098
1099        assert!(f_number_number.bindable_to(&f_number_number, &ctx));
1100        assert!(f_number_or_string_number.bindable_to(&f_number_or_string_number, &ctx));
1101        assert!(f_number_number.bindable_to(&f_number_or_string_number, &ctx));
1102        assert!(!f_number_or_string_number.bindable_to(&f_number_number, &ctx));
1103    }
1104
1105    #[test]
1106    fn template_binding() {
1107        let ctx = standard_ctx();
1108
1109        let number_t = TypeTemplate {
1110            id: 0,
1111            name: "Int".into(),
1112            params: vec!(),
1113            location: Location::none(),
1114            annotations: vec!(),
1115            attributes: vec!(),
1116            alias: None,
1117            patterns: vec!(),
1118            parser: None
1119        };
1120
1121        let string_t = TypeTemplate {
1122            id: 1,
1123            name: "String".into(),
1124            params: vec!(),
1125            location: Location::none(),
1126            annotations: vec!(),
1127            attributes: vec!(),
1128            alias: None,
1129            patterns: vec!(),
1130            parser: None
1131        };
1132
1133        let bool_t = TypeTemplate {
1134            id: 2,
1135            name: "Bool".into(),
1136            params: vec!(),
1137            location: Location::none(),
1138            annotations: vec!(),
1139            attributes: vec!(),
1140            alias: None,
1141            patterns: vec!(),
1142            parser: None
1143        };
1144
1145        let vector_t = TypeTemplate {
1146            id: 3,
1147            name: "Vector".into(),
1148            params: vec!("T".into()),
1149            location: Location::none(),
1150            annotations: vec!(),
1151            attributes: vec!(),
1152            alias: None,
1153            patterns: vec!(),
1154            parser: None
1155        };
1156
1157        let map_t = TypeTemplate {
1158            id: 3,
1159            name: "Map".into(),
1160            params: vec!("T".into(), "G".into()),
1161            location: Location::none(),
1162            annotations: vec!(),
1163            attributes: vec!(),
1164            alias: None,
1165            patterns: vec!(),
1166            parser: None
1167        };
1168
1169        let number = Type::Basic(number_t.id);
1170        let string = Type::Basic(string_t.id);
1171        let boolean = Type::Basic(bool_t.id);
1172
1173        let template_1 = Type::TemplateParam(0, vec!());
1174        let template_2 = Type::Ref(Box::new(Type::TemplateParam(0, vec!())));
1175
1176        assert!(number.bindable_to(&template_1, &ctx));
1177        assert!(string.bindable_to(&template_1, &ctx));
1178        assert!(boolean.bindable_to(&template_1, &ctx));
1179        assert!(!number.bindable_to(&template_2, &ctx));
1180        assert!(!string.bindable_to(&template_2, &ctx));
1181        assert!(!boolean.bindable_to(&template_2, &ctx));
1182        assert!(!template_1.bindable_to(&template_2, &ctx));
1183        assert!(!template_2.bindable_to(&template_1, &ctx));
1184
1185        let template_1 = Type::Template(vector_t.id, vec!(Type::TemplateParam(0, vec!()))); 
1186        let template_2 = Type::Template(map_t.id, vec!(Type::TemplateParam(0, vec!()), Type::TemplateParam(1, vec!()))); 
1187
1188        let binding_1 = Type::Template(vector_t.id, vec!(number.clone()));
1189        let binding_2 = Type::Template(map_t.id, vec!(number.clone(), string.clone()));
1190
1191        assert!(binding_1.bindable_to(&template_1, &ctx));
1192        assert!(binding_2.bindable_to(&template_2, &ctx));
1193        assert!(!binding_2.bindable_to(&template_1, &ctx));
1194        assert!(!binding_1.bindable_to(&template_2, &ctx));
1195
1196        let template_1 = Type::Template(map_t.id, vec!(Type::TemplateParam(0, vec!()), Type::TemplateParam(0, vec!()))); 
1197
1198        let binding_1 = Type::Template(map_t.id, vec!(number.clone(), number.clone()));
1199        let binding_2 = Type::Template(map_t.id, vec!(boolean.clone(), boolean.clone()));
1200        let binding_3 = Type::Template(map_t.id, vec!(number.clone(), string.clone()));
1201        
1202        assert!(binding_1.bindable_to(&template_1, &ctx));
1203        assert!(binding_2.bindable_to(&template_1, &ctx));
1204        assert!(!binding_3.bindable_to(&template_1, &ctx));
1205
1206        let template_1 = Type::Template(map_t.id, vec!(Type::TemplateParam(0, vec!()), Type::Template(map_t.id, vec!(Type::TemplateParam(1, vec!()), Type::TemplateParam(0, vec!()))))); 
1207
1208        let binding_1 = Type::Template(map_t.id, vec!(number.clone(), Type::Template(map_t.id, vec!(number.clone(), number.clone()))));
1209        let binding_2 = Type::Template(map_t.id, vec!(string.clone(), Type::Template(map_t.id, vec!(string.clone(), string.clone()))));
1210        let binding_3 = Type::Template(map_t.id, vec!(number.clone(), Type::Template(map_t.id, vec!(string.clone(), number.clone()))));
1211        let binding_4 = Type::Template(map_t.id, vec!(number.clone(), Type::Template(map_t.id, vec!(string.clone(), string.clone()))));
1212        let binding_5 = Type::Template(map_t.id, vec!(string.clone(), Type::Template(map_t.id, vec!(string.clone(), number.clone()))));
1213        
1214        assert!(binding_1.bindable_to(&template_1, &ctx));
1215        assert!(binding_2.bindable_to(&template_1, &ctx));
1216        assert!(binding_3.bindable_to(&template_1, &ctx));
1217        assert!(!binding_4.bindable_to(&template_1, &ctx));
1218        assert!(!binding_5.bindable_to(&template_1, &ctx));
1219
1220        let template_1 = Type::Template(map_t.id, vec!(Type::TemplateParam(0, vec!()), Type::Template(map_t.id, vec!(Type::TemplateParam(0, vec!()), Type::Wildcard)))); 
1221
1222        let binding_1 = Type::Template(map_t.id, vec!(number.clone(), Type::Template(map_t.id, vec!(number.clone(), number.clone()))));
1223        let binding_2 = Type::Template(map_t.id, vec!(string.clone(), Type::Template(map_t.id, vec!(string.clone(), string.clone()))));
1224        let binding_3 = Type::Template(map_t.id, vec!(number.clone(), Type::Template(map_t.id, vec!(string.clone(), number.clone()))));
1225        let binding_4 = Type::Template(map_t.id, vec!(number.clone(), Type::Template(map_t.id, vec!(string.clone(), string.clone()))));
1226        let binding_5 = Type::Template(map_t.id, vec!(string.clone(), Type::Template(map_t.id, vec!(string.clone(), number.clone()))));
1227        let binding_6 = Type::Template(map_t.id, vec!(boolean.clone(), Type::Template(map_t.id, vec!(boolean.clone(), number.clone()))));
1228        
1229        assert!(binding_1.bindable_to(&template_1, &ctx));
1230        assert!(binding_2.bindable_to(&template_1, &ctx));
1231        assert!(!binding_3.bindable_to(&template_1, &ctx));
1232        assert!(!binding_4.bindable_to(&template_1, &ctx));
1233        assert!(binding_5.bindable_to(&template_1, &ctx));
1234        assert!(binding_6.bindable_to(&template_1, &ctx));
1235
1236        let template_1 = Type::Template(map_t.id, vec!(Type::TemplateParam(0, vec!()), Type::TemplateParam(1, vec!()))); 
1237        let template_2 = Type::Template(map_t.id, vec!(Type::TemplateParam(1, vec!()), Type::TemplateParam(0, vec!()))); 
1238
1239        assert!(template_1.bindable_to(&template_1, &ctx));
1240        assert!(template_2.bindable_to(&template_2, &ctx));
1241        assert!(!template_1.bindable_to(&template_2, &ctx));
1242        assert!(!template_2.bindable_to(&template_1, &ctx));
1243
1244        let template_1 = Type::Template(map_t.id, vec!(Type::TemplateParam(0, vec!()), Type::Template(map_t.id, vec!(Type::TemplateParam(1, vec!()), Type::TemplateParam(0, vec!()))))); 
1245        let template_2 = Type::Template(map_t.id, vec!(Type::TemplateParam(1, vec!()), Type::Template(map_t.id, vec!(Type::TemplateParam(1, vec!()), Type::TemplateParam(1, vec!()))))); 
1246
1247        assert!(template_1.bindable_to(&template_2, &ctx));
1248        assert!(template_2.bindable_to(&template_1, &ctx));
1249    }
1250
1251    #[test]
1252    fn alias_type_binding() {
1253        let mut ctx = standard_ctx();
1254        let number_id = ctx.type_templates.len();
1255        let number = Type::Basic(number_id);
1256
1257        ctx.define_type(Location::none(), vec!(), "Number".into(), vec!(), vec!(), Some(Type::Or(vec!(INT, FLOAT))), vec!(), None).unwrap();
1258
1259        assert!(INT.bindable_to(&number, &ctx));
1260        assert!(FLOAT.bindable_to(&number, &ctx));
1261        assert!(!STR.bindable_to(&number, &ctx));
1262    }
1263
1264    #[test]
1265    fn recursive_type_binding() {
1266        let mut ctx = standard_ctx();
1267        let list_id = ctx.type_templates.len();
1268        let list = Type::Basic(list_id);
1269
1270        ctx.define_type(Location::none(), vec!(), "List".into(), vec!(), vec!(), Some(Type::Or(vec!(
1271            INT,
1272            Type::And(vec!(INT, list.clone()))
1273        ))), vec!(), None).unwrap();
1274
1275        let tuple_1 = Type::And(vec!(INT, INT));
1276        let tuple_2 = Type::And(vec!(INT, tuple_1.clone()));
1277        let tuple_3 = Type::And(vec!(INT, tuple_2.clone()));
1278        let tuple_4 = Type::And(vec!(INT, FLOAT));
1279        let tuple_5 = Type::And(vec!(INT, tuple_4.clone()));
1280
1281        assert!(INT.bindable_to(&list, &ctx));
1282        assert!(tuple_1.bindable_to(&list, &ctx));
1283        assert!(tuple_2.bindable_to(&list, &ctx));
1284        assert!(tuple_3.bindable_to(&list, &ctx));
1285
1286        assert!(!FLOAT.bindable_to(&list, &ctx));
1287        assert!(!tuple_4.bindable_to(&list, &ctx));
1288        assert!(!tuple_5.bindable_to(&list, &ctx));
1289    }
1290
1291    #[test]
1292    fn parametric_recursive_type_binding() {
1293        let mut ctx = standard_ctx();
1294        let nil_id = ctx.type_templates.len();
1295        let list_id = nil_id + 1;
1296        let nil = Type::Basic(nil_id);
1297        let list = Type::Template(list_id, vec!(T_0));
1298
1299        ctx.define_type(Location::none(), vec!(), "Nil".into(), vec!(), vec!(), None, vec!(), None).unwrap();
1300        ctx.define_type(Location::none(), vec!(), "List".into(), vec!(), vec!(), Some(Type::Or(vec!(
1301            nil.clone(),
1302            Type::And(vec!(T_0, list.clone()))
1303        ))), vec!(), None).unwrap();
1304
1305        let tuple_1 = Type::And(vec!(INT, nil.clone()));
1306        let tuple_2 = Type::And(vec!(INT, tuple_1.clone()));
1307        let tuple_3 = Type::And(vec!(INT, tuple_2.clone()));
1308        let tuple_4 = Type::And(vec!(FLOAT, nil.clone()));
1309        let tuple_5 = Type::And(vec!(FLOAT, tuple_4.clone()));
1310        let tuple_6 = Type::And(vec!(INT, tuple_4.clone()));
1311        let tuple_7 = Type::And(vec!(INT, tuple_6.clone()));
1312
1313        assert!(nil.bindable_to(&list, &ctx));
1314        assert!(tuple_1.bindable_to(&list, &ctx));
1315        assert!(tuple_2.bindable_to(&list, &ctx));
1316        assert!(tuple_3.bindable_to(&list, &ctx));
1317        assert!(tuple_4.bindable_to(&list, &ctx));
1318        assert!(tuple_5.bindable_to(&list, &ctx));
1319        assert!(!tuple_6.bindable_to(&list, &ctx));
1320        assert!(!tuple_7.bindable_to(&list, &ctx));
1321    }
1322
1323    #[test]
1324    fn destructor_dependencies() {
1325        let mut ctx = standard_ctx();
1326
1327        ctx.define_type(Location::none(), vec!(), "Test1".into(), vec!(), vec!(), None, vec!(), None).unwrap();
1328        ctx.define_type(Location::none(), vec!(), "Test2".into(), vec!(), vec!(), None, vec!(), None).unwrap();
1329        
1330        let test_1_id = ctx.get_type_id("Test1".into()).unwrap();
1331        let test_2_id = ctx.get_type_id("Test2".into()).unwrap();
1332
1333        let test_1 = Type::Basic(test_1_id);
1334        let test_2 = Type::Basic(test_2_id);
1335
1336        ctx.define_interface_impl("Destroyable".into(), vec!(), test_2.clone(), vec!()).unwrap();
1337
1338        assert!(!test_1.needs_destructor(&ctx));
1339        assert!(test_2.needs_destructor(&ctx));
1340        assert!(test_1.destructor_dependencies(&ctx).is_empty());
1341        assert!(test_2.destructor_dependencies(&ctx).is_empty());
1342
1343        let arr_1 = ARR_OF!(test_1.clone());
1344        let arr_2 = ARR_OF!(test_2.clone());
1345
1346        assert!(!arr_1.needs_destructor(&ctx));
1347        assert!(arr_2.needs_destructor(&ctx));
1348        assert!(arr_1.destructor_dependencies(&ctx).is_empty());
1349        assert_eq!(
1350            arr_2.destructor_dependencies(&ctx),
1351            [
1352                test_2.clone()
1353            ].iter().cloned().collect::<FxHashSet<Type>>()
1354        );
1355
1356        let arr_arr_1 = ARR_OF!(ARR_OF!(test_1.clone()));
1357        let arr_arr_2 = ARR_OF!(ARR_OF!(test_2.clone()));
1358
1359        assert!(!arr_arr_1.needs_destructor(&ctx));
1360        assert!(arr_arr_2.needs_destructor(&ctx));
1361        assert!(arr_arr_1.destructor_dependencies(&ctx).is_empty());
1362        assert_eq!(
1363            arr_arr_2.destructor_dependencies(&ctx),
1364            [
1365                ARR_OF!(test_2.clone()),
1366                test_2.clone()
1367            ].iter().cloned().collect::<FxHashSet<Type>>()
1368        );
1369    }
1370
1371    #[test]
1372    fn destructor_checking() {
1373        let mut ctx = standard_ctx();
1374
1375        ctx.define_type(Location::none(), vec!(), "Test1".into(), vec!(), vec!(), None, vec!(), None).unwrap();
1376        ctx.define_type(Location::none(), vec!(), "Test2".into(), vec!(), vec!(), None, vec!(), None).unwrap();
1377        
1378        let test_1_id = ctx.get_type_id("Test1".into()).unwrap();
1379        let test_2_id = ctx.get_type_id("Test2".into()).unwrap();
1380
1381        let test_1 = Type::Basic(test_1_id);
1382        let test_2 = Type::Basic(test_2_id);
1383
1384        ctx.define_interface_impl("Destroyable".into(), vec!(), test_2.clone(), vec!()).unwrap();
1385
1386        assert!(!test_1.needs_destructor(&ctx));
1387        assert!(test_2.needs_destructor(&ctx));
1388        assert!(!test_1.cannot_have_destructor(&ctx));
1389        assert!(!test_2.cannot_have_destructor(&ctx));
1390        assert!(!ARR_OF!(test_1.clone()).needs_destructor(&ctx));
1391        assert!(ARR_OF!(test_2.clone()).needs_destructor(&ctx));
1392        assert!(!ARR_OF!(test_1.clone()).cannot_have_destructor(&ctx));
1393        assert!(ARR_OF!(test_2.clone()).cannot_have_destructor(&ctx));
1394
1395        ctx.define_type(Location::none(), vec!(), "Test3".into(), vec!(), vec!(("".into(), test_1.clone())), None, vec!(), None).unwrap();
1396        ctx.define_type(Location::none(), vec!(), "Test4".into(), vec!(), vec!(("".into(), test_2.clone())), None, vec!(), None).unwrap();
1397        ctx.define_type(Location::none(), vec!(), "Test5".into(), vec!(), vec!(
1398            ("".into(), test_1.clone()),
1399            ("".into(), test_2.clone()),
1400        ), None, vec!(), None).unwrap();
1401
1402        let test_3_id = ctx.get_type_id("Test3".into()).unwrap();
1403        let test_4_id = ctx.get_type_id("Test4".into()).unwrap();
1404        let test_5_id = ctx.get_type_id("Test5".into()).unwrap();
1405
1406        let test_3 = Type::Basic(test_3_id);
1407        let test_4 = Type::Basic(test_4_id);
1408        let test_5 = Type::Basic(test_5_id);
1409
1410        assert!(!test_3.needs_destructor(&ctx));
1411        assert!(test_4.needs_destructor(&ctx));
1412        assert!(test_5.needs_destructor(&ctx));
1413        assert!(test_5.cannot_have_destructor(&ctx));
1414        assert!(!ARR_OF!(test_3.clone()).needs_destructor(&ctx));
1415        assert!(ARR_OF!(test_4.clone()).needs_destructor(&ctx));
1416        assert!(ARR_OF!(test_5.clone()).needs_destructor(&ctx));
1417        assert!(!ARR_OF!(test_3.clone()).cannot_have_destructor(&ctx));
1418        assert!(ARR_OF!(test_4.clone()).cannot_have_destructor(&ctx));
1419        assert!(ARR_OF!(test_5.clone()).cannot_have_destructor(&ctx));
1420
1421        ctx.define_interface_impl("Destroyable".into(), vec!(), test_3.clone(), vec!()).unwrap();
1422
1423        assert!(test_3.needs_destructor(&ctx));
1424        assert!(ARR_OF!(test_3).needs_destructor(&ctx));
1425
1426        ctx.define_type(Location::none(), vec!(), "Test6".into(), vec!(), vec!(("".into(), test_5.clone())), None, vec!(), None).unwrap();
1427        ctx.define_type(Location::none(), vec!(), "Test7".into(), vec!("T".into(), "G".into()), vec!(
1428            ("".into(), ARR_OF!(T_0)),
1429            ("".into(), ARR_OF!(T_1))
1430        ), None, vec!(), None).unwrap();
1431
1432        let test_6_id = ctx.get_type_id("Test6".into()).unwrap();
1433        let test_7_id = ctx.get_type_id("Test7".into()).unwrap();
1434
1435        let test_6 = Type::Basic(test_6_id);
1436
1437        assert!(test_6.needs_destructor(&ctx));
1438        assert!(!Type::Template(test_7_id, vec!(test_1.clone(), test_1.clone())).needs_destructor(&ctx));
1439        assert!(Type::Template(test_7_id, vec!(test_1.clone(), test_5.clone())).needs_destructor(&ctx));
1440        assert!(ARR_OF!(test_6).needs_destructor(&ctx));
1441        assert!(!ARR_OF!(Type::Template(test_7_id, vec!(test_1.clone(), test_1.clone()))).needs_destructor(&ctx));
1442        assert!(ARR_OF!(Type::Template(test_7_id, vec!(test_1.clone(), test_5.clone()))).needs_destructor(&ctx));
1443
1444        ctx.define_interface_impl("Destroyable".into(), vec!(), Type::Template(test_7_id, vec!(test_1.clone(), test_1.clone())).clone(), vec!()).unwrap();
1445
1446        assert!(Type::Template(test_7_id, vec!(test_1.clone(), test_1.clone())).needs_destructor(&ctx));
1447        assert!(!Type::Template(test_7_id, vec!(test_1.clone(), INT)).needs_destructor(&ctx));
1448        assert!(ARR_OF!(Type::Template(test_7_id, vec!(test_1.clone(), test_1.clone()))).needs_destructor(&ctx));
1449        assert!(!ARR_OF!(Type::Template(test_7_id, vec!(test_1.clone(), INT))).needs_destructor(&ctx));
1450    }
1451}