Skip to main content

mech_core/
lib.rs

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