1pub mod config;
2pub mod fingerprint;
3pub mod graph;
4pub mod vartype;
5
6use crate::components::context::config::Config;
7use crate::components::context::config::Environment;
8use crate::components::context::config::TargetLanguage;
9use crate::components::context::graph::Graph;
10use crate::components::context::unification_map::UnificationMap;
11use crate::components::context::vartype::VarType;
12use crate::components::error_message::help_data::HelpData;
13use crate::components::language::var::Var;
14use crate::components::language::var_function::VarFunction;
15use crate::components::language::Lang;
16use crate::components::r#type::argument_type::ArgumentType;
17use crate::components::r#type::kind::Kind;
18use crate::components::r#type::type_system::TypeSystem;
19use crate::components::r#type::vector_type::ConstructorCategory;
20use crate::components::r#type::Type;
21use crate::processes::type_checking::facets;
22use crate::processes::type_checking::match_types_to_generic;
23use crate::processes::type_checking::type_comparison::reduce_type;
24use crate::processes::type_checking::unification_map;
25use crate::utils::builder;
26use crate::utils::standard_library::not_in_blacklist;
27use serde::Deserialize;
28use serde::Serialize;
29use std::collections::HashMap;
30use std::collections::HashSet;
31
32use std::ops::Add;
33use std::sync::Arc;
34use tap::Pipe;
35
36fn is_anonymous_record_name(name: &str) -> bool {
40 name.strip_prefix("Record")
41 .map(|rest| !rest.is_empty() && rest.chars().all(|c| c.is_ascii_digit()))
42 .unwrap_or(false)
43}
44
45#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
46pub struct Context {
47 pub typing_context: VarType,
48 pub subtypes: Graph<Type>,
49 #[serde(default)]
51 pub type_constructors: Vec<(String, Vec<Type>, ConstructorCategory)>,
52 #[serde(default)]
56 pub interface_constraints: HashMap<String, Type>,
57 #[serde(default)]
59 pub rigid_counter: u64,
60 #[serde(default)]
67 pub record_aliases: Vec<(String, Type)>,
68 #[serde(default)]
73 pub embedded_methods: Vec<(String, String, String)>,
74 #[serde(skip)]
79 pub test_preamble: Vec<String>,
80 #[serde(skip)]
85 pub self_type: Option<Type>,
86 #[serde(skip)]
91 pub expected_return_type: Option<Type>,
92 #[serde(skip)]
96 pub module_inner_contexts: HashMap<String, Arc<Context>>,
97 #[serde(skip)]
103 pub processed_modules: HashMap<String, Type>,
104 #[serde(skip)]
108 pub modules_in_progress: HashSet<String>,
109 #[serde(default)]
112 pub extern_fns: Vec<(String, Option<String>)>,
113 #[serde(default)]
117 pub import_from_fns: Vec<(String, String)>,
118 #[serde(default)]
126 pub signature_fns: Vec<String>,
127 #[serde(default)]
136 pub vectorizable_fns: Vec<(String, bool)>,
137 config: Config,
138}
139
140fn generic_sentinels() -> Vec<Type> {
150 let h = HelpData::default();
151 let name = "_".to_string();
152 vec![
153 Type::Generic(name.clone(), h.clone()),
154 Type::KindedGen(Kind::Record, name.clone(), h.clone()),
155 Type::KindedGen(Kind::Interface, name.clone(), h.clone()),
156 Type::KindedGen(Kind::String, name.clone(), h.clone()),
157 Type::KindedGen(Kind::Boolean, name.clone(), h.clone()),
158 Type::IndexGen(name, h),
159 ]
160}
161
162fn seeded_subtype_graph() -> Graph<Type> {
168 Graph::new().add_types(&generic_sentinels(), &Context::empty())
169}
170
171impl Default for Context {
172 fn default() -> Self {
173 let config = Config::default();
174 Context {
175 config: config.clone(),
176 typing_context: VarType::from_config(config),
177 subtypes: seeded_subtype_graph(),
178 type_constructors: Vec::new(),
179 interface_constraints: HashMap::new(),
180 rigid_counter: 0,
181 record_aliases: Vec::new(),
182 embedded_methods: Vec::new(),
183 test_preamble: Vec::new(),
184 self_type: None,
185 expected_return_type: None,
186 extern_fns: Vec::new(),
187 import_from_fns: Vec::new(),
188 signature_fns: Vec::new(),
189 vectorizable_fns: Vec::new(),
190 module_inner_contexts: HashMap::new(),
191 processed_modules: HashMap::new(),
192 modules_in_progress: HashSet::new(),
193 }
194 }
195}
196
197impl From<Vec<(Lang, Type)>> for Context {
198 fn from(val: Vec<(Lang, Type)>) -> Self {
199 let val2: Vec<(Var, Type)> = val
200 .iter()
201 .map(|(lan, typ)| (Var::from_language(lan.clone()).unwrap(), typ.clone()))
202 .collect();
203 Context {
204 typing_context: val2.into(),
205 ..Context::default()
206 }
207 }
208}
209
210impl Context {
211 pub fn new(types: Vec<(Var, Type)>) -> Context {
212 Context {
213 typing_context: types.into(),
214 ..Context::default()
215 }
216 }
217
218 pub fn empty() -> Self {
219 Context {
220 config: Config::default(),
221 typing_context: VarType::new(),
222 subtypes: Graph::new(),
223 type_constructors: Vec::new(),
224 interface_constraints: HashMap::new(),
225 rigid_counter: 0,
226 record_aliases: Vec::new(),
227 embedded_methods: Vec::new(),
228 test_preamble: Vec::new(),
229 self_type: None,
230 expected_return_type: None,
231 extern_fns: Vec::new(),
232 import_from_fns: Vec::new(),
233 signature_fns: Vec::new(),
234 vectorizable_fns: Vec::new(),
235 module_inner_contexts: HashMap::new(),
236 processed_modules: HashMap::new(),
237 modules_in_progress: HashSet::new(),
238 }
239 }
240
241 pub fn is_extern_fn(&self, name: &str) -> bool {
242 self.extern_fns.iter().any(|(n, _)| n == name)
243 }
244
245 pub fn is_signature_fn(&self, name: &str) -> bool {
248 self.signature_fns.iter().any(|n| n == name)
249 }
250
251 pub fn get_extern_r_name(&self, name: &str) -> Option<String> {
252 self.extern_fns
253 .iter()
254 .find(|(n, _)| n == name)
255 .and_then(|(_, r)| r.clone())
256 }
257
258 pub fn is_import_from_fn(&self, name: &str) -> bool {
259 self.import_from_fns.iter().any(|(n, _)| n == name)
260 }
261
262 pub fn get_import_from_r_name(&self, name: &str) -> Option<String> {
263 self.import_from_fns
264 .iter()
265 .find(|(n, _)| n == name)
266 .map(|(_, r)| r.clone())
267 }
268
269 pub fn register_vectorizable_fn(mut self, name: &str, is_vectorizable: bool) -> Self {
273 match self.vectorizable_fns.iter_mut().find(|(n, _)| n == name) {
274 Some(entry) => entry.1 = entry.1 && is_vectorizable,
275 None => self.vectorizable_fns.push((name.to_string(), is_vectorizable)),
276 }
277 self
278 }
279
280 pub fn is_vectorizable_fn(&self, name: &str) -> bool {
281 self.vectorizable_fns.iter().any(|(n, v)| n == name && *v)
282 }
283
284 pub fn set_config(self, config: Config) -> Self {
285 Self { config, ..self }
286 }
287
288 pub fn set_as_module_context(self) -> Context {
289 Self {
290 config: self.config.set_as_module(),
291 ..self
292 }
293 }
294
295 pub fn set_test_mode(self, val: bool) -> Context {
296 Self {
297 config: self.config.set_test_mode(val),
298 ..self
299 }
300 }
301
302 pub fn get_test_mode(&self) -> bool {
303 self.config.test_mode
304 }
305
306 pub fn set_checked_mode(self, val: bool) -> Context {
307 Self {
308 config: self.config.set_checked_mode(val),
309 ..self
310 }
311 }
312
313 pub fn get_checked_mode(&self) -> bool {
314 self.config.checked_mode
315 }
316
317 pub fn set_test_preamble(self, lines: Vec<String>) -> Context {
318 Self {
319 test_preamble: lines,
320 ..self
321 }
322 }
323
324 pub fn set_self_type(self, self_type: Option<Type>) -> Context {
327 Self { self_type, ..self }
328 }
329
330 pub fn set_expected_return_type(self, expected_return_type: Option<Type>) -> Context {
333 Self {
334 expected_return_type,
335 ..self
336 }
337 }
338
339 pub fn get_expected_return_type(&self) -> Option<Type> {
340 self.expected_return_type.clone()
341 }
342
343 pub fn store_module_inner_context(mut self, name: &str, inner: &Context) -> Self {
344 let new_entries: HashMap<String, Arc<Context>> = inner
357 .module_inner_contexts
358 .iter()
359 .filter(|(k, _)| !self.module_inner_contexts.contains_key(k.as_str()))
360 .map(|(k, v)| (k.clone(), v.clone()))
361 .collect();
362 let mut trimmed = inner.clone();
363 trimmed.module_inner_contexts = new_entries;
364 self.module_inner_contexts.insert(name.to_string(), Arc::new(trimmed));
365 self
366 }
367
368 pub fn get_module_inner_context(&self, name: &str) -> Option<&Context> {
369 self.module_inner_contexts.get(name).map(|b| b.as_ref())
370 }
371
372 pub fn mark_module_in_progress(self, name: &str) -> Self {
375 let mut set = self.modules_in_progress.clone();
376 set.insert(name.to_string());
377 Self {
378 modules_in_progress: set,
379 ..self
380 }
381 }
382
383 pub fn unmark_module_in_progress(self, name: &str) -> Self {
386 let mut set = self.modules_in_progress.clone();
387 set.remove(name);
388 Self {
389 modules_in_progress: set,
390 ..self
391 }
392 }
393
394 pub fn is_module_in_progress(&self, name: &str) -> bool {
398 self.modules_in_progress.contains(name)
399 }
400
401 pub fn cache_processed_module(self, name: &str, module_type: Type) -> Self {
405 let mut map = self.processed_modules.clone();
406 map.insert(name.to_string(), module_type);
407 Self {
408 processed_modules: map,
409 ..self
410 }
411 }
412
413 pub fn get_processed_module(&self, name: &str) -> Option<&Type> {
416 self.processed_modules.get(name)
417 }
418
419 pub fn set_in_module_body(self) -> Self {
420 Self {
421 config: self.config.set_in_module_body(true),
422 ..self
423 }
424 }
425
426 pub fn is_in_module_body(&self) -> bool {
427 self.config.in_module_body
428 }
429
430 pub fn set_in_loop(self, val: bool) -> Self {
433 Self {
434 config: self.config.set_in_loop(val),
435 ..self
436 }
437 }
438
439 pub fn is_in_loop(&self) -> bool {
440 self.config.in_loop
441 }
442
443 pub fn with_subtypes(self, subtypes: Graph<Type>) -> Self {
445 Self { subtypes, ..self }
446 }
447
448 pub fn get_members(&self) -> Vec<(Var, Type)> {
449 self.typing_context
450 .variables()
451 .chain(self.aliases())
452 .cloned()
453 .collect::<Vec<_>>()
454 }
455
456 pub fn variable_exist(&self, var: Var) -> Option<Var> {
457 self.typing_context.variable_exist(var, self)
458 }
459
460 pub fn get_type_from_variable(&self, var: &Var) -> Result<Type, String> {
461 let res = self
462 .typing_context
463 .entries_named(&var.get_name())
464 .into_iter()
465 .flat_map(|(var2, typ)| {
466 let conditions =
467 (var.is_opaque == var2.is_opaque) && var.related_type.is_subtype(&var2.related_type, self).0;
468 if conditions {
469 Some(typ)
470 } else {
471 None
472 }
473 })
474 .reduce(|acc, x| if x.is_subtype(&acc, self).0 { x } else { acc });
475 match res {
476 Some(typ) => Ok(typ),
477 _ => Err(format!("Didn't find {} in the context", var.get_name())),
482 }
483 }
484
485 pub fn get_types_from_name(&self, name: &str) -> Vec<Type> {
486 self.typing_context
487 .entries_named(name)
488 .into_iter()
489 .map(|(_, typ)| typ)
490 .collect()
491 }
492
493 pub fn get_type_from_aliases(&self, var: &Var) -> Option<Type> {
494 self.aliases()
495 .flat_map(|(var2, type_)| {
496 let conditions = (var.name == var2.name)
497 && (var.is_opaque == var2.is_opaque)
498 && var.related_type.is_subtype(&var2.related_type, self).0;
499 if conditions {
500 Some(type_.clone())
501 } else {
502 None
503 }
504 })
505 .next()
506 }
507
508 pub fn find_alias_source_module(&self, name: &str) -> Option<String> {
515 self.variables().find_map(|(var, typ)| {
516 let module_type = typ.clone().to_module_type().ok()?;
517 module_type
518 .get_aliases()
519 .iter()
520 .any(|(alias_var, _)| alias_var.get_name() == name)
521 .then(|| var.get_name())
522 })
523 }
524
525 pub fn find_variable_source_module(&self, name: &str) -> Option<(String, bool)> {
534 self.variables().find_map(|(var, typ)| {
535 let module_type = typ.clone().to_module_type().ok()?;
536 if module_type.is_public_member(name) {
537 Some((var.get_name(), true))
538 } else if module_type.has_private_member(name) {
539 Some((var.get_name(), false))
540 } else {
541 None
542 }
543 })
544 }
545
546 fn is_matching_alias(&self, var1: &Var, var2: &Var) -> bool {
547 var1.name == var2.name
548 }
549
550 pub fn get_matching_alias_signature(&self, var: &Var) -> Option<(Type, Vec<Type>)> {
551 self.aliases()
552 .find(|(var2, _)| self.is_matching_alias(var, var2))
553 .map(|(var2, target_type)| {
554 if var2.is_opaque() {
555 (var2.clone().to_alias_type(), vec![])
556 } else if let Type::Params(types, _) = var2.get_type() {
557 (target_type.clone(), types.clone())
558 } else {
559 panic!("The related type is not Params([...])");
560 }
561 })
562 .or_else(|| {
569 self.record_aliases
570 .iter()
571 .find(|(name, _)| *name == var.get_name())
572 .map(|(_, typ)| (typ.clone(), vec![]))
573 })
574 }
575
576 pub fn variables(&self) -> impl Iterator<Item = &(Var, Type)> + '_ {
577 self.typing_context.variables()
578 }
579
580 pub fn aliases(&self) -> impl Iterator<Item = &(Var, Type)> + '_ {
581 self.typing_context.aliases()
582 }
583
584 pub fn fresh_rigid_name(self) -> (String, Self) {
586 let name = format!("__rigid_{}", self.rigid_counter);
587 (
588 name,
589 Self {
590 rigid_counter: self.rigid_counter + 1,
591 ..self
592 },
593 )
594 }
595
596 pub fn add_interface_constraint(mut self, rigid_name: String, interface: Type) -> Context {
598 self.interface_constraints.insert(rigid_name, interface);
599 self
600 }
601
602 pub fn get_interface_constraint(&self, name: &str) -> Option<&Type> {
604 self.interface_constraints.get(name)
605 }
606
607 pub fn is_rigid_constrained(&self, name: &str) -> bool {
609 self.interface_constraints.contains_key(name)
610 }
611
612 pub fn push_var_type(self, lang: Var, typ: Type, context: &Context) -> Context {
613 let reduced_type = typ.reduce(context);
614 let types = reduced_type.extract_types();
615 let new_subtypes = self.subtypes.add_types(&types, context);
616 let var_type = self
617 .typing_context
618 .pipe(|vt| {
619 if reduced_type.is_interface() && lang.is_variable() {
620 vt.push_interface(lang.clone(), reduced_type, typ.clone(), context)
621 } else {
622 vt.push_var_type(&[(lang.clone(), typ.clone())])
623 }
624 })
625 .push_types(&types);
626 Context {
627 typing_context: var_type,
628 subtypes: new_subtypes,
629 ..self
630 }
631 }
632
633 pub fn replace_or_push_var_type(self, lang: Var, typ: Type, context: &Context) -> Context {
634 let types = typ.reduce(context).extract_types();
635 let var_type = self
636 .typing_context
637 .clone()
638 .replace_or_push_var_type(&[(lang.clone(), typ.clone())])
639 .push_types(&types);
640 let new_subtypes = self.subtypes.add_types(&types, context);
641 Context {
642 typing_context: var_type,
643 subtypes: new_subtypes,
644 ..self
645 }
646 }
647
648 pub fn remove_vars(self, vars: &[Var]) -> Context {
651 Context {
652 typing_context: self.typing_context.remove_vars(vars),
653 ..self
654 }
655 }
656
657 pub fn push_types(self, types: &[Type]) -> Self {
658 let new_subtypes = self.subtypes.clone().add_types(types, &self);
663 Self {
664 typing_context: self.typing_context.clone().push_types(types),
665 subtypes: new_subtypes,
666 ..self
667 }
668 }
669
670 pub fn hoist_aliases(self, inner: &Context) -> Self {
676 let hoisted_types: Vec<Type> = self
677 .typing_context
678 .hoisted_alias_pairs(&inner.typing_context)
679 .into_iter()
680 .map(|(_, typ)| typ)
681 .collect();
682 let new_subtypes = self.subtypes.clone().add_types(&hoisted_types, &self);
683 Self {
684 typing_context: self.typing_context.clone().hoist_aliases(&inner.typing_context),
685 subtypes: new_subtypes,
686 ..self
687 }
688 }
689
690 pub fn get_type_from_existing_variable(&self, var: Var) -> Type {
691 if let Type::UnknownFunction(_) = var.get_type() {
692 var.get_type()
693 } else {
694 self.typing_context
695 .variables()
696 .find(|(v, _)| var.match_with(v, self))
697 .map(|(_, ty)| ty)
698 .unwrap_or(&Type::Any(var.get_help_data()))
700 .clone()
701 }
702 }
703
704 pub fn get_true_variable(&self, var: &Var) -> Var {
705 let res = self
706 .typing_context
707 .variables()
708 .find(|(v, _)| var.match_with(v, self))
709 .map(|(v, _)| v);
710 match res {
711 Some(vari) => vari.clone(),
712 _ => {
713 if self.is_an_untyped_function(&var.get_name()) {
716 var.clone().set_type(Type::UnknownFunction(var.get_help_data()))
717 } else {
718 var.clone().set_type(Type::Any(var.get_help_data()))
719 }
720 }
721 }
722 }
723
724 fn is_a_standard_function(&self, name: &str) -> bool {
725 !self.typing_context.name_exists_outside_of_std(name)
726 }
727
728 pub fn is_an_untyped_function(&self, name: &str) -> bool {
729 self.is_a_standard_function(name)
730 }
731
732 pub fn atomic_array_elem(&self, t: &Type) -> Option<Type> {
736 self.typing_context.atomic_array_elem(t)
737 }
738
739 pub fn get_class(&self, t: &Type) -> String {
740 if let Type::Alias(name, _, false, _) = t {
745 if let Some((_, underlying)) = self.aliases().find(|(v, _)| v.get_name() == *name) {
746 if matches!(underlying, Type::Record(_, _) | Type::Vec(_, _, _, _)) {
747 return "'".to_string() + name + "'";
748 }
749 }
750 }
751 let reduced = t.reduce(self);
752 if matches!(reduced, Type::Any(_)) {
753 if let Type::Alias(name, _, _, _) = t {
754 return "'".to_string() + name + "'";
755 }
756 }
757 self.typing_context.get_class(&reduced)
758 }
759
760 pub fn get_class_unquoted(&self, t: &Type) -> String {
761 if let Type::Alias(name, _, false, _) = t {
763 if let Some((_, underlying)) = self.aliases().find(|(v, _)| v.get_name() == *name) {
764 if matches!(underlying, Type::Record(_, _) | Type::Vec(_, _, _, _)) {
765 return name.clone();
766 }
767 }
768 }
769 let reduced = t.reduce(self);
770 if matches!(reduced, Type::Any(_)) {
771 if let Type::Alias(name, _, _, _) = t {
772 return name.clone();
773 }
774 }
775 self.typing_context.get_class_unquoted(&reduced)
776 }
777
778 pub fn module_aliases(&self) -> Vec<(Var, Type)> {
779 self.variables()
780 .flat_map(|(_, typ)| typ.clone().to_module_type())
781 .flat_map(|module| module.get_aliases())
782 .collect()
783 }
784
785 pub fn get_type_anotations(&self) -> String {
786 self.aliases()
787 .chain(
788 [
789 (Var::from_name("Integer"), builder::integer_type_default()),
790 (Var::from_name("Character"), builder::character_type_default()),
791 (Var::from_name("Number"), builder::number_type()),
792 (Var::from_name("Boolean"), builder::boolean_type()),
793 ]
794 .iter(),
795 )
796 .cloned()
797 .chain(self.module_aliases())
798 .filter(|(_, typ)| typ.clone().to_module_type().is_err())
799 .filter(|(var, typ)| !matches!(typ, Type::Record(_, _)) || is_anonymous_record_name(&var.get_name()))
804 .filter(|(_, typ)| !typ.has_generic())
810 .map(|(var, typ)| (typ, var.get_name()))
811 .map(|(typ, name)| {
812 let name0 = if ["Integer", "Character", "Boolean", "Number"].iter().any(|x| name == *x) {
813 format!("'{}', ", name)
814 } else {
815 Default::default()
816 };
817 let class_str = self.get_class(&typ);
818 let prefix = if name0.is_empty() && class_str != format!("'{}'", name) {
819 format!("'{}', ", name)
820 } else {
821 name0
822 };
823 format!(
824 "as.{} <- function(x) x |> struct(c({}{}, {}))",
825 name,
826 prefix,
827 class_str,
828 self.get_classes(&typ).unwrap()
829 )
830 })
831 .collect::<Vec<_>>()
832 .join("\n")
833 }
834
835 pub fn get_type_anotation(&self, t: &Type) -> String {
836 self.typing_context.get_type_anotation(t)
837 }
838
839 pub fn get_type_anotation_no_parentheses(&self, t: &Type) -> String {
840 self.typing_context.get_type_anotation_no_parentheses(t)
841 }
842
843 pub fn resolves_to_foreign_alias(&self, name: &str) -> bool {
847 self.typing_context.resolves_to_foreign(name)
848 }
849
850 pub fn get_classes(&self, t: &Type) -> Option<String> {
851 let mut classes: Vec<String> = self
852 .subtypes
853 .get_supertypes(t, self)
854 .iter()
855 .filter(|typ| (*typ).clone().to_module_type().is_err())
856 .filter(|typ| !typ.is_empty())
857 .filter(|typ| !typ.has_generic())
862 .map(|typ| self.get_class(typ))
863 .collect();
864 if let Type::Vec(_, _, elem, _) = t {
875 let mut iface_array_classes: Vec<String> = self
876 .aliases()
877 .filter_map(|(_, other_typ)| match &other_typ {
878 Type::Vec(_, _, other_elem, _)
879 if facets::interface_facet(self, other_elem).is_some()
880 && elem.is_subtype_raw(other_elem, self) =>
881 {
882 Some(self.get_class(&other_typ))
883 }
884 _ => None,
885 })
886 .filter(|cls| !classes.contains(cls))
887 .collect();
888 iface_array_classes.sort();
889 iface_array_classes.dedup();
890 classes.extend(iface_array_classes);
891 }
892 let res = classes.join(", ");
893 if res.is_empty() {
894 Some("'None'".to_string())
895 } else {
896 Some(res)
897 }
898 }
899
900 pub fn get_functions(&self, var1: Var) -> Vec<(Var, Type)> {
901 self.typing_context
902 .variables()
903 .filter(|(var2, typ)| {
904 let reduced_type1 = var1.get_type().reduce(self);
905 let reduced_type2 = var2.get_type().reduce(self);
906 var1.get_name() == var2.get_name()
907 && typ.is_function()
908 && reduced_type1.is_subtype(&reduced_type2, self).0
909 })
910 .cloned()
911 .collect()
912 }
913
914 pub fn get_all_generic_functions(&self) -> Vec<(Var, Type)> {
915 let res = self
916 .typing_context
917 .variables()
918 .filter(|(_, typ)| typ.is_function())
919 .filter(|(var, _)| not_in_blacklist(&var.get_name()))
920 .filter(|(var, _)| !var.get_type().is_any())
921 .filter(|(var, _)| !self.is_extern_fn(&var.get_name()))
930 .filter(|(var, _)| !self.is_import_from_fn(&var.get_name()))
931 .collect::<HashSet<_>>();
932 let mut result: Vec<(Var, Type)> = res
933 .iter()
934 .map(|(var, typ)| (var.clone().add_backticks_if_percent(), typ.clone()))
935 .collect();
936 result.sort_by_key(|(var, _)| var.get_name());
939 result
940 }
941
942 pub fn get_first_matching_function(&self, var1: Var) -> Type {
943 let res = self.typing_context.variables().find(|(var2, typ)| {
944 let reduced_type1 = var1.get_type().reduce(self);
945 let reduced_type2 = var2.get_type().reduce(self);
946 var1.get_name() == var2.get_name()
947 && typ.is_function()
948 && (reduced_type1.is_subtype(&reduced_type2, self).0 || reduced_type1.is_upperrank_of(&reduced_type2))
949 });
950 if let Some(res) = res {
951 res.1.clone()
952 } else {
953 self.typing_context
954 .standard_library()
955 .iter()
956 .find(|(var2, _)| var2.get_name() == var1.get_name())
957 .unwrap_or_else(|| {
958 panic!(
959 "Can't find var {} in the context:\n {}",
960 var1,
961 self.display_typing_context()
962 )
963 })
964 .1
965 .clone()
966 }
967 }
968
969 pub fn get_matching_typed_functions(&self, var1: Var) -> Vec<Type> {
970 self.typing_context
971 .variables()
972 .filter(|(var2, typ)| {
973 let reduced_type1 = var1.get_type().reduce(self);
974 let reduced_type2 = var2.get_type().reduce(self);
975 var1.get_name() == var2.get_name()
976 && typ.is_function()
977 && (reduced_type1.is_subtype(&reduced_type2, self).0
978 || reduced_type1.is_upperrank_of(&reduced_type2))
979 })
980 .map(|(_, typ)| typ.clone())
981 .collect::<Vec<_>>()
982 }
983
984 pub fn get_matching_untyped_functions(&self, var: Var) -> Result<Vec<Type>, String> {
985 let name1 = var.get_name();
986 let std_lib = self.typing_context.standard_library();
987 let res = std_lib
988 .iter()
989 .find(|(var2, _)| var2.get_name() == name1)
990 .map(|(_, typ)| typ);
991 match res {
992 Some(val) => Ok(vec![val.clone()]),
993 _ => Err(format!(
994 "Can't find var {} in the context:\n {}",
995 var,
996 self.display_typing_context()
997 )),
998 }
999 }
1000
1001 pub fn get_matching_functions(&self, var: Var) -> Result<Vec<Type>, String> {
1002 let res = self.get_matching_typed_functions(var.clone());
1003 if res.is_empty() {
1004 self.get_matching_untyped_functions(var)
1005 } else {
1006 Ok(res)
1007 }
1008 }
1009
1010 pub fn get_type_from_class(&self, class: &str) -> Type {
1011 self.typing_context.get_type_from_class(class)
1012 }
1013
1014 pub fn add_arg_types(&self, params: &[ArgumentType]) -> Context {
1015 let param_types = params
1016 .iter()
1017 .map(|arg_typ| reduce_type(self, &arg_typ.get_type()).for_var())
1018 .map(|typ| match typ.to_owned() {
1019 Type::Function(typs, _, _) => {
1020 if !typs.is_empty() {
1021 typs[0].get_type()
1022 } else {
1023 typ
1024 }
1025 }
1026 t => t,
1027 })
1028 .collect::<Vec<_>>();
1029 params
1030 .iter()
1031 .zip(param_types.clone())
1032 .map(|(arg_typ, par_typ): (&ArgumentType, Type)| {
1033 (
1034 Var::from_name(&arg_typ.get_argument_str()).set_type(reduce_type(self, &par_typ)),
1035 reduce_type(self, &arg_typ.get_type()),
1036 )
1037 })
1038 .fold(self.clone(), |cont: Context, (var, typ): (Var, Type)| {
1039 cont.clone().push_var_type(var, typ, &cont)
1040 })
1041 }
1042
1043 pub fn set_environment(&self, e: Environment) -> Context {
1044 Context {
1045 config: self.config.set_environment(e),
1046 ..self.clone()
1047 }
1048 }
1049
1050 pub fn display_typing_context(&self) -> String {
1051 let res = self
1052 .variables()
1053 .chain(self.aliases())
1054 .map(|(var, typ)| format!("{} ==> {}", var, typ))
1055 .collect::<Vec<_>>()
1056 .join("\n");
1057 format!("CONTEXT:\n{}", res)
1058 }
1059
1060 pub fn error(&self, msg: String) -> String {
1061 format!("{}{}", msg, self.display_typing_context())
1062 }
1063
1064 pub fn push_alias(self, alias_name: String, typ: Type) -> Self {
1065 Context {
1066 typing_context: self.typing_context.push_alias(alias_name, typ),
1067 ..self
1068 }
1069 }
1070
1071 pub fn push_type_constructor(self, name: String, parameters: Vec<Type>, category: ConstructorCategory) -> Self {
1073 let mut type_constructors = self.type_constructors.clone();
1074 type_constructors.retain(|(n, _, _)| n != &name);
1076 type_constructors.push((name, parameters, category));
1077 Context {
1078 type_constructors,
1079 ..self
1080 }
1081 }
1082
1083 pub fn get_type_constructor(&self, name: &str) -> Option<&(String, Vec<Type>, ConstructorCategory)> {
1085 self.type_constructors.iter().find(|(n, _, _)| n == name)
1086 }
1087
1088 pub fn push_record_alias(self, name: String, typ: Type) -> Self {
1092 if !matches!(typ, Type::Record(_, _)) {
1093 return self;
1094 }
1095 let mut record_aliases = self.record_aliases.clone();
1096 record_aliases.retain(|(n, _)| n != &name);
1097 record_aliases.push((name, typ));
1098 Context { record_aliases, ..self }
1099 }
1100
1101 pub fn merge_record_aliases(self, other: &Context) -> Self {
1106 let mut record_aliases = self.record_aliases.clone();
1107 for (name, typ) in &other.record_aliases {
1108 if !record_aliases.iter().any(|(n, _)| n == name) {
1109 record_aliases.push((name.clone(), typ.clone()));
1110 }
1111 }
1112 Context { record_aliases, ..self }
1113 }
1114
1115 pub fn push_embedded_method(self, type_name: String, method_name: String, field_name: String) -> Self {
1119 let mut embedded_methods = self.embedded_methods.clone();
1120 embedded_methods.push((type_name, method_name, field_name));
1121 Context {
1122 embedded_methods,
1123 ..self
1124 }
1125 }
1126
1127 pub fn get_embedded_method(&self, type_name: &str, method_name: &str) -> Option<String> {
1130 self.embedded_methods
1131 .iter()
1132 .find(|(t, m, _)| t == type_name && m == method_name)
1133 .map(|(_, _, field)| field.clone())
1134 }
1135
1136 pub fn push_alias2(self, alias_var: Var, typ: Type) -> Self {
1137 Context {
1138 typing_context: self.typing_context.push_alias2(alias_var, typ),
1139 ..self
1140 }
1141 }
1142
1143 pub fn in_a_project(&self) -> bool {
1144 self.config.environment == Environment::Project
1145 }
1146
1147 pub fn get_unification_map(&self, entered_types: &[Type], param_types: &[Type]) -> Option<UnificationMap> {
1148 let res = entered_types
1149 .iter()
1150 .zip(param_types.iter())
1151 .map(|(val_typ, par_typ)| match_types_to_generic(self, &val_typ.clone(), par_typ))
1152 .collect::<Option<Vec<_>>>();
1153
1154 res.map(|vec| vec.iter().flatten().cloned().collect::<Vec<_>>())
1155 .and_then(UnificationMap::try_new)
1156 }
1157
1158 fn s3_type_definition(&self, var: &Var, typ: &Type) -> String {
1159 let first_part = format!("{} <- function(x) x |> ", var.get_name());
1160 match typ {
1161 Type::RClass(v, _) => format!(
1162 "{} struct(c({}))",
1163 first_part,
1164 v.iter().cloned().collect::<Vec<_>>().join(", ")
1165 ),
1166 _ => {
1167 let class = if typ.is_primitive() {
1168 format!("'{}'", var.get_name())
1169 } else {
1170 self.get_class(typ)
1171 };
1172 format!("{} struct(c({}))", first_part, class)
1173 }
1174 }
1175 }
1176
1177 fn get_primitive_type_definition(&self) -> Vec<String> {
1178 let primitives = [
1179 ("Integer", builder::integer_type_default()),
1180 ("Character", builder::character_type_default()),
1181 ("Number", builder::number_type()),
1182 ("Boolean", builder::boolean_type()),
1183 ];
1184 let new_context = self
1185 .clone()
1186 .push_types(&primitives.iter().map(|(_, typ)| typ).cloned().collect::<Vec<_>>());
1187 primitives
1188 .iter()
1189 .map(|(name, prim)| {
1190 (
1191 name,
1192 new_context.get_classes(prim).unwrap(),
1193 new_context.get_class(prim),
1194 )
1195 })
1196 .map(|(name, cls, cl)| format!("{} <- function(x) x |> struct(c({}, {}))", name, cls, cl))
1197 .collect::<Vec<_>>()
1198 }
1199
1200 pub fn get_related_functions(&self, typ: &Type, functions: &VarFunction) -> Vec<Lang> {
1201 let names = self.typing_context.get_related_functions(typ);
1202 functions.get_bodies(&names)
1203 }
1204
1205 pub fn get_functions_from_type(&self, typ: &Type) -> Vec<(Var, Type)> {
1206 let reduced_typ = reduce_type(self, typ);
1214 self.variables()
1215 .filter(|&(var, typ2)| {
1216 if !typ2.is_function() {
1217 return false;
1218 }
1219 if var.get_type() == *typ || reduce_type(self, &var.get_type()) == reduced_typ {
1220 return true;
1221 }
1222 typ2.get_first_parameter()
1233 .is_some_and(|p| p == *typ || reduce_type(self, &p) == reduced_typ)
1234 })
1235 .cloned()
1236 .collect()
1237 }
1238
1239 pub fn get_functions_from_name(&self, name: &str) -> Vec<(Var, Type)> {
1240 self.typing_context
1241 .entries_named(name)
1242 .into_iter()
1243 .filter(|(_, typ2)| typ2.is_function())
1244 .collect()
1245 }
1246
1247 pub fn get_type_definition(&self, _functions: &VarFunction) -> String {
1248 match self.get_target_language() {
1249 TargetLanguage::R => self
1250 .typing_context
1251 .aliases
1252 .iter()
1253 .map(|(var, typ)| self.s3_type_definition(var, typ))
1254 .chain(self.get_primitive_type_definition().iter().cloned())
1255 .collect::<Vec<_>>()
1256 .join("\n"),
1257 TargetLanguage::JS => {
1258 todo!();
1259 }
1260 }
1261 }
1262
1263 pub fn update_variable(self, var: Var) -> Self {
1264 Self {
1265 typing_context: self.typing_context.update_variable(var),
1266 ..self
1267 }
1268 }
1269
1270 pub fn set_target_language(self, language: TargetLanguage) -> Self {
1271 Self {
1272 config: self.config.set_target_language(language),
1273 typing_context: self.typing_context.source(language),
1274 ..self
1275 }
1276 }
1277
1278 pub fn set_default_var_types(self) -> Self {
1279 Self {
1280 typing_context: self.typing_context.set_default_var_types(),
1281 ..self
1282 }
1283 }
1284
1285 pub fn get_target_language(&self) -> TargetLanguage {
1286 self.config.get_target_language()
1287 }
1288
1289 pub fn set_new_aliase_signature(self, alias: &str, related_type: Type) -> Self {
1290 let alias = Var::from_type(alias.parse::<Type>().unwrap()).unwrap();
1291 self.clone().push_alias2(alias, related_type)
1292 }
1293
1294 pub fn extract_module_as_vartype(&self, module_name: &str) -> Self {
1295 let typ = self
1296 .get_type_from_variable(&Var::from_name(module_name))
1297 .expect("The module name was not found");
1298 let empty_context = Context::default();
1299 let new_context = match typ.clone() {
1300 Type::Module(args, _, _) => {
1301 args.iter()
1302 .rev()
1303 .map(|arg_type| (Var::try_from(arg_type.0.clone()).unwrap(), arg_type.1.clone())) .fold(empty_context.clone(), |acc, (var, typ)| {
1306 acc.clone().push_var_type(var, typ, &acc)
1307 })
1308 }
1309 _ => panic!("{} is not a module", module_name),
1310 };
1311 new_context
1312 .clone()
1313 .push_var_type(Var::from_name(module_name), typ, &new_context)
1314 }
1315
1316 pub fn get_vartype(&self) -> VarType {
1317 self.clone().typing_context
1318 }
1319
1320 pub fn get_environment(&self) -> Environment {
1321 self.config.environment
1322 }
1323 pub fn extend_typing_context(self, var_types: VarType) -> Self {
1324 Self {
1325 typing_context: self.typing_context + var_types,
1326 ..self
1327 }
1328 }
1329}
1330
1331impl Add for Context {
1332 type Output = Self;
1333
1334 fn add(self, other: Self) -> Self::Output {
1335 let mut type_constructors = self.type_constructors;
1336 for (name, params, cat) in other.type_constructors {
1337 type_constructors.retain(|(n, _, _)| n != &name);
1338 type_constructors.push((name, params, cat));
1339 }
1340 let mut interface_constraints = self.interface_constraints;
1341 interface_constraints.extend(other.interface_constraints);
1342 let rigid_counter = self.rigid_counter.max(other.rigid_counter);
1343 let mut test_preamble = self.test_preamble;
1344 test_preamble.extend(other.test_preamble);
1345 let mut record_aliases = self.record_aliases;
1346 for entry in other.record_aliases {
1347 if !record_aliases.contains(&entry) {
1348 record_aliases.push(entry);
1349 }
1350 }
1351 let mut embedded_methods = self.embedded_methods;
1352 for entry in other.embedded_methods {
1353 if !embedded_methods.contains(&entry) {
1354 embedded_methods.push(entry);
1355 }
1356 }
1357 let mut extern_fns = self.extern_fns;
1358 for entry in other.extern_fns {
1359 if !extern_fns.iter().any(|(n, _)| n == &entry.0) {
1360 extern_fns.push(entry);
1361 }
1362 }
1363 let mut import_from_fns = self.import_from_fns;
1364 for entry in other.import_from_fns {
1365 if !import_from_fns.iter().any(|(n, _)| n == &entry.0) {
1366 import_from_fns.push(entry);
1367 }
1368 }
1369 let mut signature_fns = self.signature_fns;
1370 for name in other.signature_fns {
1371 if !signature_fns.contains(&name) {
1372 signature_fns.push(name);
1373 }
1374 }
1375 let mut vectorizable_fns = self.vectorizable_fns;
1376 for (name, is_vec) in other.vectorizable_fns {
1377 match vectorizable_fns.iter_mut().find(|(n, _)| n == &name) {
1378 Some(entry) => entry.1 = entry.1 && is_vec,
1379 None => vectorizable_fns.push((name, is_vec)),
1380 }
1381 }
1382 let mut module_inner_contexts = self.module_inner_contexts;
1383 module_inner_contexts.extend(other.module_inner_contexts);
1384 let mut processed_modules = self.processed_modules;
1385 processed_modules.extend(other.processed_modules);
1386 let mut modules_in_progress = self.modules_in_progress;
1387 modules_in_progress.extend(other.modules_in_progress);
1388 Context {
1389 typing_context: self.typing_context + other.typing_context,
1390 subtypes: self.subtypes + other.subtypes,
1391 type_constructors,
1392 interface_constraints,
1393 rigid_counter,
1394 record_aliases,
1395 embedded_methods,
1396 test_preamble,
1397 self_type: None,
1398 expected_return_type: None,
1399 extern_fns,
1400 import_from_fns,
1401 signature_fns,
1402 vectorizable_fns,
1403 config: self.config,
1404 module_inner_contexts,
1405 processed_modules,
1406 modules_in_progress,
1407 }
1408 }
1409}
1410
1411#[cfg(test)]
1412mod tests {
1413 use super::*;
1414
1415 #[test]
1416 fn test_default_context1() {
1417 let context = Context::default();
1418 assert!(!context.display_typing_context().is_empty());
1419 }
1420
1421 #[test]
1422 fn test_record_nests_under_grecord_sentinel() {
1423 let ctx = Context::default();
1424 let rec = builder::record_type(&[("x".to_string(), builder::integer_type_default())]);
1425 let graph = ctx.subtypes.clone().add_type(rec.clone(), &ctx);
1426 let supers = graph.get_supertypes(&rec, &ctx);
1427 assert!(
1428 supers.iter().any(|t| matches!(t, Type::KindedGen(Kind::Record, _, _))),
1429 "a record must nest under the GRecord (%_) sentinel; supers = {:?}",
1430 supers
1431 );
1432 assert!(
1433 supers.iter().any(|t| matches!(t, Type::Generic(_, _))),
1434 "GRecord must itself sit under the bare Generic sentinel; supers = {:?}",
1435 supers
1436 );
1437 }
1438
1439 #[test]
1440 fn test_generic_sentinels_absent_from_r_classes() {
1441 let ctx = Context::default();
1442 let rec = builder::record_type(&[("x".to_string(), builder::integer_type_default())]);
1443 let graph = ctx.subtypes.clone().add_type(rec.clone(), &ctx);
1444 let ctx = ctx.with_subtypes(graph);
1445 let classes = ctx.get_classes(&rec).unwrap();
1446 assert!(
1447 !classes.contains("GRecord") && !classes.contains('%') && !classes.contains("Generic"),
1448 "generic sentinels must be filtered out of generated R classes, got: {}",
1449 classes
1450 );
1451 }
1452}