1use std::borrow::Borrow;
2
3use cpclib_common::itertools::Itertools;
4use cpclib_common::smol_str::SmolStr;
5use cpclib_tokens::ExprResult;
6use substring::Substring;
7
8use crate::error::{AssemblerError, ExpressionError};
9
10pub fn fix_string<S: Borrow<str>>(s: S) -> SmolStr {
11 s.borrow().replace("\\n", "\n").into()
12}
13
14pub fn list_new(count: usize, value: ExprResult) -> ExprResult {
16 ExprResult::List(vec![value; count])
17}
18
19pub fn string_new(count: usize, value: ExprResult) -> Result<ExprResult, AssemblerError> {
21 let value = value.char()?;
22 let s = (0..count).map(|_| value).collect::<SmolStr>();
23 Ok(ExprResult::String(fix_string(s)))
24}
25
26pub fn list_set(
28 mut list: ExprResult,
29 index: usize,
30 value: ExprResult
31) -> Result<ExprResult, crate::AssemblerError> {
32 match list {
33 ExprResult::String(s) => {
34 if index >= s.len() {
35 return Err(AssemblerError::ExpressionError(
36 ExpressionError::InvalidSize(s.len(), index)
37 ));
38 }
39 let c = value.int()? as u8 as char;
40 let c = format!("{}", c);
41 let mut s = s.to_string();
42 s.replace_range(index..index + 1, &c);
43 Ok(ExprResult::String(fix_string(s)))
44 },
45 ExprResult::List(_) => {
46 if index >= list.list_len() {
47 return Err(AssemblerError::ExpressionError(
48 ExpressionError::InvalidSize(list.list_len(), index)
49 ));
50 }
51 list.list_set(index, value);
52 Ok(list)
53 },
54
55 _ => {
56 Err(AssemblerError::ExpressionError(ExpressionError::OwnError(
57 Box::new(AssemblerError::AssemblingError {
58 msg: format!("{} is not a list", list)
59 })
60 )))
61 },
62 }
63}
64
65pub fn list_get(list: &ExprResult, index: usize) -> Result<ExprResult, crate::AssemblerError> {
67 match list {
68 ExprResult::String(s) => {
69 if index >= s.len() {
70 return Err(AssemblerError::ExpressionError(
71 ExpressionError::InvalidSize(s.len(), index)
72 ));
73 }
74 Ok(ExprResult::Value(s.chars().nth(index).unwrap() as _))
75 },
76 ExprResult::List(_) => {
77 if index >= list.list_len() {
78 return Err(AssemblerError::ExpressionError(
79 ExpressionError::InvalidSize(list.list_len(), index)
80 ));
81 }
82 Ok(list.list_get(index).clone())
83 },
84
85 _ => {
86 Err(AssemblerError::ExpressionError(ExpressionError::OwnError(
87 Box::new(AssemblerError::AssemblingError {
88 msg: format!("{} is not a list", list)
89 })
90 )))
91 },
92 }
93}
94
95pub fn list_sublist(
97 list: &ExprResult,
98 start: usize,
99 end: usize ) -> Result<ExprResult, crate::AssemblerError> {
101 match list {
102 ExprResult::String(s) => {
103 if start >= s.len() {
104 return Err(AssemblerError::ExpressionError(
105 ExpressionError::InvalidSize(s.len(), start)
106 ));
107 }
108 if end > s.len() {
109 return Err(AssemblerError::ExpressionError(
110 ExpressionError::InvalidSize(s.len(), end)
111 ));
112 }
113 Ok(ExprResult::String(s.substring(start, end).into()))
114 },
115 ExprResult::List(l) => {
116 if start >= l.len() {
117 return Err(AssemblerError::ExpressionError(
118 ExpressionError::InvalidSize(l.len(), start)
119 ));
120 }
121 if end > l.len() {
122 return Err(AssemblerError::ExpressionError(
123 ExpressionError::InvalidSize(l.len(), end)
124 ));
125 }
126 Ok(ExprResult::List(l[start..end].to_vec()))
127 },
128
129 _ => {
130 Err(AssemblerError::ExpressionError(ExpressionError::OwnError(
131 Box::new(AssemblerError::AssemblingError {
132 msg: format!("{} is not a list", list)
133 })
134 )))
135 },
136 }
137}
138
139pub fn list_len(list: &ExprResult) -> Result<ExprResult, crate::AssemblerError> {
140 match list {
141 ExprResult::List(l) => Ok(l.len().into()),
142 ExprResult::String(s) => Ok(s.len().into()),
143 _ => {
144 Err(AssemblerError::ExpressionError(ExpressionError::OwnError(
145 Box::new(AssemblerError::AssemblingError {
146 msg: format!("{} is not a list", list)
147 })
148 )))
149 },
150 }
151}
152
153pub fn list_push(list: ExprResult, elem: ExprResult) -> Result<ExprResult, crate::AssemblerError> {
154 match list {
155 ExprResult::List(mut l) => {
156 l.push(elem);
157 Ok(ExprResult::List(l))
158 },
159 _ => {
160 Err(AssemblerError::ExpressionError(ExpressionError::OwnError(
161 Box::new(AssemblerError::AssemblingError {
162 msg: format!("{} is not a list", list)
163 })
164 )))
165 },
166 }
167}
168
169pub fn list_extend(
170 list1: ExprResult,
171 list2: ExprResult
172) -> Result<ExprResult, crate::AssemblerError> {
173 match list1 {
174 ExprResult::List(mut l) => {
175 match list2 {
176 ExprResult::List(l2) => {
177 for item in l2 {
178 l.push(item);
179 }
180 Ok(ExprResult::List(l))
181 },
182 _ => {
183 Err(AssemblerError::ExpressionError(ExpressionError::OwnError(
184 Box::new(AssemblerError::AssemblingError {
185 msg: format!("{} is not a list", list2)
186 })
187 )))
188 },
189 }
190 },
191 _ => {
192 Err(AssemblerError::ExpressionError(ExpressionError::OwnError(
193 Box::new(AssemblerError::AssemblingError {
194 msg: format!("{} is not a list", list1)
195 })
196 )))
197 },
198 }
199}
200
201pub fn list_sort(list: ExprResult) -> Result<ExprResult, crate::AssemblerError> {
202 match list {
203 ExprResult::List(mut l) => {
204 l.sort();
205 Ok(ExprResult::List(l))
206 },
207 _ => {
208 Err(AssemblerError::ExpressionError(ExpressionError::OwnError(
209 Box::new(AssemblerError::AssemblingError {
210 msg: format!("{} is not a list", list)
211 })
212 )))
213 },
214 }
215}
216
217pub fn list_argsort(list: &ExprResult) -> Result<ExprResult, crate::AssemblerError> {
218 match list {
219 ExprResult::List(l) => {
220 fn argsort<T: Ord>(data: &[T]) -> Vec<ExprResult> {
222 let mut indices = (0..data.len()).map(ExprResult::from).collect_vec();
223 indices.sort_by_key(|i| &data[i.int().unwrap() as usize]);
224 indices
225 }
226
227 let l = argsort(l);
228 Ok(ExprResult::List(l))
229 },
230 _ => {
231 Err(AssemblerError::ExpressionError(ExpressionError::OwnError(
232 Box::new(AssemblerError::AssemblingError {
233 msg: format!("{} is not a list", list)
234 })
235 )))
236 },
237 }
238}
239
240pub fn string_from_list(s1: ExprResult) -> Result<ExprResult, crate::AssemblerError> {
242 match s1 {
243 ExprResult::List(l1) => {
244 let bytes = l1
245 .iter()
246 .enumerate()
247 .map(|(idx, v)| {
248 let v = v.int()?;
249 if !(0..=255).contains(&v) {
250 Err(AssemblerError::AssemblingError {
251 msg: format!("{} at {} is not a valid byte value", v, idx)
252 })
253 }
254 else {
255 Ok(v as u8)
256 }
257 })
258 .collect::<Result<Vec<u8>, AssemblerError>>()?;
259
260 String::from_utf8(bytes)
261 .map_err(|e| {
262 AssemblerError::AssemblingError {
263 msg: format!("Error when generating a string. {e}")
264 }
265 })
266 .map(|s| s.into())
267 },
268
269 _ => {
270 Err(AssemblerError::ExpressionError(ExpressionError::OwnError(
271 Box::new(AssemblerError::AssemblingError {
272 msg: "string_from_list must take a list as an argument".to_string()
273 })
274 )))
275 },
276 }
277}
278
279pub fn string_push(s1: ExprResult, s2: ExprResult) -> Result<ExprResult, crate::AssemblerError> {
280 match (&s1, &s2) {
281 (ExprResult::Char(s1), ExprResult::Char(s2)) => {
282 let s1 = format!("{}{}", *s1 as char, *s2 as char);
283 Ok(ExprResult::String(s1.into()))
284 },
285
286 (ExprResult::String(s1), ExprResult::Char(s2)) => {
287 let s1 = format!("{}{}", s1, *s2 as char);
288 Ok(ExprResult::String(s1.into()))
289 },
290
291 (ExprResult::String(s1), ExprResult::String(s2)) => {
292 let s1 = s1.to_string() + fix_string(s2.clone()).as_str();
293 Ok(ExprResult::String(s1.into()))
294 },
295 (ExprResult::String(s1), ExprResult::List(l)) => {
296 let mut s1 = s1.to_string() + "[";
297
298 for (i, e) in l.iter().cloned().enumerate() {
299 if i != 0 {
300 s1 += ","
301 }
302
303 s1 = string_push(s1.into(), e)?.string().unwrap().to_string();
304 }
305
306 s1 += "]";
307 Ok(ExprResult::String(s1.into()))
308 },
309
310 (ExprResult::String(s1), ExprResult::Float(s2)) => {
311 let mut s1 = s1.to_string();
312 s1 += &s2.into_inner().to_string();
313 Ok(ExprResult::String(s1.into()))
314 },
315
316 (ExprResult::String(s1), ExprResult::Value(s2)) => {
317 let mut s1 = s1.to_string();
318
319 s1 += &s2.to_string();
320 Ok(ExprResult::String(s1.into()))
321 },
322
323 (ExprResult::String(s1), ExprResult::Bool(s2)) => {
324 let mut s1 = s1.to_string();
325
326 s1 += &s2.to_string();
327 Ok(ExprResult::String(s1.into()))
328 },
329
330 _ => {
331 Err(AssemblerError::ExpressionError(ExpressionError::OwnError(
332 Box::new(AssemblerError::AssemblingError {
333 msg: format!("string_push called with wrong types {:?} {:?}", s1, s2)
334 })
335 )))
336 },
337 }
338}