Skip to main content

typr_core/processes/transpiling/
translatable.rs

1use crate::components::context::Context;
2use crate::components::language::argument_value::ArgumentValue;
3use crate::components::language::Lang;
4use std::ops::Add;
5
6pub trait TranslateAppendable {
7    fn to_translatable(self) -> Translatable;
8}
9
10pub trait RTranslatable<T: TranslateAppendable> {
11    fn to_r(&self, context: &Context) -> T;
12}
13
14pub struct Translatable {
15    context: Context,
16    code: String,
17}
18
19impl Translatable {
20    pub fn to_r<T: TranslateAppendable>(self, lang: &impl RTranslatable<T>) -> Translatable {
21        let res = lang.to_r(&self.context);
22        self.append(res)
23    }
24
25    pub fn to_r_safe<T: TranslateAppendable>(self, lang: &impl RTranslatable<T>) -> Translatable {
26        let res = lang.to_r(&self.context);
27        self.append_safe(res)
28    }
29
30    pub fn reset_context(self) -> Translatable {
31        Translatable {
32            context: Context::default(),
33            ..self
34        }
35    }
36
37    pub fn to_r_arg_val(self, arg_val: &ArgumentValue, joint: &str) -> Translatable {
38        let res = arg_val.to_r(&self.context);
39        self.add(&res).add(joint)
40    }
41
42    #[allow(clippy::should_implement_trait)]
43    pub fn add(self, s: &str) -> Translatable {
44        Translatable {
45            code: self.code + s,
46            ..self
47        }
48    }
49
50    pub fn append(self, val: impl TranslateAppendable) -> Translatable {
51        self + val.to_translatable()
52    }
53
54    pub fn append_safe(self, val: impl TranslateAppendable) -> Translatable {
55        self + val.to_translatable().reset_context()
56    }
57
58    pub fn get_code(&self) -> String {
59        self.code.clone()
60    }
61
62    pub fn join(self, vals: &[Lang], joint: &str) -> Translatable {
63        if !vals.is_empty() {
64            vals.iter()
65                .fold(self, |trans, val| trans.to_r(val).add(joint))
66                .sub(joint.len())
67        } else {
68            self
69        }
70    }
71
72    pub fn join_arg_val(self, vals: &[ArgumentValue], joint: &str) -> Translatable {
73        vals.iter()
74            .fold(self, |trans, val| trans.to_r_arg_val(val, joint))
75            .sub(joint.len())
76    }
77
78    #[allow(clippy::should_implement_trait)]
79    pub fn sub(self, len: usize) -> Translatable {
80        let new_code = if self.code.len() > len {
81            &self.code[0..(self.code.len() - len)]
82        } else {
83            &self.code
84        };
85        Translatable {
86            code: new_code.to_string(),
87            ..self
88        }
89    }
90}
91
92impl Add for Translatable {
93    type Output = Translatable;
94
95    fn add(self, other: Self) -> Self::Output {
96        let new_context = if other.context == Context::default() {
97            self.context
98        } else {
99            other.context
100        };
101        Translatable {
102            context: new_context,
103            code: self.code + &other.code,
104        }
105    }
106}
107
108impl From<Context> for Translatable {
109    fn from(val: Context) -> Self {
110        Translatable {
111            context: val,
112            code: "".to_string(),
113        }
114    }
115}
116
117impl From<Translatable> for (String, Context) {
118    fn from(val: Translatable) -> Self {
119        (val.code, val.context)
120    }
121}
122
123impl TranslateAppendable for (String, Context) {
124    fn to_translatable(self) -> Translatable {
125        Translatable {
126            context: self.1,
127            code: self.0,
128        }
129    }
130}
131
132impl TranslateAppendable for String {
133    fn to_translatable(self) -> Translatable {
134        Translatable {
135            context: Context::default(),
136            code: self,
137        }
138    }
139}
140
141impl RTranslatable<(String, Context)> for Box<Lang> {
142    fn to_r(&self, context: &Context) -> (String, Context) {
143        (**self).to_r(context)
144    }
145}