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