1pub mod config;
2pub mod graph;
3pub mod vartype;
4
5use crate::components::context::config::Config;
6use crate::components::context::config::Environment;
7use crate::components::context::config::TargetLanguage;
8use crate::components::context::graph::Graph;
9use crate::components::context::unification_map::UnificationMap;
10use crate::components::context::vartype::VarType;
11use crate::components::error_message::help_data::HelpData;
12use crate::components::language::var::Var;
13use crate::components::language::var_function::VarFunction;
14use crate::components::language::Lang;
15use crate::components::r#type::argument_type::ArgumentType;
16use crate::components::r#type::kind::Kind;
17use crate::components::r#type::type_system::TypeSystem;
18use crate::components::r#type::vector_type::ConstructorCategory;
19use crate::components::r#type::Type;
20use crate::processes::type_checking::match_types_to_generic;
21use crate::processes::type_checking::type_comparison::reduce_type;
22use crate::processes::type_checking::unification_map;
23use crate::utils::builder;
24use crate::utils::standard_library::not_in_blacklist;
25use serde::Deserialize;
26use serde::Serialize;
27use std::collections::HashMap;
28use std::collections::HashSet;
29use std::iter::Rev;
30use std::ops::Add;
31use tap::Pipe;
32
33fn is_anonymous_record_name(name: &str) -> bool {
37 name.strip_prefix("Record")
38 .map(|rest| !rest.is_empty() && rest.chars().all(|c| c.is_ascii_digit()))
39 .unwrap_or(false)
40}
41
42#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
43pub struct Context {
44 pub typing_context: VarType,
45 pub subtypes: Graph<Type>,
46 #[serde(default)]
48 pub type_constructors: Vec<(String, Vec<Type>, ConstructorCategory)>,
49 #[serde(default)]
53 pub interface_constraints: HashMap<String, Type>,
54 #[serde(default)]
56 pub rigid_counter: u64,
57 #[serde(default)]
64 pub record_aliases: Vec<(String, Type)>,
65 #[serde(default)]
70 pub embedded_methods: Vec<(String, String, String)>,
71 #[serde(skip)]
76 pub test_preamble: Vec<String>,
77 #[serde(skip)]
82 pub self_type: Option<Type>,
83 config: Config,
84}
85
86fn generic_sentinels() -> Vec<Type> {
96 let h = HelpData::default();
97 let name = "_".to_string();
98 vec![
99 Type::Generic(name.clone(), h.clone()),
100 Type::KindedGen(Kind::Record, name.clone(), h.clone()),
101 Type::KindedGen(Kind::Interface, name.clone(), h.clone()),
102 Type::KindedGen(Kind::String, name.clone(), h.clone()),
103 Type::KindedGen(Kind::Boolean, name.clone(), h.clone()),
104 Type::IndexGen(name, h),
105 ]
106}
107
108fn seeded_subtype_graph() -> Graph<Type> {
114 Graph::new().add_types(&generic_sentinels(), &Context::empty())
115}
116
117impl Default for Context {
118 fn default() -> Self {
119 let config = Config::default();
120 Context {
121 config: config.clone(),
122 typing_context: VarType::from_config(config),
123 subtypes: seeded_subtype_graph(),
124 type_constructors: Vec::new(),
125 interface_constraints: HashMap::new(),
126 rigid_counter: 0,
127 record_aliases: Vec::new(),
128 embedded_methods: Vec::new(),
129 test_preamble: Vec::new(),
130 self_type: None,
131 }
132 }
133}
134
135impl From<Vec<(Lang, Type)>> for Context {
136 fn from(val: Vec<(Lang, Type)>) -> Self {
137 let val2: Vec<(Var, Type)> = val
138 .iter()
139 .map(|(lan, typ)| (Var::from_language(lan.clone()).unwrap(), typ.clone()))
140 .collect();
141 Context {
142 typing_context: val2.into(),
143 ..Context::default()
144 }
145 }
146}
147
148impl Context {
149 pub fn new(types: Vec<(Var, Type)>) -> Context {
150 Context {
151 typing_context: types.into(),
152 ..Context::default()
153 }
154 }
155
156 pub fn empty() -> Self {
157 Context {
158 config: Config::default(),
159 typing_context: VarType::new(),
160 subtypes: Graph::new(),
161 type_constructors: Vec::new(),
162 interface_constraints: HashMap::new(),
163 rigid_counter: 0,
164 record_aliases: Vec::new(),
165 embedded_methods: Vec::new(),
166 test_preamble: Vec::new(),
167 self_type: None,
168 }
169 }
170
171 pub fn set_config(self, config: Config) -> Self {
172 Self { config, ..self }
173 }
174
175 pub fn set_as_module_context(self) -> Context {
176 Self {
177 config: self.config.set_as_module(),
178 ..self
179 }
180 }
181
182 pub fn set_test_mode(self, val: bool) -> Context {
183 Self {
184 config: self.config.set_test_mode(val),
185 ..self
186 }
187 }
188
189 pub fn get_test_mode(&self) -> bool {
190 self.config.test_mode
191 }
192
193 pub fn set_test_preamble(self, lines: Vec<String>) -> Context {
194 Self {
195 test_preamble: lines,
196 ..self
197 }
198 }
199
200 pub fn set_self_type(self, self_type: Option<Type>) -> Context {
203 Self { self_type, ..self }
204 }
205
206 pub fn set_in_module_body(self) -> Self {
207 Self {
208 config: self.config.set_in_module_body(true),
209 ..self
210 }
211 }
212
213 pub fn is_in_module_body(&self) -> bool {
214 self.config.in_module_body
215 }
216
217 pub fn with_subtypes(self, subtypes: Graph<Type>) -> Self {
219 Self { subtypes, ..self }
220 }
221
222 pub fn get_members(&self) -> Vec<(Var, Type)> {
223 self.typing_context
224 .variables()
225 .chain(self.aliases())
226 .cloned()
227 .collect::<Vec<_>>()
228 }
229
230 pub fn variable_exist(&self, var: Var) -> Option<Var> {
231 self.typing_context.variable_exist(var)
232 }
233
234 pub fn get_type_from_variable(&self, var: &Var) -> Result<Type, String> {
235 let res = self
236 .variables()
237 .flat_map(|(var2, typ)| {
238 let conditions = (var.name == var2.name)
239 && (var.is_opaque == var2.is_opaque)
240 && var.related_type.is_subtype(&var2.related_type, self).0;
241 if conditions {
242 Some(typ.clone())
243 } else {
244 None
245 }
246 })
247 .reduce(|acc, x| if x.is_subtype(&acc, self).0 { x } else { acc });
248 match res {
249 Some(typ) => Ok(typ),
250 _ => Err(format!(
251 "Didn't find {} in the context: {}",
252 var.get_name(),
253 self.display_typing_context()
254 )),
255 }
256 }
257
258 pub fn get_types_from_name(&self, name: &str) -> Vec<Type> {
259 self.variables()
260 .filter(|(var, _)| var.get_name() == name)
261 .map(|(_, typ)| typ.clone())
262 .collect()
263 }
264
265 pub fn get_type_from_aliases(&self, var: &Var) -> Option<Type> {
266 self.aliases()
267 .flat_map(|(var2, type_)| {
268 let conditions = (var.name == var2.name)
269 && (var.is_opaque == var2.is_opaque)
270 && var.related_type.is_subtype(&var2.related_type, self).0;
271 if conditions {
272 Some(type_.clone())
273 } else {
274 None
275 }
276 })
277 .next()
278 }
279
280 fn is_matching_alias(&self, var1: &Var, var2: &Var) -> bool {
281 var1.name == var2.name
282 }
283
284 pub fn get_matching_alias_signature(&self, var: &Var) -> Option<(Type, Vec<Type>)> {
285 self.aliases()
286 .find(|(var2, _)| self.is_matching_alias(var, var2))
287 .map(|(var2, target_type)| {
288 if var2.is_opaque() {
289 (var2.clone().to_alias_type(), vec![])
290 } else if let Type::Params(types, _) = var2.get_type() {
291 (target_type.clone(), types.clone())
292 } else {
293 panic!("The related type is not Params([...])");
294 }
295 })
296 }
297
298 pub fn variables(&self) -> Rev<std::vec::IntoIter<&(Var, Type)>> {
299 self.typing_context.variables()
300 }
301
302 pub fn aliases(&self) -> Rev<std::vec::IntoIter<&(Var, Type)>> {
303 self.typing_context.aliases()
304 }
305
306 pub fn fresh_rigid_name(self) -> (String, Self) {
308 let name = format!("__rigid_{}", self.rigid_counter);
309 (
310 name,
311 Self {
312 rigid_counter: self.rigid_counter + 1,
313 ..self
314 },
315 )
316 }
317
318 pub fn add_interface_constraint(mut self, rigid_name: String, interface: Type) -> Context {
320 self.interface_constraints.insert(rigid_name, interface);
321 self
322 }
323
324 pub fn get_interface_constraint(&self, name: &str) -> Option<&Type> {
326 self.interface_constraints.get(name)
327 }
328
329 pub fn is_rigid_constrained(&self, name: &str) -> bool {
331 self.interface_constraints.contains_key(name)
332 }
333
334 pub fn push_var_type(self, lang: Var, typ: Type, context: &Context) -> Context {
335 let reduced_type = typ.reduce(context);
336 let types = reduced_type.extract_types();
337 let var_type = self
338 .typing_context
339 .clone()
340 .pipe(|vt| {
341 if reduced_type.is_interface() && lang.is_variable() {
342 vt.clone()
343 .push_interface(lang.clone(), reduced_type, typ.clone(), context)
344 } else {
345 vt.push_var_type(&[(lang.clone(), typ.clone())])
346 }
347 })
348 .push_types(&types);
349 let new_subtypes = self.subtypes.add_types(&types, context);
350 Context {
351 typing_context: var_type,
352 subtypes: new_subtypes,
353 ..self
354 }
355 }
356
357 pub fn replace_or_push_var_type(self, lang: Var, typ: Type, context: &Context) -> Context {
358 let types = typ.reduce(context).extract_types();
359 let var_type = self
360 .typing_context
361 .clone()
362 .replace_or_push_var_type(&[(lang.clone(), typ.clone())])
363 .push_types(&types);
364 let new_subtypes = self.subtypes.add_types(&types, context);
365 Context {
366 typing_context: var_type,
367 subtypes: new_subtypes,
368 ..self
369 }
370 }
371
372 pub fn remove_vars(self, vars: &[Var]) -> Context {
375 Context {
376 typing_context: self.typing_context.remove_vars(vars),
377 ..self
378 }
379 }
380
381 pub fn push_types(self, types: &[Type]) -> Self {
382 Self {
383 typing_context: self.typing_context.push_types(types),
384 ..self
385 }
386 }
387
388 pub fn get_type_from_existing_variable(&self, var: Var) -> Type {
389 if let Type::UnknownFunction(_) = var.get_type() {
390 var.get_type()
391 } else {
392 self.typing_context
393 .variables()
394 .find(|(v, _)| var.match_with(v, self))
395 .map(|(_, ty)| ty)
396 .unwrap_or(&Type::Any(var.get_help_data()))
398 .clone()
399 }
400 }
401
402 pub fn get_true_variable(&self, var: &Var) -> Var {
403 let res = self
404 .typing_context
405 .variables()
406 .find(|(v, _)| var.match_with(v, self))
407 .map(|(v, _)| v);
408 match res {
409 Some(vari) => vari.clone(),
410 _ => {
411 if self.is_an_untyped_function(&var.get_name()) {
414 var.clone()
415 .set_type(Type::UnknownFunction(var.get_help_data()))
416 } else {
417 var.clone().set_type(Type::Any(var.get_help_data()))
418 }
419 }
420 }
421 }
422
423 fn is_a_standard_function(&self, name: &str) -> bool {
424 !self.typing_context.name_exists_outside_of_std(name)
425 }
426
427 pub fn is_an_untyped_function(&self, name: &str) -> bool {
428 self.is_a_standard_function(name)
429 }
430
431 pub fn get_class(&self, t: &Type) -> String {
432 if let Type::Alias(name, _, false, _) = t {
437 if let Some((_, underlying)) = self.aliases().find(|(v, _)| v.get_name() == *name) {
438 if matches!(underlying, Type::Record(_, _)) {
439 return "'".to_string() + name + "'";
440 }
441 }
442 }
443 let reduced = t.reduce(self);
444 if matches!(reduced, Type::Any(_)) {
445 if let Type::Alias(name, _, _, _) = t {
446 return "'".to_string() + name + "'";
447 }
448 }
449 self.typing_context.get_class(&reduced)
450 }
451
452 pub fn get_class_unquoted(&self, t: &Type) -> String {
453 if let Type::Alias(name, _, false, _) = t {
455 if let Some((_, underlying)) = self.aliases().find(|(v, _)| v.get_name() == *name) {
456 if matches!(underlying, Type::Record(_, _)) {
457 return name.clone();
458 }
459 }
460 }
461 let reduced = t.reduce(self);
462 if matches!(reduced, Type::Any(_)) {
463 if let Type::Alias(name, _, _, _) = t {
464 return name.clone();
465 }
466 }
467 self.typing_context.get_class_unquoted(&reduced)
468 }
469
470 pub fn module_aliases(&self) -> Vec<(Var, Type)> {
471 self.variables()
472 .flat_map(|(_, typ)| typ.clone().to_module_type())
473 .flat_map(|module| module.get_aliases())
474 .collect()
475 }
476
477 pub fn get_type_anotations(&self) -> String {
478 self.aliases()
479 .chain(
480 [
481 (Var::from_name("Integer"), builder::integer_type_default()),
482 (
483 Var::from_name("Character"),
484 builder::character_type_default(),
485 ),
486 (Var::from_name("Number"), builder::number_type()),
487 (Var::from_name("Boolean"), builder::boolean_type()),
488 ]
489 .iter(),
490 )
491 .cloned()
492 .chain(self.module_aliases())
493 .filter(|(_, typ)| typ.clone().to_module_type().is_err())
494 .filter(|(var, typ)| {
499 !matches!(typ, Type::Record(_, _)) || is_anonymous_record_name(&var.get_name())
500 })
501 .filter(|(_, typ)| !typ.has_generic())
507 .map(|(var, typ)| (typ, var.get_name()))
508 .map(|(typ, name)| {
509 let name0 = if ["Integer", "Character", "Boolean", "Number"]
510 .iter()
511 .any(|x| name == *x)
512 {
513 format!("'{}', ", name)
514 } else {
515 Default::default()
516 };
517 let class_str = self.get_class(&typ);
518 let prefix = if name0.is_empty() && class_str != format!("'{}'", name) {
519 format!("'{}', ", name)
520 } else {
521 name0
522 };
523 format!(
524 "as.{} <- function(x) x |> struct(c({}{}, {}))",
525 name,
526 prefix,
527 class_str,
528 self.get_classes(&typ).unwrap()
529 )
530 })
531 .collect::<Vec<_>>()
532 .join("\n")
533 }
534
535 pub fn get_type_anotation(&self, t: &Type) -> String {
536 self.typing_context.get_type_anotation(t)
537 }
538
539 pub fn get_type_anotation_no_parentheses(&self, t: &Type) -> String {
540 self.typing_context.get_type_anotation_no_parentheses(t)
541 }
542
543 pub fn get_classes(&self, t: &Type) -> Option<String> {
544 let res = self
545 .subtypes
546 .get_supertypes(t, self)
547 .iter()
548 .filter(|typ| (*typ).clone().to_module_type().is_err())
549 .filter(|typ| !typ.is_empty())
550 .filter(|typ| !typ.has_generic())
555 .map(|typ| self.get_class(typ))
556 .collect::<Vec<_>>()
557 .join(", ");
558 if res.is_empty() {
559 Some("'None'".to_string())
560 } else {
561 Some(res)
562 }
563 }
564
565 pub fn get_functions(&self, var1: Var) -> Vec<(Var, Type)> {
566 self.typing_context
567 .variables()
568 .filter(|(var2, typ)| {
569 let reduced_type1 = var1.get_type().reduce(self);
570 let reduced_type2 = var2.get_type().reduce(self);
571 var1.get_name() == var2.get_name()
572 && typ.is_function()
573 && reduced_type1.is_subtype(&reduced_type2, self).0
574 })
575 .cloned()
576 .collect()
577 }
578
579 pub fn get_all_generic_functions(&self) -> Vec<(Var, Type)> {
580 let res = self
581 .typing_context
582 .variables()
583 .filter(|(_, typ)| typ.is_function())
584 .filter(|(var, _)| not_in_blacklist(&var.get_name()))
585 .filter(|(var, _)| !var.get_type().is_any())
586 .collect::<HashSet<_>>();
587 res.iter()
588 .map(|(var, typ)| (var.clone().add_backticks_if_percent(), typ.clone()))
589 .collect()
590 }
591
592 pub fn get_first_matching_function(&self, var1: Var) -> Type {
593 let res = self.typing_context.variables().find(|(var2, typ)| {
594 let reduced_type1 = var1.get_type().reduce(self);
595 let reduced_type2 = var2.get_type().reduce(self);
596 var1.get_name() == var2.get_name()
597 && typ.is_function()
598 && (reduced_type1.is_subtype(&reduced_type2, self).0
599 || reduced_type1.is_upperrank_of(&reduced_type2))
600 });
601 if let Some(res) = res {
602 res.1.clone()
603 } else {
604 self.typing_context
605 .standard_library()
606 .iter()
607 .find(|(var2, _)| var2.get_name() == var1.get_name())
608 .unwrap_or_else(|| {
609 panic!(
610 "Can't find var {} in the context:\n {}",
611 var1,
612 self.display_typing_context()
613 )
614 })
615 .1
616 .clone()
617 }
618 }
619
620 pub fn get_matching_typed_functions(&self, var1: Var) -> Vec<Type> {
621 self.typing_context
622 .variables()
623 .filter(|(var2, typ)| {
624 let reduced_type1 = var1.get_type().reduce(self);
625 let reduced_type2 = var2.get_type().reduce(self);
626 var1.get_name() == var2.get_name()
627 && typ.is_function()
628 && (reduced_type1.is_subtype(&reduced_type2, self).0
629 || reduced_type1.is_upperrank_of(&reduced_type2))
630 })
631 .map(|(_, typ)| typ.clone())
632 .collect::<Vec<_>>()
633 }
634
635 pub fn get_matching_untyped_functions(&self, var: Var) -> Result<Vec<Type>, String> {
636 let name1 = var.get_name();
637 let std_lib = self.typing_context.standard_library();
638 let res = std_lib
639 .iter()
640 .find(|(var2, _)| var2.get_name() == name1)
641 .map(|(_, typ)| typ);
642 match res {
643 Some(val) => Ok(vec![val.clone()]),
644 _ => Err(format!(
645 "Can't find var {} in the context:\n {}",
646 var,
647 self.display_typing_context()
648 )),
649 }
650 }
651
652 pub fn get_matching_functions(&self, var: Var) -> Result<Vec<Type>, String> {
653 let res = self.get_matching_typed_functions(var.clone());
654 if res.is_empty() {
655 self.get_matching_untyped_functions(var)
656 } else {
657 Ok(res)
658 }
659 }
660
661 pub fn get_type_from_class(&self, class: &str) -> Type {
662 self.typing_context.get_type_from_class(class)
663 }
664
665 pub fn add_arg_types(&self, params: &[ArgumentType]) -> Context {
666 let param_types = params
667 .iter()
668 .map(|arg_typ| reduce_type(self, &arg_typ.get_type()).for_var())
669 .map(|typ| match typ.to_owned() {
670 Type::Function(typs, _, _) => {
671 if !typs.is_empty() {
672 typs[0].get_type()
673 } else {
674 typ
675 }
676 }
677 t => t,
678 })
679 .collect::<Vec<_>>();
680 params
681 .iter()
682 .zip(param_types.clone())
683 .map(|(arg_typ, par_typ): (&ArgumentType, Type)| {
684 (
685 Var::from_name(&arg_typ.get_argument_str())
686 .set_type(reduce_type(self, &par_typ)),
687 reduce_type(self, &arg_typ.get_type()),
688 )
689 })
690 .fold(self.clone(), |cont: Context, (var, typ): (Var, Type)| {
691 cont.clone().push_var_type(var, typ, &cont)
692 })
693 }
694
695 pub fn set_environment(&self, e: Environment) -> Context {
696 Context {
697 config: self.config.set_environment(e),
698 ..self.clone()
699 }
700 }
701
702 pub fn display_typing_context(&self) -> String {
703 let res = self
704 .variables()
705 .chain(self.aliases())
706 .map(|(var, typ)| format!("{} ==> {}", var, typ))
707 .collect::<Vec<_>>()
708 .join("\n");
709 format!("CONTEXT:\n{}", res)
710 }
711
712 pub fn error(&self, msg: String) -> String {
713 format!("{}{}", msg, self.display_typing_context())
714 }
715
716 pub fn push_alias(self, alias_name: String, typ: Type) -> Self {
717 Context {
718 typing_context: self.typing_context.push_alias(alias_name, typ),
719 ..self
720 }
721 }
722
723 pub fn push_type_constructor(
725 self,
726 name: String,
727 parameters: Vec<Type>,
728 category: ConstructorCategory,
729 ) -> Self {
730 let mut type_constructors = self.type_constructors.clone();
731 type_constructors.retain(|(n, _, _)| n != &name);
733 type_constructors.push((name, parameters, category));
734 Context {
735 type_constructors,
736 ..self
737 }
738 }
739
740 pub fn get_type_constructor(
742 &self,
743 name: &str,
744 ) -> Option<&(String, Vec<Type>, ConstructorCategory)> {
745 self.type_constructors.iter().find(|(n, _, _)| n == name)
746 }
747
748 pub fn push_record_alias(self, name: String, typ: Type) -> Self {
752 if !matches!(typ, Type::Record(_, _)) {
753 return self;
754 }
755 let mut record_aliases = self.record_aliases.clone();
756 record_aliases.retain(|(n, _)| n != &name);
757 record_aliases.push((name, typ));
758 Context {
759 record_aliases,
760 ..self
761 }
762 }
763
764 pub fn merge_record_aliases(self, other: &Context) -> Self {
769 let mut record_aliases = self.record_aliases.clone();
770 for (name, typ) in &other.record_aliases {
771 if !record_aliases.iter().any(|(n, _)| n == name) {
772 record_aliases.push((name.clone(), typ.clone()));
773 }
774 }
775 Context {
776 record_aliases,
777 ..self
778 }
779 }
780
781 pub fn push_embedded_method(
785 self,
786 type_name: String,
787 method_name: String,
788 field_name: String,
789 ) -> Self {
790 let mut embedded_methods = self.embedded_methods.clone();
791 embedded_methods.push((type_name, method_name, field_name));
792 Context {
793 embedded_methods,
794 ..self
795 }
796 }
797
798 pub fn get_embedded_method(&self, type_name: &str, method_name: &str) -> Option<String> {
801 self.embedded_methods
802 .iter()
803 .find(|(t, m, _)| t == type_name && m == method_name)
804 .map(|(_, _, field)| field.clone())
805 }
806
807 pub fn push_alias2(self, alias_var: Var, typ: Type) -> Self {
808 Context {
809 typing_context: self.typing_context.push_alias2(alias_var, typ),
810 ..self
811 }
812 }
813
814 pub fn in_a_project(&self) -> bool {
815 self.config.environment == Environment::Project
816 }
817
818 pub fn get_unification_map(
819 &self,
820 entered_types: &[Type],
821 param_types: &[Type],
822 ) -> Option<UnificationMap> {
823 let res = entered_types
824 .iter()
825 .zip(param_types.iter())
826 .map(|(val_typ, par_typ)| match_types_to_generic(self, &val_typ.clone(), par_typ))
827 .collect::<Option<Vec<_>>>();
828
829 let val = res
830 .map(|vec| vec.iter().flatten().cloned().collect::<Vec<_>>())
831 .map(UnificationMap::new);
832
833 val
834 }
835
836 fn s3_type_definition(&self, var: &Var, typ: &Type) -> String {
837 let first_part = format!("{} <- function(x) x |> ", var.get_name());
838 match typ {
839 Type::RClass(v, _) => format!(
840 "{} struct(c({}))",
841 first_part,
842 v.iter().cloned().collect::<Vec<_>>().join(", ")
843 ),
844 _ => {
845 let class = if typ.is_primitive() {
846 format!("'{}'", var.get_name())
847 } else {
848 self.get_class(typ)
849 };
850 format!("{} struct(c({}))", first_part, class)
851 }
852 }
853 }
854
855 fn get_primitive_type_definition(&self) -> Vec<String> {
856 let primitives = [
857 ("Integer", builder::integer_type_default()),
858 ("Character", builder::character_type_default()),
859 ("Number", builder::number_type()),
860 ("Boolean", builder::boolean_type()),
861 ];
862 let new_context = self.clone().push_types(
863 &primitives
864 .iter()
865 .map(|(_, typ)| typ)
866 .cloned()
867 .collect::<Vec<_>>(),
868 );
869 primitives
870 .iter()
871 .map(|(name, prim)| {
872 (
873 name,
874 new_context.get_classes(prim).unwrap(),
875 new_context.get_class(prim),
876 )
877 })
878 .map(|(name, cls, cl)| {
879 format!("{} <- function(x) x |> struct(c({}, {}))", name, cls, cl)
880 })
881 .collect::<Vec<_>>()
882 }
883
884 pub fn get_related_functions(&self, typ: &Type, functions: &VarFunction) -> Vec<Lang> {
885 let names = self.typing_context.get_related_functions(typ);
886 functions.get_bodies(&names)
887 }
888
889 pub fn get_functions_from_type(&self, typ: &Type) -> Vec<(Var, Type)> {
890 self.variables()
891 .filter(|&(var, typ2)| typ2.is_function() && var.get_type() == *typ)
892 .cloned()
893 .collect()
894 }
895
896 pub fn get_functions_from_name(&self, name: &str) -> Vec<(Var, Type)> {
897 self.variables()
898 .filter(|&(var, typ2)| typ2.is_function() && var.get_name() == name)
899 .cloned()
900 .collect()
901 }
902
903 pub fn get_type_definition(&self, _functions: &VarFunction) -> String {
904 match self.get_target_language() {
905 TargetLanguage::R => self
906 .typing_context
907 .aliases
908 .iter()
909 .map(|(var, typ)| self.s3_type_definition(var, typ))
910 .chain(self.get_primitive_type_definition().iter().cloned())
911 .collect::<Vec<_>>()
912 .join("\n"),
913 TargetLanguage::JS => {
914 todo!();
915 }
916 }
917 }
918
919 pub fn update_variable(self, var: Var) -> Self {
920 Self {
921 typing_context: self.typing_context.update_variable(var),
922 ..self
923 }
924 }
925
926 pub fn set_target_language(self, language: TargetLanguage) -> Self {
927 Self {
928 config: self.config.set_target_language(language),
929 typing_context: self.typing_context.source(language),
930 ..self
931 }
932 }
933
934 pub fn set_default_var_types(self) -> Self {
935 Self {
936 typing_context: self.typing_context.set_default_var_types(),
937 ..self
938 }
939 }
940
941 pub fn get_target_language(&self) -> TargetLanguage {
942 self.config.get_target_language()
943 }
944
945 pub fn set_new_aliase_signature(self, alias: &str, related_type: Type) -> Self {
946 let alias = Var::from_type(alias.parse::<Type>().unwrap()).unwrap();
947 self.clone().push_alias2(alias, related_type)
948 }
949
950 pub fn extract_module_as_vartype(&self, module_name: &str) -> Self {
951 let typ = self
952 .get_type_from_variable(&Var::from_name(module_name))
953 .expect("The module name was not found");
954 let empty_context = Context::default();
955 let new_context = match typ.clone() {
956 Type::Module(args, _) => {
957 args.iter()
958 .rev()
959 .map(|arg_type| {
960 (
961 Var::try_from(arg_type.0.clone()).unwrap(),
962 arg_type.1.clone(),
963 )
964 }) .fold(empty_context.clone(), |acc, (var, typ)| {
967 acc.clone().push_var_type(var, typ, &acc)
968 })
969 }
970 _ => panic!("{} is not a module", module_name),
971 };
972 new_context
973 .clone()
974 .push_var_type(Var::from_name(module_name), typ, &new_context)
975 }
976
977 pub fn get_vartype(&self) -> VarType {
978 self.clone().typing_context
979 }
980
981 pub fn get_environment(&self) -> Environment {
982 self.config.environment
983 }
984 pub fn extend_typing_context(self, var_types: VarType) -> Self {
985 Self {
986 typing_context: self.typing_context + var_types,
987 ..self
988 }
989 }
990}
991
992impl Add for Context {
993 type Output = Self;
994
995 fn add(self, other: Self) -> Self::Output {
996 let mut type_constructors = self.type_constructors;
997 for (name, params, cat) in other.type_constructors {
998 type_constructors.retain(|(n, _, _)| n != &name);
999 type_constructors.push((name, params, cat));
1000 }
1001 let mut interface_constraints = self.interface_constraints;
1002 interface_constraints.extend(other.interface_constraints);
1003 let rigid_counter = self.rigid_counter.max(other.rigid_counter);
1004 let mut test_preamble = self.test_preamble;
1005 test_preamble.extend(other.test_preamble);
1006 let mut record_aliases = self.record_aliases;
1007 for entry in other.record_aliases {
1008 if !record_aliases.contains(&entry) {
1009 record_aliases.push(entry);
1010 }
1011 }
1012 let mut embedded_methods = self.embedded_methods;
1013 for entry in other.embedded_methods {
1014 if !embedded_methods.contains(&entry) {
1015 embedded_methods.push(entry);
1016 }
1017 }
1018 Context {
1019 typing_context: self.typing_context + other.typing_context,
1020 subtypes: self.subtypes + other.subtypes,
1021 type_constructors,
1022 interface_constraints,
1023 rigid_counter,
1024 record_aliases,
1025 embedded_methods,
1026 test_preamble,
1027 self_type: None,
1028 config: self.config,
1029 }
1030 }
1031}
1032
1033#[cfg(test)]
1034mod tests {
1035 use super::*;
1036
1037 #[test]
1038 fn test_default_context1() {
1039 let context = Context::default();
1040 assert!(!context.display_typing_context().is_empty());
1041 }
1042
1043 #[test]
1044 fn test_record_nests_under_grecord_sentinel() {
1045 let ctx = Context::default();
1046 let rec = builder::record_type(&[("x".to_string(), builder::integer_type_default())]);
1047 let graph = ctx.subtypes.clone().add_type(rec.clone(), &ctx);
1048 let supers = graph.get_supertypes(&rec, &ctx);
1049 assert!(
1050 supers
1051 .iter()
1052 .any(|t| matches!(t, Type::KindedGen(Kind::Record, _, _))),
1053 "a record must nest under the GRecord (%_) sentinel; supers = {:?}",
1054 supers
1055 );
1056 assert!(
1057 supers.iter().any(|t| matches!(t, Type::Generic(_, _))),
1058 "GRecord must itself sit under the bare Generic sentinel; supers = {:?}",
1059 supers
1060 );
1061 }
1062
1063 #[test]
1064 fn test_generic_sentinels_absent_from_r_classes() {
1065 let ctx = Context::default();
1066 let rec = builder::record_type(&[("x".to_string(), builder::integer_type_default())]);
1067 let graph = ctx.subtypes.clone().add_type(rec.clone(), &ctx);
1068 let ctx = ctx.with_subtypes(graph);
1069 let classes = ctx.get_classes(&rec).unwrap();
1070 assert!(
1071 !classes.contains("GRecord") && !classes.contains('%') && !classes.contains("Generic"),
1072 "generic sentinels must be filtered out of generated R classes, got: {}",
1073 classes
1074 );
1075 }
1076}