Skip to main content

typr_core/components/language/
var.rs

1#![allow(
2    dead_code,
3    unused_variables,
4    unused_imports,
5    unreachable_code,
6    unused_assignments
7)]
8use crate::components::context::Context;
9use crate::components::error_message::help_data::HelpData;
10use crate::components::error_message::locatable::Locatable;
11use crate::components::language::Lang;
12use crate::components::r#type::function_type::FunctionType;
13use crate::components::r#type::tchar::Tchar;
14use crate::components::r#type::type_system::TypeSystem;
15use crate::components::r#type::Type;
16use crate::processes::parsing::elements::is_pascal_case;
17use crate::processes::transpiling::translatable::RTranslatable;
18use crate::processes::type_checking::typing;
19use crate::utils::builder;
20use serde::{Deserialize, Serialize};
21use std::fmt;
22
23type Name = String;
24type IsPackageOpaque = bool;
25
26#[derive(Debug, PartialEq, Clone, Copy, Serialize, Deserialize, Eq, Hash)]
27pub enum Permission {
28    Private,
29    Public,
30}
31
32impl fmt::Display for Permission {
33    fn fmt(self: &Self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34        match self {
35            Permission::Private => write!(f, "private"),
36            Permission::Public => write!(f, "public"),
37        }
38    }
39}
40
41impl From<Permission> for bool {
42    fn from(val: Permission) -> Self {
43        match val {
44            Permission::Public => true,
45            _ => false,
46        }
47    }
48}
49
50#[derive(Debug, Clone, Serialize, Deserialize, Hash)]
51pub struct Var {
52    pub name: Name,
53    pub is_opaque: IsPackageOpaque,
54    pub related_type: Type,
55    pub help_data: HelpData,
56}
57
58impl PartialEq for Var {
59    fn eq(&self, other: &Self) -> bool {
60        self.name == other.name
61            && self.is_opaque == other.is_opaque
62            && self.related_type == other.related_type
63    }
64}
65
66impl Eq for Var {}
67
68impl Locatable for Var {
69    fn get_help_data(&self) -> HelpData {
70        self.help_data.clone()
71    }
72}
73
74impl Var {
75    pub fn set_type_from_params(self, params: &[Lang], context: &Context) -> Self {
76        let typ = (params.len() > 0)
77            .then(|| typing(context, &params[0]).value)
78            .unwrap_or_default();
79        self.set_type(typ)
80    }
81
82    pub fn add_backticks_if_percent(self) -> Self {
83        let s = self.get_name();
84        let res = if s.starts_with('%') && s.ends_with('%') {
85            format!("`{}`", s)
86        } else {
87            s.to_string()
88        };
89        self.set_name(&res)
90    }
91
92    pub fn alias(name: &str, params: &[Type]) -> Self {
93        Var::from(name).set_type(Type::Params(params.to_vec(), HelpData::default()))
94    }
95
96    pub fn set_var_related_type(&self, types: &Vec<Type>, context: &Context) -> Var {
97        if types.len() > 0 {
98            let first_arg = types.iter().nth(0).unwrap().clone();
99            self.clone().set_type(first_arg.clone())
100        } else {
101            self.clone()
102        }
103    }
104
105    fn keep_minimal(liste: Vec<Type>, context: &Context) -> Option<Type> {
106        let mut mins: Vec<Type> = Vec::new();
107
108        for candidat in liste {
109            let mut keep_candidat = true;
110            let mut indices_to_delete = Vec::new();
111
112            for (i, existant) in mins.iter().enumerate() {
113                if candidat.is_subtype(existant, context).0 {
114                    indices_to_delete.push(i);
115                } else if existant.is_subtype(&candidat, context).0 {
116                    keep_candidat = false;
117                    break;
118                }
119            }
120
121            if keep_candidat {
122                for &i in indices_to_delete.iter().rev() {
123                    mins.remove(i);
124                }
125                mins.push(candidat);
126            }
127        }
128        // get smallest type
129        if mins.iter().any(|x| !x.is_interface()) {
130            mins.iter().cloned().skip_while(|x| x.is_interface()).next()
131        } else {
132            mins.iter().cloned().next()
133        }
134    }
135
136    pub fn get_functions_from_name(&self, context: &Context) -> Vec<FunctionType> {
137        context
138            .get_functions_from_name(&self.get_name())
139            .iter()
140            .flat_map(|(_, typ)| typ.clone().to_function_type())
141            .collect()
142    }
143
144    pub fn from_language(l: Lang) -> Option<Var> {
145        match l {
146            Lang::Variable(name, muta, typ, h) => Some(Var {
147                name,
148                is_opaque: muta,
149                related_type: typ,
150                help_data: h,
151            }),
152            _ => None,
153        }
154    }
155
156    pub fn from_type(t: Type) -> Option<Var> {
157        match t {
158            Type::Alias(name, concret_types, opacity, h) => {
159                let var = Var::from_name(&name)
160                    .set_type(Type::Params(
161                        concret_types.to_vec(),
162                        concret_types.clone().into(),
163                    ))
164                    .set_help_data(h)
165                    .set_opacity(opacity);
166                Some(var)
167            }
168            Type::Char(val, h) => {
169                let var = Var::from_name(&val.get_val()).set_help_data(h);
170                Some(var)
171            }
172            _ => None,
173        }
174    }
175
176    pub fn from_name(name: &str) -> Self {
177        Var {
178            name: name.to_string(),
179            is_opaque: false,
180            related_type: builder::empty_type(),
181            help_data: HelpData::default(),
182        }
183    }
184
185    pub fn to_language(self) -> Lang {
186        Lang::Variable(self.name, self.is_opaque, self.related_type, self.help_data)
187    }
188
189    pub fn set_name(self, s: &str) -> Var {
190        Var {
191            name: s.to_string(),
192            is_opaque: self.is_opaque,
193            related_type: self.related_type,
194            help_data: self.help_data,
195        }
196    }
197
198    pub fn set_type(self, typ: Type) -> Var {
199        let typ = match typ {
200            Type::Function(params, _, h) => {
201                if params.len() >= 1 {
202                    params[0].clone()
203                } else {
204                    Type::Any(h)
205                }
206            }
207            _ => typ,
208        };
209        Var {
210            name: self.name,
211            is_opaque: self.is_opaque,
212            related_type: typ,
213            help_data: self.help_data,
214        }
215    }
216
217    pub fn set_type_raw(self, typ: Type) -> Var {
218        Var {
219            name: self.name,
220            is_opaque: self.is_opaque,
221            related_type: typ,
222            help_data: self.help_data,
223        }
224    }
225
226    pub fn set_opacity(self, opa: bool) -> Var {
227        Var {
228            name: self.name,
229            is_opaque: opa,
230            related_type: self.related_type,
231            help_data: self.help_data,
232        }
233    }
234
235    pub fn get_name(&self) -> String {
236        self.name.to_string()
237    }
238
239    pub fn get_type(&self) -> Type {
240        self.related_type.clone()
241    }
242
243    pub fn get_help_data(&self) -> HelpData {
244        self.help_data.clone()
245    }
246
247    pub fn match_with(&self, var: &Var, context: &Context) -> bool {
248        (self.get_name() == var.get_name())
249            && self.get_type().is_subtype(&var.get_type(), context).0
250    }
251
252    pub fn set_help_data(self, h: HelpData) -> Var {
253        Var {
254            name: self.name,
255            is_opaque: self.is_opaque,
256            related_type: self.related_type,
257            help_data: h,
258        }
259    }
260
261    pub fn is_imported(&self) -> bool {
262        self.is_variable() && self.is_opaque.clone()
263    }
264
265    pub fn is_alias(&self) -> bool {
266        match self.get_type() {
267            Type::Params(_, _) => true,
268            _ => false,
269        }
270    }
271
272    pub fn is_variable(&self) -> bool {
273        !self.is_alias()
274    }
275
276    pub fn is_opaque(&self) -> bool {
277        self.is_alias() && self.is_opaque
278    }
279
280    pub fn get_opacity(&self) -> bool {
281        self.is_opaque
282    }
283
284    pub fn to_alias_type(self) -> Type {
285        Type::Alias(
286            self.get_name(),
287            vec![],
288            self.get_opacity(),
289            self.get_help_data(),
290        )
291    }
292
293    pub fn to_alias_lang(self) -> Lang {
294        Lang::Alias(
295            Box::new(self.clone().to_language()),
296            vec![],
297            builder::unknown_function_type(),
298            self.get_help_data(),
299        )
300    }
301
302    pub fn to_let(self) -> Lang {
303        Lang::Let(
304            Box::new(self.clone().to_language()),
305            builder::unknown_function_type(),
306            Box::new(builder::empty_lang()),
307            self.get_help_data(),
308        )
309    }
310
311    pub fn contains(&self, s: &str) -> bool {
312        self.get_name().contains(s)
313    }
314
315    pub fn replace(self, old: &str, new: &str) -> Self {
316        let res = self.get_name().replace(old, new);
317        self.set_name(&res)
318    }
319
320    pub fn display_type(self, cont: &Context) -> Self {
321        if !self.get_name().contains(".") {
322            let type_str = match self.get_type() {
323                Type::Empty(_) | Type::Any(_) => "".to_string(),
324                ty => ".".to_string() + &cont.get_class(&ty).replace("'", ""),
325            };
326            let new_name = if self.contains("`") {
327                "`".to_string() + &self.get_name().replace("`", "") + &type_str + "`"
328            } else {
329                self.get_name() + &type_str
330            };
331            self.set_name(&new_name)
332        } else {
333            self
334        }
335    }
336
337    pub fn get_digit(&self, s: &str) -> i8 {
338        self.get_name()[s.len()..].parse::<i8>().unwrap()
339    }
340
341    pub fn add_digit(self, d: i8) -> Self {
342        self.clone().set_name(&(self.get_name() + &d.to_string()))
343    }
344
345    pub fn exist(&self, context: &Context) -> Option<Self> {
346        context.variable_exist(self.clone())
347    }
348}
349
350impl fmt::Display for Var {
351    fn fmt(self: &Self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
352        write!(f, "{}<{}>", self.name, self.related_type)
353    }
354}
355
356impl Default for Var {
357    fn default() -> Self {
358        Var {
359            name: "".to_string(),
360            is_opaque: false,
361            related_type: Type::Empty(HelpData::default()),
362            help_data: HelpData::default(),
363        }
364    }
365}
366
367impl RTranslatable<String> for Var {
368    fn to_r(&self, _: &Context) -> String {
369        format!("{}", self.name)
370    }
371}
372
373impl TryFrom<Lang> for Var {
374    type Error = ();
375
376    fn try_from(value: Lang) -> Result<Self, Self::Error> {
377        match value {
378            Lang::Variable(name, muta, typ, h) => Ok(Var {
379                name,
380                is_opaque: muta,
381                related_type: typ,
382                help_data: h,
383            }),
384            _ => Err(()),
385        }
386    }
387}
388
389impl TryFrom<Box<Lang>> for Var {
390    type Error = ();
391
392    fn try_from(value: Box<Lang>) -> Result<Self, Self::Error> {
393        Var::try_from((*value).clone())
394    }
395}
396
397impl TryFrom<&Box<Lang>> for Var {
398    type Error = ();
399
400    fn try_from(value: &Box<Lang>) -> Result<Self, Self::Error> {
401        Var::try_from((*value).clone())
402    }
403}
404
405impl From<&str> for Var {
406    fn from(val: &str) -> Self {
407        Var {
408            name: val.to_string(),
409            is_opaque: false,
410            related_type: Type::Empty(HelpData::default()),
411            help_data: HelpData::default(),
412        }
413    }
414}
415
416impl TryFrom<Type> for Var {
417    type Error = String;
418
419    fn try_from(value: Type) -> Result<Self, Self::Error> {
420        match value {
421            Type::Char(tchar, h) => match tchar {
422                Tchar::Val(name) => {
423                    let var = if is_pascal_case(&name) {
424                        Var::from_name(&name)
425                            .set_help_data(h)
426                            .set_type(builder::params_type())
427                    } else {
428                        Var::from_name(&name).set_help_data(h)
429                    };
430                    Ok(var)
431                }
432                _ => todo!(),
433            },
434            _ => Err("From type to Var, not possible".to_string()),
435        }
436    }
437}