1pub mod primitive;
2use std::collections::BTreeMap;
3
4use constants::{
5 BREAK, CAPITALIZE, CEIL, DROP, ELSE, EULER_NUMBER, FALSE, FLOOR, FOR, IF,
6 IN, IS_ARRAY, IS_BOOL, IS_DOUBLE, IS_ERROR, IS_FUNCTION, IS_I8, IS_INT,
7 IS_MATCH, IS_STRUCT, IS_U8, JSONIFY, MAKE_ERROR, MATCH, MULTILINE, NULL,
8 PARSE_JSON, PI, REPLACE, REPLACE_ALL, REQUIRE, RETURN, ROUND, STRUCT, TAU,
9 TO_BINARY, TO_HEX, TO_LOWER, TO_UPPER, TRUE, WHILE,
10};
11pub use primitive::Primitive;
12
13use serde::{Deserialize, Serialize};
14use strum::EnumCount;
15
16use self::constants::TO_STRING;
17use self::constants::{
18 ABS, COS, EVAL, INCLUDE, LENGTH, LN, LOG, PRINT, PRINT_LN, SIN, SQRT, TAN,
19 TO_BOOL, TO_DOUBLE, TO_INT, TYPE_OF,
20};
21
22#[macro_use]
23pub mod constants {
24 macro_rules! pi {
25 () => {
26 'π'
27 };
28 }
29 macro_rules! euler_number {
30 () => {
31 'γ'
32 };
33 }
34 macro_rules! tau {
35 () => {
36 'τ'
37 };
38 }
39 pub const TRUE: &str = "true";
40 pub const FALSE: &str = "false";
41 pub const IF: &str = "if";
42 pub const ELSE: &str = "else";
43 pub const WHILE: &str = "while";
44 pub const TAU: &str = concat!(tau!());
45 pub const PI: &str = concat!(pi!());
46 pub const EULER_NUMBER: &str = concat!(euler_number!());
47 pub const SQRT: &str = "sqrt";
48 pub const TO_HEX: &str = "to_hex";
49 pub const TO_BINARY: &str = "to_binary";
50 pub const TO_INT: &str = "to_int";
51 pub const TO_BOOL: &str = "to_bool";
52 pub const TO_UPPER: &str = "to_upper";
53 pub const TO_LOWER: &str = "to_lower";
54 pub const CAPITALIZE: &str = "capitalize";
55 pub const REPLACE: &str = "replace";
56 pub const REPLACE_ALL: &str = "replace_all";
57 pub const FLOOR: &str = "floor";
58 pub const CEIL: &str = "ceil";
59 pub const ROUND: &str = "round";
60 pub const TO_DOUBLE: &str = "to_double";
61 pub const TO_STRING: &str = "to_string";
62 pub const IS_ERROR: &str = "is_error";
63 pub const IS_U8: &str = "is_u8";
64 pub const IS_I8: &str = "is_i8";
65 pub const IS_INT: &str = "is_int";
66 pub const IS_DOUBLE: &str = "is_double";
67 pub const IS_BOOL: &str = "is_bool";
68 pub const IS_FUNCTION: &str = "is_function";
69 pub const IS_ARRAY: &str = "is_array";
70 pub const IS_STRUCT: &str = "is_struct";
71 pub const JSONIFY: &str = "jsonify";
72 pub const PARSE_JSON: &str = "parse_json";
73 pub const MAKE_ERROR: &str = "make_err";
74 pub const ABS: &str = "abs";
75 pub const LENGTH: &str = "length";
76 pub const LOG: &str = "log";
77 pub const LN: &str = "ln";
78 pub const SIN: &str = "sin";
79 pub const COS: &str = "cos";
80 pub const TAN: &str = "tan";
81 pub const BREAK: &str = "break";
82 pub const RETURN: &str = "return";
83 pub const PRINT_LN: &str = "println";
84 pub const PRINT: &str = "print";
85 pub const INCLUDE: &str = "include";
86 pub const DROP: &str = "drop";
87 pub const NULL: &str = "null";
88 pub const MULTILINE: &str = "multiline";
89 pub const STRUCT: &str = "struct";
90 pub const EVAL: &str = "eval";
91 pub const TYPE_OF: &str = "type_of";
92 pub const IS_MATCH: &str = "is_match";
93 pub const MATCH: &str = "match";
94 pub const FOR: &str = "for";
95 pub const IN: &str = "in";
96 pub const REQUIRE: &str = "require";
97 pub const NATIVE_LIB: &[u8; 14] = b"__native_lib__";
98}
99
100#[derive(Debug, EnumCount)]
101pub enum MathConstants {
102 Pi,
103 EulerNumber,
104 Tau,
105}
106
107impl MathConstants {
108 pub const fn get_symbol(&self) -> char {
109 match self {
110 MathConstants::Pi => pi!(),
111 MathConstants::EulerNumber => euler_number!(),
112 MathConstants::Tau => tau!(),
113 }
114 }
115 pub const fn get_symbols() -> &'static str {
116 concat!(pi!(), euler_number!(), tau!())
117 }
118
119 pub const fn _get_variants()
120 -> &'static [&'static MathConstants; MathConstants::COUNT] {
121 &[&MathConstants::Pi, &MathConstants::EulerNumber, &MathConstants::Tau]
122 }
123}
124
125impl Value {
126 pub fn is_divisible_or_multipliable(&self) -> bool {
127 matches!(
128 self,
129 Value::Primitive(_)
130 | Value::U8(_)
131 | Value::I8(_)
132 | Value::Integer(_)
133 | Value::Decimal(_)
134 | Value::Const(_)
135 | Value::Array(_)
136 | Value::MultiDepthAccess { .. }
137 | Value::Variable(_)
138 | Value::VariableNegate(_)
139 | Value::VariableRef(_)
140 )
141 }
142}
143#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
144pub enum Value {
145 Break,
146 Primitive(Primitive),
147 EarlyReturn(Box<Option<Value>>),
148 Drop(Box<Value>),
149 Expression(Vec<Value>),
150 ImplicitMultiply(Box<Value>),
151 Operation(Operator),
152 BuiltInFunction {
153 fn_type: BuiltInFunctionType,
154 expr: Box<Value>,
155 },
156 Function {
157 parameters: Box<Value>,
158 exprs: Vec<Value>,
159 },
160 FunctionCall {
161 parameters: Box<Value>,
162 function: Box<Value>,
163 },
164 Null,
165 Decimal(f64),
166 U8(u8),
167 I8(i8),
168 Integer(i128),
169 Bool(bool),
170 Range {
171 start: Box<Value>,
172 incl_both_end: bool,
173 end: Box<Value>,
174 },
175 NoOp,
176 String(String),
177 FString(String, Vec<(String, Value)>),
178 BlockParen(Vec<Value>),
179 Variable(String),
180 VariableRef(String),
181 VariableUnused,
182 Const(char),
183 VariableNegate(String),
184 VariableExpr {
185 name: Box<Value>,
186 expr: Box<Value>,
187 },
188 IfExpr {
189 cond: Box<Value>,
190 exprs: Vec<Value>,
191 else_expr: Option<Vec<Value>>,
192 },
193 WhileExpr {
194 cond: Box<Value>,
195 exprs: Vec<Value>,
196 },
197 ForeachExpr {
198 var: String,
199 index_var: Option<String>,
200 iterator: Box<Value>,
201 exprs: Vec<Value>,
202 },
203 Array(Vec<Value>),
204 Struct(BTreeMap<String, Value>),
205
206 MultiDepthAccess {
207 root: Box<Value>,
208 next_keys: Vec<KeyAccess>,
209 },
210}
211#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
212pub enum KeyAccess {
213 Index(Primitive),
214 Key(Primitive),
215 Variable(Value),
216 FunctionCall { key: Box<KeyAccess>, parameters: Value },
217}
218#[derive(Debug, Copy, Clone, Eq, PartialEq, Serialize, Deserialize)]
219pub enum BuiltInFunctionType {
220 Sqrt,
221 Abs,
222 Log,
223 Ln,
224 Sin,
225 Cos,
226 ToInt,
227 ToBinary,
228 ToHex,
229 ToDouble,
230 ToBool,
231 ToUpper,
232 ToLower,
233 Capitalize,
234 Replace,
235 ReplaceAll,
236 Floor,
237 Round,
238 Ceil,
239 ToString,
240 Tan,
241 Println,
242 Print,
243 Eval,
244 TypeOf,
245 Match,
246 IsMatch,
247 Length,
248 Include,
249 Require,
250 IsError,
251 IsU8,
252 IsI8,
253 IsStruct,
254 IsBool,
255 IsInt,
256 MakeError,
257 IsDouble,
258 IsFunction,
259 IsArray,
260 ParseJson,
261 Jsonify,
262}
263
264#[derive(Debug, Eq, PartialEq, Copy, Clone, Serialize, Deserialize)]
265pub enum Operator {
266 Add,
267 Subtr,
268 Mult,
269 Div,
270 Mod,
271 Pow,
272 Pow2,
273 Pow3,
274 Not,
275 Less,
276 Greater,
277 LessOrEqual,
278 GreaterOrEqual,
279 Equal,
280 NotEqual,
281 And,
282 Or,
283 BitwiseNot,
284 BitwiseAnd,
285 BitwiseOr,
286 BitwiseXor,
287 BitwiseLShift,
288 BitwiseRShift,
289}
290
291#[derive(Debug)]
292pub enum TreeNodeValue {
293 Break,
294 EarlyReturn(Option<Value>),
295 Drop(Vec<Value>),
296 VariableUnused,
297 VariableAssign(Option<String>),
298 MultiDepthVariableAssign { root: Value, next_keys: Vec<KeyAccess> },
299 Ops(Operator),
300 Primitive(Primitive),
301 VariableRef(String),
302 BuiltInFunction { fn_type: BuiltInFunctionType, params: Value },
303 IfExpr(Value),
304 FString(String, Vec<(String, Value)>),
305 WhileExpr(Value),
306 Array(Vec<Value>),
307 Struct(BTreeMap<String, Value>),
308 MultiDepthAccess { root: Value, keys: Vec<KeyAccess> },
309 Function(Value),
310 FunctionCall(Value),
311 Foreach(Value),
312 Null,
313}
314
315impl BuiltInFunctionType {
316 pub fn as_str(&self) -> &'static str {
317 match self {
318 BuiltInFunctionType::Sqrt => SQRT,
319 BuiltInFunctionType::Abs => ABS,
320 BuiltInFunctionType::Log => LOG,
321 BuiltInFunctionType::Ln => LN,
322 BuiltInFunctionType::Length => LENGTH,
323 BuiltInFunctionType::Sin => SIN,
324 BuiltInFunctionType::Cos => COS,
325 BuiltInFunctionType::Tan => TAN,
326 BuiltInFunctionType::TypeOf => TYPE_OF,
327 BuiltInFunctionType::IsMatch => IS_MATCH,
328 BuiltInFunctionType::Match => MATCH,
329 BuiltInFunctionType::Println => PRINT_LN,
330 BuiltInFunctionType::Print => PRINT,
331 BuiltInFunctionType::Eval => EVAL,
332 BuiltInFunctionType::Include => INCLUDE,
333 BuiltInFunctionType::Require => REQUIRE,
334 BuiltInFunctionType::ToInt => TO_INT,
335 BuiltInFunctionType::ToHex => TO_HEX,
336 BuiltInFunctionType::ToBinary => TO_BINARY,
337 BuiltInFunctionType::ToDouble => TO_DOUBLE,
338 BuiltInFunctionType::ToBool => TO_BOOL,
339 BuiltInFunctionType::ToUpper => TO_UPPER,
340 BuiltInFunctionType::ToLower => TO_LOWER,
341 BuiltInFunctionType::Capitalize => CAPITALIZE,
342 BuiltInFunctionType::Replace => REPLACE,
343 BuiltInFunctionType::ReplaceAll => REPLACE_ALL,
344 BuiltInFunctionType::Floor => FLOOR,
345 BuiltInFunctionType::Ceil => CEIL,
346 BuiltInFunctionType::Round => ROUND,
347 BuiltInFunctionType::ToString => TO_STRING,
348 BuiltInFunctionType::IsError => IS_ERROR,
349 BuiltInFunctionType::IsU8 => IS_U8,
350 BuiltInFunctionType::IsI8 => IS_I8,
351 BuiltInFunctionType::IsStruct => IS_STRUCT,
352 BuiltInFunctionType::IsBool => IS_BOOL,
353 BuiltInFunctionType::IsInt => IS_INT,
354 BuiltInFunctionType::IsDouble => IS_DOUBLE,
355 BuiltInFunctionType::IsFunction => IS_FUNCTION,
356 BuiltInFunctionType::IsArray => IS_ARRAY,
357 BuiltInFunctionType::MakeError => MAKE_ERROR,
358 BuiltInFunctionType::Jsonify => JSONIFY,
359 BuiltInFunctionType::ParseJson => PARSE_JSON,
360 }
361 }
362}
363impl Operator {
364 pub const fn as_str(&self) -> &'static str {
365 match self {
366 Operator::Add => "+",
367 Operator::Subtr => "-",
368 Operator::Div => "/",
369 Operator::Mult => "*",
370 Operator::Pow => "^",
371 Operator::Pow2 => "²",
372 Operator::Pow3 => "³",
373 Operator::Not => "!",
374 Operator::Mod => "%",
375 Operator::Less => "<",
376 Operator::Greater => ">",
377 Operator::LessOrEqual => "<=",
378 Operator::GreaterOrEqual => ">=",
379 Operator::Equal => "==",
380 Operator::NotEqual => "!=",
381 Operator::And => "&&",
382 Operator::Or => "||",
383 Operator::BitwiseNot => "~",
384 Operator::BitwiseAnd => "@",
385 Operator::BitwiseOr => "|",
386 Operator::BitwiseXor => "$",
387 Operator::BitwiseLShift => "<<",
388 Operator::BitwiseRShift => ">>",
389 }
390 }
391}
392
393pub const FORBIDDEN_VARIABLE_NAME: &[&str] = &[
394 TRUE,
395 FALSE,
396 TAU,
397 IF,
398 PI,
399 PRINT_LN,
400 PRINT,
401 LENGTH,
402 EULER_NUMBER,
403 ABS,
404 LOG,
405 TO_INT,
406 TO_DOUBLE,
407 TO_HEX,
408 CEIL,
409 ROUND,
410 FLOOR,
411 TO_UPPER,
412 TO_LOWER,
413 REPLACE,
414 REPLACE_ALL,
415 CAPITALIZE,
416 IS_MATCH,
417 MATCH,
418 TO_BINARY,
419 TO_STRING,
420 IS_FUNCTION,
421 IS_DOUBLE,
422 IS_INT,
423 IS_STRUCT,
424 IS_U8,
425 IS_ERROR,
426 IS_I8,
427 IS_BOOL,
428 IS_ARRAY,
429 MAKE_ERROR,
430 JSONIFY,
431 PARSE_JSON,
432 EVAL,
433 TO_BOOL,
434 SQRT,
435 BREAK,
436 NULL,
437 FOR,
438 IN,
439 DROP,
440 RETURN,
442 LN,
443 SIN,
444 COS,
445 TYPE_OF,
446 TAN,
447 INCLUDE,
448 WHILE,
449 ELSE,
450 REQUIRE,
451 MULTILINE,
452 STRUCT,
453 Operator::Add.as_str(),
454 Operator::Subtr.as_str(),
455 Operator::Div.as_str(),
456 Operator::Mult.as_str(),
457 Operator::Pow.as_str(),
458 Operator::Pow2.as_str(),
459 Operator::Pow3.as_str(),
460 Operator::Not.as_str(),
461 Operator::Mod.as_str(),
462 Operator::Less.as_str(),
463 Operator::Greater.as_str(),
464 Operator::LessOrEqual.as_str(),
465 Operator::GreaterOrEqual.as_str(),
466 Operator::Equal.as_str(),
467 Operator::NotEqual.as_str(),
468 Operator::And.as_str(),
469 Operator::Or.as_str(),
470 Operator::BitwiseNot.as_str(),
471 Operator::BitwiseAnd.as_str(),
472 Operator::BitwiseOr.as_str(),
473 Operator::BitwiseXor.as_str(),
474 Operator::BitwiseLShift.as_str(),
475 Operator::BitwiseRShift.as_str(),
476];