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