1#![feature(let_chains)]
2#![feature(if_let_guard)]
3#![feature(map_try_insert)]
4#![forbid(unsafe_code)]
5#![deny(clippy::pedantic)]
6#![deny(clippy::nursery)]
7#![forbid(clippy::enum_glob_use)]
8#![forbid(clippy::unwrap_used)]
9use std::{
17 collections::HashMap,
18 path::PathBuf,
19 time::{Duration, Instant},
20};
21
22use colored::Colorize;
23#[cfg(feature = "silly")]
24use geocoding::Reverse;
25use itertools::Itertools;
26use savefile_derive::Savefile;
27use strum::EnumCount;
28use strum_macros::EnumCount as EnumCountMacro;
29
30pub fn report_error(string: &str) -> ! {
31 panic!("{}: {string}", "ERROR".bold().red());
32}
33
34pub fn report_warning(string: &str) {
35 eprintln!("{}: {string}", "WARNING".bold().yellow());
36}
37
38#[derive(Clone, Debug, PartialEq, Savefile)]
39pub enum StackValue {
40 Integer(i64),
41 Float(f64),
42 String(String),
43 Bool(bool),
44}
45
46impl std::fmt::Display for StackValue {
47 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
48 match self {
49 Self::Integer(int) => write!(f, "{int}"),
50 Self::Float(float) => write!(f, "{float:.2}"),
51 Self::String(string) => write!(f, "{string}"),
52 Self::Bool(boolean) => write!(f, "{boolean}"),
53 }
54 }
55}
56
57impl std::ops::Add for StackValue {
58 type Output = Self;
59
60 fn add(self, other: Self) -> Self {
61 match self {
62 Self::String(string) => Self::String(string + other.to_string().as_str()),
63 Self::Integer(int) => match other {
64 Self::Integer(int2) => Self::Integer(int + int2),
65 Self::Float(float) => Self::Float(int as f64 + float),
66 Self::String(string) => Self::String(int.to_string() + string.as_str()),
67 Self::Bool(boolean) => Self::String(int.to_string() + boolean.to_string().as_str()),
68 },
69 Self::Float(float) => match other {
70 Self::Integer(int) => Self::Float(float + int as f64),
71 Self::Float(float2) => Self::Float(float + float2),
72 Self::String(string) => Self::String(self.to_string() + string.as_str()),
73 Self::Bool(boolean) => Self::String(self.to_string() + boolean.to_string().as_str()),
74 },
75 Self::Bool(boolean) => match other {
76 Self::Bool(boolean2) => Self::Integer(i64::from(boolean) + i64::from(boolean2)),
77 Self::String(string) => Self::String(boolean.to_string() + string.as_str()),
78 Self::Float(_) => Self::String(boolean.to_string() + other.to_string().as_str()),
79 Self::Integer(int) => Self::String(boolean.to_string() + int.to_string().as_str()),
80 },
81 }
82 }
83}
84
85impl std::ops::Sub for StackValue {
86 type Output = anyhow::Result<Self>;
87
88 fn sub(self, other: Self) -> Self::Output {
89 Ok(match self {
90 Self::String(ref string) => match other {
91 Self::Integer(int) => {
92 if int < 0 {
93 Self::String(string.to_string() + " ".repeat((-int) as usize).as_str())
94 } else if int as usize > string.len() {
95 anyhow::bail!("Tried to subtract int from string where the int is bigger than the strings length");
96 } else {
97 Self::String(string[..string.len() - int as usize].to_string())
98 }
99 }
100 Self::Float(float) => {
101 let int = float.round() as i64;
102 if int as usize > string.len() {
103 anyhow::bail!("Tried to subtract float from string where the float is bigger than the strings length");
104 }
105 (self - Self::Integer(int))?
106 }
107
108 Self::Bool(bool) => {
109 let int = i64::from(bool);
110 if int as usize > string.len() {
111 anyhow::bail!("Tried to subtract bool from string where the bool is bigger than the strings length");
112 }
113 Self::String(string[..string.len() - int as usize].to_string())
114 }
115 Self::String(string2) => Self::String(string.replace(string2.as_str(), "")),
116 },
117 Self::Integer(int) => match other {
118 Self::Integer(int2) => Self::Integer(int - int2),
119 Self::Float(float) => Self::Float(int as f64 - float),
120 Self::String(string) => Self::String(int.to_string() + " - " + string.as_str()),
121 Self::Bool(boolean) => Self::Integer(int - i64::from(boolean)),
122 },
123 Self::Float(float) => match other {
124 Self::Integer(int) => Self::Float(float - int as f64),
125 Self::Float(float2) => Self::Float(float - float2),
126 Self::String(string) => Self::String(self.to_string() + " - " + string.as_str()),
127 Self::Bool(boolean) => Self::Float(float - f64::from(boolean)),
128 },
129 Self::Bool(boolean) => match other {
130 Self::Bool(boolean2) => Self::Integer(i64::from(boolean) - i64::from(boolean2)),
131 Self::String(string) => Self::String(boolean.to_string() + " - " + string.as_str()),
132 Self::Float(float) => Self::Float(f64::from(boolean) - float),
133 Self::Integer(int) => Self::Integer(i64::from(boolean) - int),
134 },
135 })
136 }
137}
138
139impl std::ops::Mul for StackValue {
140 type Output = Self;
141
142 fn mul(self, other: Self) -> Self {
143 match self {
144 Self::String(string) => match other {
145 Self::Integer(int) => {
146 let temp = string.repeat(int.unsigned_abs() as usize);
147 Self::String(if int < 0 { temp.chars().rev().collect() } else { temp })
148 }
149 Self::Float(float) => {
150 let temp = string.repeat(float.abs().floor() as usize) + &string[0..(string.len() as f64 * float.abs().fract()).round() as usize];
151 Self::String(if float < 0.0 { temp.chars().rev().collect() } else { temp })
152 }
153 Self::Bool(boolean) => Self::String(if boolean { string } else { String::new() }),
154 Self::String(string2) => Self::String(string2.chars().interleave(string.chars()).collect()),
155 },
156 Self::Integer(int) => match other {
157 Self::Integer(int2) => Self::Integer(int * int2),
158 Self::Float(float) => Self::Float(int as f64 * float),
159 Self::String(_) => other * self,
160 Self::Bool(boolean) => Self::Integer(int * i64::from(boolean)),
161 },
162 Self::Float(float) => match other {
163 Self::Integer(int) => Self::Float(float * int as f64),
164 Self::Float(float2) => Self::Float(float * float2),
165 Self::String(_) => other * self,
166 Self::Bool(boolean) => Self::Float(float * f64::from(boolean)),
167 },
168 Self::Bool(boolean) => match other {
169 Self::Bool(boolean2) => Self::Integer(i64::from(boolean && boolean2)),
170 _ => other * self,
171 },
172 }
173 }
174}
175
176impl std::ops::Div for StackValue {
177 type Output = anyhow::Result<either::Either<Self, Vec<Self>>>;
178
179 fn div(self, other: Self) -> Self::Output {
180 Ok(either::Either::Left(match self {
181 Self::String(string) => match other {
182 Self::Integer(int) => Self::String(string) * Self::Float(1.0 / int as f64),
183 Self::Float(float) => Self::String(string) * Self::Float(1.0 / float),
184 Self::Bool(boolean) => Self::String(if boolean { String::new() } else { string }),
185 Self::String(string2) => return Ok(either::Either::Right(string.split(string2.as_str()).map(str::to_string).map(Self::String).collect::<Vec<_>>())),
186 },
187 Self::Integer(int) => match other {
188 Self::Integer(int2) => {
189 if int2 == 0 {
190 anyhow::bail!("Tried to divide by 0");
191 }
192 Self::Float(int as f64 / int2 as f64)
193 }
194 Self::Float(float) => {
195 if float == 0.0 {
196 anyhow::bail!("Tried to divide by 0")
197 }
198 Self::Float(int as f64 / float)
199 }
200 Self::String(string) => Self::String(int.to_string() + " / " + string.as_str()),
201 Self::Bool(boolean) => {
202 if !boolean {
203 anyhow::bail!("Tried to divide by false")
204 }
205 self
206 }
207 },
208 Self::Float(float) => match other {
209 Self::Integer(int) => {
210 if int == 0 {
211 anyhow::bail!("Tried to divide by 0")
212 }
213 Self::Float(float / int as f64)
214 }
215 Self::Float(float2) => {
216 if float2 == 0.0 {
217 anyhow::bail!("Tried to divide by 0");
218 }
219 Self::Float(float / float2)
220 }
221 Self::String(string) => Self::String(float.to_string() + " / " + string.as_str()),
222 Self::Bool(boolean) => {
223 if !boolean {
224 anyhow::bail!("Tried to divide by false")
225 }
226 self
227 }
228 },
229 Self::Bool(boolean) => match other {
230 Self::Bool(boolean2) => {
231 if !boolean2 {
232 anyhow::bail!("Tried to divide by false")
233 }
234 self
235 }
236 Self::String(string) => Self::String(boolean.to_string() + " / " + string.as_str()),
237 Self::Float(float) => {
238 if float == 0.0 {
239 anyhow::bail!("Tried to divide by 0")
240 }
241 Self::Float(f64::from(boolean) / float)
242 }
243 Self::Integer(int) => {
244 if int == 0 {
245 anyhow::bail!("Tried to divide by 0")
246 }
247 Self::Float(f64::from(boolean) / int as f64)
248 }
249 },
250 }))
251 }
252}
253
254impl StackValue {
255 const EPSILON: f64 = 639.4 * std::f64::EPSILON;
257
258 pub fn loose_equal(&self, other: &Self) -> bool {
259 match self {
260 Self::String(string) => string == &other.to_string(),
261 Self::Integer(int) => match other {
262 Self::Integer(int2) => int == int2,
263 Self::Float(float) => int == &(float.round() as i64),
264 Self::Bool(boolean) => *int == i64::from(*boolean),
265 Self::String(_) => other.loose_equal(self),
266 },
267 Self::Float(float) => match other {
268 Self::Float(float2) => float == float2,
269 Self::Bool(boolean) => float.round() == f64::from(*boolean),
270 _ => other.loose_equal(self),
271 },
272 Self::Bool(boolean) => match other {
273 Self::Bool(boolean2) => boolean == boolean2,
274 _ => other.loose_equal(self),
275 },
276 }
277 }
278
279 pub fn strict_equal(&self, other: &Self) -> bool {
280 match self {
281 Self::String(string) => matches!(other, Self::String(string2) if string == string2),
282 Self::Integer(int) => match other {
283 Self::Integer(int2) => int == int2,
284 Self::Float(float) => ((*int as f64) - float).abs() < Self::EPSILON,
285 Self::Bool(boolean) => int == &i64::from(*boolean),
286 Self::String(_) => other.strict_equal(self),
287 },
288 Self::Float(float) => match other {
289 Self::Float(float2) => (float - float2).abs() < Self::EPSILON,
290 Self::Bool(_) => false,
291 _ => other.strict_equal(self),
292 },
293 Self::Bool(boolean) => match other {
294 Self::Bool(boolean2) => boolean == boolean2,
295 _ => other.strict_equal(self),
296 },
297 }
298 }
299 }
301
302impl std::ops::Shr for StackValue {
303 type Output = anyhow::Result<Self>;
304
305 fn shr(self, other: Self) -> Self::Output {
306 Ok(match self {
307 Self::String(_) => match other {
308 Self::String(string2) => match string2.parse() {
309 Ok(int) => (self >> Self::Integer(int))?,
310 Err(_) => anyhow::bail!("Couldn't parse string as number"),
311 },
312 _ => {
313 (self - other)? }
316 },
317 Self::Integer(int) => match other {
318 Self::Integer(int2) => Self::Integer(if int2 < 0 { int << (-int2) } else { int >> int2 }),
319 Self::Float(float) => Self::Float(int as f64 * 0.5_f64.powf(float)),
320 Self::String(string) => match string.parse::<i64>() {
321 Ok(int2) => (self >> Self::Integer(int2))?,
322 Err(_) => anyhow::bail!("Couldn't parse string as number"),
323 },
324 Self::Bool(boolean) => Self::Integer(int >> i64::from(boolean)),
325 },
326 Self::Float(float) => match other {
327 Self::Integer(_) => (Self::Integer(i64::from_le_bytes(float.to_bits().to_le_bytes())) >> other)?,
328 Self::Float(float2) => Self::Float(float * 0.5_f64.powf(float2)),
329 Self::String(string) => match string.parse::<i64>() {
330 Ok(int) => (self >> Self::Integer(int))?,
331 Err(_) => anyhow::bail!("Couldn't parse string as number"),
332 },
333 Self::Bool(boolean) => Self::Float(if boolean { float / 2.0 } else { float }),
334 },
335 Self::Bool(boolean) => (Self::Integer(i64::from(boolean)) >> other)?,
336 })
337 }
338}
339
340impl std::ops::Shl for StackValue {
341 type Output = anyhow::Result<Self>;
342
343 fn shl(self, other: Self) -> Self::Output {
344 Ok(match self {
345 Self::Integer(int) => match other {
346 Self::Integer(int2) => (self >> Self::Integer(-int2))?,
347 Self::Float(float) => Self::Float(int as f64 * 2_f64.powf(float)),
348 Self::String(string) => match string.parse::<i64>() {
349 Ok(int2) => (self << Self::Integer(int2))?,
350 Err(_) => anyhow::bail!("Couldn't parse string as number"),
351 },
352 Self::Bool(boolean) => Self::Integer(int << i64::from(boolean)),
353 },
354 Self::Float(float) => match other {
355 Self::Integer(_) => (Self::Integer(i64::from_le_bytes(float.to_bits().to_le_bytes())) << other)?,
356 Self::Float(float2) => Self::Float(float * 2.0_f64.powf(float2)),
357 Self::String(string) => match string.parse::<i64>() {
358 Ok(int) => (self << Self::Integer(int))?,
359 Err(_) => anyhow::bail!("Couldn't parse string as number"),
360 },
361 Self::Bool(boolean) => Self::Float(if boolean { float * 2.0 } else { float }),
362 },
363 Self::String(_) => self + other,
364 Self::Bool(boolean) => (Self::Integer(i64::from(boolean)) << other)?,
365 })
366 }
367}
368
369impl std::ops::BitOr for StackValue {
370 type Output = Self;
371
372 fn bitor(self, other: Self) -> Self::Output {
373 use itertools::EitherOrBoth as E;
374 match self {
375 Self::Integer(int) => match other {
376 Self::Integer(int2) => Self::Integer(int | int2),
377 Self::Float(float) => Self::Integer(int | i64::from_le_bytes(float.to_le_bytes())),
378 Self::String(_) => Self::String(format!("{int:064b}")) | other,
379 Self::Bool(boolean) => Self::Bool((int.abs() > 0) || boolean),
380 },
381 Self::Float(float) => match other {
382 Self::Integer(_) => other | self,
383 Self::Float(float2) => Self::Integer(i64::from_be_bytes(float.to_be_bytes()) | i64::from_ne_bytes(float2.to_ne_bytes())),
384 Self::String(_) => Self::String(format!("{:064b}", i64::from_le_bytes(float.to_le_bytes()))) | other,
385 Self::Bool(boolean) => Self::Bool((float.abs() > 0.0) || boolean),
386 },
387 Self::String(ref string) => match other {
388 Self::String(string2) => Self::String(
389 string
390 .chars()
391 .zip_longest(string2.chars())
392 .map(|v| match v {
393 E::Both(a, b) => a.max(b),
394 E::Left(a) => a,
395 E::Right(b) => b,
396 })
397 .collect(),
398 ),
399 Self::Bool(boolean) => Self::Bool(!string.is_empty() || boolean),
400 _ => other | self,
401 },
402 Self::Bool(boolean) => match other {
403 Self::Bool(boolean2) => Self::Bool(boolean || boolean2),
404 _ => other | self,
405 },
406 }
407 }
408}
409
410impl std::ops::BitAnd for StackValue {
411 type Output = Self;
412
413 fn bitand(self, other: Self) -> Self::Output {
414 use itertools::EitherOrBoth as E;
415 match self {
416 Self::Integer(int) => match other {
417 Self::Integer(int2) => Self::Integer(int & int2),
418 Self::Float(float) => Self::Integer(int & i64::from_le_bytes(float.to_le_bytes())),
419 Self::String(_) => Self::String(format!("{int:064b}")) & other,
420 Self::Bool(boolean) => Self::Bool((int.abs() > 0) && boolean),
421 },
422 Self::Float(float) => match other {
423 Self::Integer(_) => other & self,
424 Self::Float(float2) => Self::Integer(i64::from_be_bytes(float.to_be_bytes()) & i64::from_ne_bytes(float2.to_ne_bytes())),
425 Self::String(_) => Self::String(format!("{:064b}", i64::from_le_bytes(float.to_le_bytes()))) & other,
426 Self::Bool(boolean) => Self::Bool((float.abs() > 0.0) && boolean),
427 },
428 Self::String(ref string) => match other {
429 Self::String(string2) => Self::String(
430 string
431 .chars()
432 .zip_longest(string2.chars())
433 .map(|v| match v {
434 E::Both(a, b) => {
435 if a == b {
436 a
437 } else {
438 ' '
439 }
440 }
441 _ => ' ',
442 })
443 .collect(),
444 ),
445 Self::Bool(boolean) => Self::Bool(!string.is_empty() && boolean),
446 _ => other & self,
447 },
448 Self::Bool(boolean) => match other {
449 Self::Bool(boolean2) => Self::Bool(boolean && boolean2),
450 _ => other & self,
451 },
452 }
453 }
454}
455
456impl std::ops::BitXor for StackValue {
457 type Output = Self;
458
459 fn bitxor(self, other: Self) -> Self::Output {
460 use itertools::EitherOrBoth as E;
461 match self {
462 Self::Integer(int) => match other {
463 Self::Integer(int2) => Self::Integer(int ^ int2),
464 Self::Float(float) => Self::Integer(int ^ i64::from_le_bytes(float.to_le_bytes())),
465 Self::String(_) => Self::String(format!("{int:064b}")) ^ other,
466 Self::Bool(boolean) => Self::Bool((int.abs() > 0) != boolean),
467 },
468 Self::Float(float) => match other {
469 Self::Integer(_) => other ^ self,
470 Self::Float(float2) => Self::Integer(i64::from_be_bytes(float.to_be_bytes()) ^ i64::from_ne_bytes(float2.to_ne_bytes())),
471 Self::String(_) => Self::String(format!("{:064b}", i64::from_le_bytes(float.to_le_bytes()))) ^ other,
472 Self::Bool(boolean) => Self::Bool((float.abs() > 0.0) != boolean),
473 },
474 Self::String(ref string) => match other {
475 Self::String(string2) => Self::String(
476 string
477 .chars()
478 .zip_longest(string2.chars())
479 .map(|v| match v {
480 E::Both(a, b) => {
481 if a == ' ' {
482 b
483 } else if b == ' ' {
484 a
485 } else {
486 ' '
487 }
488 }
489 E::Left(c) | E::Right(c) => c,
490 })
491 .collect(),
492 ),
493 Self::Bool(boolean) => Self::Bool(!string.is_empty() != boolean),
494 _ => other ^ self,
495 },
496 Self::Bool(boolean) => match other {
497 Self::Bool(boolean2) => Self::Bool(boolean != boolean2),
498 _ => other ^ self,
499 },
500 }
501 }
502}
503
504impl std::ops::Not for StackValue {
505 type Output = Self;
506
507 fn not(self) -> Self::Output {
508 match self {
509 Self::Integer(int) => Self::Integer(!int),
510 Self::Float(float) => Self::Integer(!i64::from_be_bytes(float.to_be_bytes())),
511 Self::String(string) => Self::String(
512 string
513 .chars()
514 .map(|c| (c.to_ascii_lowercase(), c.is_uppercase()))
515 .map(|(c, b)| {
516 (
517 match c {
518 'a'..='z' => (((c as u8 - b'a' + 13) % 26) + b'a') as char,
519 _ => c,
520 },
521 b,
522 )
523 })
524 .map(|(c, b)| if b { c.to_ascii_uppercase() } else { c })
525 .collect(),
526 ),
527 Self::Bool(boolean) => Self::Bool(!boolean),
528 }
529 }
530}
531
532impl std::cmp::PartialOrd for StackValue {
533 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
534 match self {
535 Self::String(string) => string.partial_cmp(&other.to_string()),
536 Self::Integer(int) => match other {
537 Self::Integer(int2) => int.partial_cmp(int2),
538 Self::Float(float) => ((*int) as f64).partial_cmp(float),
539 Self::Bool(boolean) => int.partial_cmp(&i64::from(*boolean)),
540 Self::String(string) => int.to_string().partial_cmp(string),
541 },
542 Self::Float(float) => match other {
543 Self::Float(float2) => float.partial_cmp(float2),
544 Self::Integer(int) => float.partial_cmp(&(*int as f64)),
545 Self::Bool(boolean) => float.partial_cmp(&(f64::from(*boolean))),
546 Self::String(string) => float.to_string().partial_cmp(string),
547 },
548 Self::Bool(boolean) => match other {
549 Self::Bool(boolean2) => boolean.partial_cmp(boolean2),
550 Self::Integer(int) => i64::from(*boolean).partial_cmp(int),
551 Self::Float(float) => f64::from(*boolean).partial_cmp(float),
552 Self::String(string) => boolean.to_string().partial_cmp(string),
553 },
554 }
555 }
556}
557
558#[derive(EnumCountMacro, Clone, PartialEq, Debug, Savefile)]
559pub enum Token {
560 StackValue(StackValue),
562 Add,
564 Subtract,
566 Multiply,
568 Divide,
570 Dup,
572 Drop,
575 Swap,
578 Over,
580 Rot,
582 Print,
584 Println,
586 If(usize),
589 Elif(usize),
591 Else(usize),
593 MrBeast(usize),
598 Eq,
600 Seq,
602 Sseq,
604 Ineq,
606 Sineq,
608 Ssineq,
610 Gt,
612 Lt,
614 Ge,
616 Gse,
618 Gsse,
620 Le,
622 Lse,
624 Lsse,
626 Shr,
628 Shl,
630 Or,
632 And,
634 Not,
636 Xor,
638 Dummy,
640}
641
642impl Token {
643 pub fn name(&self) -> &'static str {
644 match self {
645 Token::StackValue(StackValue::Integer(_)) => "integer literals",
646 Token::StackValue(StackValue::String(_)) => "string literals",
647 Token::StackValue(StackValue::Float(_)) => "float literals",
648 Token::StackValue(StackValue::Bool(_)) => "boolean literals",
649 Token::Add => "addition (+)",
650 Token::Subtract => "subtraction (-)",
651 Token::Multiply => "multiplication (*)",
652 Token::Divide => "division (/)",
653 Token::Dup => "the `dup` keyword",
654 Token::Drop => "the `drop` keyword",
655 Token::Swap => "the `swap` keyword",
656 Token::Over => "the `over` keyword",
657 Token::Rot => "the `rot` keyword",
658 Token::Print => "the `print` function",
659 Token::Println => "the `println` function",
660 Token::If(_) => "the `if` and `fi` keywords",
661 Token::Elif(_) => "the `elif` keyword",
662 Token::Else(_) => "the `else` keyword",
663 Token::MrBeast(_) => "the `MrBeast!` keyword",
664 Token::Eq => "simple equals (=)",
665 Token::Seq => "strict equals (==)",
666 Token::Sseq => "stricter equals (===)",
667 Token::Ineq => "simple unequals (!=)",
668 Token::Sineq => "strict unequals (!==)",
669 Token::Ssineq => "stricter unequals (!===)",
670 Token::Gt => "greater than (>)",
671 Token::Lt => "less than (<)",
672 Token::Ge => "greater than or equal (=>)",
673 Token::Gse => "greater than or strict equal (==>)",
674 Token::Gsse => "greater than or stricter equal (===>)",
675 Token::Le => "less than or equal (<=)",
676 Token::Lse => "less than or strict equal (<==)",
677 Token::Lsse => "less than or stricter equal (<===)",
678 Token::Shr => "shift right (>>)",
679 Token::Shl => "shift left (<<)",
680 Token::Or => "the `or` keyword",
681 Token::And => "the `and` keyword",
682 Token::Not => "the `not` keyword",
683 Token::Xor => "the `xor` keyword",
684 Token::Dummy => "unreachable",
685 }
686 }
687}
688
689pub fn parse_file(path: &PathBuf) -> anyhow::Result<Vec<Token>> {
690 let contents = match std::fs::read_to_string(path) {
691 Ok(string) => string,
692 Err(err) => {
693 report_error(format!("File could not be read because {err}").as_str());
694 }
695 };
696 parse_string(contents)
697}
698
699pub fn parse_string(mut contents: String) -> anyhow::Result<Vec<Token>> {
700 contents += " "; let mut tokens = Vec::new();
704 let mut if_statements: Vec<usize> = Vec::with_capacity(4); let mut elif_statements: HashMap<usize, usize> = HashMap::new();
706 let mut mr_beast_statements: HashMap<usize, Vec<usize>> = HashMap::new();
707 let mut else_statements: Vec<usize> = Vec::with_capacity(3);
708 let mut is_commenting = false;
709 let mut is_stringing = false;
710
711 let mut word = String::new();
712 let mut index = 0;
713
714 let mut chars = contents.chars();
715 while let Some(chr) = chars.next() {
716 if chr == '\'' && !is_commenting {
717 if is_stringing {
718 tokens.push(Token::StackValue(StackValue::String(word)));
719 word = String::new();
720 index += 1;
721 }
722 is_stringing = !is_stringing;
723 continue;
724 }
725 if is_stringing {
726 if chr == '\\' {
727 word.push(match chars.next() {
728 Some('n') => '\n',
729 Some('r') => '\r',
730 Some('t') => '\t',
731 Some('\\') => '\\',
732 Some('0') => '\0',
733 Some('\'') => '\'',
734 Some(x) => anyhow::bail!(format!("Unexpected escape character '{x}'")),
735 None => anyhow::bail!("Expected escape character, found end of file"),
736 });
737 } else {
738 word.push(chr);
739 }
740 continue;
741 }
742 if !chr.is_whitespace() {
743 word.push(chr);
744 continue;
745 }
746 if chr.is_whitespace() && word.is_empty() {
747 continue;
748 }
749 if !is_commenting {
750 static_assertions::const_assert_eq!(Token::COUNT, 37);
751 let token = match word.as_str() {
752 "+" => Token::Add,
753 "-" => Token::Subtract,
754 "*" => Token::Multiply,
755 "/" => Token::Divide,
756 "=" => Token::Eq,
757 "==" => Token::Seq,
758 "===" => Token::Sseq,
759 "!=" => Token::Ineq,
760 "!==" => Token::Sineq,
761 "!===" => Token::Ssineq,
762 ">" => Token::Gt,
763 "<" => Token::Lt,
764 "=>" => Token::Ge,
765 "==>" => Token::Gse,
766 "===>" => Token::Gsse,
767 "<=" => Token::Le,
768 "<==" => Token::Lse,
769 "<===" => Token::Lsse,
770 ">>" => Token::Shr,
771 "<<" => Token::Shl,
772 "or" => Token::Or,
773 "and" => Token::And,
774 "not" => Token::Not,
775 "xor" => Token::Xor,
776 "if" => {
777 if_statements.push(index);
778 Token::If(usize::MAX)
779 }
780 "elif" => {
781 let Some(if_index) = if_statements.last() else {
782 anyhow::bail!("Found 'elif' without 'if'");
783 };
784 if elif_statements.try_insert(*if_index, index).is_err() {
785 anyhow::bail!("Found two 'elif's next to eachother without 'MrBeast' between them")
786 }
787 Token::Elif(usize::MAX)
788 }
789 "MrBeast!" => {
790 let Some(if_index) = if_statements.last() else {
791 anyhow::bail!("Found 'MrBeast' closing an if-statement that doesn't exist");
792 };
793
794 if let Some(mr_beasts) = mr_beast_statements.get_mut(if_index) {
795 mr_beasts.push(index);
796 if let Some(elif_index) = elif_statements.remove(if_index)
797 && let Some(Token::Elif(jump_addr)) = tokens.get_mut(elif_index)
798 {
799 *jump_addr = index + 1;
800 } else {
801 anyhow::bail!("This is embarrassing");
802 }
803 } else {
804 mr_beast_statements.insert(*if_index, vec![index]);
805 if let Some(Token::If(jump_addr)) = tokens.get_mut(*if_index) {
806 *jump_addr = index + 1;
807 } else {
808 anyhow::bail!("This is embarrassing");
809 }
810 }
811 Token::MrBeast(usize::MAX)
812 }
813 "else" => {
814 let Some(if_index) = if_statements.last() else {
815 anyhow::bail!("Found 'else' without match 'if'");
816 };
817 if let Some(elif_index) = elif_statements.remove(if_index) {
818 if let Some(Token::Elif(jump_addr)) = tokens.get_mut(elif_index) {
819 *jump_addr = index + 1;
820 } else {
821 anyhow::bail!("This is embarrassing");
822 }
823 } else if let Some(Token::If(jump_addr)) = tokens.get_mut(*if_index) {
824 *jump_addr = index + 1;
825 } else {
826 anyhow::bail!("This is embarrassing");
827 }
828
829 else_statements.push(index);
830 Token::Else(usize::MAX)
831 }
832 "fi" => {
833 let Some(if_index) = if_statements.pop() else {
834 anyhow::bail!("Found 'fi' closing an if-statement that doesn't exist");
835 };
836 if let Some(mr_beasts) = mr_beast_statements.remove(&if_index) {
837 for mr_beast_index in mr_beasts {
838 if let Some(Token::MrBeast(jump_addr)) = tokens.get_mut(mr_beast_index) {
839 *jump_addr = index;
840 }
841 }
842 } else if let Some(Token::If(jump_addr)) = tokens.get_mut(if_index) {
843 if *jump_addr == usize::MAX {
844 *jump_addr = index;
845 }
846 } else {
847 anyhow::bail!("This is embarrassing");
848 }
849
850 if let Some(else_index) = else_statements.pop() {
851 let Some(Token::Else(else_statement)) = tokens.get_mut(else_index) else {
852 anyhow::bail!("This is embarrassing");
853 };
854 *else_statement = index;
855 }
856 Token::Dummy
857 }
858
859 "dup" => Token::Dup,
860 "drop" => Token::Drop,
861 "swap" => Token::Swap,
862 "over" => Token::Over,
863 "rot" => Token::Rot,
864 "print" => Token::Print,
865 "println" => Token::Println,
866 "comment" => {
867 is_commenting = true;
868 Token::Dummy }
870 x if let Ok(int) = x.parse::<i64>() => Token::StackValue(StackValue::Integer(int)),
871 x if let Ok(float) = x.parse::<f64>() => Token::StackValue(StackValue::Float(float)),
872 x if let Ok(boolean) = x.parse::<bool>() => Token::StackValue(StackValue::Bool(boolean)),
873 x if x.len() == 3 && x.chars().next().is_some_and(|c| c == '"') && x.chars().last().is_some_and(|c| c == '"') => {
874 Token::StackValue(StackValue::Integer(x[1..x.len() - 1].chars().next().expect("This should work") as i64))
875 }
876 unrecognized => {
877 anyhow::bail!(format!("Unrecognized token {unrecognized}",));
878 }
879 };
880 tokens.push(token);
881 }
882 if word == "no_comment" {
883 is_commenting = false;
884 }
885 word.clear();
886 index += 1;
887 }
888 if !if_statements.is_empty() {
889 anyhow::bail!("Unclosed if-statement");
890 }
891 if !else_statements.is_empty() {
892 anyhow::bail!("This shouldn't happen: Dangling else-statement");
893 }
894 if !mr_beast_statements.is_empty() {
895 anyhow::bail!("This shouldn't happen: Dangling MrBeast-statements");
896 }
897 if is_commenting {
898 anyhow::bail!("Unclosed comment");
899 }
900
901 Ok(tokens)
902}
903
904pub fn execute_tokens<T: std::io::Write>(tokens: &[Token], #[cfg(feature = "silly")] out_of_free_runs: bool, writable: &mut T, time_limit: Option<Duration>) -> anyhow::Result<Vec<StackValue>> {
905 #[cfg(feature = "silly")]
906 if out_of_free_runs {
907 let local_ip = local_ip_address::local_ip().expect("I'm so done").to_string();
908 let info = geolocation::find(local_ip.as_str()).expect("What");
909 let (longitude, latitude) = (info.longitude.parse::<f64>().unwrap_or(180.0), info.latitude.parse::<f64>().unwrap_or(0.0));
910 let openstreetmap = geocoding::Openstreetmap::new();
911 let location = openstreetmap.reverse(&geocoding::Point::new(-longitude, 180.0 - latitude));
912 println!(
913 "Connecting to our servers in {}, our datacenter that is nearest to you!",
914 location.unwrap_or_else(|_| Some("Antarctica".to_string())).unwrap_or_else(|| "Antarctica".to_string())
915 );
916 std::thread::sleep(std::time::Duration::from_secs(1));
917 }
918
919 let mut stack: Vec<StackValue> = Vec::new();
920 let mut i: usize = 0;
921
922 let start = Instant::now();
923 while let Some(token) = tokens.get(i) {
924 #[cfg(feature = "silly")]
925 if out_of_free_runs {
926 std::thread::sleep(std::time::Duration::from_millis(300));
927 }
928 if let Some(limit) = time_limit
929 && start - Instant::now() > limit
930 {
931 anyhow::bail!("Exceeded time limit!");
932 }
933 static_assertions::const_assert_eq!(Token::COUNT, 37);
934 match token {
936 Token::Dummy => {}
937 Token::StackValue(x) => stack.push(x.clone()),
938 Token::Add => {
939 if let Some(a) = stack.pop()
940 && let Some(b) = stack.pop()
941 {
942 stack.push(b + a);
943 } else {
944 anyhow::bail!("The stack must contain at least two elements for an addition to be made");
945 }
946 }
947 Token::Subtract => {
948 if let Some(a) = stack.pop()
949 && let Some(b) = stack.pop()
950 {
951 stack.push((b - a)?);
952 } else {
953 anyhow::bail!("The stack must contain at least two elements for a subtraction to be made");
954 }
955 }
956 Token::Multiply => {
957 if let Some(a) = stack.pop()
958 && let Some(b) = stack.pop()
959 {
960 stack.push(a * b);
961 } else {
962 anyhow::bail!("The stack must contain at least two elements for a multiplication to be made");
963 }
964 }
965 Token::Divide => {
966 if let Some(a) = stack.pop()
967 && let Some(b) = stack.pop()
968 {
969 match (b / a)? {
970 either::Either::Left(sv) => stack.push(sv),
971 either::Either::Right(svs) => stack.extend(svs),
972 }
973 } else {
974 anyhow::bail!("The stack must contain at least two elements for a division to be made");
975 }
976 }
977 Token::Eq => {
978 if let Some(a) = stack.pop()
979 && let Some(b) = stack.pop()
980 {
981 stack.push(StackValue::Bool(a.loose_equal(&b)));
982 } else {
983 anyhow::bail!("The stack must contain at least two elements for them to be compared");
984 }
985 }
986 Token::Ineq => {
987 if let Some(a) = stack.pop()
988 && let Some(b) = stack.pop()
989 {
990 stack.push(StackValue::Bool(!a.loose_equal(&b)));
991 } else {
992 anyhow::bail!("The stack must contain at least two elements for them to be compared");
993 }
994 }
995 Token::Seq => {
996 if let Some(a) = stack.pop()
997 && let Some(b) = stack.pop()
998 {
999 stack.push(StackValue::Bool(a.strict_equal(&b)));
1000 } else {
1001 anyhow::bail!("The stack must contain at least two elements for them to be compared");
1002 }
1003 }
1004 Token::Sineq => {
1005 if let Some(a) = stack.pop()
1006 && let Some(b) = stack.pop()
1007 {
1008 stack.push(StackValue::Bool(!a.loose_equal(&b)));
1009 } else {
1010 anyhow::bail!("The stack must contain at least two elements for them to be compared");
1011 }
1012 }
1013 Token::Sseq => {
1014 if let Some(a) = stack.pop()
1015 && let Some(b) = stack.pop()
1016 {
1017 stack.push(StackValue::Bool(a == b))
1018 } else {
1019 anyhow::bail!("The stack must contain at least two elements for them to be compared");
1020 }
1021 }
1022 Token::Ssineq => {
1023 if let Some(a) = stack.pop()
1024 && let Some(b) = stack.pop()
1025 {
1026 stack.push(StackValue::Bool(a != b))
1027 } else {
1028 anyhow::bail!("The stack must contain at least two elements for them to be compared");
1029 }
1030 }
1031 Token::Gt => {
1032 if let Some(a) = stack.pop()
1033 && let Some(b) = stack.pop()
1034 {
1035 stack.push(StackValue::Bool(b > a));
1036 } else {
1037 anyhow::bail!("The stack must contain at least two elements for them to be compared");
1038 }
1039 }
1040 Token::Lt => {
1041 if let Some(a) = stack.pop()
1042 && let Some(b) = stack.pop()
1043 {
1044 stack.push(StackValue::Bool(b < a));
1045 } else {
1046 anyhow::bail!("The stack must contain at least two elements for them to be compared");
1047 }
1048 }
1049 Token::Ge => {
1050 if let Some(a) = stack.pop()
1051 && let Some(b) = stack.pop()
1052 {
1053 stack.push(StackValue::Bool(b > a || b.loose_equal(&a)));
1054 } else {
1055 anyhow::bail!("The stack must contain at least two elements for them to be compared");
1056 }
1057 }
1058 Token::Le => {
1059 if let Some(a) = stack.pop()
1060 && let Some(b) = stack.pop()
1061 {
1062 stack.push(StackValue::Bool(b < a || b.loose_equal(&a)));
1063 } else {
1064 anyhow::bail!("The stack must contain at least two elements for them to be compared");
1065 }
1066 }
1067 Token::Gse => {
1068 if let Some(a) = stack.pop()
1069 && let Some(b) = stack.pop()
1070 {
1071 stack.push(StackValue::Bool(b > a || b.strict_equal(&a)));
1072 } else {
1073 anyhow::bail!("The stack must contain at least two elements for them to be compared");
1074 }
1075 }
1076 Token::Lse => {
1077 if let Some(a) = stack.pop()
1078 && let Some(b) = stack.pop()
1079 {
1080 stack.push(StackValue::Bool(b < a || b.strict_equal(&a)));
1081 } else {
1082 anyhow::bail!("The stack must contain at least two elements for them to be compared");
1083 }
1084 }
1085 Token::Gsse => {
1086 if let Some(a) = stack.pop()
1087 && let Some(b) = stack.pop()
1088 {
1089 stack.push(StackValue::Bool(b > a || b == a));
1090 } else {
1091 anyhow::bail!("The stack must contain at least two elements for them to be compared");
1092 }
1093 }
1094 Token::Lsse => {
1095 if let Some(a) = stack.pop()
1096 && let Some(b) = stack.pop()
1097 {
1098 stack.push(StackValue::Bool(b < a || b == a));
1099 } else {
1100 anyhow::bail!("The stack must contain at least two elements for them to be compared");
1101 }
1102 }
1103 Token::Shr => {
1104 if let Some(a) = stack.pop()
1105 && let Some(b) = stack.pop()
1106 {
1107 stack.push((b >> a)?);
1108 } else {
1109 anyhow::bail!("The stack must contain at least two elements for them to be manipulated");
1110 }
1111 }
1112 Token::Shl => {
1113 if let Some(a) = stack.pop()
1114 && let Some(b) = stack.pop()
1115 {
1116 stack.push((b << a)?);
1117 } else {
1118 anyhow::bail!("The stack must contain at least two elements for them to be manipulated");
1119 }
1120 }
1121 Token::Or => {
1122 if let Some(a) = stack.pop()
1123 && let Some(b) = stack.pop()
1124 {
1125 stack.push(b | a);
1126 } else {
1127 anyhow::bail!("The stack must contain at least two elements for them to be manipulated");
1128 }
1129 }
1130 Token::And => {
1131 if let Some(a) = stack.pop()
1132 && let Some(b) = stack.pop()
1133 {
1134 stack.push(b & a);
1135 } else {
1136 anyhow::bail!("The stack must contain at least two elements for them to be manipulated");
1137 }
1138 }
1139 Token::Not => {
1140 if let Some(a) = stack.pop() {
1141 stack.push(!a);
1142 } else {
1143 anyhow::bail!("The stack must contain at least one element for it to be negated");
1144 }
1145 }
1146 Token::Xor => {
1147 if let Some(a) = stack.pop()
1148 && let Some(b) = stack.pop()
1149 {
1150 stack.push(b ^ a);
1151 } else {
1152 anyhow::bail!("The stack must contain at least two elements for them to be manipulated");
1153 }
1154 }
1155 Token::Dup => {
1156 if let Some(a) = stack.last() {
1157 stack.push(a.clone());
1158 } else {
1159 anyhow::bail!("The stack must contain at least one element for it to be duplicated");
1160 }
1161 }
1162 Token::Drop => {
1163 if stack.is_empty() {
1164 anyhow::bail!("The stack must contain at least one element for it to be dropped");
1165 }
1166 let _ = stack.pop();
1167 }
1168 Token::Swap => {
1169 if let Some(a) = stack.pop()
1170 && let Some(b) = stack.pop()
1171 {
1172 stack.push(a);
1173 stack.push(b);
1174 } else {
1175 anyhow::bail!("The stack must contain at least two elements for them to be swapped");
1176 }
1177 }
1178 Token::Over => {
1179 if let Some(a) = stack.pop()
1180 && let Some(b) = stack.pop()
1181 {
1182 stack.push(b.clone());
1183 stack.push(a);
1184 stack.push(b);
1185 } else {
1186 anyhow::bail!("The stack must contain at least two elements for them to be overed");
1187 }
1188 }
1189 Token::Rot => {
1190 if let Some(a) = stack.pop()
1191 && let Some(b) = stack.pop()
1192 && let Some(c) = stack.pop()
1193 {
1194 stack.push(b);
1195 stack.push(a);
1196 stack.push(c);
1197 } else {
1198 anyhow::bail!("The stack must contain at least three elements for them to be roted");
1199 }
1200 }
1201 Token::Print => {
1202 if let Some(a) = stack.pop() {
1203 if let Err(err) = write!(writable, "{a}") {
1204 anyhow::bail!("Couldn't write to writable because {err}");
1205 };
1206 } else {
1207 anyhow::bail!("The stack must contain at least one element for it to be printed");
1208 }
1209 }
1210 Token::Println => {
1211 if let Some(a) = stack.pop() {
1212 if let Err(err) = writeln!(writable, "{a}") {
1213 anyhow::bail!("Couldn't write to writable because {err}");
1214 }
1215 } else {
1216 anyhow::bail!("The stack must contain at least one element for it to be printed");
1217 }
1218 }
1219 Token::If(jump_addr) | Token::Elif(jump_addr) => {
1220 if let Some(StackValue::Bool(boolean)) = stack.pop() {
1221 if !boolean {
1222 i = *jump_addr;
1223 continue;
1224 }
1225 } else {
1226 anyhow::bail!("If needs one boolean to be on the stack");
1227 }
1228 }
1229 Token::MrBeast(jump_addr) | Token::Else(jump_addr) => {
1230 i = *jump_addr;
1231 continue;
1232 } }
1234 i += 1;
1235 }
1236 Ok(stack)
1237}