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