mech_core/
lib.rs

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
10//extern crate core as rust_core;
11extern 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// Mech Source Code
128// ---------------------------------------------------------------------------
129
130#[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
235// Humanize
236// ---------------------------------------------------------------------------
237
238// Turn bytes into something more readable by humans
239// Useful for visualizing register dumps, hashes, etc.
240
241pub 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
341// Emoji list is for quicker visual scanning/recognition when comparing registers
342
343pub const EMOJILIST: &[&str; 256] = &[
344  "๐Ÿต","๐Ÿถ","๐Ÿบ","๐ŸฆŠ","๐Ÿฆ","๐Ÿฑ","๐Ÿˆ","๐Ÿˆ","๐Ÿฆ","๐Ÿท","๐Ÿฎ","๐Ÿฆฌ","๐Ÿฏ","๐Ÿด","๐ŸซŽ","๐Ÿฆ„","๐Ÿฆ“","๐Ÿฆ™","๐Ÿฆ’","๐Ÿ˜","๐Ÿฆฃ","๐Ÿฆ","๐Ÿฆ›","๐Ÿซ","๐Ÿ","๐Ÿญ","๐Ÿฐ","๐Ÿฟ๏ธ","๐Ÿฆซ","๐Ÿฆ”","๐Ÿฆ‡","๐Ÿป","๐Ÿจ","๐Ÿผ","๐Ÿฆฅ","๐Ÿฆฆ","๐Ÿฆจ","๐Ÿฆ˜","๐Ÿฆก","๐Ÿฆƒ","๐Ÿ”","๐Ÿฆ","๐Ÿง","๐Ÿ•Š๏ธ","๐Ÿฆ…","๐Ÿฆ†","๐Ÿฆโ€๐Ÿ”ฅ","๐Ÿฆ‰","๐Ÿฆค","๐Ÿฆฉ","๐Ÿฆš","๐Ÿฆœ","๐Ÿธ","๐ŸŠ","๐Ÿข","๐ŸฆŽ","๐Ÿ","๐Ÿฒ","๐Ÿฆ–","๐Ÿณ","๐Ÿฌ","๐Ÿฆญ","๐Ÿ ","๐Ÿฆˆ","๐Ÿ™","๐Ÿชผ","๐Ÿฆ€","๐Ÿฆž","๐Ÿฆ","๐Ÿฆ‘","๐ŸŒ","๐Ÿฆ‹","๐Ÿ›","๐Ÿ","๐Ÿชฒ","๐Ÿž","๐Ÿฆ—","๐Ÿ•ธ๏ธ","๐Ÿชฐ","๐Ÿชฑ","๐Ÿฆ ","๐Ÿ‘ป","๐Ÿ‘ฝ","๐Ÿถ","๐Ÿฎ","๐Ÿš","๐Ÿชธ","๐Ÿชถ","๐Ÿฆง","๐Ÿชฟ","๐Ÿฆข","๐Ÿค–",
345  "๐ŸŒน","๐ŸŒณ","๐ŸŒด","๐ŸŒต","๐Ÿ€","๐Ÿ","๐Ÿ„","๐ŸŒ›","๐ŸŒž","๐Ÿช","โญ","โ›…","๐ŸŒง๏ธ","๐ŸŒจ๏ธ","๐ŸŒˆ","โ„๏ธ","โ˜ƒ๏ธ","โ˜„๏ธ","๐Ÿ”ฅ","๐ŸŒป",
346  "๐Ÿ‡","๐Ÿ‰","๐ŸŠ","๐Ÿ‹","๐Ÿ‹โ€๐ŸŸฉ","๐ŸŒ","๐Ÿ","๐Ÿฅญ","๐ŸŽ","๐Ÿ","๐Ÿ“","๐Ÿฅ","๐Ÿ…","๐Ÿซ’","๐Ÿฅฅ","๐Ÿฅ”","๐Ÿฅ•","๐ŸŒฝ","๐ŸŒถ๏ธ","๐Ÿซ‘","๐Ÿฅ’","๐Ÿฅฆ","๐Ÿง„","๐Ÿง…","๐Ÿซ›","๐Ÿฆ","๐Ÿง","๐Ÿฉ","๐Ÿช","๐Ÿฐ","๐Ÿง","๐Ÿฅง","๐Ÿซ","๐Ÿญ","๐Ÿž","๐Ÿฅจ","๐Ÿฅฏ","๐Ÿง‡","๐ŸŸ","๐Ÿฟ","๐Ÿงƒ",
347  "๐ŸŽค","๐ŸŽง","๐Ÿ“ป","๐ŸŽท","๐Ÿช—","๐ŸŽธ","๐ŸŽน","๐ŸŽบ","๐ŸŽป","๐Ÿช‡","๐Ÿฅ","โš—๏ธ","๐Ÿ“ท","๐Ÿงณ","๐ŸŒก๏ธ","๐Ÿงธ","๐Ÿงถ","๐Ÿ”Ž","๐Ÿ•ฏ๏ธ","๐Ÿ’ก","๐Ÿ”ฆ","๐Ÿ”’","๐Ÿ—๏ธ","๐Ÿชš","๐Ÿ”ง","๐Ÿช›","๐Ÿ”ฉ","โš™๏ธ","โš–๏ธ","๐Ÿงฐ","๐Ÿงฒ","๐Ÿชœ","๐Ÿ”ฌ","๐Ÿ“ก","๐Ÿงท","๐Ÿงน","๐Ÿงบ","๐Ÿชฃ","๐Ÿงผ","๐Ÿงฝ","๐Ÿงฏ","๐Ÿ›’",  
348  "โฐ","๐Ÿ›Ÿ","๐Ÿ›ฉ๏ธ","๐Ÿš","๐Ÿ›ฐ๏ธ","๐Ÿš€","๐Ÿ›ธ","โš“","๐Ÿš‚","๐Ÿš‘","๐Ÿš’","๐Ÿš•","๐Ÿš—","๐Ÿšš","๐Ÿšœ","๐ŸŽ๏ธ","๐Ÿ๏ธ","๐Ÿ›ต","๐Ÿฆผ","๐Ÿšฒ","๐Ÿ›น","๐Ÿ›ผ","๐Ÿ›ž","๐Ÿ“ฐ","๐Ÿ“ฆ","๐Ÿ“ซ","โœ๏ธ","๐Ÿ–Š๏ธ","๐Ÿ–Œ๏ธ","๐Ÿ–๏ธ","๐Ÿ“Œ","๐Ÿ“","โœ‚๏ธ","๐Ÿ—‘๏ธ","๐Ÿ†","โšพ","๐Ÿ€","๐ŸŽพ","๐ŸŽณ","โ›ณ","โ›ธ๏ธ","๐Ÿคฟ","๐Ÿ›ท","๐ŸŽฏ","๐Ÿช","๐Ÿงฉ","๐Ÿช…","๐ŸŽจ","๐Ÿงญ","๐Ÿ”๏ธ","๐Ÿ๏ธ","โ›ฒ","โ›บ","๐ŸŽ ","๐Ÿ›","๐Ÿงต","๐Ÿ’ˆ","๐ŸŽช","๐Ÿ›Ž๏ธ","๐Ÿ’Ž","โ›ต"
349];