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::match_types_to_generic;
22use crate::processes::type_checking::type_comparison::reduce_type;
23use crate::processes::type_checking::unification_map;
24use crate::utils::builder;
25use crate::utils::standard_library::not_in_blacklist;
26use serde::Deserialize;
27use serde::Serialize;
28use std::collections::HashMap;
29use std::collections::HashSet;
30
31use std::ops::Add;
32use std::sync::Arc;
33use tap::Pipe;
34
35fn is_anonymous_record_name(name: &str) -> bool {
39 name.strip_prefix("Record")
40 .map(|rest| !rest.is_empty() && rest.chars().all(|c| c.is_ascii_digit()))
41 .unwrap_or(false)
42}
43
44#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
45pub struct Context {
46 pub typing_context: VarType,
47 pub subtypes: Graph<Type>,
48 #[serde(default)]
50 pub type_constructors: Vec<(String, Vec<Type>, ConstructorCategory)>,
51 #[serde(default)]
55 pub interface_constraints: HashMap<String, Type>,
56 #[serde(default)]
58 pub rigid_counter: u64,
59 #[serde(default)]
66 pub record_aliases: Vec<(String, Type)>,
67 #[serde(default)]
72 pub embedded_methods: Vec<(String, String, String)>,
73 #[serde(skip)]
78 pub test_preamble: Vec<String>,
79 #[serde(skip)]
84 pub self_type: Option<Type>,
85 #[serde(skip)]
89 pub module_inner_contexts: HashMap<String, Arc<Context>>,
90 #[serde(skip)]
96 pub processed_modules: HashMap<String, Type>,
97 #[serde(skip)]
101 pub modules_in_progress: HashSet<String>,
102 #[serde(default)]
105 pub extern_fns: Vec<(String, Option<String>)>,
106 #[serde(default)]
110 pub import_from_fns: Vec<(String, String)>,
111 config: Config,
112}
113
114fn generic_sentinels() -> Vec<Type> {
124 let h = HelpData::default();
125 let name = "_".to_string();
126 vec![
127 Type::Generic(name.clone(), h.clone()),
128 Type::KindedGen(Kind::Record, name.clone(), h.clone()),
129 Type::KindedGen(Kind::Interface, name.clone(), h.clone()),
130 Type::KindedGen(Kind::String, name.clone(), h.clone()),
131 Type::KindedGen(Kind::Boolean, name.clone(), h.clone()),
132 Type::IndexGen(name, h),
133 ]
134}
135
136fn seeded_subtype_graph() -> Graph<Type> {
142 Graph::new().add_types(&generic_sentinels(), &Context::empty())
143}
144
145impl Default for Context {
146 fn default() -> Self {
147 let config = Config::default();
148 Context {
149 config: config.clone(),
150 typing_context: VarType::from_config(config),
151 subtypes: seeded_subtype_graph(),
152 type_constructors: Vec::new(),
153 interface_constraints: HashMap::new(),
154 rigid_counter: 0,
155 record_aliases: Vec::new(),
156 embedded_methods: Vec::new(),
157 test_preamble: Vec::new(),
158 self_type: None,
159 extern_fns: Vec::new(),
160 import_from_fns: Vec::new(),
161 module_inner_contexts: HashMap::new(),
162 processed_modules: HashMap::new(),
163 modules_in_progress: HashSet::new(),
164 }
165 }
166}
167
168impl From<Vec<(Lang, Type)>> for Context {
169 fn from(val: Vec<(Lang, Type)>) -> Self {
170 let val2: Vec<(Var, Type)> = val
171 .iter()
172 .map(|(lan, typ)| (Var::from_language(lan.clone()).unwrap(), typ.clone()))
173 .collect();
174 Context {
175 typing_context: val2.into(),
176 ..Context::default()
177 }
178 }
179}
180
181impl Context {
182 pub fn new(types: Vec<(Var, Type)>) -> Context {
183 Context {
184 typing_context: types.into(),
185 ..Context::default()
186 }
187 }
188
189 pub fn empty() -> Self {
190 Context {
191 config: Config::default(),
192 typing_context: VarType::new(),
193 subtypes: Graph::new(),
194 type_constructors: Vec::new(),
195 interface_constraints: HashMap::new(),
196 rigid_counter: 0,
197 record_aliases: Vec::new(),
198 embedded_methods: Vec::new(),
199 test_preamble: Vec::new(),
200 self_type: None,
201 extern_fns: Vec::new(),
202 import_from_fns: Vec::new(),
203 module_inner_contexts: HashMap::new(),
204 processed_modules: HashMap::new(),
205 modules_in_progress: HashSet::new(),
206 }
207 }
208
209 pub fn is_extern_fn(&self, name: &str) -> bool {
210 self.extern_fns.iter().any(|(n, _)| n == name)
211 }
212
213 pub fn get_extern_r_name(&self, name: &str) -> Option<String> {
214 self.extern_fns
215 .iter()
216 .find(|(n, _)| n == name)
217 .and_then(|(_, r)| r.clone())
218 }
219
220 pub fn is_import_from_fn(&self, name: &str) -> bool {
221 self.import_from_fns.iter().any(|(n, _)| n == name)
222 }
223
224 pub fn get_import_from_r_name(&self, name: &str) -> Option<String> {
225 self.import_from_fns
226 .iter()
227 .find(|(n, _)| n == name)
228 .map(|(_, r)| r.clone())
229 }
230
231 pub fn set_config(self, config: Config) -> Self {
232 Self { config, ..self }
233 }
234
235 pub fn set_as_module_context(self) -> Context {
236 Self {
237 config: self.config.set_as_module(),
238 ..self
239 }
240 }
241
242 pub fn set_test_mode(self, val: bool) -> Context {
243 Self {
244 config: self.config.set_test_mode(val),
245 ..self
246 }
247 }
248
249 pub fn get_test_mode(&self) -> bool {
250 self.config.test_mode
251 }
252
253 pub fn set_test_preamble(self, lines: Vec<String>) -> Context {
254 Self {
255 test_preamble: lines,
256 ..self
257 }
258 }
259
260 pub fn set_self_type(self, self_type: Option<Type>) -> Context {
263 Self { self_type, ..self }
264 }
265
266 pub fn store_module_inner_context(mut self, name: &str, inner: &Context) -> Self {
267 let new_entries: HashMap<String, Arc<Context>> = inner
280 .module_inner_contexts
281 .iter()
282 .filter(|(k, _)| !self.module_inner_contexts.contains_key(k.as_str()))
283 .map(|(k, v)| (k.clone(), v.clone()))
284 .collect();
285 let mut trimmed = inner.clone();
286 trimmed.module_inner_contexts = new_entries;
287 self.module_inner_contexts
288 .insert(name.to_string(), Arc::new(trimmed));
289 self
290 }
291
292 pub fn get_module_inner_context(&self, name: &str) -> Option<&Context> {
293 self.module_inner_contexts.get(name).map(|b| b.as_ref())
294 }
295
296 pub fn mark_module_in_progress(self, name: &str) -> Self {
299 let mut set = self.modules_in_progress.clone();
300 set.insert(name.to_string());
301 Self {
302 modules_in_progress: set,
303 ..self
304 }
305 }
306
307 pub fn unmark_module_in_progress(self, name: &str) -> Self {
310 let mut set = self.modules_in_progress.clone();
311 set.remove(name);
312 Self {
313 modules_in_progress: set,
314 ..self
315 }
316 }
317
318 pub fn is_module_in_progress(&self, name: &str) -> bool {
322 self.modules_in_progress.contains(name)
323 }
324
325 pub fn cache_processed_module(self, name: &str, module_type: Type) -> Self {
329 let mut map = self.processed_modules.clone();
330 map.insert(name.to_string(), module_type);
331 Self {
332 processed_modules: map,
333 ..self
334 }
335 }
336
337 pub fn get_processed_module(&self, name: &str) -> Option<&Type> {
340 self.processed_modules.get(name)
341 }
342
343 pub fn set_in_module_body(self) -> Self {
344 Self {
345 config: self.config.set_in_module_body(true),
346 ..self
347 }
348 }
349
350 pub fn is_in_module_body(&self) -> bool {
351 self.config.in_module_body
352 }
353
354 pub fn with_subtypes(self, subtypes: Graph<Type>) -> Self {
356 Self { subtypes, ..self }
357 }
358
359 pub fn get_members(&self) -> Vec<(Var, Type)> {
360 self.typing_context
361 .variables()
362 .chain(self.aliases())
363 .cloned()
364 .collect::<Vec<_>>()
365 }
366
367 pub fn variable_exist(&self, var: Var) -> Option<Var> {
368 self.typing_context.variable_exist(var, self)
369 }
370
371 pub fn get_type_from_variable(&self, var: &Var) -> Result<Type, String> {
372 let res = self
373 .typing_context
374 .entries_named(&var.get_name())
375 .into_iter()
376 .flat_map(|(var2, typ)| {
377 let conditions = (var.is_opaque == var2.is_opaque)
378 && var.related_type.is_subtype(&var2.related_type, self).0;
379 if conditions {
380 Some(typ)
381 } else {
382 None
383 }
384 })
385 .reduce(|acc, x| if x.is_subtype(&acc, self).0 { x } else { acc });
386 match res {
387 Some(typ) => Ok(typ),
388 _ => Err(format!("Didn't find {} in the context", var.get_name())),
393 }
394 }
395
396 pub fn get_types_from_name(&self, name: &str) -> Vec<Type> {
397 self.typing_context
398 .entries_named(name)
399 .into_iter()
400 .map(|(_, typ)| typ)
401 .collect()
402 }
403
404 pub fn get_type_from_aliases(&self, var: &Var) -> Option<Type> {
405 self.aliases()
406 .flat_map(|(var2, type_)| {
407 let conditions = (var.name == var2.name)
408 && (var.is_opaque == var2.is_opaque)
409 && var.related_type.is_subtype(&var2.related_type, self).0;
410 if conditions {
411 Some(type_.clone())
412 } else {
413 None
414 }
415 })
416 .next()
417 }
418
419 fn is_matching_alias(&self, var1: &Var, var2: &Var) -> bool {
420 var1.name == var2.name
421 }
422
423 pub fn get_matching_alias_signature(&self, var: &Var) -> Option<(Type, Vec<Type>)> {
424 self.aliases()
425 .find(|(var2, _)| self.is_matching_alias(var, var2))
426 .map(|(var2, target_type)| {
427 if var2.is_opaque() {
428 (var2.clone().to_alias_type(), vec![])
429 } else if let Type::Params(types, _) = var2.get_type() {
430 (target_type.clone(), types.clone())
431 } else {
432 panic!("The related type is not Params([...])");
433 }
434 })
435 .or_else(|| {
442 self.record_aliases
443 .iter()
444 .find(|(name, _)| *name == var.get_name())
445 .map(|(_, typ)| (typ.clone(), vec![]))
446 })
447 }
448
449 pub fn variables(&self) -> impl Iterator<Item = &(Var, Type)> + '_ {
450 self.typing_context.variables()
451 }
452
453 pub fn aliases(&self) -> impl Iterator<Item = &(Var, Type)> + '_ {
454 self.typing_context.aliases()
455 }
456
457 pub fn fresh_rigid_name(self) -> (String, Self) {
459 let name = format!("__rigid_{}", self.rigid_counter);
460 (
461 name,
462 Self {
463 rigid_counter: self.rigid_counter + 1,
464 ..self
465 },
466 )
467 }
468
469 pub fn add_interface_constraint(mut self, rigid_name: String, interface: Type) -> Context {
471 self.interface_constraints.insert(rigid_name, interface);
472 self
473 }
474
475 pub fn get_interface_constraint(&self, name: &str) -> Option<&Type> {
477 self.interface_constraints.get(name)
478 }
479
480 pub fn is_rigid_constrained(&self, name: &str) -> bool {
482 self.interface_constraints.contains_key(name)
483 }
484
485 pub fn push_var_type(self, lang: Var, typ: Type, context: &Context) -> Context {
486 let reduced_type = typ.reduce(context);
487 let types = reduced_type.extract_types();
488 let new_subtypes = self.subtypes.add_types(&types, context);
489 let var_type = self
490 .typing_context
491 .pipe(|vt| {
492 if reduced_type.is_interface() && lang.is_variable() {
493 vt.push_interface(lang.clone(), reduced_type, typ.clone(), context)
494 } else {
495 vt.push_var_type(&[(lang.clone(), typ.clone())])
496 }
497 })
498 .push_types(&types);
499 Context {
500 typing_context: var_type,
501 subtypes: new_subtypes,
502 ..self
503 }
504 }
505
506 pub fn replace_or_push_var_type(self, lang: Var, typ: Type, context: &Context) -> Context {
507 let types = typ.reduce(context).extract_types();
508 let var_type = self
509 .typing_context
510 .clone()
511 .replace_or_push_var_type(&[(lang.clone(), typ.clone())])
512 .push_types(&types);
513 let new_subtypes = self.subtypes.add_types(&types, context);
514 Context {
515 typing_context: var_type,
516 subtypes: new_subtypes,
517 ..self
518 }
519 }
520
521 pub fn remove_vars(self, vars: &[Var]) -> Context {
524 Context {
525 typing_context: self.typing_context.remove_vars(vars),
526 ..self
527 }
528 }
529
530 pub fn push_types(self, types: &[Type]) -> Self {
531 let new_subtypes = self.subtypes.clone().add_types(types, &self);
536 Self {
537 typing_context: self.typing_context.clone().push_types(types),
538 subtypes: new_subtypes,
539 ..self
540 }
541 }
542
543 pub fn hoist_aliases(self, inner: &Context) -> Self {
549 let hoisted_types: Vec<Type> = self
550 .typing_context
551 .hoisted_alias_pairs(&inner.typing_context)
552 .into_iter()
553 .map(|(_, typ)| typ)
554 .collect();
555 let new_subtypes = self.subtypes.clone().add_types(&hoisted_types, &self);
556 Self {
557 typing_context: self
558 .typing_context
559 .clone()
560 .hoist_aliases(&inner.typing_context),
561 subtypes: new_subtypes,
562 ..self
563 }
564 }
565
566 pub fn get_type_from_existing_variable(&self, var: Var) -> Type {
567 if let Type::UnknownFunction(_) = var.get_type() {
568 var.get_type()
569 } else {
570 self.typing_context
571 .variables()
572 .find(|(v, _)| var.match_with(v, self))
573 .map(|(_, ty)| ty)
574 .unwrap_or(&Type::Any(var.get_help_data()))
576 .clone()
577 }
578 }
579
580 pub fn get_true_variable(&self, var: &Var) -> Var {
581 let res = self
582 .typing_context
583 .variables()
584 .find(|(v, _)| var.match_with(v, self))
585 .map(|(v, _)| v);
586 match res {
587 Some(vari) => vari.clone(),
588 _ => {
589 if self.is_an_untyped_function(&var.get_name()) {
592 var.clone()
593 .set_type(Type::UnknownFunction(var.get_help_data()))
594 } else {
595 var.clone().set_type(Type::Any(var.get_help_data()))
596 }
597 }
598 }
599 }
600
601 fn is_a_standard_function(&self, name: &str) -> bool {
602 !self.typing_context.name_exists_outside_of_std(name)
603 }
604
605 pub fn is_an_untyped_function(&self, name: &str) -> bool {
606 self.is_a_standard_function(name)
607 }
608
609 pub fn get_class(&self, t: &Type) -> String {
610 if let Type::Alias(name, _, false, _) = t {
615 if let Some((_, underlying)) = self.aliases().find(|(v, _)| v.get_name() == *name) {
616 if matches!(underlying, Type::Record(_, _)) {
617 return "'".to_string() + name + "'";
618 }
619 }
620 }
621 let reduced = t.reduce(self);
622 if matches!(reduced, Type::Any(_)) {
623 if let Type::Alias(name, _, _, _) = t {
624 return "'".to_string() + name + "'";
625 }
626 }
627 self.typing_context.get_class(&reduced)
628 }
629
630 pub fn get_class_unquoted(&self, t: &Type) -> String {
631 if let Type::Alias(name, _, false, _) = t {
633 if let Some((_, underlying)) = self.aliases().find(|(v, _)| v.get_name() == *name) {
634 if matches!(underlying, Type::Record(_, _)) {
635 return name.clone();
636 }
637 }
638 }
639 let reduced = t.reduce(self);
640 if matches!(reduced, Type::Any(_)) {
641 if let Type::Alias(name, _, _, _) = t {
642 return name.clone();
643 }
644 }
645 self.typing_context.get_class_unquoted(&reduced)
646 }
647
648 pub fn module_aliases(&self) -> Vec<(Var, Type)> {
649 self.variables()
650 .flat_map(|(_, typ)| typ.clone().to_module_type())
651 .flat_map(|module| module.get_aliases())
652 .collect()
653 }
654
655 pub fn get_type_anotations(&self) -> String {
656 self.aliases()
657 .chain(
658 [
659 (Var::from_name("Integer"), builder::integer_type_default()),
660 (
661 Var::from_name("Character"),
662 builder::character_type_default(),
663 ),
664 (Var::from_name("Number"), builder::number_type()),
665 (Var::from_name("Boolean"), builder::boolean_type()),
666 ]
667 .iter(),
668 )
669 .cloned()
670 .chain(self.module_aliases())
671 .filter(|(_, typ)| typ.clone().to_module_type().is_err())
672 .filter(|(var, typ)| {
677 !matches!(typ, Type::Record(_, _)) || is_anonymous_record_name(&var.get_name())
678 })
679 .filter(|(_, typ)| !typ.has_generic())
685 .map(|(var, typ)| (typ, var.get_name()))
686 .map(|(typ, name)| {
687 let name0 = if ["Integer", "Character", "Boolean", "Number"]
688 .iter()
689 .any(|x| name == *x)
690 {
691 format!("'{}', ", name)
692 } else {
693 Default::default()
694 };
695 let class_str = self.get_class(&typ);
696 let prefix = if name0.is_empty() && class_str != format!("'{}'", name) {
697 format!("'{}', ", name)
698 } else {
699 name0
700 };
701 format!(
702 "as.{} <- function(x) x |> struct(c({}{}, {}))",
703 name,
704 prefix,
705 class_str,
706 self.get_classes(&typ).unwrap()
707 )
708 })
709 .collect::<Vec<_>>()
710 .join("\n")
711 }
712
713 pub fn get_type_anotation(&self, t: &Type) -> String {
714 self.typing_context.get_type_anotation(t)
715 }
716
717 pub fn get_type_anotation_no_parentheses(&self, t: &Type) -> String {
718 self.typing_context.get_type_anotation_no_parentheses(t)
719 }
720
721 pub fn get_classes(&self, t: &Type) -> Option<String> {
722 let res = self
723 .subtypes
724 .get_supertypes(t, self)
725 .iter()
726 .filter(|typ| (*typ).clone().to_module_type().is_err())
727 .filter(|typ| !typ.is_empty())
728 .filter(|typ| !typ.has_generic())
733 .map(|typ| self.get_class(typ))
734 .collect::<Vec<_>>()
735 .join(", ");
736 if res.is_empty() {
737 Some("'None'".to_string())
738 } else {
739 Some(res)
740 }
741 }
742
743 pub fn get_functions(&self, var1: Var) -> Vec<(Var, Type)> {
744 self.typing_context
745 .variables()
746 .filter(|(var2, typ)| {
747 let reduced_type1 = var1.get_type().reduce(self);
748 let reduced_type2 = var2.get_type().reduce(self);
749 var1.get_name() == var2.get_name()
750 && typ.is_function()
751 && reduced_type1.is_subtype(&reduced_type2, self).0
752 })
753 .cloned()
754 .collect()
755 }
756
757 pub fn get_all_generic_functions(&self) -> Vec<(Var, Type)> {
758 let res = self
759 .typing_context
760 .variables()
761 .filter(|(_, typ)| typ.is_function())
762 .filter(|(var, _)| not_in_blacklist(&var.get_name()))
763 .filter(|(var, _)| !var.get_type().is_any())
764 .collect::<HashSet<_>>();
765 let mut result: Vec<(Var, Type)> = res
766 .iter()
767 .map(|(var, typ)| (var.clone().add_backticks_if_percent(), typ.clone()))
768 .collect();
769 result.sort_by_key(|(var, _)| var.get_name());
772 result
773 }
774
775 pub fn get_first_matching_function(&self, var1: Var) -> Type {
776 let res = self.typing_context.variables().find(|(var2, typ)| {
777 let reduced_type1 = var1.get_type().reduce(self);
778 let reduced_type2 = var2.get_type().reduce(self);
779 var1.get_name() == var2.get_name()
780 && typ.is_function()
781 && (reduced_type1.is_subtype(&reduced_type2, self).0
782 || reduced_type1.is_upperrank_of(&reduced_type2))
783 });
784 if let Some(res) = res {
785 res.1.clone()
786 } else {
787 self.typing_context
788 .standard_library()
789 .iter()
790 .find(|(var2, _)| var2.get_name() == var1.get_name())
791 .unwrap_or_else(|| {
792 panic!(
793 "Can't find var {} in the context:\n {}",
794 var1,
795 self.display_typing_context()
796 )
797 })
798 .1
799 .clone()
800 }
801 }
802
803 pub fn get_matching_typed_functions(&self, var1: Var) -> Vec<Type> {
804 self.typing_context
805 .variables()
806 .filter(|(var2, typ)| {
807 let reduced_type1 = var1.get_type().reduce(self);
808 let reduced_type2 = var2.get_type().reduce(self);
809 var1.get_name() == var2.get_name()
810 && typ.is_function()
811 && (reduced_type1.is_subtype(&reduced_type2, self).0
812 || reduced_type1.is_upperrank_of(&reduced_type2))
813 })
814 .map(|(_, typ)| typ.clone())
815 .collect::<Vec<_>>()
816 }
817
818 pub fn get_matching_untyped_functions(&self, var: Var) -> Result<Vec<Type>, String> {
819 let name1 = var.get_name();
820 let std_lib = self.typing_context.standard_library();
821 let res = std_lib
822 .iter()
823 .find(|(var2, _)| var2.get_name() == name1)
824 .map(|(_, typ)| typ);
825 match res {
826 Some(val) => Ok(vec![val.clone()]),
827 _ => Err(format!(
828 "Can't find var {} in the context:\n {}",
829 var,
830 self.display_typing_context()
831 )),
832 }
833 }
834
835 pub fn get_matching_functions(&self, var: Var) -> Result<Vec<Type>, String> {
836 let res = self.get_matching_typed_functions(var.clone());
837 if res.is_empty() {
838 self.get_matching_untyped_functions(var)
839 } else {
840 Ok(res)
841 }
842 }
843
844 pub fn get_type_from_class(&self, class: &str) -> Type {
845 self.typing_context.get_type_from_class(class)
846 }
847
848 pub fn add_arg_types(&self, params: &[ArgumentType]) -> Context {
849 let param_types = params
850 .iter()
851 .map(|arg_typ| reduce_type(self, &arg_typ.get_type()).for_var())
852 .map(|typ| match typ.to_owned() {
853 Type::Function(typs, _, _) => {
854 if !typs.is_empty() {
855 typs[0].get_type()
856 } else {
857 typ
858 }
859 }
860 t => t,
861 })
862 .collect::<Vec<_>>();
863 params
864 .iter()
865 .zip(param_types.clone())
866 .map(|(arg_typ, par_typ): (&ArgumentType, Type)| {
867 (
868 Var::from_name(&arg_typ.get_argument_str())
869 .set_type(reduce_type(self, &par_typ)),
870 reduce_type(self, &arg_typ.get_type()),
871 )
872 })
873 .fold(self.clone(), |cont: Context, (var, typ): (Var, Type)| {
874 cont.clone().push_var_type(var, typ, &cont)
875 })
876 }
877
878 pub fn set_environment(&self, e: Environment) -> Context {
879 Context {
880 config: self.config.set_environment(e),
881 ..self.clone()
882 }
883 }
884
885 pub fn display_typing_context(&self) -> String {
886 let res = self
887 .variables()
888 .chain(self.aliases())
889 .map(|(var, typ)| format!("{} ==> {}", var, typ))
890 .collect::<Vec<_>>()
891 .join("\n");
892 format!("CONTEXT:\n{}", res)
893 }
894
895 pub fn error(&self, msg: String) -> String {
896 format!("{}{}", msg, self.display_typing_context())
897 }
898
899 pub fn push_alias(self, alias_name: String, typ: Type) -> Self {
900 Context {
901 typing_context: self.typing_context.push_alias(alias_name, typ),
902 ..self
903 }
904 }
905
906 pub fn push_type_constructor(
908 self,
909 name: String,
910 parameters: Vec<Type>,
911 category: ConstructorCategory,
912 ) -> Self {
913 let mut type_constructors = self.type_constructors.clone();
914 type_constructors.retain(|(n, _, _)| n != &name);
916 type_constructors.push((name, parameters, category));
917 Context {
918 type_constructors,
919 ..self
920 }
921 }
922
923 pub fn get_type_constructor(
925 &self,
926 name: &str,
927 ) -> Option<&(String, Vec<Type>, ConstructorCategory)> {
928 self.type_constructors.iter().find(|(n, _, _)| n == name)
929 }
930
931 pub fn push_record_alias(self, name: String, typ: Type) -> Self {
935 if !matches!(typ, Type::Record(_, _)) {
936 return self;
937 }
938 let mut record_aliases = self.record_aliases.clone();
939 record_aliases.retain(|(n, _)| n != &name);
940 record_aliases.push((name, typ));
941 Context {
942 record_aliases,
943 ..self
944 }
945 }
946
947 pub fn merge_record_aliases(self, other: &Context) -> Self {
952 let mut record_aliases = self.record_aliases.clone();
953 for (name, typ) in &other.record_aliases {
954 if !record_aliases.iter().any(|(n, _)| n == name) {
955 record_aliases.push((name.clone(), typ.clone()));
956 }
957 }
958 Context {
959 record_aliases,
960 ..self
961 }
962 }
963
964 pub fn push_embedded_method(
968 self,
969 type_name: String,
970 method_name: String,
971 field_name: String,
972 ) -> Self {
973 let mut embedded_methods = self.embedded_methods.clone();
974 embedded_methods.push((type_name, method_name, field_name));
975 Context {
976 embedded_methods,
977 ..self
978 }
979 }
980
981 pub fn get_embedded_method(&self, type_name: &str, method_name: &str) -> Option<String> {
984 self.embedded_methods
985 .iter()
986 .find(|(t, m, _)| t == type_name && m == method_name)
987 .map(|(_, _, field)| field.clone())
988 }
989
990 pub fn push_alias2(self, alias_var: Var, typ: Type) -> Self {
991 Context {
992 typing_context: self.typing_context.push_alias2(alias_var, typ),
993 ..self
994 }
995 }
996
997 pub fn in_a_project(&self) -> bool {
998 self.config.environment == Environment::Project
999 }
1000
1001 pub fn get_unification_map(
1002 &self,
1003 entered_types: &[Type],
1004 param_types: &[Type],
1005 ) -> Option<UnificationMap> {
1006 let res = entered_types
1007 .iter()
1008 .zip(param_types.iter())
1009 .map(|(val_typ, par_typ)| match_types_to_generic(self, &val_typ.clone(), par_typ))
1010 .collect::<Option<Vec<_>>>();
1011
1012 let val = res
1013 .map(|vec| vec.iter().flatten().cloned().collect::<Vec<_>>())
1014 .map(UnificationMap::new);
1015
1016 val
1017 }
1018
1019 fn s3_type_definition(&self, var: &Var, typ: &Type) -> String {
1020 let first_part = format!("{} <- function(x) x |> ", var.get_name());
1021 match typ {
1022 Type::RClass(v, _) => format!(
1023 "{} struct(c({}))",
1024 first_part,
1025 v.iter().cloned().collect::<Vec<_>>().join(", ")
1026 ),
1027 _ => {
1028 let class = if typ.is_primitive() {
1029 format!("'{}'", var.get_name())
1030 } else {
1031 self.get_class(typ)
1032 };
1033 format!("{} struct(c({}))", first_part, class)
1034 }
1035 }
1036 }
1037
1038 fn get_primitive_type_definition(&self) -> Vec<String> {
1039 let primitives = [
1040 ("Integer", builder::integer_type_default()),
1041 ("Character", builder::character_type_default()),
1042 ("Number", builder::number_type()),
1043 ("Boolean", builder::boolean_type()),
1044 ];
1045 let new_context = self.clone().push_types(
1046 &primitives
1047 .iter()
1048 .map(|(_, typ)| typ)
1049 .cloned()
1050 .collect::<Vec<_>>(),
1051 );
1052 primitives
1053 .iter()
1054 .map(|(name, prim)| {
1055 (
1056 name,
1057 new_context.get_classes(prim).unwrap(),
1058 new_context.get_class(prim),
1059 )
1060 })
1061 .map(|(name, cls, cl)| {
1062 format!("{} <- function(x) x |> struct(c({}, {}))", name, cls, cl)
1063 })
1064 .collect::<Vec<_>>()
1065 }
1066
1067 pub fn get_related_functions(&self, typ: &Type, functions: &VarFunction) -> Vec<Lang> {
1068 let names = self.typing_context.get_related_functions(typ);
1069 functions.get_bodies(&names)
1070 }
1071
1072 pub fn get_functions_from_type(&self, typ: &Type) -> Vec<(Var, Type)> {
1073 self.variables()
1074 .filter(|&(var, typ2)| typ2.is_function() && var.get_type() == *typ)
1075 .cloned()
1076 .collect()
1077 }
1078
1079 pub fn get_functions_from_name(&self, name: &str) -> Vec<(Var, Type)> {
1080 self.typing_context
1081 .entries_named(name)
1082 .into_iter()
1083 .filter(|(_, typ2)| typ2.is_function())
1084 .collect()
1085 }
1086
1087 pub fn get_type_definition(&self, _functions: &VarFunction) -> String {
1088 match self.get_target_language() {
1089 TargetLanguage::R => self
1090 .typing_context
1091 .aliases
1092 .iter()
1093 .map(|(var, typ)| self.s3_type_definition(var, typ))
1094 .chain(self.get_primitive_type_definition().iter().cloned())
1095 .collect::<Vec<_>>()
1096 .join("\n"),
1097 TargetLanguage::JS => {
1098 todo!();
1099 }
1100 }
1101 }
1102
1103 pub fn update_variable(self, var: Var) -> Self {
1104 Self {
1105 typing_context: self.typing_context.update_variable(var),
1106 ..self
1107 }
1108 }
1109
1110 pub fn set_target_language(self, language: TargetLanguage) -> Self {
1111 Self {
1112 config: self.config.set_target_language(language),
1113 typing_context: self.typing_context.source(language),
1114 ..self
1115 }
1116 }
1117
1118 pub fn set_default_var_types(self) -> Self {
1119 Self {
1120 typing_context: self.typing_context.set_default_var_types(),
1121 ..self
1122 }
1123 }
1124
1125 pub fn get_target_language(&self) -> TargetLanguage {
1126 self.config.get_target_language()
1127 }
1128
1129 pub fn set_new_aliase_signature(self, alias: &str, related_type: Type) -> Self {
1130 let alias = Var::from_type(alias.parse::<Type>().unwrap()).unwrap();
1131 self.clone().push_alias2(alias, related_type)
1132 }
1133
1134 pub fn extract_module_as_vartype(&self, module_name: &str) -> Self {
1135 let typ = self
1136 .get_type_from_variable(&Var::from_name(module_name))
1137 .expect("The module name was not found");
1138 let empty_context = Context::default();
1139 let new_context = match typ.clone() {
1140 Type::Module(args, _, _) => {
1141 args.iter()
1142 .rev()
1143 .map(|arg_type| {
1144 (
1145 Var::try_from(arg_type.0.clone()).unwrap(),
1146 arg_type.1.clone(),
1147 )
1148 }) .fold(empty_context.clone(), |acc, (var, typ)| {
1151 acc.clone().push_var_type(var, typ, &acc)
1152 })
1153 }
1154 _ => panic!("{} is not a module", module_name),
1155 };
1156 new_context
1157 .clone()
1158 .push_var_type(Var::from_name(module_name), typ, &new_context)
1159 }
1160
1161 pub fn get_vartype(&self) -> VarType {
1162 self.clone().typing_context
1163 }
1164
1165 pub fn get_environment(&self) -> Environment {
1166 self.config.environment
1167 }
1168 pub fn extend_typing_context(self, var_types: VarType) -> Self {
1169 Self {
1170 typing_context: self.typing_context + var_types,
1171 ..self
1172 }
1173 }
1174}
1175
1176impl Add for Context {
1177 type Output = Self;
1178
1179 fn add(self, other: Self) -> Self::Output {
1180 let mut type_constructors = self.type_constructors;
1181 for (name, params, cat) in other.type_constructors {
1182 type_constructors.retain(|(n, _, _)| n != &name);
1183 type_constructors.push((name, params, cat));
1184 }
1185 let mut interface_constraints = self.interface_constraints;
1186 interface_constraints.extend(other.interface_constraints);
1187 let rigid_counter = self.rigid_counter.max(other.rigid_counter);
1188 let mut test_preamble = self.test_preamble;
1189 test_preamble.extend(other.test_preamble);
1190 let mut record_aliases = self.record_aliases;
1191 for entry in other.record_aliases {
1192 if !record_aliases.contains(&entry) {
1193 record_aliases.push(entry);
1194 }
1195 }
1196 let mut embedded_methods = self.embedded_methods;
1197 for entry in other.embedded_methods {
1198 if !embedded_methods.contains(&entry) {
1199 embedded_methods.push(entry);
1200 }
1201 }
1202 let mut extern_fns = self.extern_fns;
1203 for entry in other.extern_fns {
1204 if !extern_fns.iter().any(|(n, _)| n == &entry.0) {
1205 extern_fns.push(entry);
1206 }
1207 }
1208 let mut import_from_fns = self.import_from_fns;
1209 for entry in other.import_from_fns {
1210 if !import_from_fns.iter().any(|(n, _)| n == &entry.0) {
1211 import_from_fns.push(entry);
1212 }
1213 }
1214 let mut module_inner_contexts = self.module_inner_contexts;
1215 module_inner_contexts.extend(other.module_inner_contexts);
1216 let mut processed_modules = self.processed_modules;
1217 processed_modules.extend(other.processed_modules);
1218 let mut modules_in_progress = self.modules_in_progress;
1219 modules_in_progress.extend(other.modules_in_progress);
1220 Context {
1221 typing_context: self.typing_context + other.typing_context,
1222 subtypes: self.subtypes + other.subtypes,
1223 type_constructors,
1224 interface_constraints,
1225 rigid_counter,
1226 record_aliases,
1227 embedded_methods,
1228 test_preamble,
1229 self_type: None,
1230 extern_fns,
1231 import_from_fns,
1232 config: self.config,
1233 module_inner_contexts,
1234 processed_modules,
1235 modules_in_progress,
1236 }
1237 }
1238}
1239
1240#[cfg(test)]
1241mod tests {
1242 use super::*;
1243
1244 #[test]
1245 fn test_default_context1() {
1246 let context = Context::default();
1247 assert!(!context.display_typing_context().is_empty());
1248 }
1249
1250 #[test]
1251 fn test_record_nests_under_grecord_sentinel() {
1252 let ctx = Context::default();
1253 let rec = builder::record_type(&[("x".to_string(), builder::integer_type_default())]);
1254 let graph = ctx.subtypes.clone().add_type(rec.clone(), &ctx);
1255 let supers = graph.get_supertypes(&rec, &ctx);
1256 assert!(
1257 supers
1258 .iter()
1259 .any(|t| matches!(t, Type::KindedGen(Kind::Record, _, _))),
1260 "a record must nest under the GRecord (%_) sentinel; supers = {:?}",
1261 supers
1262 );
1263 assert!(
1264 supers.iter().any(|t| matches!(t, Type::Generic(_, _))),
1265 "GRecord must itself sit under the bare Generic sentinel; supers = {:?}",
1266 supers
1267 );
1268 }
1269
1270 #[test]
1271 fn test_generic_sentinels_absent_from_r_classes() {
1272 let ctx = Context::default();
1273 let rec = builder::record_type(&[("x".to_string(), builder::integer_type_default())]);
1274 let graph = ctx.subtypes.clone().add_type(rec.clone(), &ctx);
1275 let ctx = ctx.with_subtypes(graph);
1276 let classes = ctx.get_classes(&rec).unwrap();
1277 assert!(
1278 !classes.contains("GRecord") && !classes.contains('%') && !classes.contains("Generic"),
1279 "generic sentinels must be filtered out of generated R classes, got: {}",
1280 classes
1281 );
1282 }
1283}