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