Skip to main content

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