1#![deny(missing_docs)]
2#![doc = include_str!("../README.md")]
3
4use std::sync::Arc;
5
6use self::Expr::*;
7use self::Op::*;
8use self::Value::*;
9use self::Knowledge::*;
10use self::Symbol::*;
11
12pub use val::*;
13pub use expr::*;
14pub use op::Op;
15pub use sym::*;
16pub use standard_library::*;
17pub use parsing::*;
18pub use knowledge::*;
19
20mod val;
21mod expr;
22mod op;
23mod sym;
24mod knowledge;
25mod standard_library;
26mod parsing;
27mod arity;
28mod matrix;
29
30pub mod prelude {
32 pub use super::*;
33 pub use super::Expr::*;
34 pub use super::Op::*;
35 pub use super::Value::*;
36 pub use super::Knowledge::*;
37 pub use super::Symbol::*;
38}
39
40impl Into<Expr> for bool {
41 fn into(self) -> Expr {Ret(Bool(self))}
42}
43
44impl Into<Expr> for f64 {
45 fn into(self) -> Expr {Ret(F64(self))}
46}
47
48impl<T, U> Into<Expr> for (T, U)
49 where T: Into<Expr>, U: Into<Expr>
50{
51 fn into(self) -> Expr {Tup(vec![self.0.into(), self.1.into()])}
52}
53
54impl<T0, T1, T2> Into<Expr> for (T0, T1, T2)
55 where T0: Into<Expr>, T1: Into<Expr>, T2: Into<Expr>
56{
57 fn into(self) -> Expr {Tup(vec![self.0.into(), self.1.into(), self.2.into()])}
58}
59
60impl Expr {
61 pub fn equivalences(&self, knowledge: &[Knowledge]) -> Vec<(Expr, usize)> {
63 let mut ctx = Context {vars: vec![]};
64 let mut res = vec![];
65 for i in 0..knowledge.len() {
66 if let Eqv(a, b) | EqvEval(a, b) = &knowledge[i] {
67 if ctx.bind(a, self) {
68 let expr = match ctx.substitute(b) {
69 Ok(expr) => expr,
70 Err(_) => {
71 ctx.vars.clear();
74 continue;
75 }
76 };
77 res.push((expr, i));
78 ctx.vars.clear();
79 } else if ctx.bind(b, self) {
80 let expr = match ctx.substitute(a) {
81 Ok(expr) => expr,
82 Err(_) => {
83 ctx.vars.clear();
86 continue;
87 }
88 };
89 res.push((expr, i));
90 ctx.vars.clear();
91 }
92 }
93 }
94
95 match self {
96 Sym(_) | Ret(_) => {}
97 EOp(op, a, b) => {
98 for (ea, i) in a.equivalences(knowledge).into_iter() {
99 res.push((EOp(*op, Box::new(ea), b.clone()), i));
100 }
101 for (eb, i) in b.equivalences(knowledge).into_iter() {
102 res.push((EOp(*op, a.clone(), Box::new(eb)), i));
103 }
104 }
105 Tup(items) | List(items) => {
106 for i in 0..items.len() {
107 for (expr, j) in items[i].equivalences(knowledge).into_iter() {
108 let mut new_items: Vec<Expr> = items[0..i].into();
109 new_items.push(expr);
110 new_items.extend(items[i+1..].iter().map(|n| n.clone()));
111 if let Tup(_) = self {
112 res.push((Tup(new_items), j));
113 } else if let List(_) = self {
114 res.push((List(new_items), j));
115 }
116 }
117 }
118 }
119 }
120
121 res
122 }
123
124 pub fn contains_nan(&self) -> bool {
126 match self {
127 Sym(_) => false,
128 Ret(F64(v)) => v.is_nan(),
129 Ret(_) => false,
130 EOp(_, a, b) => a.contains_nan() || b.contains_nan(),
131 Tup(items) | List(items) => items.iter().any(|n| n.contains_nan()),
132 }
133 }
134
135 pub fn eval(&self, knowledge: &[Knowledge]) -> Result<Expr, Error> {
139 let mut me = self.clone();
140 while !me.contains_nan() {
141 let expr = me.reduce_eval_all(knowledge, true).inline_all(knowledge)?;
142 if expr == me {break};
143 me = expr;
144 }
145 Ok(me)
146 }
147
148 pub fn reduce_all(&self, knowledge: &[Knowledge]) -> Expr {
150 self.reduce_eval_all(knowledge, false)
151 }
152
153 pub fn reduce_eval_all(&self, knowledge: &[Knowledge], eval: bool) -> Expr {
155 let mut me = self.clone();
156 while let Ok((expr, _)) = me.reduce_eval(knowledge, eval) {me = expr}
157 me
158 }
159
160 pub fn reduce(&self, knowledge: &[Knowledge]) -> Result<(Expr, usize), Error> {
162 self.reduce_eval(knowledge, false)
163 }
164
165 pub fn reduce_eval(&self, knowledge: &[Knowledge], eval: bool) -> Result<(Expr, usize), Error> {
169 let mut ctx = Context {vars: vec![]};
170 let mut me: Result<(Expr, usize), Error> = Err(Error::NoReductionRule);
171 for i in 0..knowledge.len() {
172 if eval {
173 if let Red(a, b) | EqvEval(a, b) = &knowledge[i] {
174 if ctx.bind(a, self) {
175 me = match ctx.substitute(b) {
176 Ok(expr) => Ok((expr, i)),
177 Err(err) => Err(err),
178 };
179 break;
180 }
181 }
182 } else {
183 if let Red(a, b) = &knowledge[i] {
184 if ctx.bind(a, self) {
185 me = match ctx.substitute(b) {
186 Ok(expr) => Ok((expr, i)),
187 Err(err) => Err(err),
188 };
189 break;
190 }
191 }
192 }
193 }
194
195 match self {
196 EOp(op, a, b) => {
197 if let Type = op {
204 if let List(_) = **a {} else {return me}
206 }
207
208 if let Ok((a, i)) = a.reduce_eval(knowledge, eval) {
209 if let Ok((expr, j)) = me {if j < i {return Ok((expr, j))}};
211 return Ok((EOp(*op, Box::new(a), b.clone()), i));
212 }
213 if let Ok((b, i)) = b.reduce_eval(knowledge, eval) {
214 if let Ok((expr, j)) = me {if j < i {return Ok((expr, j))}};
216 return Ok((EOp(*op, a.clone(), Box::new(b)), i));
217 }
218 }
219 Tup(a) | List(a) => {
220 let mut res = vec![];
221 for i in 0..a.len() {
222 if let Ok((n, j)) = a[i].reduce_eval(knowledge, eval) {
223 if let Ok((expr, k)) = me {if k < j {return Ok((expr, k))}};
225 res.push(n);
226 res.extend(a[i+1..].iter().map(|n| n.clone()));
227 if let Tup(_) = self {
228 return Ok((Tup(res), j));
229 } else if let List(_) = self {
230 return Ok((List(res), j));
231 } else {
232 unreachable!();
233 }
234 } else {
235 res.push(a[i].clone());
236 }
237 }
238 }
239 _ => {}
240 }
241
242 me
243 }
244
245 pub fn inline_all(&self, knowledge: &[Knowledge]) -> Result<Expr, Error> {
249 match self {
250 Sym(a) => {
251 for i in 0..knowledge.len() {
252 if let Def(b, c) = &knowledge[i] {
253 if b == a {
254 return Ok(c.clone());
255 }
256 }
257 }
258 Err(Error::NoDefinition)
259 }
260 Ret(_) => Ok(self.clone()),
261 EOp(op, a, b) => {
262 if let Constrain = op {
263 let a = a.inline_all(knowledge)?;
264 match b.inline_all(knowledge) {
265 Err(Error::NoDefinition) => Ok(a),
266 Err(err) => Err(err),
267 Ok(b) => Ok(constr(a, b)),
268 }
269 } else {
270 match (a.inline_all(knowledge), b.inline_all(knowledge)) {
271 (Ok(a), Ok(b)) => Ok(EOp(
272 *op,
273 Box::new(a),
274 Box::new(b)
275 )),
276 (Ok(a), Err(_)) => Ok(EOp(
277 *op,
278 Box::new(a),
279 b.clone()
280 )),
281 (Err(_), Ok(b)) => Ok(EOp(
282 *op,
283 a.clone(),
284 Box::new(b)
285 )),
286 (err, _) => err,
287 }
288 }
289 }
290 Tup(a) => {
291 let mut res = vec![];
292 for i in 0..a.len() {
293 res.push(a[i].inline_all(knowledge)?);
294 }
295 Ok(Tup(res))
296 }
297 List(a) => {
298 let mut res = vec![];
299 for i in 0..a.len() {
300 res.push(a[i].inline_all(knowledge)?);
301 }
302 Ok(List(res))
303 }
304 }
305 }
306
307 pub fn inline(&self, sym: &Symbol, knowledge: &[Knowledge]) -> Result<Expr, Error> {
309 match self {
310 Sym(a) if a == sym => {
311 for i in 0..knowledge.len() {
312 if let Def(b, c) = &knowledge[i] {
313 if b == a {
314 return Ok(c.clone());
315 }
316 }
317 }
318 Err(Error::NoDefinition)
319 }
320 Sym(_) | Ret(_) => Ok(self.clone()),
321 EOp(op, a, b) => {
322 Ok(EOp(
323 *op,
324 Box::new(a.inline(sym, knowledge)?),
325 Box::new(b.inline(sym, knowledge)?)
326 ))
327 }
328 Tup(a) => {
329 let mut res = vec![];
330 for i in 0..a.len() {
331 res.push(a[i].inline(sym, knowledge)?);
332 }
333 Ok(Tup(res))
334 }
335 List(a) => {
336 let mut res = vec![];
337 for i in 0..a.len() {
338 res.push(a[i].inline(sym, knowledge)?);
339 }
340 Ok(List(res))
341 }
342 }
343 }
344
345 pub fn has_constraint(&self, arity_args: usize) -> bool {
367 match self {
368 EOp(Constrain, f, a) => {
369 if let Some(arity) = a.arity() {
370 if arity > arity_args {true}
371 else {f.has_constraint(arity_args - arity)}
372 } else {
373 true
374 }
375 }
376 EOp(Compose, a, b) => b.has_constraint(arity_args) || a.has_constraint(0),
377 EOp(Apply, f, _) => f.has_constraint(arity_args + 1),
378 Sym(_) => false,
379 Ret(_) => false,
380 _ => true
381 }
382 }
383
384 pub fn is_substitution(&self) -> bool {
386 self.sub_is_substitution(3)
387 }
388
389 fn sub_is_substitution(&self, args: usize) -> bool {
390 match self {
391 EOp(Apply, f, _) if args > 0 => f.sub_is_substitution(args - 1),
392 Sym(Subst) if args == 0 => true,
393 _ => false,
394 }
395 }
396
397 pub fn has_non_constant_type_judgement(&self) -> bool {
399 match self {
400 EOp(Type, _, b) if **b == Sym(RetType) => false,
401 EOp(Type, _, _) => true,
402 _ => false
403 }
404 }
405}
406
407pub struct Context {
409 pub vars: Vec<(Arc<String>, Expr)>,
411}
412
413impl Context {
414 pub fn bind(&mut self, name: &Expr, value: &Expr) -> bool {
416 match (name, value) {
417 (Sym(NoSubstVar(_)), v) if v.is_substitution() => {
418 self.vars.clear();
419 false
420 }
421 (Sym(NoConstrVar(_)), v) if v.has_constraint(0) => {
422 self.vars.clear();
423 false
424 }
425 (Sym(Var(_)), Tup(_)) | (Sym(NoConstrVar(_)), Tup(_)) => {
426 self.vars.clear();
427 false
428 }
429 (Sym(Var(_)), v) if v.has_non_constant_type_judgement() => {
433 self.vars.clear();
434 false
435 }
436 (Sym(Var(name)), x) |
437 (Sym(NoConstrVar(name)), x) |
438 (Sym(NoSubstVar(name)), x) => {
439 for i in (0..self.vars.len()).rev() {
440 if &self.vars[i].0 == name {
441 if &self.vars[i].1 == x {
442 break
443 } else {
444 self.vars.clear();
445 return false;
446 }
447 }
448 }
449 self.vars.push((name.clone(), x.clone()));
450 true
451 }
452 (Sym(ArityVar(name, n)), x) if x.arity() == Some(*n) => {
453 for i in (0..self.vars.len()).rev() {
454 if &self.vars[i].0 == name {
455 if &self.vars[i].1 == x {
456 break
457 } else {
458 self.vars.clear();
459 return false;
460 }
461 }
462 }
463 self.vars.push((name.clone(), x.clone()));
464 true
465 }
466 (Sym(NotInVarName(name, y)), x) => {
469 fn get_names(expr: &Expr, ret: &mut Vec<Arc<String>>) {
471 match expr {
472 Sym(Var(y)) => ret.push(y.clone()),
473 Sym(y) if y.arity().is_some() => {}
474 Ret(_) => {}
475 Tup(list) | List(list) => {
476 for x in list {
477 get_names(x, ret);
478 }
479 }
480 EOp(Apply, a, b) => {
481 get_names(a, ret);
482 get_names(b, ret);
483 }
484 _ => {}
486 }
488 }
489 fn contains(expr: &Expr, x: &Arc<String>) -> bool {
491 match expr {
492 Sym(Var(y)) => return x == y,
493 Sym(y) if y.arity().is_some() => return false,
494 Ret(_) => return false,
495 Tup(list) | List(list) => return list.iter().any(|expr| contains(expr, x)),
496 EOp(Apply, a, b) => return contains(a, x) || contains(b, x),
497 _ => {}
499 }
501 true
502 }
503
504 let mut names = vec![];
505 get_names(x, &mut names);
506 for i in (0..self.vars.len()).rev() {
507 if &self.vars[i].0 == name {
509 if &self.vars[i].1 == x {continue}
510 else {
511 self.vars.clear();
512 return false;
513 }
514 } else if &self.vars[i].0 == y {
515 if names.iter().any(|name| {
518 !contains(&self.vars[i].1, name)
519 }) {continue}
520 else {
521 self.vars.clear();
522 return false;
523 }
524 }
525 }
526 self.vars.push((name.clone(), x.clone()));
527 true
528 }
529 (Sym(NotRetVar(_)), Ret(_)) | (Sym(NotRetVar(_)), Tup(_)) => {
530 self.vars.clear();
531 false
532 }
533 (Sym(NotRetVar(name)), _) => {
534 for i in (0..self.vars.len()).rev() {
535 if &self.vars[i].0 == name {
536 if &self.vars[i].1 == value {
537 break
538 } else {
539 self.vars.clear();
540 return false;
541 }
542 }
543 }
544 self.vars.push((name.clone(), value.clone()));
545 true
546 }
547 (Sym(RetVar(name)), Ret(_)) => {
548 for i in (0..self.vars.len()).rev() {
549 if &self.vars[i].0 == name {
550 if &self.vars[i].1 == value {
551 break
552 } else {
553 self.vars.clear();
554 return false;
555 }
556 }
557 }
558 self.vars.push((name.clone(), value.clone()));
559 true
560 }
561 (Sym(RetIntVar(name)), Ret(F64(x))) if x % 1.0 == 0.0 => {
562 for i in (0..self.vars.len()).rev() {
563 if &self.vars[i].0 == name {
564 if &self.vars[i].1 == value {
565 break
566 } else {
567 self.vars.clear();
568 return false;
569 }
570 }
571 }
572 self.vars.push((name.clone(), value.clone()));
573 true
574 }
575 (Sym(RetPosVar(name)), Ret(F64(x))) if *x >= 0.0 => {
576 for i in (0..self.vars.len()).rev() {
577 if &self.vars[i].0 == name {
578 if &self.vars[i].1 == value {
579 break
580 } else {
581 self.vars.clear();
582 return false;
583 }
584 }
585 }
586 self.vars.push((name.clone(), value.clone()));
587 true
588 }
589 (Sym(RetStrictPosVar(name)), Ret(F64(x))) if *x > 0.0 => {
590 for i in (0..self.vars.len()).rev() {
591 if &self.vars[i].0 == name {
592 if &self.vars[i].1 == value {
593 break
594 } else {
595 self.vars.clear();
596 return false;
597 }
598 }
599 }
600 self.vars.push((name.clone(), value.clone()));
601 true
602 }
603 (Sym(RetNegVar(name)), Ret(F64(x))) if *x < 0.0 => {
604 for i in (0..self.vars.len()).rev() {
605 if &self.vars[i].0 == name {
606 if &self.vars[i].1 == value {
607 break
608 } else {
609 self.vars.clear();
610 return false;
611 }
612 }
613 }
614 self.vars.push((name.clone(), Ret(F64(x.abs()))));
615 true
616 }
617 (Sym(Singleton(name)), List(x)) if x.len() == 1 => {
618 self.vars.push((name.clone(), x[0].clone()));
619 true
620 }
621 (Sym(ListVar(name)), List(_)) => {
622 self.vars.push((name.clone(), value.clone()));
623 true
624 }
625 (Sym(HeadTailTup(head, tail)), Tup(list)) |
626 (Sym(HeadTailList(head, tail)), List(list)) => {
627 if list.len() < 2 {return false};
628
629 let r = self.bind(head, &list[0]);
630 let b: Expr = if let (Sym(HeadTailTup(_, _)), Tup(_)) = (name, value) {
631 if list[1..].len() == 1 {
632 list[1].clone()
633 } else {
634 Tup(list[1..].into())
635 }
636 } else {
637 List(list[1..].into())
638 };
639
640 if r {
641 if let Sym(Var(tail)) = &**tail {
642 for i in (0..self.vars.len()).rev() {
643 if &self.vars[i].0 == tail {
644 if &self.vars[i].1 == &b {
645 break
646 } else {
647 self.vars.clear();
648 return false;
649 }
650 }
651 }
652 self.vars.push((tail.clone(), b));
653 true
654 } else {
655 self.vars.clear();
656 false
657 }
658 } else {
659 self.vars.clear();
660 false
661 }
662 }
663 (Sym(Any), _) => true,
664 (Sym(a), Sym(b)) if a == b => true,
665 (Ret(a), Ret(b)) if a == b => true,
666 (EOp(op1, a1, b1), EOp(op2, a2, b2)) if op1 == op2 => {
667 let r = self.bind(a1, a2) && self.bind(b1, b2);
668 if !r {self.vars.clear()};
669 r
670 }
671 (Tup(a), Tup(b)) if a.len() == b.len() => {
672 let mut all = true;
673 for i in 0..a.len() {
674 let r = self.bind(&a[i], &b[i]);
675 if !r {
676 all = false;
677 break;
678 }
679 }
680 if !all {self.vars.clear()};
681 all
682 }
683 (List(a), List(b)) if a.len() == b.len() => {
684 let mut all = true;
685 for i in 0..a.len() {
686 let r = self.bind(&a[i], &b[i]);
687 if !r {
688 all = false;
689 break;
690 }
691 }
692 if !all {self.vars.clear()};
693 all
694 }
695 _ => {
696 self.vars.clear();
697 false
698 }
699 }
700 }
701
702 pub fn substitute(&self, x: &Expr) -> Result<Expr, Error> {
706 match x {
707 Sym(Any) => Err(Error::InvalidComputation),
709 Sym(NoSubstVar(_)) => Err(Error::InvalidComputation),
710 Sym(RetNegVar(_)) => Err(Error::InvalidComputation),
711 Sym(Var(name)) | Sym(ArityVar(name, _)) => {
712 for i in (0..self.vars.len()).rev() {
713 if &self.vars[i].0 == name {
714 return Ok(self.vars[i].1.clone())
715 }
716 }
717 Err(Error::CouldNotFind(name.clone()))
718 }
719 Sym(UnopRetVar(a, f)) => {
720 let mut av: Option<Expr> = None;
721 for i in (0..self.vars.len()).rev() {
722 if &self.vars[i].0 == a {
723 av = Some(self.vars[i].1.clone());
724 }
725 }
726 match av {
727 Some(Ret(F64(a))) => {
728 Ok(match **f {
729 Even => Ret(Bool(a.round() % 2.0 == 0.0)),
730 Odd => Ret(Bool(a.round() % 2.0 == 1.0)),
731 Neg => Ret(F64(-a)),
732 Inc => Ret(F64(a + 1.0)),
733 Reci => if a == 0.0 {
734 return Err(Error::InvalidComputation)
735 } else {
736 Ret(F64(a.recip()))
737 },
738 Abs => Ret(F64(a.abs())),
739 Prob => Ret(Bool(a >= 0.0 && a <= 1.0)),
740 Probl => Ret(Bool(a >= 0.0 && a < 1.0)),
741 Probr => Ret(Bool(a > 0.0 && a <= 1.0)),
742 Probm => Ret(Bool(a > 0.0 && a < 1.0)),
743 Sqrt => Ret(F64(a.sqrt())),
744 Ln => Ret(F64(a.ln())),
745 Log2 => Ret(F64(a.log2())),
746 Log10 => Ret(F64(a.log10())),
747 Exp => Ret(F64(a.exp())),
748 Sin => Ret(F64(a.sin())),
749 Asin => Ret(F64(a.asin())),
750 Cos => Ret(F64(a.cos())),
751 Acos => Ret(F64(a.acos())),
752 Tan => Ret(F64(a.tan())),
753 Atan => Ret(F64(a.atan())),
754 TypeOf => Sym(F64Type),
755 _ => return Err(Error::InvalidComputation),
756 })
757 }
758 Some(List(a)) => {
759 Ok(match **f {
760 Len => Ret(F64(a.len() as f64)),
761 Dim => matrix::dim(&a)?,
762 Transpose => matrix::transpose(&a)?,
763 IsSquareMat => matrix::is_square_mat(&a)?,
764 _ => return Err(Error::InvalidComputation),
765 })
766 }
767 Some(a) => {
768 Ok(match **f {
769 Arity => {
770 if let Some(n) = a.arity() {Ret(F64(n as f64))}
771 else {return Err(Error::InvalidComputation)}
772 }
773 _ => return Err(Error::InvalidComputation),
774 })
775 }
776 _ => Err(Error::CouldNotFind(a.clone())),
777 }
778 }
779 Sym(BinopRetVar(a, b, f)) => {
780 let mut av: Option<Expr> = None;
781 let mut bv: Option<Expr> = None;
782 for i in (0..self.vars.len()).rev() {
783 if &self.vars[i].0 == a {
784 av = Some(self.vars[i].1.clone());
785 }
786 if &self.vars[i].0 == b {
787 bv = Some(self.vars[i].1.clone());
788 }
789 }
790 match (av, bv) {
791 (Some(Ret(a)), Some(Ret(b))) if **f == Eq => Ok(Ret(Bool(a == b))),
792 (Some(Ret(F64(a))), Some(Ret(F64(b)))) => {
793 Ok(Ret(F64(match **f {
794 Lt => return Ok(Ret(Bool(a < b))),
795 Le => return Ok(Ret(Bool(a <= b))),
796 Gt => return Ok(Ret(Bool(a > b))),
797 Ge => return Ok(Ret(Bool(a >= b))),
798 Add => a + b,
799 Sub => a - b,
800 Mul => a * b,
801 Pow => a.powf(b),
802 Rem => if b == 0.0 {
803 return Err(Error::InvalidComputation)
804 } else {
805 a % b
806 }
807 Div => if b == 0.0 {
808 return Err(Error::InvalidComputation)
809 } else {
810 a / b
811 }
812 Max2 => if a >= b {a} else {b},
813 Min2 => if a <= b {a} else {b},
814 Base if b >= 0.0 && b < a => {
815 let mut r = vec![Ret(F64(0.0)); a as usize];
816 r[b as usize] = Ret(F64(1.0));
817 return Ok(List(r))
818 }
819 Atan2 => return Ok(Ret(F64(a.atan2(b)))),
820 _ => return Err(Error::InvalidComputation),
821 })))
822 }
823 (Some(Ret(F64(a))), Some(List(b))) => {
824 Ok(match **f {
825 Item if a >= 0.0 && a < b.len() as f64 =>
826 b[a as usize].clone(),
827 Col if a >= 0.0 => matrix::col(a, &b)?,
828 _ => return Err(Error::InvalidComputation),
829 })
830 }
831 (Some(List(a)), Some(List(b))) => {
832 Ok(match **f {
833 Concat => {
834 let mut a = a.clone();
835 a.extend(b.iter().map(|n| n.clone()));
836 List(a)
837 }
838 MulMat => matrix::mul_mat(&a, &b)?,
839 _ => return Err(Error::InvalidComputation),
840 })
841 }
842 (Some(List(a)), Some(b)) => {
843 Ok(match **f {
844 Push => {
845 let mut a = a.clone();
846 a.push(b);
847 List(a)
848 }
849 PushFront => {
850 let mut a = a.clone();
851 a.insert(0, b);
852 List(a)
853 }
854 _ => return Err(Error::InvalidComputation),
855 })
856 }
857 (av, _) => {
858 if av.is_none() {
859 Err(Error::CouldNotFind(a.clone()))
860 } else {
861 Err(Error::CouldNotFind(b.clone()))
862 }
863 }
864 }
865 }
866 Sym(TernopRetVar(a, b, c, f)) => {
867 let mut av: Option<Expr> = None;
868 let mut bv: Option<Expr> = None;
869 let mut cv: Option<Expr> = None;
870 for i in (0..self.vars.len()).rev() {
871 if &self.vars[i].0 == a {
872 av = Some(self.vars[i].1.clone());
873 }
874 if &self.vars[i].0 == b {
875 bv = Some(self.vars[i].1.clone());
876 }
877 if &self.vars[i].0 == c {
878 cv = Some(self.vars[i].1.clone());
879 }
880 }
881 match (av, bv, cv) {
882 (Some(Ret(F64(a))), Some(Ret(F64(b))), Some(Ret(F64(c)))) => {
883 Ok(match **f {
884 Range => if c >= a && c <= b {Ret(Bool(true))}
885 else {Ret(Bool(false))},
886 Rangel => if c >= a && c < b {Ret(Bool(true))}
887 else {Ret(Bool(false))},
888 Ranger => if c > a && c <= b {Ret(Bool(true))}
889 else {Ret(Bool(false))},
890 Rangem => if c > a && c < b {Ret(Bool(true))}
891 else {Ret(Bool(false))},
892 _ => return Err(Error::InvalidComputation)
893 })
894 }
895 (av, bv, _) => {
896 if av.is_none() {
897 Err(Error::CouldNotFind(a.clone()))
898 } else if bv.is_none() {
899 Err(Error::CouldNotFind(b.clone()))
900 } else {
901 Err(Error::CouldNotFind(c.clone()))
902 }
903 }
904 }
905 }
906 Sym(_) | Ret(_) => Ok(x.clone()),
907 EOp(op, a, b) => {
908 Ok(EOp(*op, Box::new(self.substitute(a)?), Box::new(self.substitute(b)?)))
909 }
910 Tup(a) => {
911 let mut res = vec![];
912 for i in 0..a.len() {
913 res.push(self.substitute(&a[i])?);
914 }
915 Ok(Tup(res))
916 }
917 List(a) => {
918 let mut res = vec![];
919 for i in 0..a.len() {
920 res.push(self.substitute(&a[i])?);
921 }
922 Ok(List(res))
923 }
924 }
925 }
926}
927
928#[derive(Debug, PartialEq)]
930pub enum Error {
931 InvalidComputation,
933 NoDefinition,
935 NoReductionRule,
937 CouldNotFind(Arc<String>),
939}
940
941impl Into<Expr> for Symbol {
942 fn into(self) -> Expr {Sym(self)}
943}
944
945impl Into<Expr> for &'static str {
946 fn into(self) -> Expr {Sym(self.into())}
947}
948
949impl Into<Symbol> for &'static str {
950 fn into(self) -> Symbol {Symbol::from(Arc::new(self.into()))}
951}
952
953pub fn app<A: Into<Expr>, B: Into<Expr>>(a: A, b: B) -> Expr {
955 EOp(Apply, Box::new(a.into()), Box::new(b.into()))
956}
957
958pub fn app2<A: Into<Expr>, B: Into<Expr>, C: Into<Expr>>(a: A, b: B, c: C) -> Expr {
960 app(app(a, b), c)
961}
962
963pub fn app3<A: Into<Expr>, B: Into<Expr>, C: Into<Expr>, D: Into<Expr>>(
965 a: A, b: B, c: C, d: D
966) -> Expr {
967 app2(app(a, b), c, d)
968}
969
970pub fn comp<A: Into<Expr>, B: Into<Expr>>(a: A, b: B) -> Expr {
972 EOp(Compose, Box::new(a.into()), Box::new(b.into()))
973}
974
975pub fn path<A: Into<Expr>, B: Into<Expr>>(a: A, b: B) -> Expr {
977 EOp(Path, Box::new(a.into()), Box::new(b.into()))
978}
979
980pub fn constr<A: Into<Expr>, B: Into<Expr>>(a: A, b: B) -> Expr {
982 EOp(Constrain, Box::new(a.into()), Box::new(b.into()))
983}
984
985pub fn constr2<A: Into<Expr>, B: Into<Expr>, C: Into<Expr>>(a: A, b: B, c: C) -> Expr {
987 constr(constr(a, b), c)
988}
989
990pub fn typ<A: Into<Expr>, B: Into<Expr>>(a: A, b: B) -> Expr {
992 EOp(Type, Box::new(a.into()), Box::new(b.into()))
993}
994
995pub fn _if<A: Into<Expr>, B: Into<Expr>>(a: A, b: B) -> Expr {app(app(If, a), b)}
997
998pub fn head_tail_tup<A: Into<Expr>, B: Into<Expr>>(a: A, b: B) -> Expr {
1000 HeadTailTup(Box::new(a.into()), Box::new(b.into())).into()
1001}
1002
1003pub fn head_tail_list<A: Into<Expr>, B: Into<Expr>>(a: A, b: B) -> Expr {
1005 HeadTailList(Box::new(a.into()), Box::new(b.into())).into()
1006}
1007
1008pub fn arity_var<A: Into<String>>(a: A, n: usize) -> Expr {Sym(ArityVar(Arc::new(a.into()), n))}
1010
1011pub fn list_var<A: Into<String>>(a: A) -> Expr {Sym(ListVar(Arc::new(a.into())))}
1013
1014pub fn singleton<A: Into<String>>(a: A) -> Expr {Sym(Singleton(Arc::new(a.into())))}
1016
1017pub fn ret_var<A: Into<String>>(a: A) -> Expr {Sym(RetVar(Arc::new(a.into())))}
1019
1020pub fn ret_int_var<A: Into<String>>(a: A) -> Expr {Sym(RetIntVar(Arc::new(a.into())))}
1022
1023pub fn ret_pos_var<A: Into<String>>(a: A) -> Expr {Sym(RetPosVar(Arc::new(a.into())))}
1025
1026pub fn ret_strict_pos_var<A: Into<String>>(a: A) -> Expr {Sym(RetStrictPosVar(Arc::new(a.into())))}
1028
1029pub fn ret_neg_var<A: Into<String>>(a: A) -> Expr {Sym(RetNegVar(Arc::new(a.into())))}
1033
1034pub fn not_ret_var<A: Into<String>>(a: A) -> Expr {Sym(NotRetVar(Arc::new(a.into())))}
1036
1037pub fn ret_type_var<A: Into<String>>(a: A) -> Expr {
1039 EOp(Type, Box::new(Sym(Var(Arc::new(a.into())))), Box::new(Sym(RetType)))
1040}
1041
1042pub fn binop_ret_var<A: Into<String>, B: Into<String>, F: Into<Symbol>>(a: A, b: B, f: F) -> Expr {
1044 Sym(BinopRetVar(Arc::new(a.into()), Arc::new(b.into()), Box::new(f.into())))
1045}
1046
1047pub fn ternop_ret_var<A: Into<String>, B: Into<String>, C: Into<String>, F: Into<Symbol>>(
1049 a: A, b: B, c: C, f: F
1050) -> Expr {
1051 Sym(TernopRetVar(Arc::new(a.into()), Arc::new(b.into()), Arc::new(c.into()), Box::new(f.into())))
1052}
1053
1054pub fn unop_ret_var<A: Into<String>, F: Into<Symbol>>(a: A, f: F) -> Expr {
1056 Sym(UnopRetVar(Arc::new(a.into()), Box::new(f.into())))
1057}
1058
1059pub fn no_constr<A: Into<String>>(a: A) -> Expr {
1061 Sym(NoConstrVar(Arc::new(a.into())))
1062}
1063
1064pub fn vec2<A: Into<Expr>, B: Into<Expr>>(a: A, b: B) -> Expr {List(vec![a.into(), b.into()])}
1066
1067pub fn vec4<X: Into<Expr>, Y: Into<Expr>, Z: Into<Expr>, W: Into<Expr>>(
1069 x: X, y: Y, z: Z, w: W
1070) -> Expr {
1071 List(vec![x.into(), y.into(), z.into(), w.into()])
1072}
1073
1074pub fn quat<X: Into<Expr>, Y: Into<Expr>, Z: Into<Expr>, W: Into<Expr>>(
1076 x: X, y: Y, z: Z, w: W
1077) -> Expr {
1078 typ(List(vec![x.into(), y.into(), z.into(), w.into()]), QuatType)
1079}
1080
1081pub fn vec_op<S: Into<Symbol>>(s: S) -> Knowledge {
1083 let s = s.into();
1084 Red(app(constr(app(constr(s.clone(), app(Rty, VecType)), "x"), app(Rty, VecType)), "y"),
1085 app2(app(VecOp, s), "x", "y"))
1086}
1087
1088pub fn concrete_op<S: Into<Symbol>>(s: S) -> Knowledge {
1090 let s = s.into();
1091 Red(app2(s.clone(), ret_type_var("x"), ret_type_var("y")), typ(app2(s, "x", "y"), RetType))
1092}
1093
1094pub fn commutative<S: Into<Symbol>>(s: S) -> Knowledge {
1096 let s = s.into();
1097 let a: Expr = "a".into();
1098 let b: Expr = "b".into();
1099 Eqv(app(app(s.clone(), a.clone()), b.clone()), app(app(s, b), a))
1100}
1101
1102pub fn associative<S: Into<Symbol>>(s: S) -> Knowledge {
1104 let s = s.into();
1105 let a: Expr = "a".into();
1106 let b: Expr = "b".into();
1107 let c: Expr = "c".into();
1108 Eqv(app(app(s.clone(), a.clone()), app(app(s.clone(), b.clone()), c.clone())),
1109 app(app(s.clone(), app(app(s, a), b)), c))
1110}
1111
1112pub fn distributive<M: Into<Symbol>, A: Into<Symbol>>(mul: M, add: A) -> Knowledge {
1114 let mul = mul.into();
1115 let add = add.into();
1116 let a: Expr = "a".into();
1117 let b: Expr = "b".into();
1118 let c: Expr = "c".into();
1119 Eqv(app(app(mul.clone(), a.clone()), app(app(add.clone(), b.clone()), c.clone())),
1120 app(app(add, app(app(mul.clone(), a.clone()), b)), app(app(mul, a), c)))
1121}
1122
1123#[cfg(test)]
1124mod tests {
1125 use super::*;
1126
1127 #[test]
1128 fn apply_not() {
1129 let ref std = std();
1130 let a = app(Not, true);
1131 let a = a.inline(&Not, std).unwrap();
1132 let a = a.reduce(std).unwrap().0;
1133 assert_eq!(a, false.into());
1134
1135 let a = app(Not, false);
1136 let a = a.inline(&Not, std).unwrap();
1137 let a = a.reduce(std).unwrap().0;
1138 assert_eq!(a, true.into());
1139 }
1140
1141 #[test]
1142 fn comp_not_not() {
1143 let ref std = std();
1144 let a = comp(Not, Not);
1145 let a = a.reduce(std).unwrap().0;
1146 assert_eq!(a, Idb.into());
1147 }
1148
1149 #[test]
1150 fn path_not_not() {
1151 let ref std = std();
1152 let a = path(Not, Not);
1153 let a = a.reduce(std).unwrap().0;
1154 assert_eq!(a, Not.into());
1155 }
1156
1157 #[test]
1158 fn comp_id() {
1159 let ref std = std();
1160
1161 let a = comp(Not, Id);
1162 let a = a.reduce(std).unwrap().0;
1163 assert_eq!(a, Not.into());
1164
1165 let a = comp(Id, Not);
1166 let a = a.reduce(std).unwrap().0;
1167 assert_eq!(a, Not.into());
1168 }
1169
1170 #[test]
1171 fn path_not_id() {
1172 let ref std = std();
1173 let a = path(Not, Id);
1174 let a = a.reduce(std).unwrap().0;
1175 assert_eq!(a, Not.into());
1176 }
1177
1178 #[test]
1179 fn constraints() {
1180 let f: Expr = "f".into();
1181 assert_eq!(f.has_constraint(0), false);
1182 let f: Expr = app(Not, false);
1183 assert_eq!(f.has_constraint(0), false);
1184 let f: Expr = constr(Not, true);
1185 assert_eq!(f.has_constraint(0), true);
1186 let f: Expr = And.into();
1187 assert_eq!(f.has_constraint(0), false);
1188 let f: Expr = constr(And, Eqb);
1189 assert_eq!(f.has_constraint(0), true);
1190 let f: Expr = constr(And, Not);
1191 assert_eq!(f.has_constraint(0), true);
1192 let f: Expr = app(constr(And, Not), "x");
1193 assert_eq!(f.has_constraint(0), false);
1194 let f: Expr = app(constr(And, Eqb), "x");
1195 assert_eq!(f.has_constraint(0), true);
1196 let f: Expr = app(And, false);
1197 assert_eq!(f.has_constraint(0), false);
1198 let f: Expr = constr(Sum, app(Rty, VecType));
1200 assert_eq!(f.has_constraint(0), true);
1201 let f: Expr = constr(Add, app(Rge, 0.0));
1203 assert_eq!(f.has_constraint(0), true);
1204 let f: Expr = comp(Not, Not);
1205 assert_eq!(f.has_constraint(0), false);
1206 let f: Expr = constr(comp(Not, Not), true);
1208 assert_eq!(f.has_constraint(0), true);
1209 let f: Expr = comp(constr(Not, Not), Not);
1211 assert_eq!(f.has_constraint(0), true);
1212 let f: Expr = comp(Not, constr(Not, Not));
1214 assert_eq!(f.has_constraint(0), true);
1215 let f: Expr = true.into();
1216 assert_eq!(f.has_constraint(0), false);
1217 }
1218
1219 #[test]
1220 fn eval_var() {
1221 let def = &[Def("x".into(), 0.0.into())];
1222 let f: Expr = "x".into();
1223 assert_eq!(f.eval(def).unwrap(), Ret(F64(0.0)));
1224
1225 let mut def = std();
1226 def.push(Def("x".into(), 2.0.into()));
1227 let f: Expr = app2(Add, 1.0, "x");
1228 assert_eq!(f.eval(&def).unwrap(), Ret(F64(3.0)));
1229
1230 let mut def = std();
1231 def.push(Def("x".into(), 0.0.into()));
1232 let f: Expr = app("sin", "x");
1233 assert_eq!(f.eval(&def).unwrap(), Ret(F64(0.0)));
1234 }
1235}