1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
use crate::value::{
ValueEnum, ValId,
primitive::{
logical::{Unary, Binary, LogicalOp}
},
expr::SexprArgs,
error::{
ValueError,
NotAFunction
}
};
impl SexprArgs {
/// Apply a unary logical operation to an argument stack.
/// Return whether any computation occured.
pub(crate) fn apply_binary_logical(&mut self, b: Binary, _ptr: Option<&ValId>)
-> Result<bool, ValueError> {
let res = Ok(false);
let left = if let Some(left) = self.pop() { left } else { return res };
{
let data = left.data();
match data.value {
ValueEnum::Bool(l) => {
if let Some(right) = self.pop() {
{
let data = right.data();
match data.value {
ValueEnum::Bool(r) => {
self.push(ValId::from(b.apply(l, r)));
return Ok(true)
},
//TODO: type errors and such
_ => {}
}
}
self.push(right);
}
self.push(ValId::from(b.partial_apply(l)));
return Ok(true)
},
//TODO: type errors and such
_ => {}
}
}
self.push(left);
res
}
/// Apply a unary logical operation to an argument stack.
/// Return whether any computation occured.
pub(crate) fn apply_unary_logical(&mut self, u: Unary, _ptr: Option<&ValId>)
-> Result<bool, ValueError> {
let res = Ok(false);
let arg = if let Some(arg) = self.pop() { arg } else { return res };
{
let data = arg.data();
match data.value {
ValueEnum::Bool(b) => {
self.push(ValId::from(u.apply(b)));
return Ok(true)
},
//TODO: type errors and such
_ => {}
}
}
// Cleanup
self.push(arg);
res
}
/// Apply a logical operation to an argument stack.
/// Return whether any computation occured.
pub(crate) fn apply_logical(&mut self, l: LogicalOp, ptr: Option<&ValId>)
-> Result<bool, ValueError> {
match l {
LogicalOp::Binary(b) => self.apply_binary_logical(b, ptr),
LogicalOp::Unary(u) => self.apply_unary_logical(u, ptr)
}
}
/// Attempt to normalize these arguments
pub(crate) fn try_normalize(&mut self) -> Result<(), ValueError> {
while self.len() > 1 {
let arg = self.pop().unwrap();
match {
let data = arg.data();
match data.value {
ValueEnum::LogicalOp(l) => {
self.apply_logical(l, Some(&arg))
},
//TODO: sexpr flattening?
_ => {
if !data.value.applicable() { // This cannot be a function, giving an error
Err(ValueError::NotAFunction(NotAFunction{
applied: Some(arg.clone()),
argument: self.last().cloned()
}))
} else { Ok(false) }
}
}
} {
Ok(true) => {},
Ok(false) => { self.push(arg); return Ok(()) },
Err(err) => { self.push(arg); return Err(err) }
}
}
Ok(())
}
}