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_exp", feature = "f64", feature = "f32", feature = "complex", feature = "rational"))]
60extern crate num_traits;
61
62use paste::paste;
63
64#[cfg(any(feature = "math_exp", 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;
113pub mod program;
114pub mod stdlib;
115pub mod types;
116
117pub use self::error::*;
118pub use self::kind::*;
119pub use self::nodes::*;
120pub use self::structures::*;
121pub use self::value::*;
122#[cfg(feature = "functions")]
123pub use self::functions::*;
124pub use self::program::*;
125pub use self::stdlib::*;
126pub use self::types::*;
127
128#[cfg(feature = "functions")]
132inventory::collect!(FunctionDescriptor);
133
134#[cfg(feature = "functions")]
135inventory::collect!(FunctionCompilerDescriptor);
136
137#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
138#[derive(Clone, Debug, PartialEq, Eq)]
139pub enum MechSourceCode {
140 String(String),
141 Tree(Program),
142 Html(String),
143 ByteCode(Vec<u8>),
144 Program(Vec<MechSourceCode>),
145 Image(String,Vec<u8>),
146}
147
148impl MechSourceCode {
149
150 pub fn to_string(&self) -> String {
151 match self {
152 MechSourceCode::ByteCode(bc) => {
153 #[cfg(feature = "program")]
154 match ParsedProgram::from_bytes(bc) {
155 Ok(program) => {
156 format!("{:#?}",program)
157 },
158 Err(e) => return format!("Error parsing bytecode: {:?}", e),
159 }
160 #[cfg(not(feature = "program"))]
161 format!("{:#?}", bc)
162 }
163 MechSourceCode::Image(extension,img) => {
164 format!("Image (.{}) with {} bytes", extension, img.len())
165 }
166 MechSourceCode::String(s) => s.clone(),
167 MechSourceCode::Tree(p) => todo!("Print the tree!"),
168 MechSourceCode::Html(h) => h.clone(),
169 MechSourceCode::Program(v) => v.iter().map(|c| c.to_string()).collect::<Vec<String>>().join("\n"),
170 }
171 }
172}
173
174#[derive(Clone, Debug, PartialEq, Eq)]
175pub struct IndexedString {
176 pub data: Vec<char>,
177 pub index_map: Vec<Vec<usize>>,
178 pub rows: usize,
179 pub cols: usize,
180}
181
182impl IndexedString {
183
184 fn new(input: &str) -> Self {
185 let mut data = Vec::new();
186 let mut index_map = Vec::new();
187 let mut current_row = 0;
188 let mut current_col = 0;
189 index_map.push(Vec::new());
190 for c in input.chars() {
191 data.push(c);
192 if c == '\n' {
193 index_map.push(Vec::new());
194 current_row += 1;
195 current_col = 0;
196 } else {
197 index_map[current_row].push(data.len() - 1);
198 current_col += 1;
199 }
200 }
201 let rows = index_map.len();
202 let cols = if rows > 0 { index_map[0].len() } else { 0 };
203 IndexedString {
204 data,
205 index_map,
206 rows,
207 cols,
208 }
209 }
210
211 fn to_string(&self) -> String {
212 self.data.iter().collect()
213 }
214
215 fn get(&self, row: usize, col: usize) -> Option<char> {
216 if row < self.rows {
217 let rowz = &self.index_map[row];
218 if col < rowz.len() {
219 let index = self.index_map[row][col];
220 Some(self.data[index])
221 } else {
222 None
223 }
224 } else {
225 None
226 }
227 }
228
229 fn set(&mut self, row: usize, col: usize, new_char: char) -> Result<(), String> {
230 if row < self.rows {
231 let row_indices = &mut self.index_map[row];
232 if col < row_indices.len() {
233 let index = row_indices[col];
234 self.data[index] = new_char;
235 Ok(())
236 } else {
237 Err("Column index out of bounds".to_string())
238 }
239 } else {
240 Err("Row index out of bounds".to_string())
241 }
242 }
243}
244
245pub fn hash_chars(input: &Vec<char>) -> u64 {
252 seahash::hash(input.iter().map(|s| String::from(*s)).collect::<String>().as_bytes()) & 0x00FFFFFFFFFFFFFF
253}
254
255pub fn hash_bytes(input: &Vec<u8>) -> u64 {
256 seahash::hash(input) & 0x00FFFFFFFFFFFFFF
257}
258
259pub fn hash_str(input: &str) -> u64 {
260 seahash::hash(input.as_bytes()) & 0x00FFFFFFFFFFFFFF
261}
262
263pub fn emojify_bytes(bytes: &[u8]) -> String {
264 let start = bytes.iter().position(|&b| b != 0).unwrap_or(bytes.len() - 1);
265 let mut out = String::new();
266 for &b in &bytes[start..] {
267 out.push_str(EMOJILIST[b as usize]);
268 }
269 out
270}
271
272pub fn humanize_bytes(bytes: &[u8]) -> String {
273 let parts: Vec<&str> = bytes
274 .iter()
275 .enumerate()
276 .filter_map(|(ix, &b)| if ix % 2 == 1 { Some(WORDLIST[b as usize]) } else { None })
277 .collect();
278 parts.join("-")
279}
280
281pub fn emojify<T>(num: &T) -> String
282where
283 T: Display + Copy + TryInto<u128>,
284 <T as TryInto<u128>>::Error: std::fmt::Debug,
285{
286 match (*num).try_into() {
287 Ok(v) => {
288 let bytes = v.to_be_bytes();
289 emojify_bytes(&bytes)
290 }
291 Err(_) => format!("{}", num),
292 }
293}
294
295pub fn humanize<T>(num: &T) -> String
296where
297 T: Display + Copy + TryInto<u128>,
298 <T as TryInto<u128>>::Error: Debug,
299{
300 match (*num).try_into() {
301 Ok(v) => {
302 let bytes = v.to_be_bytes();
303 let first_non_zero = bytes.iter().position(|&b| b != 0).unwrap_or(bytes.len() - 1);
304 let trimmed = &bytes[first_non_zero..];
305 humanize_bytes(trimmed)
306 }
307 Err(_) => format!("{}", num),
308}
309}
310
311pub const WORDLIST: &[&str;256] = &[
312 "nil", "ama", "ine", "ska", "pha", "gel", "art",
313 "ona", "sas", "ist", "aus", "pen", "ust", "umn",
314 "ado", "con", "loo", "man", "eer", "lin", "ium",
315 "ack", "som", "lue", "ird", "avo", "dog", "ger",
316 "ter", "nia", "bon", "nal", "ina", "pet", "cat",
317 "ing", "lie", "ken", "fee", "ola", "old", "rad",
318 "met", "cut", "azy", "cup", "ota", "dec", "del",
319 "elt", "iet", "don", "ble", "ear", "rth", "eas",
320 "war", "eig", "tee", "ele", "emm", "ene", "qua",
321 "tst", "fan", "fif", "fil", "fin", "fis", "fiv",
322 "flo", "for", "foo", "fou", "fot", "fox", "fre",
323 "fri", "fru", "gee", "gia", "glu", "fol", "gre",
324 "ham", "hap", "har", "haw", "hel", "hig", "hot",
325 "hyd", "ida", "ill", "ind", "ini", "ink", "iwa",
326 "and", "ite", "jer", "jig", "joh", "jul", "uly",
327 "kan", "ket", "kil", "kin", "kit", "lac", "lak",
328 "lem", "ard", "lim", "lio", "lit", "lon", "lou",
329 "low", "mag", "nes", "mai", "gam", "arc", "mar",
330 "mao", "mas", "may", "mex", "mic", "mik", "ril",
331 "min", "mir", "mis", "mio", "mob", "moc", "ech",
332 "moe", "tan", "oon", "ain", "mup", "sic", "neb",
333 "une", "net", "nev", "nin", "een", "nit", "nor",
334 "nov", "nut", "oct", "ohi", "okl", "one", "ora",
335 "ges", "ore", "osc", "ove", "oxy", "pap", "par",
336 "pey", "pip", "piz", "plu", "pot", "pri", "pur",
337 "que", "uqi", "qui", "red", "riv", "rob", "roi",
338 "rug", "sad", "sal", "sat", "sep", "sev", "eve",
339 "sha", "sie", "sin", "sik", "six", "sit", "sky",
340 "soc", "sod", "sol", "sot", "tir", "ker", "spr",
341 "sta", "ste", "mam", "mer", "swe", "tab", "tag",
342 "see", "nis", "tex", "thi", "the", "tim", "tri",
343 "twe", "ent", "two", "unc", "ess", "uni", "ura",
344 "veg", "ven", "ver", "vic", "vid", "vio", "vir",
345 "was", "est", "whi", "hit", "iam", "win", "his",
346 "wis", "olf", "wyo", "ray", "ank", "yel", "zeb",
347 "ulu", "fix", "gry", "hol", "jup", "lam", "pas",
348 "rom", "sne", "ten", "uta"];
349
350pub const EMOJILIST: &[&str; 256] = &[
353 "๐ต","๐ถ","๐บ","๐ฆ","๐ฆ","๐ฑ","๐","๐","๐ฆ","๐ท","๐ฎ","๐ฆฌ","๐ฏ","๐ด","๐ซ","๐ฆ","๐ฆ","๐ฆ","๐ฆ","๐","๐ฆฃ","๐ฆ","๐ฆ","๐ซ","๐","๐ญ","๐ฐ","๐ฟ๏ธ","๐ฆซ","๐ฆ","๐ฆ","๐ป","๐จ","๐ผ","๐ฆฅ","๐ฆฆ","๐ฆจ","๐ฆ","๐ฆก","๐ฆ","๐","๐ฆ","๐ง","๐๏ธ","๐ฆ
","๐ฆ","๐ฆโ๐ฅ","๐ฆ","๐ฆค","๐ฆฉ","๐ฆ","๐ฆ","๐ธ","๐","๐ข","๐ฆ","๐","๐ฒ","๐ฆ","๐ณ","๐ฌ","๐ฆญ","๐ ","๐ฆ","๐","๐ชผ","๐ฆ","๐ฆ","๐ฆ","๐ฆ","๐","๐ฆ","๐","๐","๐ชฒ","๐","๐ฆ","๐ธ๏ธ","๐ชฐ","๐ชฑ","๐ฆ ","๐ป","๐ฝ","๐ถ","๐ฎ","๐","๐ชธ","๐ชถ","๐ฆง","๐ชฟ","๐ฆข","๐ค",
354 "๐น","๐ณ","๐ด","๐ต","๐","๐","๐","๐","๐","๐ช","โญ","โ
","๐ง๏ธ","๐จ๏ธ","๐","โ๏ธ","โ๏ธ","โ๏ธ","๐ฅ","๐ป",
355 "๐","๐","๐","๐","๐โ๐ฉ","๐","๐","๐ฅญ","๐","๐","๐","๐ฅ","๐
","๐ซ","๐ฅฅ","๐ฅ","๐ฅ","๐ฝ","๐ถ๏ธ","๐ซ","๐ฅ","๐ฅฆ","๐ง","๐ง
","๐ซ","๐ฆ","๐ง","๐ฉ","๐ช","๐ฐ","๐ง","๐ฅง","๐ซ","๐ญ","๐","๐ฅจ","๐ฅฏ","๐ง","๐","๐ฟ","๐ง",
356 "๐ค","๐ง","๐ป","๐ท","๐ช","๐ธ","๐น","๐บ","๐ป","๐ช","๐ฅ","โ๏ธ","๐ท","๐งณ","๐ก๏ธ","๐งธ","๐งถ","๐","๐ฏ๏ธ","๐ก","๐ฆ","๐","๐๏ธ","๐ช","๐ง","๐ช","๐ฉ","โ๏ธ","โ๏ธ","๐งฐ","๐งฒ","๐ช","๐ฌ","๐ก","๐งท","๐งน","๐งบ","๐ชฃ","๐งผ","๐งฝ","๐งฏ","๐",
357 "โฐ","๐","๐ฉ๏ธ","๐","๐ฐ๏ธ","๐","๐ธ","โ","๐","๐","๐","๐","๐","๐","๐","๐๏ธ","๐๏ธ","๐ต","๐ฆผ","๐ฒ","๐น","๐ผ","๐","๐ฐ","๐ฆ","๐ซ","โ๏ธ","๐๏ธ","๐๏ธ","๐๏ธ","๐","๐","โ๏ธ","๐๏ธ","๐","โพ","๐","๐พ","๐ณ","โณ","โธ๏ธ","๐คฟ","๐ท","๐ฏ","๐ช","๐งฉ","๐ช
","๐จ","๐งญ","๐๏ธ","๐๏ธ","โฒ","โบ","๐ ","๐","๐งต","๐","๐ช","๐๏ธ","๐","โต"
358];