1use crate::{btoi, drop, drop_end, macros::*, p::Node, take, take_end};
2use colored::Colorize;
3use rand::Rng;
4use std::{ascii, borrow::Cow, cmp, fs, iter::zip};
5
6macro_rules! err_nyi {
11 ($($t:tt)*) => {{
12 err_fmt!("{}\n{}", "'nyi".purple(), format!($($t)*))
13 }};
14}
15
16macro_rules! err_domain {
17 ($($t:tt)*) => {{
18 err_fmt!("{}\n{}", "'domain".yellow(), format!($($t)*))
19 }};
20}
21
22macro_rules! err_io {
23 ($($t:tt)*) => {{
24 err_fmt!("{}\n{}", "'io".green(), format!($($t)*))
25 }};
26}
27
28type EvalResult<'a, T> = Result<(T, Cow<'a, State>), String>;
30type OkNode<'a> = EvalResult<'a, Node>;
31
32#[derive(Debug, Clone)]
33pub struct State {
34 vars: Vec<(Node, Node)>,
35}
36
37impl State {
38 pub fn new() -> Self {
39 Self { vars: Vec::new() }
40 }
41
42 pub fn with(x: Vec<(Node, Node)>) -> Self {
43 Self { vars: x }
44 }
45
46 pub fn with_var<'a>(&self, x: Cow<'static, str>, y: Node) -> Cow<'a, Self> {
47 let mut v = self.vars.clone();
48 v.push((Node::X(x), y));
49
50 Cow::Owned(State::with(v))
51 }
52
53 pub fn with_vars<'a>(
54 &self,
55 x: Vec<(Cow<'static, str>, Node)>,
56 ) -> Cow<'a, Self> {
57 let mut v = self.vars.clone();
58
59 for (x, y) in x.into_iter() {
60 v.push((Node::X(x), y));
61 }
62
63 Cow::Owned(State::with(v))
64 }
65
66 pub fn with_verb<'a>(&self, x: Node, y: Node) -> Cow<'a, Self> {
67 let mut v = self.vars.clone();
68 v.push((x, y));
69
70 Cow::Owned(State::with(v))
71 }
72
73 pub fn get_bind(&self, x: &Node) -> Option<Node> {
74 for (k, v) in self.vars.iter().rev() {
75 if x == k {
76 return Some(v.clone());
77 }
78 }
79
80 None
81 }
82
83 pub fn with_bind<'a>(&self, x: Node, y: Node) -> Cow<'a, Self> {
84 let mut v = self.vars.clone();
85 v.push((x, y));
86
87 Cow::Owned(State::with(v))
88 }
89
90 pub fn has_fn(&self, f: &str) -> bool {
91 for (x, _) in self.vars.iter() {
92 if x == &(Node::M {
93 verb: f.to_string().into(),
94 rhs: None,
95 }) {
96 return true;
97 }
98 }
99 false
100 }
101
102 pub fn get_fn<T>(&self, f: T) -> Option<Node>
103 where
104 String: From<T>,
105 {
106 let f = &String::from(f);
107 for (k, v) in self.vars.iter().rev() {
108 if &(Node::M {
109 verb: f.to_string().into(),
110 rhs: None,
111 }) == k
112 {
113 return Some(v.clone());
114 }
115 }
116 None
117 }
118}
119
120macro_rules! mk_ok {
121 ($a:ident, $x:ty, $n:path) => {
122 fn $a<'a>(x: $x, s: Cow<'a, State>) -> OkNode<'a> {
123 Ok(($n(x), s))
124 }
125 };
126}
127
128mk_ok!(ok_i, i64, Node::I);
129mk_ok!(ok_f, f64, Node::F);
130mk_ok!(ok_c, char, Node::C);
131mk_ok!(ok_a, Vec<Node>, Node::A);
132mk_ok!(ok_s, Box<Node>, Node::S);
133
134fn is_homogenous(x: &[Node]) -> bool {
135 if x.len() > 0 {
136 let t = node_type(&x[0]);
137 x.iter().all(|x| t == node_type(&x))
138 } else {
139 false
140 }
141}
142
143fn node_type(x: &Node) -> String {
144 match x {
145 Node::I(_) => "i".to_string(),
146 Node::F(_) => "f".to_string(),
147 Node::C(_) => "c".to_string(),
148 Node::A(x) => {
149 if is_homogenous(&x) {
150 node_type(&x[0]).to_uppercase()
151 } else {
152 "A".to_string()
153 }
154 }
155 Node::S(_) => "s".to_string(),
156 Node::O(_) => "o".to_string(),
157 Node::P(_) => "p".to_string(),
158 Node::T(_) => "t".to_string(),
159 Node::X(_) => "x".to_string(),
160 Node::D { .. } => "d".to_string(),
161 Node::M { .. } => "m".to_string(),
162 }
163}
164
165pub fn eval_each<'a>(
166 x: &[Node],
167 s: Cow<'a, State>,
168) -> EvalResult<'a, Vec<Node>> {
169 let mut r = Vec::new();
170 let mut s = s;
171
172 for i in x.iter() {
173 let (c, _s) = eval(i, s)?;
174 s = _s;
175 r.push(c);
176 }
177
178 Ok((r, s))
179}
180
181#[allow(unreachable_patterns)]
182pub fn eval<'a>(x: &Node, s: Cow<'a, State>) -> EvalResult<'a, Node> {
183 match x {
184 x @ (Node::I(_)
185 | Node::F(_)
186 | Node::C(_)
187 | Node::O(_)
188 | Node::T(_)
189 | Node::S(_)
190 | Node::D {
191 verb: _,
192 lhs: _,
193 rhs: None,
194 }
195 | Node::M { verb: _, rhs: None }) => Ok((x.clone(), s)),
196
197 Node::A(x) => {
198 let mut v = Vec::new();
199 let mut _s = s.clone();
200 #[allow(unused_assignments)]
201 let mut p = Node::empty();
202
203 for i in x.iter() {
204 (p, _s) = eval(i, _s)?;
205 v.push(p);
206 }
207
208 ok_a(v, s)
209 }
210
211 x @ Node::X(xs) => match s.get_bind(&x) {
213 Some(v) => Ok((v, s)),
214 None => err_fmt!("'value\n {xs} is not defined"),
215 },
216
217 Node::P(x) => Ok((
219 {
220 let (x, _) = eval_each(x, s.clone())?;
221 match x.into_iter().last() {
222 Some(x) => x,
223 None => Node::empty(),
224 }
225 },
226 s,
227 )),
228
229 Node::M {
230 verb: v,
231 rhs: Some(x),
232 } => {
233 let (x, s) = eval(&*x, s)?;
234 match (&**v, x) {
235 ("!", Node::I(x)) => ok_a(
237 (if x > 0 { 0..x } else { x..0 })
238 .map(|x| Node::I(x))
239 .collect(),
240 s,
241 ),
242 ("-", Node::I(x)) => ok_i(-x, s),
244 ("-", Node::F(x)) => ok_f(-x, s),
245 ("_", Node::I(x)) => ok_i(x, s),
247 ("_", Node::F(x)) => ok_i(x.floor() as i64, s),
248 (",", x) => ok_a(vec![x], s),
250 ("$", x) => Ok((Node::from_str(format!("{x}")), s)),
252 ("*", Node::A(x)) => match x.into_iter().nth(0) {
254 Some(x) => Ok((x, s)),
255 None => ok_a(Vec::new(), s),
256 },
257 ("*", x) => Ok((x, s)),
258 ("%", Node::A(x)) => ok_a(drop(x, 1), s),
260 ("%", x) => Ok((x, s)),
261 ("#", Node::A(x)) => ok_i(x.len() as i64, s),
263 ("#", _) => ok_i(1, s),
264 ("|", Node::A(x)) => ok_a(x.into_iter().rev().collect(), s),
266 ("~", Node::I(0)) => ok_i(1, s),
268 ("~", Node::I(1)) => ok_i(0, s),
269 ("~", Node::I(x)) => {
270 err_nyi!(
271 "not must be applied to 1 or 0\n -> {}",
272 format!("~{x}").blue()
273 )
274 }
275 ("@", x) => ok_s(Box::new(Node::X(node_type(&x).into())), s),
277 ("<<", x @ Node::A(_)) if x.is_str() => {
279 println!("{}", x.un_str());
280 Ok((Node::empty(), s))
281 }
282 ("<", x @ Node::A(_)) if x.is_str() => {
283 puts!("{}", x.un_str());
284 Ok((Node::empty(), s))
285 }
286 ("<<!", x @ Node::A(_)) if x.is_str() => {
288 eprintln!("{}", x.un_str());
289 Ok((Node::empty(), s))
290 }
291 ("<!", x @ Node::A(_)) if x.is_str() => {
292 eputs!("{}", x.un_str());
293 Ok((Node::empty(), s))
294 }
295 (">>", x @ Node::A(_)) if x.is_str() => {
297 let f = x.un_str();
298 match fs::read_to_string(f) {
299 Ok(x) => Ok((Node::from_str(x), s)),
300 Err(e) => err_io!("failed to read file to string: {e}"),
301 }
302 }
303 (v, x) if s.has_fn(v) => {
305 let f = s
306 .get_fn(v)
307 .expect("unreachable: state has fn but can't get_fn()");
308 eval(&Node::dyad(".", f, x), s)
309 }
310 (v, x) => {
311 let t = node_type(&x);
312 err_fmt!(
313 "'nyi\nmonadic {v}{t} is not yet implemented\n -> {}",
314 format!("{v}{x}").blue()
315 )
316 }
317 }
318 }
319
320 Node::D {
321 verb: v,
322 lhs: x,
323 rhs: Some(y),
324 } => {
325 match &**v {
327 ":" => {
328 let (y, s) = eval(&*y, s)?;
329 return match (*x.clone(), y) {
330 (Node::X(x), y) => Ok((y.clone(), (*s).with_var(x, y))),
331 (x @ Node::M { verb: _, rhs: None }, y) => {
332 Ok((y.clone(), (*s).with_verb(x, y)))
333 }
334 (x, y) => err_nyi!(
335 "{x} gets {y} is not yet implemented\n -> {}",
336 format!("{x}:{y}").blue()
337 ),
338 };
339 }
340 "::" => {
341 let (y, s) = eval(&*y, s)?;
342 return match (*x.clone(), y) {
343 (Node::A(x), y) if x[0].is_x() && x[1].is_i() => {
344 let i = x[1].un_i();
345 let b = &x[0];
346 let a = s.get_bind(b);
347
348 match a {
349 Some(Node::A(mut v)) => {
350 v[i as usize] = y;
351 let s = (*s).with_bind(
352 b.clone(),
353 Node::A(v.clone()),
354 );
355 ok_a(v, s)
356 }
357 Some(a) => err_nyi!(
358 "can only mend arrays, not {a}\n -> {}",
359 format!("{}::{y}", Node::A(x)).blue()
360 ),
361 None => err_nyi!("bind {} not found", x[0]),
362 }
363 }
364 (x, y) => err_nyi!(
365 "{x} mend {y} is not yet implemented\n -> {}",
366 format!("{x}::{y}").blue()
367 ),
368 };
369 }
370 _ => {}
371 };
372
373 let (y, s) = eval(&*y, s)?;
374 let (x, s) = eval(&*x, s)?;
375 match (&**v, x, y) {
376 ("+", Node::I(x), Node::I(y)) => ok_i(x + y, s),
378 ("-", Node::I(x), Node::I(y)) => ok_i(x - y, s),
379 ("*", Node::I(x), Node::I(y)) => ok_i(x * y, s),
380 ("%", Node::I(x), Node::I(y)) => ok_f(x as f64 / y as f64, s),
381 ("<", Node::I(x), Node::I(y)) => ok_i(btoi(x < y), s),
382 (">", Node::I(x), Node::I(y)) => ok_i(btoi(x > y), s),
383 ("&", Node::I(x), Node::I(y)) => ok_i(cmp::min(x, y), s),
384 ("|", Node::I(x), Node::I(y)) => ok_i(cmp::max(x, y), s),
385 ("^", Node::I(x), Node::I(y)) => {
386 ok_f((x as f64).powf(y as f64), s)
387 }
388 ("!", Node::I(x), Node::I(y)) => ok_i(y % x, s),
389 (
391 v @ ("+" | "-" | "*" | "%" | "<" | ">" | "&" | "|" | "^"
392 | "!"),
393 x,
394 Node::A(y),
395 ) => {
396 let mut r = Vec::new();
397 let mut s = s;
398 for i in y.into_iter() {
399 let (c, _s) = eval(&Node::dyad(v, x.clone(), i), s)?;
400 s = _s;
401 r.push(c);
402 }
403 ok_a(r, s)
404 }
405 ("~", x, y) => ok_i(btoi(x == y), s),
407 ("?", Node::I(x), Node::I(y)) => {
409 ok_i(rand::thread_rng().gen_range(x..y + 1), s)
410 }
411 ("$", Node::S(x), y) => match (*x, y) {
412 (Node::X(x), Node::I(y)) if &*x == "c" => {
413 match ascii::Char::from_u8(y as u8) {
414 Some(c) => ok_c(c.into(), s),
415 None => err_fmt!("cannot cast {y} to char"),
416 }
417 }
418 (x, y) => err_fmt!("cannot cast {y} to `{x}"),
419 },
420 (",", Node::A(mut x), Node::A(mut y)) => ok_a(
422 {
423 x.append(&mut y);
424 x.clone()
425 },
426 s,
427 ),
428 (",", Node::A(mut x), y) => ok_a(
429 {
430 x.push(y);
431 x.clone()
432 },
433 s,
434 ),
435 (",", x, Node::A(mut y)) => ok_a(
436 {
437 y.insert(0, x);
438 y.clone()
439 },
440 s,
441 ),
442 (",", x, y) => ok_a(vec![x, y], s),
443 ("/", x @ Node::A(_), Node::A(y))
445 if (x.is_str() || x.is_c())
446 && y.iter().all(|x| x.is_str()) =>
447 {
448 let i = x.un_str();
449 Ok((
450 Node::from_str(
451 y.into_iter()
452 .map(|x| x.un_str())
453 .collect::<Vec<_>>()
454 .join(&i),
455 ),
456 s,
457 ))
458 }
459 ("|||", Node::I(x), Node::A(mut y)) => {
461 let mut r = Vec::new();
462 loop {
463 if y.len() > x as usize {
464 let h = take(&mut y, x);
465 r.push(Node::A(h));
466 } else {
467 r.push(Node::A(y));
468 break;
469 }
470 }
471 ok_a(r, s)
472 }
473 ("?", x, Node::A(y)) => ok_i(
475 match y.into_iter().position(|i| x == i) {
476 Some(x) => x as i64,
477 None => -1,
478 },
479 s,
480 ),
481 ("#", Node::I(n), Node::A(mut v)) => ok_a(take(&mut v, n), s),
483 ("#", Node::A(mut v), Node::I(n)) => {
484 ok_a(take_end(&mut v, n), s)
485 }
486 ("_", Node::I(n), Node::A(v)) => ok_a(drop(v, n), s),
488 ("_", Node::A(mut v), Node::I(n)) => {
489 ok_a(drop_end(&mut v, n), s)
490 }
491 ("_", Node::M { verb: x, rhs: None }, Node::A(y)) => ok_a(
492 {
493 let mut v = Vec::new();
494 for i in y.into_iter() {
495 if let (Node::I(1), _) =
496 eval(&Node::monad(&*x, i.clone()), s.clone())?
497 {
498 v.push(i);
499 }
500 }
501 v
502 },
503 s,
504 ),
505 ("'", x, Node::A(y)) => {
508 let (e, _) = eval_each(
509 &y.into_iter()
510 .map(|i| match node_type(&i).as_str() {
511 t if t.chars().all(|x| x.is_ascii_uppercase()) => {
512 Node::dyad(".", x.clone(), Node::monad(",", i))
513 }
514 _ => Node::dyad(".", x.clone(), i),
515 })
516 .collect::<Vec<_>>(),
517 s.clone(),
518 )?;
519 ok_a(e, s)
520 }
521 (".", ref wx @ Node::A(ref x), wy @ Node::I(y)) => {
523 match x.iter().nth(y as usize) {
524 Some(x) => Ok((x.clone(), s)),
525 None => {
526 err_domain!(" -> {}", format!("{wx} . {wy}").blue())
527 }
528 }
529 }
530 (".", Node::A(x), Node::A(y)) if y.iter().all(|x| x.is_i()) => {
531 let mut v = Vec::new();
532 for i in y.into_iter() {
533 v.push(x[i.un_i() as usize].clone());
534 }
535 ok_a(v, s)
536 }
537 (".", Node::M { verb: v, rhs: None }, Node::A(y)) => {
538 if y.len() == 2 {
539 eval(&Node::dyad(&*v, y[0].clone(), y[1].clone()), s)
540 } else {
541 err_nyi!(" -> {v}{}", Node::A(y))
542 }
543 }
544 (".", Node::M { verb: v, rhs: None }, y) => {
545 eval(&Node::monad(&*v, y), s)
546 }
547 (
548 ".",
549 Node::D {
550 verb: v,
551 lhs,
552 rhs: None,
553 },
554 y,
555 ) => eval(&Node::dyad(&*v, *lhs, y), s),
556 (".", Node::O(x), Node::A(y)) => {
557 let mut v: Vec<_> = ["x", "y", "z"]
558 .into_iter()
559 .map(|x| Cow::from(x))
560 .collect();
561 let v = take(&mut v, y.len() as i64);
562 let (e, _) = eval_each(
563 &x,
564 s.with_vars(zip(v, y).collect::<Vec<_>>()),
565 )?;
566 match e.into_iter().last() {
567 Some(x) => Ok((x, s)),
568 None => Ok((Node::empty(), s)),
569 }
570 }
571 (".", Node::O(x), y) => {
572 eval(&Node::dyad(".", Node::O(x), Node::A(vec![y])), s)
573 }
574 (v, x, y) if s.has_fn(v) => {
576 let f = s.get_fn(v).expect(
577 "unreachable: state has fn but not found by get_fn()",
578 );
579 eval(&Node::dyad(".", f, Node::A(vec![x, y])), s)
580 }
581 (v, x, y) => {
582 let xt = node_type(&x);
583 let yt = node_type(&y);
584 err_nyi!(
585 "dyadic {xt}{v}{yt} is not yet implemented\n -> {}",
586 format!("{x}{v}{y}").blue()
587 )
588 }
589 }
590 }
591
592 _ => err_nyi!(" -> {x}"),
593 }
594}
595
596#[cfg(test)]
597mod tests {
598 use crate::{
599 p::{parse, Node},
600 x::{eval, eval_each, State},
601 };
602 use std::borrow::Cow;
603
604 fn exec(x: &Node) -> Result<Node, String> {
605 let (r, _) = eval(x, Cow::Owned(State::new()))?;
606 Ok(r)
607 }
608
609 #[test]
610 fn eval_one() {
611 assert_eq!(exec(&Node::I(1)).unwrap(), Node::I(1));
612 }
613
614 #[test]
615 fn monads() {
616 for (x, y) in [
617 (
618 "!4",
619 Node::A([0, 1, 2, 3].iter().map(|x| Node::I(*x)).collect()),
620 ),
621 ("-1", Node::I(-1)),
622 (
623 "! -4",
624 Node::A([4, 3, 2, 1].iter().map(|x| Node::I(-*x)).collect()),
625 ),
626 ("_1", Node::I(1)),
627 ("_1.0", Node::I(1)),
628 ("* !10", Node::I(0)),
629 ("# !10", Node::I(10)),
630 (
631 "| !3",
632 Node::A([2, 1, 0].iter().map(|x| Node::I(*x)).collect()),
633 ),
634 ("~1", Node::I(0)),
635 ("~0", Node::I(1)),
636 (",1", Node::A(vec![Node::I(1)])),
637 (
638 "% !3",
639 Node::A([1, 2].iter().map(|x| Node::I(*x)).collect()),
640 ),
641 ]
642 .into_iter()
643 {
644 assert_eq!(exec(&parse(x).unwrap()[0].clone()).unwrap(), y);
645 }
646 }
647
648 #[test]
649 fn dyads() {
650 let abc = Node::A("abc".chars().map(|x| Node::C(x)).collect());
651
652 for (x, y) in [
653 ("1+1", Node::I(2)),
654 (
655 "1+ !3",
656 Node::A([1, 2, 3].iter().map(|x| Node::I(*x)).collect()),
657 ),
658 (
659 "2% 1+ !2",
660 Node::A([2, 1].iter().map(|x| Node::F(*x as f64)).collect()),
661 ),
662 ("1-1", Node::I(0)),
663 ("4*3", Node::I(12)),
664 ("10%2", Node::F(5.0)),
665 (r#""ab","c""#, abc.clone()),
666 (r#""a","bc""#, abc.clone()),
667 (r#""a","b","c""#, abc.clone()),
668 ("1|0&1", Node::I(1)),
669 ("5<1>2", Node::I(0)),
670 (
671 "3||| !9",
672 Node::A(
673 [[0, 1, 2], [3, 4, 5], [6, 7, 8]]
674 .iter()
675 .map(|x| {
676 Node::A(x.iter().map(|x| Node::I(*x)).collect())
677 })
678 .collect(),
679 ),
680 ),
681 ("(!10) . 2", Node::I(2)),
682 ("(+) . (1;2)", Node::I(3)),
683 (
684 "(~)_(1;0;1;0;1;0)",
685 Node::A([0, 0, 0].iter().map(|x| Node::I(*x)).collect()),
686 ),
687 ("{x+1} . ,1", Node::I(2)),
688 ("{x+y}.(1;2)", Node::I(3)),
689 (
690 "{x+1}' !3",
691 Node::A([1, 2, 3].iter().map(|x| Node::I(*x)).collect()),
692 ),
693 ("{x+y+z}.1+ !4", Node::I(6)),
694 ("{a:x;a+1}. ,1", Node::I(2)),
695 (
696 "(1+)'(1;2)",
697 Node::A([2, 3].iter().map(|x| Node::I(*x)).collect()),
698 ),
699 (
700 "{1+ !x}' 1+ !3",
701 Node::A(
702 [0, 1, 2]
703 .iter()
704 .map(|x| {
705 Node::A((0..1+*x).map(|x| Node::I(1 + x)).collect())
706 })
707 .collect(),
708 ),
709 ),
710 (
711 "{$x}'\"abc\"",
712 Node::A(
713 "abc"
714 .chars()
715 .map(|x| Node::from_str(format!("\"{x}\"")))
716 .collect(),
717 ),
718 ),
719 (
720 r#"{$x}'("abc";"def")"#,
721 Node::A(
722 ["abc", "def"]
723 .iter()
724 .map(|x| Node::from_str(format!("\"{x}\"")))
725 .collect(),
726 ),
727 ),
728 ("a+a:1", Node::I(2)),
729 (
730 r#""abcdefghijklmnopqrstuvwxyz"[0;2;4;6]"#,
731 Node::A("aceg".chars().map(|x| Node::C(x)).collect()),
732 ),
733 ]
734 .into_iter()
735 {
736 assert_eq!(
737 exec(&parse(x).unwrap().last().unwrap().clone()).unwrap(),
738 y
739 );
740 }
741 }
742
743 #[test]
745 fn state() {
746 assert_eq!(
747 {
748 let (x, s) = eval_each(
749 &parse("a:1;a+1").unwrap(),
750 Cow::Owned(State::new()),
751 )
752 .unwrap();
753 assert_eq!(
754 s.vars,
755 vec![(Node::X(Cow::Borrowed("a")), Node::I(1))]
756 );
757 x
758 },
759 vec![Node::I(1), Node::I(2)]
760 );
761 }
762
763 #[test]
764 fn progn() {
765 for (x, y) in
766 [("[1;2;3]", Node::I(3)), ("[a:1;a+1]", Node::I(2))].into_iter()
767 {
768 assert_eq!(
769 eval_each(&parse(x).unwrap(), Cow::Owned(State::new()))
770 .unwrap()
771 .0
772 .into_iter()
773 .last()
774 .unwrap(),
775 y
776 );
777 }
778 }
779
780 #[test]
781 fn def_verb() {
782 for (x, y) in [
783 ("(++):{x+y};1++1", Node::I(2)),
784 ("(++):(-);++1", Node::I(-1)),
785 (
786 "(!):{-x};!3",
787 Node::A([0, 1, 2].iter().map(|x| Node::I(*x)).collect()),
788 ),
789 ]
790 .into_iter()
791 {
792 assert_eq!(
793 eval_each(&parse(x).unwrap(), Cow::Owned(State::new()))
794 .unwrap()
795 .0
796 .into_iter()
797 .last()
798 .unwrap(),
799 y
800 );
801 }
802 }
803}