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
19pub 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 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 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,
101
102 InferenceMarker,
104
105 SelfType,
107
108 Basic(usize),
110
111 Ref(Box<Type>),
113 MutRef(Box<Type>),
114
115 Or(Vec<Type>),
117 And(Vec<Type>),
118
119 Wildcard,
121 TemplateParam(usize, Vec<InterfaceConstraint>),
122 TemplateParamStr(String, Vec<InterfaceConstraint>),
123 Template(usize, Vec<Type>),
124
125 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 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 pub fn cannot_have_destructor(&self, ctx: &RynaContext) -> bool {
233 self.needs_destructor_rec(ctx, false)
234 }
235
236 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 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!("{}<{}>", 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 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) { 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)"); }
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
908pub 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
945pub 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#[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}