1#![cfg_attr(feature = "no_std", no_std)]
2#![feature(get_mut_unchecked)]
3#![allow(warnings)]
4#![feature(iter_intersperse)]
5#![feature(extract_if)]
6#![allow(dead_code)]
7#![feature(step_trait)]
8#![feature(box_patterns)]
9#![feature(where_clause_attrs)]
10
11extern crate seahash;
13
14#[cfg(feature="no_std")] #[macro_use]
15extern crate alloc;
16#[cfg(not(feature = "no_std"))]
17extern crate core;
18
19#[cfg(feature="no_std")]
20use hashbrown::HashMap;
21#[cfg(not(feature = "no_std"))]
22use std::collections::HashMap;
23
24#[cfg(feature="no_std")]
25use alloc::fmt::{self, Debug, Display};
26#[cfg(not(feature = "no_std"))]
27use std::fmt::{self, Debug, Display};
28
29#[cfg(feature="no_std")]
30use alloc::vec::Vec;
31
32#[cfg(feature="no_std")]
33use fxhash::FxHasher;
34
35#[cfg(feature = "no_std")]
36use embedded_io::{self, Read, Write};
37#[cfg(not(feature = "no_std"))]
38use std::io::{self, Error as ioError, Cursor, Read, Write};
39
40#[cfg(feature = "no_std")]
41use alloc::string::{String, ToString};
42
43#[cfg(feature = "no_std")]
44use core::hash::{Hash, Hasher};
45#[cfg(not(feature = "no_std"))]
46use std::hash::{Hash, Hasher};
47
48#[cfg(feature = "no_std")]
49use alloc::boxed::Box;
50
51#[cfg(feature = "matrix")]
52extern crate nalgebra as na;
53#[cfg(feature = "pretty_print")]
54extern crate tabled;
55#[cfg(feature = "serde")] #[macro_use]
56extern crate serde_derive;
57#[cfg(feature = "serde")]
58extern crate serde;
59#[cfg(any(feature = "math_pow", feature = "f64", feature = "f32", feature = "complex", feature = "rational"))]
60extern crate num_traits;
61
62use paste::paste;
63
64#[cfg(any(feature = "math_pow", feature = "f64"))]
65use num_traits::*;
66#[cfg(feature = "rational")]
67use num_rational::Rational64;
68#[cfg(feature = "vector3")]
69use nalgebra::Vector3;
70#[cfg(feature = "vectord")]
71use nalgebra::DVector;
72#[cfg(feature = "vector2")]
73use nalgebra::Vector2;
74#[cfg(feature = "vector4")]
75use nalgebra::Vector4;
76#[cfg(feature = "row_vectord")]
77use nalgebra::RowDVector;
78#[cfg(feature = "matrix1")]
79use nalgebra::Matrix1;
80#[cfg(feature = "matrix3")]
81use nalgebra::Matrix3;
82#[cfg(feature = "matrix4")]
83use nalgebra::Matrix4;
84#[cfg(feature = "row_vector3")]
85use nalgebra::RowVector3;
86#[cfg(feature = "row_vector4")]
87use nalgebra::RowVector4;
88#[cfg(feature = "row_vector2")]
89use nalgebra::RowVector2;
90#[cfg(feature = "matrixd")]
91use nalgebra::DMatrix;
92#[cfg(feature = "matrix2x3")]
93use nalgebra::Matrix2x3;
94#[cfg(feature = "matrix3x2")]
95use nalgebra::Matrix3x2;
96#[cfg(feature = "matrix2")]
97use nalgebra::Matrix2;
98
99#[cfg(feature = "pretty_print")]
100use tabled::{
101 builder::Builder,
102 settings::{object::Rows,Panel, Span, Alignment, Modify, Style},
103 Tabled,
104};
105
106pub mod error;
107pub mod kind;
108pub mod nodes;
109pub mod structures;
110pub mod value;
111#[cfg(feature = "functions")]
112pub mod functions;
113#[cfg(feature = "mika")]
114pub mod mika;
115pub mod program;
116pub mod stdlib;
117pub mod types;
118
119pub use self::error::*;
120pub use self::kind::*;
121pub use self::nodes::*;
122pub use self::structures::*;
123pub use self::value::*;
124#[cfg(feature = "functions")]
125pub use self::functions::*;
126#[cfg(feature = "mika")]
127pub use self::mika::*;
128pub use self::program::*;
129pub use self::stdlib::*;
130pub use self::types::*;
131
132#[cfg(feature = "functions")]
136inventory::collect!(FunctionDescriptor);
137
138#[cfg(feature = "functions")]
139inventory::collect!(FunctionCompilerDescriptor);
140
141#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
142#[derive(Clone, Debug, PartialEq, Eq)]
143pub enum MechSourceCode {
144 String(String),
145 Tree(Program),
146 Html(String),
147 ByteCode(Vec<u8>),
148 Program(Vec<MechSourceCode>),
149 Image(String,Vec<u8>),
150}
151
152impl MechSourceCode {
153
154 pub fn to_string(&self) -> String {
155 match self {
156 MechSourceCode::ByteCode(bc) => {
157 #[cfg(feature = "program")]
158 match ParsedProgram::from_bytes(bc) {
159 Ok(program) => {
160 format!("{:#?}",program)
161 },
162 Err(e) => return format!("Error parsing bytecode: {:?}", e),
163 }
164 #[cfg(not(feature = "program"))]
165 format!("{:#?}", bc)
166 }
167 MechSourceCode::Image(extension,img) => {
168 format!("Image (.{}) with {} bytes", extension, img.len())
169 }
170 MechSourceCode::String(s) => s.clone(),
171 MechSourceCode::Tree(p) => todo!("Print the tree!"),
172 MechSourceCode::Html(h) => h.clone(),
173 MechSourceCode::Program(v) => v.iter().map(|c| c.to_string()).collect::<Vec<String>>().join("\n"),
174 }
175 }
176}
177
178#[derive(Clone, Debug, PartialEq, Eq)]
179pub struct IndexedString {
180 pub data: Vec<char>,
181 pub index_map: Vec<Vec<usize>>,
182 pub rows: usize,
183 pub cols: usize,
184}
185
186impl IndexedString {
187
188 fn new(input: &str) -> Self {
189 let mut data = Vec::new();
190 let mut index_map = Vec::new();
191 let mut current_row = 0;
192 let mut current_col = 0;
193 index_map.push(Vec::new());
194 for c in input.chars() {
195 data.push(c);
196 if c == '\n' {
197 index_map.push(Vec::new());
198 current_row += 1;
199 current_col = 0;
200 } else {
201 index_map[current_row].push(data.len() - 1);
202 current_col += 1;
203 }
204 }
205 let rows = index_map.len();
206 let cols = if rows > 0 { index_map[0].len() } else { 0 };
207 IndexedString {
208 data,
209 index_map,
210 rows,
211 cols,
212 }
213 }
214
215 fn to_string(&self) -> String {
216 self.data.iter().collect()
217 }
218
219 fn get(&self, row: usize, col: usize) -> Option<char> {
220 if row < self.rows {
221 let rowz = &self.index_map[row];
222 if col < rowz.len() {
223 let index = self.index_map[row][col];
224 Some(self.data[index])
225 } else {
226 None
227 }
228 } else {
229 None
230 }
231 }
232
233 fn set(&mut self, row: usize, col: usize, new_char: char) -> Result<(), String> {
234 if row < self.rows {
235 let row_indices = &mut self.index_map[row];
236 if col < row_indices.len() {
237 let index = row_indices[col];
238 self.data[index] = new_char;
239 Ok(())
240 } else {
241 Err("Column index out of bounds".to_string())
242 }
243 } else {
244 Err("Row index out of bounds".to_string())
245 }
246 }
247}
248
249pub fn hash_chars(input: &Vec<char>) -> u64 {
256 seahash::hash(input.iter().map(|s| String::from(*s)).collect::<String>().as_bytes()) & 0x00FFFFFFFFFFFFFF
257}
258
259pub fn hash_bytes(input: &Vec<u8>) -> u64 {
260 seahash::hash(input) & 0x00FFFFFFFFFFFFFF
261}
262
263pub fn hash_str(input: &str) -> u64 {
264 seahash::hash(input.as_bytes()) & 0x00FFFFFFFFFFFFFF
265}
266
267pub fn emojify_bytes(bytes: &[u8]) -> String {
268 let start = bytes.iter().position(|&b| b != 0).unwrap_or(bytes.len() - 1);
269 let mut out = String::new();
270 for &b in &bytes[start..] {
271 out.push_str(EMOJILIST[b as usize]);
272 }
273 out
274}
275
276pub fn humanize_bytes(bytes: &[u8]) -> String {
277 let parts: Vec<&str> = bytes
278 .iter()
279 .enumerate()
280 .filter_map(|(ix, &b)| if ix % 2 == 1 { Some(WORDLIST[b as usize]) } else { None })
281 .collect();
282 parts.join("-")
283}
284
285pub fn emojify<T>(num: &T) -> String
286where
287 T: Display + Copy + TryInto<u128>,
288 <T as TryInto<u128>>::Error: std::fmt::Debug,
289{
290 match (*num).try_into() {
291 Ok(v) => {
292 let bytes = v.to_be_bytes();
293 emojify_bytes(&bytes)
294 }
295 Err(_) => format!("{}", num),
296 }
297}
298
299pub fn humanize<T>(num: &T) -> String
300where
301 T: Display + Copy + TryInto<u128>,
302 <T as TryInto<u128>>::Error: Debug,
303{
304 match (*num).try_into() {
305 Ok(v) => {
306 let bytes = v.to_be_bytes();
307 let first_non_zero = bytes.iter().position(|&b| b != 0).unwrap_or(bytes.len() - 1);
308 let trimmed = &bytes[first_non_zero..];
309 humanize_bytes(trimmed)
310 }
311 Err(_) => format!("{}", num),
312}
313}
314
315pub const WORDLIST: &[&str;256] = &[
316 "nil", "ama", "ine", "ska", "pha", "gel", "art",
317 "ona", "sas", "ist", "aus", "pen", "ust", "umn",
318 "ado", "con", "loo", "man", "eer", "lin", "ium",
319 "ack", "som", "lue", "ird", "avo", "dog", "ger",
320 "ter", "nia", "bon", "nal", "ina", "pet", "cat",
321 "ing", "lie", "ken", "fee", "ola", "old", "rad",
322 "met", "cut", "azy", "cup", "ota", "dec", "del",
323 "elt", "iet", "don", "ble", "ear", "rth", "eas",
324 "war", "eig", "tee", "ele", "emm", "ene", "qua",
325 "tst", "fan", "fif", "fil", "fin", "fis", "fiv",
326 "flo", "for", "foo", "fou", "fot", "fox", "fre",
327 "fri", "fru", "gee", "gia", "glu", "fol", "gre",
328 "ham", "hap", "har", "haw", "hel", "hig", "hot",
329 "hyd", "ida", "ill", "ind", "ini", "ink", "iwa",
330 "and", "ite", "jer", "jig", "joh", "jul", "uly",
331 "kan", "ket", "kil", "kin", "kit", "lac", "lak",
332 "lem", "ard", "lim", "lio", "lit", "lon", "lou",
333 "low", "mag", "nes", "mai", "gam", "arc", "mar",
334 "mao", "mas", "may", "mex", "mic", "mik", "ril",
335 "min", "mir", "mis", "mio", "mob", "moc", "ech",
336 "moe", "tan", "oon", "ain", "mup", "sic", "neb",
337 "une", "net", "nev", "nin", "een", "nit", "nor",
338 "nov", "nut", "oct", "ohi", "okl", "one", "ora",
339 "ges", "ore", "osc", "ove", "oxy", "pap", "par",
340 "pey", "pip", "piz", "plu", "pot", "pri", "pur",
341 "que", "uqi", "qui", "red", "riv", "rob", "roi",
342 "rug", "sad", "sal", "sat", "sep", "sev", "eve",
343 "sha", "sie", "sin", "sik", "six", "sit", "sky",
344 "soc", "sod", "sol", "sot", "tir", "ker", "spr",
345 "sta", "ste", "mam", "mer", "swe", "tab", "tag",
346 "see", "nis", "tex", "thi", "the", "tim", "tri",
347 "twe", "ent", "two", "unc", "ess", "uni", "ura",
348 "veg", "ven", "ver", "vic", "vid", "vio", "vir",
349 "was", "est", "whi", "hit", "iam", "win", "his",
350 "wis", "olf", "wyo", "ray", "ank", "yel", "zeb",
351 "ulu", "fix", "gry", "hol", "jup", "lam", "pas",
352 "rom", "sne", "ten", "uta"];
353
354pub const EMOJILIST: &[&str; 256] = &[
357 "๐ต","๐ถ","๐บ","๐ฆ","๐ฆ","๐ฑ","๐","๐","๐ฆ","๐ท","๐ฎ","๐ฆฌ","๐ฏ","๐ด","๐ซ","๐ฆ","๐ฆ","๐ฆ","๐ฆ","๐","๐ฆฃ","๐ฆ","๐ฆ","๐ซ","๐","๐ญ","๐ฐ","๐ฟ๏ธ","๐ฆซ","๐ฆ","๐ฆ","๐ป","๐จ","๐ผ","๐ฆฅ","๐ฆฆ","๐ฆจ","๐ฆ","๐ฆก","๐ฆ","๐","๐ฆ","๐ง","๐๏ธ","๐ฆ
","๐ฆ","๐ฆโ๐ฅ","๐ฆ","๐ฆค","๐ฆฉ","๐ฆ","๐ฆ","๐ธ","๐","๐ข","๐ฆ","๐","๐ฒ","๐ฆ","๐ณ","๐ฌ","๐ฆญ","๐ ","๐ฆ","๐","๐ชผ","๐ฆ","๐ฆ","๐ฆ","๐ฆ","๐","๐ฆ","๐","๐","๐ชฒ","๐","๐ฆ","๐ธ๏ธ","๐ชฐ","๐ชฑ","๐ฆ ","๐ป","๐ฝ","๐ถ","๐ฎ","๐","๐ชธ","๐ชถ","๐ฆง","๐ชฟ","๐ฆข","๐ค",
358 "๐น","๐ณ","๐ด","๐ต","๐","๐","๐","๐","๐","๐ช","โญ","โ
","๐ง๏ธ","๐จ๏ธ","๐","โ๏ธ","โ๏ธ","โ๏ธ","๐ฅ","๐ป",
359 "๐","๐","๐","๐","๐โ๐ฉ","๐","๐","๐ฅญ","๐","๐","๐","๐ฅ","๐
","๐ซ","๐ฅฅ","๐ฅ","๐ฅ","๐ฝ","๐ถ๏ธ","๐ซ","๐ฅ","๐ฅฆ","๐ง","๐ง
","๐ซ","๐ฆ","๐ง","๐ฉ","๐ช","๐ฐ","๐ง","๐ฅง","๐ซ","๐ญ","๐","๐ฅจ","๐ฅฏ","๐ง","๐","๐ฟ","๐ง",
360 "๐ค","๐ง","๐ป","๐ท","๐ช","๐ธ","๐น","๐บ","๐ป","๐ช","๐ฅ","โ๏ธ","๐ท","๐งณ","๐ก๏ธ","๐งธ","๐งถ","๐","๐ฏ๏ธ","๐ก","๐ฆ","๐","๐๏ธ","๐ช","๐ง","๐ช","๐ฉ","โ๏ธ","โ๏ธ","๐งฐ","๐งฒ","๐ช","๐ฌ","๐ก","๐งท","๐งน","๐งบ","๐ชฃ","๐งผ","๐งฝ","๐งฏ","๐",
361 "โฐ","๐","๐ฉ๏ธ","๐","๐ฐ๏ธ","๐","๐ธ","โ","๐","๐","๐","๐","๐","๐","๐","๐๏ธ","๐๏ธ","๐ต","๐ฆผ","๐ฒ","๐น","๐ผ","๐","๐ฐ","๐ฆ","๐ซ","โ๏ธ","๐๏ธ","๐๏ธ","๐๏ธ","๐","๐","โ๏ธ","๐๏ธ","๐","โพ","๐","๐พ","๐ณ","โณ","โธ๏ธ","๐คฟ","๐ท","๐ฏ","๐ช","๐งฉ","๐ช
","๐จ","๐งญ","๐๏ธ","๐๏ธ","โฒ","โบ","๐ ","๐","๐งต","๐","๐ช","๐๏ธ","๐","โต"
362];