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::language::var::Var;
12use crate::components::language::var_function::VarFunction;
13use crate::components::language::Lang;
14use crate::components::r#type::argument_type::ArgumentType;
15use crate::components::r#type::type_system::TypeSystem;
16use crate::components::r#type::Type;
17use crate::processes::type_checking::match_types_to_generic;
18use crate::processes::type_checking::type_comparison::reduce_type;
19use crate::processes::type_checking::unification_map;
20use crate::utils::builder;
21use crate::utils::standard_library::not_in_blacklist;
22use std::collections::HashSet;
23use std::iter::Rev;
24use std::ops::Add;
25use tap::Pipe;
26
27#[derive(Debug, Clone, PartialEq)]
28pub struct Context {
29 pub typing_context: VarType,
30 pub subtypes: Graph<Type>,
31 config: Config,
32}
33
34impl Default for Context {
35 fn default() -> Self {
36 let config = Config::default();
37 Context {
38 config: config.clone(),
39 typing_context: VarType::from_config(config),
40 subtypes: Graph::new(),
41 }
42 }
43}
44
45impl From<Vec<(Lang, Type)>> for Context {
46 fn from(val: Vec<(Lang, Type)>) -> Self {
47 let val2: Vec<(Var, Type)> = val
48 .iter()
49 .map(|(lan, typ)| (Var::from_language(lan.clone()).unwrap(), typ.clone()))
50 .collect();
51 Context {
52 typing_context: val2.into(),
53 ..Context::default()
54 }
55 }
56}
57
58impl Context {
59 pub fn new(types: Vec<(Var, Type)>) -> Context {
60 Context {
61 typing_context: types.into(),
62 ..Context::default()
63 }
64 }
65
66 pub fn empty() -> Self {
67 Context {
68 config: Config::default(),
69 typing_context: VarType::new(),
70 subtypes: Graph::new(),
71 }
72 }
73
74 pub fn set_config(self, config: Config) -> Self {
75 Self {
76 config: config,
77 ..self
78 }
79 }
80
81 pub fn set_as_module_context(self) -> Context {
82 Self {
83 config: self.config.set_as_module(),
84 ..self
85 }
86 }
87
88 pub fn with_subtypes(self, subtypes: Graph<Type>) -> Self {
90 Self { subtypes, ..self }
91 }
92
93 pub fn get_members(&self) -> Vec<(Var, Type)> {
94 self.typing_context
95 .variables()
96 .chain(self.aliases())
97 .cloned()
98 .collect::<Vec<_>>()
99 }
100
101 pub fn print_hierarchy(&self) {
102 self.subtypes.print_hierarchy();
103 }
104
105 pub fn variable_exist(&self, var: Var) -> Option<Var> {
106 self.typing_context.variable_exist(var)
107 }
108
109 pub fn get_type_from_variable(&self, var: &Var) -> Result<Type, String> {
110 let res = self
111 .variables()
112 .flat_map(|(var2, typ)| {
113 let conditions = (var.name == var2.name)
114 && (var.is_opaque == var2.is_opaque)
115 && var.related_type.is_subtype(&var2.related_type, self).0;
116 if conditions {
117 Some(typ.clone())
118 } else {
119 None
120 }
121 })
122 .reduce(|acc, x| if x.is_subtype(&acc, self).0 { x } else { acc });
123 match res {
124 Some(typ) => Ok(typ),
125 _ => Err(format!(
126 "Didn't find {} in the context: {}",
127 var.get_name(),
128 self.display_typing_context()
129 )),
130 }
131 }
132
133 pub fn get_types_from_name(&self, name: &str) -> Vec<Type> {
134 self.variables()
135 .filter(|(var, _)| var.get_name() == name)
136 .map(|(_, typ)| typ.clone())
137 .collect()
138 }
139
140 pub fn get_type_from_aliases(&self, var: &Var) -> Option<Type> {
141 self.aliases()
142 .flat_map(|(var2, type_)| {
143 let conditions = (var.name == var2.name)
144 && (var.is_opaque == var2.is_opaque)
145 && var.related_type.is_subtype(&var2.related_type, self).0;
146 if conditions {
147 Some(type_.clone())
148 } else {
149 None
150 }
151 })
152 .next()
153 }
154
155 fn is_matching_alias(&self, var1: &Var, var2: &Var) -> bool {
156 var1.name == var2.name
157 }
158
159 pub fn get_matching_alias_signature(&self, var: &Var) -> Option<(Type, Vec<Type>)> {
160 self.aliases()
161 .find(|(var2, _)| self.is_matching_alias(var, var2))
162 .map(|(var2, target_type)| {
163 if var2.is_opaque() {
164 (var2.clone().to_alias_type(), vec![])
165 } else {
166 if let Type::Params(types, _) = var2.get_type() {
167 (target_type.clone(), types.clone())
168 } else {
169 panic!("The related type is not Params([...])");
170 }
171 }
172 })
173 }
174
175 pub fn variables(&self) -> Rev<std::vec::IntoIter<&(Var, Type)>> {
176 self.typing_context.variables()
177 }
178
179 pub fn aliases(&self) -> Rev<std::vec::IntoIter<&(Var, Type)>> {
180 self.typing_context.aliases()
181 }
182
183 pub fn push_var_type(self, lang: Var, typ: Type, context: &Context) -> Context {
184 let reduced_type = typ.reduce(context);
185 let types = reduced_type.extract_types();
186 let var_type = self
187 .typing_context
188 .clone()
189 .pipe(|vt| {
190 (reduced_type.is_interface() && lang.is_variable())
191 .then(|| {
192 vt.clone()
193 .push_interface(lang.clone(), reduced_type, typ.clone(), context)
194 })
195 .unwrap_or(vt.push_var_type(&[(lang.clone(), typ.clone())]))
196 })
197 .push_types(&types);
198 let new_subtypes = self.subtypes.add_types(&types, context);
199 Context {
200 typing_context: var_type,
201 subtypes: new_subtypes,
202 ..self
203 }
204 }
205
206 pub fn replace_or_push_var_type(self, lang: Var, typ: Type, context: &Context) -> Context {
207 let types = typ.reduce(context).extract_types();
208 let var_type = self
209 .typing_context
210 .clone()
211 .replace_or_push_var_type(&[(lang.clone(), typ.clone())])
212 .push_types(&types);
213 let new_subtypes = self.subtypes.add_types(&types, context);
214 Context {
215 typing_context: var_type,
216 subtypes: new_subtypes,
217 ..self
218 }
219 }
220
221 pub fn remove_vars(self, vars: &[Var]) -> Context {
224 Context {
225 typing_context: self.typing_context.remove_vars(vars),
226 ..self
227 }
228 }
229
230 pub fn push_types(self, types: &[Type]) -> Self {
231 Self {
232 typing_context: self.typing_context.push_types(types),
233 ..self
234 }
235 }
236
237 pub fn get_type_from_existing_variable(&self, var: Var) -> Type {
238 if let Type::UnknownFunction(_) = var.get_type() {
239 var.get_type()
240 } else {
241 self.typing_context
242 .variables()
243 .find(|(v, _)| var.match_with(v, self))
244 .map(|(_, ty)| ty)
245 .unwrap_or(&Type::Any(var.get_help_data()))
247 .clone()
248 }
249 }
250
251 pub fn get_true_variable(&self, var: &Var) -> Var {
252 let res = self
253 .typing_context
254 .variables()
255 .find(|(v, _)| var.match_with(v, self))
256 .map(|(v, _)| v);
257 match res {
258 Some(vari) => vari.clone(),
259 _ => {
260 if self.is_an_untyped_function(&var.get_name()) {
263 var.clone()
264 .set_type(Type::UnknownFunction(var.get_help_data()))
265 } else {
266 var.clone().set_type(Type::Any(var.get_help_data()))
267 }
268 }
269 }
270 }
271
272 fn is_a_standard_function(&self, name: &str) -> bool {
273 !self.typing_context.name_exists_outside_of_std(name)
274 }
275
276 pub fn is_an_untyped_function(&self, name: &str) -> bool {
277 self.is_a_standard_function(name)
278 }
279
280 pub fn get_class(&self, t: &Type) -> String {
281 self.typing_context.get_class(&t.reduce(self))
282 }
283
284 pub fn get_class_unquoted(&self, t: &Type) -> String {
285 self.typing_context.get_class_unquoted(t)
286 }
287
288 pub fn module_aliases(&self) -> Vec<(Var, Type)> {
289 self.variables()
290 .flat_map(|(_, typ)| typ.clone().to_module_type())
291 .flat_map(|module| module.get_aliases())
292 .collect()
293 }
294
295 pub fn get_type_anotations(&self) -> String {
296 self.aliases()
297 .chain(
298 [
299 (Var::from_name("Integer"), builder::integer_type_default()),
300 (
301 Var::from_name("Character"),
302 builder::character_type_default(),
303 ),
304 (Var::from_name("Number"), builder::number_type()),
305 (Var::from_name("Boolean"), builder::boolean_type()),
306 ]
307 .iter(),
308 )
309 .cloned()
310 .chain(self.module_aliases())
311 .filter(|(_, typ)| typ.clone().to_module_type().is_err())
312 .map(|(var, typ)| (typ, var.get_name()))
313 .map(|(typ, name)| {
314 format!(
315 "{} <- function(x) x |> struct(c('{}', {}, {}))",
316 name,
317 name,
318 self.get_class(&typ),
319 self.get_classes(&typ).unwrap()
320 )
321 })
322 .collect::<Vec<_>>()
323 .join("\n")
324 }
325
326 pub fn get_type_anotation(&self, t: &Type) -> String {
327 self.typing_context.get_type_anotation(t)
328 }
329
330 pub fn get_type_anotation_no_parentheses(&self, t: &Type) -> String {
331 self.typing_context.get_type_anotation_no_parentheses(t)
332 }
333
334 pub fn get_classes(&self, t: &Type) -> Option<String> {
335 let res = self
336 .subtypes
337 .get_supertypes(t, self)
338 .iter()
339 .filter(|typ| (*typ).clone().to_module_type().is_err())
340 .filter(|typ| !typ.is_empty())
341 .map(|typ| self.get_class(typ))
342 .collect::<Vec<_>>()
343 .join(", ");
344 if res == "" {
345 Some("'None'".to_string())
346 } else {
347 Some(res)
348 }
349 }
350
351 pub fn get_functions(&self, var1: Var) -> Vec<(Var, Type)> {
352 self.typing_context
353 .variables()
354 .filter(|(var2, typ)| {
355 let reduced_type1 = var1.get_type().reduce(self);
356 let reduced_type2 = var2.get_type().reduce(self);
357 var1.get_name() == var2.get_name()
358 && typ.is_function()
359 && reduced_type1.is_subtype(&reduced_type2, self).0
360 })
361 .cloned()
362 .collect()
363 }
364
365 pub fn get_all_generic_functions(&self) -> Vec<(Var, Type)> {
366 let res = self
367 .typing_context
368 .variables()
369 .filter(|(_, typ)| typ.is_function())
370 .filter(|(var, _)| not_in_blacklist(&var.get_name()))
371 .filter(|(var, _)| !var.get_type().is_any())
372 .collect::<HashSet<_>>();
373 res.iter()
374 .map(|(var, typ)| (var.clone().add_backticks_if_percent(), typ.clone()))
375 .collect()
376 }
377
378 pub fn get_first_matching_function(&self, var1: Var) -> Type {
379 let res = self.typing_context.variables().find(|(var2, typ)| {
380 let reduced_type1 = var1.get_type().reduce(self);
381 let reduced_type2 = var2.get_type().reduce(self);
382 var1.get_name() == var2.get_name()
383 && typ.is_function()
384 && (reduced_type1.is_subtype(&reduced_type2, self).0
385 || reduced_type1.is_upperrank_of(&reduced_type2))
386 });
387 if res.is_none() {
388 self.typing_context
389 .standard_library()
390 .iter()
391 .find(|(var2, _)| var2.get_name() == var1.get_name())
392 .expect(&format!(
393 "Can't find var {} in the context:\n {}",
394 var1.to_string(),
395 self.display_typing_context()
396 ))
397 .clone()
398 } else {
399 res.unwrap().clone()
400 }
401 .1
402 }
403
404 pub fn get_matching_typed_functions(&self, var1: Var) -> Vec<Type> {
405 self.typing_context
406 .variables()
407 .filter(|(var2, typ)| {
408 let reduced_type1 = var1.get_type().reduce(self);
409 let reduced_type2 = var2.get_type().reduce(self);
410 var1.get_name() == var2.get_name()
411 && typ.is_function()
412 && (reduced_type1.is_subtype(&reduced_type2, self).0
413 || reduced_type1.is_upperrank_of(&reduced_type2))
414 })
415 .map(|(_, typ)| typ.clone())
416 .collect::<Vec<_>>()
417 }
418
419 pub fn get_matching_untyped_functions(&self, var: Var) -> Result<Vec<Type>, String> {
420 let name1 = var.get_name();
421 let std_lib = self.typing_context.standard_library();
422 let res = std_lib
423 .iter()
424 .find(|(var2, _)| var2.get_name() == name1)
425 .map(|(_, typ)| typ);
426 match res {
427 Some(val) => Ok(vec![val.clone()]),
428 _ => Err(format!(
429 "Can't find var {} in the context:\n {}",
430 var.to_string(),
431 self.display_typing_context()
432 )),
433 }
434 }
435
436 pub fn get_matching_functions(&self, var: Var) -> Result<Vec<Type>, String> {
437 let res = self.get_matching_typed_functions(var.clone());
438 if res.len() == 0 {
439 self.get_matching_untyped_functions(var)
440 } else {
441 Ok(res)
442 }
443 }
444
445 pub fn get_type_from_class(&self, class: &str) -> Type {
446 self.typing_context.get_type_from_class(class)
447 }
448
449 pub fn add_arg_types(&self, params: &[ArgumentType]) -> Context {
450 let param_types = params
451 .iter()
452 .map(|arg_typ| reduce_type(self, &arg_typ.get_type()).for_var())
453 .map(|typ| match typ.to_owned() {
454 Type::Function(typs, _, _) => {
455 if typs.len() > 0 {
456 typs[0].clone()
457 } else {
458 typ
459 }
460 }
461 t => t,
462 })
463 .collect::<Vec<_>>();
464 params
465 .into_iter()
466 .zip(param_types.clone().into_iter())
467 .map(|(arg_typ, par_typ)| {
468 (
469 Var::from_name(&arg_typ.get_argument_str())
470 .set_type(reduce_type(self, &par_typ)),
471 reduce_type(self, &arg_typ.get_type()),
472 )
473 })
474 .fold(self.clone(), |cont, (var, typ)| {
475 cont.clone().push_var_type(var, typ, &cont)
476 })
477 }
478
479 pub fn set_environment(&self, e: Environment) -> Context {
480 Context {
481 config: self.config.set_environment(e),
482 ..self.clone()
483 }
484 }
485
486 pub fn display_typing_context(&self) -> String {
487 let res = self
488 .variables()
489 .chain(self.aliases())
490 .map(|(var, typ)| format!("{} ==> {}", var.to_string(), typ.to_string()))
491 .collect::<Vec<_>>()
492 .join("\n");
493 format!("CONTEXT:\n{}", res)
494 }
495
496 pub fn error(&self, msg: String) -> String {
497 format!("{}{}", msg, self.display_typing_context())
498 }
499
500 pub fn push_alias(self, alias_name: String, typ: Type) -> Self {
501 Context {
502 typing_context: self.typing_context.push_alias(alias_name, typ),
503 ..self
504 }
505 }
506
507 pub fn push_alias2(self, alias_var: Var, typ: Type) -> Self {
508 Context {
509 typing_context: self.typing_context.push_alias2(alias_var, typ),
510 ..self
511 }
512 }
513
514 pub fn in_a_project(&self) -> bool {
515 self.config.environment == Environment::Project
516 }
517
518 pub fn get_unification_map(
519 &self,
520 entered_types: &[Type],
521 param_types: &[Type],
522 ) -> Option<UnificationMap> {
523 let res = entered_types
524 .iter()
525 .zip(param_types.iter())
526 .map(|(val_typ, par_typ)| match_types_to_generic(self, &val_typ.clone(), par_typ))
527 .collect::<Option<Vec<_>>>();
528
529 let val = res
530 .map(|vec| vec.iter().cloned().flatten().collect::<Vec<_>>())
531 .map(|vec| UnificationMap::new(vec));
532
533 val
534 }
535
536 fn s3_type_definition(&self, var: &Var, typ: &Type) -> String {
537 let first_part = format!("{} <- function(x) x |> ", var.get_name());
538 match typ {
539 Type::RClass(v, _) => format!(
540 "{} struct(c({}))",
541 first_part,
542 v.iter().cloned().collect::<Vec<_>>().join(", ")
543 ),
544 _ => {
545 let class = if typ.is_primitive() {
546 format!("'{}'", var.get_name())
547 } else {
548 self.get_class(typ)
549 };
550 format!("{} struct(c({}))", first_part, class)
551 }
552 }
553 }
554
555 fn get_primitive_type_definition(&self) -> Vec<String> {
556 let primitives = [
557 ("Integer", builder::integer_type_default()),
558 ("Character", builder::character_type_default()),
559 ("Number", builder::number_type()),
560 ("Boolean", builder::boolean_type()),
561 ];
562 let new_context = self.clone().push_types(
563 &primitives
564 .iter()
565 .map(|(_, typ)| typ)
566 .cloned()
567 .collect::<Vec<_>>(),
568 );
569 primitives
570 .iter()
571 .map(|(name, prim)| {
572 (
573 name,
574 new_context.get_classes(prim).unwrap(),
575 new_context.get_class(prim),
576 )
577 })
578 .map(|(name, cls, cl)| {
579 format!("{} <- function(x) x |> struct(c({}, {}))", name, cls, cl)
580 })
581 .collect::<Vec<_>>()
582 }
583
584 pub fn get_related_functions(&self, typ: &Type, functions: &VarFunction) -> Vec<Lang> {
585 let names = self.typing_context.get_related_functions(typ);
586 functions.get_bodies(&names)
587 }
588
589 pub fn get_functions_from_type(&self, typ: &Type) -> Vec<(Var, Type)> {
590 self.variables()
591 .cloned()
592 .filter(|(var, typ2)| typ2.is_function() && &var.get_type() == typ)
593 .collect()
594 }
595
596 pub fn get_functions_from_name(&self, name: &str) -> Vec<(Var, Type)> {
597 self.variables()
598 .cloned()
599 .filter(|(var, typ2)| typ2.is_function() && &var.get_name() == name)
600 .collect()
601 }
602
603 pub fn get_type_definition(&self, _functions: &VarFunction) -> String {
604 match self.get_target_language() {
605 TargetLanguage::R => self
606 .typing_context
607 .aliases
608 .iter()
609 .map(|(var, typ)| self.s3_type_definition(var, typ))
610 .chain(self.get_primitive_type_definition().iter().cloned())
611 .collect::<Vec<_>>()
612 .join("\n"),
613 TargetLanguage::JS => {
614 todo!();
615 }
616 }
617 }
618
619 pub fn update_variable(self, var: Var) -> Self {
620 Self {
621 typing_context: self.typing_context.update_variable(var),
622 ..self
623 }
624 }
625
626 pub fn set_target_language(self, language: TargetLanguage) -> Self {
627 Self {
628 config: self.config.set_target_language(language),
629 typing_context: self.typing_context.source(language),
630 ..self
631 }
632 }
633
634 pub fn set_default_var_types(self) -> Self {
635 Self {
636 typing_context: self.typing_context.set_default_var_types(),
637 ..self
638 }
639 }
640
641 pub fn get_target_language(&self) -> TargetLanguage {
642 self.config.get_target_language()
643 }
644
645 pub fn set_new_aliase_signature(self, alias: &str, related_type: Type) -> Self {
646 let alias = Var::from_type(alias.parse::<Type>().unwrap()).unwrap();
647 self.clone().push_alias2(alias, related_type)
648 }
649
650 pub fn extract_module_as_vartype(&self, module_name: &str) -> Self {
651 let typ = self
652 .get_type_from_variable(&Var::from_name(module_name))
653 .expect("The module name was not found");
654 let empty_context = Context::default();
655 let new_context = match typ.clone() {
656 Type::Module(args, _) => {
657 args.iter()
658 .rev()
659 .map(|arg_type| {
660 (
661 Var::try_from(arg_type.0.clone()).unwrap(),
662 arg_type.1.clone(),
663 )
664 }) .fold(empty_context.clone(), |acc, (var, typ)| {
667 acc.clone().push_var_type(var, typ, &acc)
668 })
669 }
670 _ => panic!("{} is not a module", module_name),
671 };
672 new_context
673 .clone()
674 .push_var_type(Var::from_name(module_name), typ, &new_context)
675 }
676
677 pub fn get_vartype(&self) -> VarType {
678 self.clone().typing_context
679 }
680
681 pub fn get_environment(&self) -> Environment {
682 self.config.environment
683 }
684 pub fn extend_typing_context(self, var_types: VarType) -> Self {
685 Self {
686 typing_context: self.typing_context + var_types,
687 ..self
688 }
689 }
690}
691
692impl Add for Context {
693 type Output = Self;
694
695 fn add(self, other: Self) -> Self::Output {
696 Context {
697 typing_context: self.typing_context + other.typing_context,
698 subtypes: self.subtypes + other.subtypes,
699 config: self.config,
700 }
701 }
702}
703
704#[cfg(test)]
705mod tests {
706 use super::*;
707
708 #[test]
709 fn test_default_context1() {
710 let context = Context::default();
711 println!("{}", context.display_typing_context());
712 assert!(true)
713 }
714}