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