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