1use rand::{Rng, thread_rng};
2use crate::core::*;
3use crate::executor::execute;
4use crate::executor_state::*;
5
6pub fn add_stdlib<S: 'static>(es: &mut EState<S>) {
7 es.functions.insert("repeat".to_string(), Function::from_proc2(repeat));
8 es.functions.insert("show".to_string(), Function::from_proc1(show));
9
10 es.functions.insert("abs".to_string(), Function::from_fn1(abs));
11 es.functions.insert("arctan".to_string(), Function::from_fn1(arctan));
12 es.functions.insert("cos".to_string(), Function::from_fn1(cos));
13 es.functions.insert("difference".to_string(), Function::from_fn2(difference));
14 es.functions.insert("exp".to_string(), Function::from_fn1(exp));
15 es.functions.insert("greater?".to_string(), Function::from_fn2(greater));
16 es.functions.insert("less?".to_string(), Function::from_fn2(less));
17 es.functions.insert("int".to_string(), Function::from_fn1(int));
18 es.functions.insert("log".to_string(), Function::from_fn1(log));
19 es.functions.insert("ln".to_string(), Function::from_fn1(ln));
20 es.functions.insert("minus".to_string(), Function::from_fn1(minus));
21 es.functions.insert("pi".to_string(), Function::from_fn(pi));
22 es.functions.insert("power".to_string(), Function::from_fn2(power));
23 es.functions.insert("product".to_string(), Function::from_fn2(product));
24 es.functions.insert("quotient".to_string(), Function::from_fn2(quotient));
25 es.functions.insert("remainder".to_string(), Function::from_fn2(remainder));
26 es.functions.insert("random".to_string(), Function::from_fn1(random));
27 es.functions.insert("round".to_string(), Function::from_fn1(round));
28 es.functions.insert("sin".to_string(), Function::from_fn1(sin));
29 es.functions.insert("sqrt".to_string(), Function::from_fn1(sqrt));
30 es.functions.insert("sum".to_string(), Function::from_fn2(sum));
31 es.functions.insert("tan".to_string(), Function::from_fn1(tan));
32
33 es.functions.insert("bf".to_string(), Function::from_fn1(bf));
34 es.functions.insert("butfirst".to_string(), Function::from_fn1(bf));
35 es.functions.insert("bl".to_string(), Function::from_fn1(bl));
36 es.functions.insert("butlast".to_string(), Function::from_fn1(bl));
37 es.functions.insert("count".to_string(), Function::from_fn1(count));
38 es.functions.insert("empty?".to_string(), Function::from_fn1(empty));
39 es.functions.insert("equal?".to_string(), Function::from_fn2(equal));
40 es.functions.insert("identical?".to_string(), Function::from_fn2(equal));
41 es.functions.insert("first".to_string(), Function::from_fn1(first));
42 es.functions.insert("fput".to_string(), Function::from_fn2(fput));
43 es.functions.insert("item".to_string(), Function::from_fn2(item));
44 es.functions.insert("last".to_string(), Function::from_fn1(last));
45 es.functions.insert("list".to_string(), Function::from_fn2(list));
46 es.functions.insert("list?".to_string(), Function::from_fn1(is_list));
47 es.functions.insert("lput".to_string(), Function::from_fn2(lput));
48 es.functions.insert("member?".to_string(), Function::from_fn2(member));
49 es.functions.insert("number?".to_string(), Function::from_fn1(number));
50 es.functions.insert("pick".to_string(), Function::from_fn1(pick));
51 es.functions.insert("word?".to_string(), Function::from_fn1(word));
52
53 es.functions.insert("and".to_string(), Function::from_fn2(and));
54 es.functions.insert("or".to_string(), Function::from_fn2(or));
55 es.functions.insert("not".to_string(), Function::from_fn1(not));
56 es.functions.insert("if".to_string(), Function::from_proc2(if_fn));
57 es.functions.insert("ifelse".to_string(), Function::from_proc3(if_else_fn));
58
59 es.functions.insert("make".to_string(), Function::from_proc2(make));
60 es.functions.insert("clearname".to_string(), Function::from_proc1(clearname));
61 es.functions.insert("clearnames".to_string(), Function::from_proc(clearnames));
62 es.functions.insert("name?".to_string(), Function::from_fn1(name));
63 es.functions.insert("names".to_string(), Function::from_fn(names));
64 es.functions.insert("thing".to_string(), Function::from_fn1(thing));
65
66 es.functions.insert("output".to_string(), Function::from_proc1(output));
67}
68
69fn repeat<S>(state: &mut EState<S>, n: i32, cmd: Vec<LogoValue>) -> Result<(), String> {
70 for _ in 0..n {
71 execute(state, cmd.clone())?;
72 }
73 Ok(())
74}
75
76fn show<S>(_: &mut EState<S>, val: LogoValue) -> Result<(), String> {
77 println!("{}", val);
78 Ok(())
79}
80
81fn abs<S>(_: &mut EState<S>, val: f64) -> Result<f64, String> {
82 Ok(val.abs())
83}
84
85fn arctan<S>(_: &mut EState<S>, val: f64) -> Result<f64, String> {
86 Ok(val.atan().to_degrees())
87}
88
89fn cos<S>(_: &mut EState<S>, val: f64) -> Result<f64, String> {
90 Ok(val.to_radians().cos())
91}
92
93fn difference<S>(_: &mut EState<S>, a: f64, b: f64) -> Result<f64, String> {
94 Ok(a - b)
95}
96
97fn exp<S>(_: &mut EState<S>, val: f64) -> Result<f64, String> {
98 Ok(val.exp())
99}
100
101fn greater<S>(_: &mut EState<S>, a: f64, b: f64) -> Result<bool, String> {
102 Ok(a > b)
103}
104
105fn less<S>(_: &mut EState<S>, a: f64, b: f64) -> Result<bool, String> {
106 Ok(a < b)
107}
108
109fn int<S>(_: &mut EState<S>, val: f64) -> Result<i32, String> {
110 Ok(val as i32)
111}
112
113fn log<S>(_: &mut EState<S>, val: f64) -> Result<f64, String> {
114 Ok(val.log(10f64))
115}
116
117fn ln<S>(_: &mut EState<S>, val: f64) -> Result<f64, String> {
118 Ok(val.ln())
119}
120
121fn minus<S>(_: &mut EState<S>, val: f64) -> Result<f64, String> {
122 Ok(-val)
123}
124
125fn pi<S>(_: &mut EState<S>) -> Result<f64, String> {
126 Ok(std::f64::consts::PI)
127}
128
129fn power<S>(_: &mut EState<S>, a: f64, b: f64) -> Result<f64, String> {
130 Ok(a.powf(b))
131}
132
133fn product<S>(_: &mut EState<S>, a: f64, b: f64) -> Result<f64, String> {
134 Ok(a * b)
135}
136
137fn quotient<S>(_: &mut EState<S>, a: f64, b: f64) -> Result<f64, String> {
138 Ok(a / b)
139}
140
141fn remainder<S>(_: &mut EState<S>, a: i32, b: i32) -> Result<i32, String> {
142 Ok(a % b)
143}
144
145fn random<S>(_: &mut EState<S>, val: i32) -> Result<i32, String> {
146 if val < 1 {
147 return Err("Input to random must be greater than 0".to_string());
148 }
149 Ok((rand::thread_rng().gen::<u32>() % val as u32) as i32)
150}
151
152fn round<S>(_: &mut EState<S>, val: f64) -> Result<i32, String> {
153 Ok(val.round() as i32)
154}
155
156fn sin<S>(_: &mut EState<S>, val: f64) -> Result<f64, String> {
157 Ok(val.to_radians().sin())
158}
159
160fn sqrt<S>(_: &mut EState<S>, val: f64) -> Result<f64, String> {
161 Ok(val.sqrt())
162}
163
164fn sum<S>(_: &mut EState<S>, x: f64, y: f64) -> Result<f64, String> {
165 Ok(x + y)
166}
167
168fn tan<S>(_: &mut EState<S>, val: f64) -> Result<f64, String> {
169 Ok(val.to_radians().tan())
170}
171
172
173fn bf<S>(_: &mut EState<S>, mut val: Vec<LogoValue>) -> Result<Vec<LogoValue>, String> {
174 if val.len() == 0 {
175 return Err("Can't remove an element from an empty list".to_string());
176 }
177 val.remove(0);
178 Ok(val)
179}
180
181fn bl<S>(_: &mut EState<S>, mut val: Vec<LogoValue>) -> Result<Vec<LogoValue>, String> {
182 if val.len() == 0 {
183 return Err("Can't remove an element from an empty list".to_string());
184 }
185 val.pop();
186 Ok(val)
187}
188
189fn count<S>(_: &mut EState<S>, val: Vec<LogoValue>) -> Result<i32, String> {
190 Ok(val.len() as i32)
191}
192
193fn empty<S>(_: &mut EState<S>, val: Vec<LogoValue>) -> Result<bool, String> {
194 Ok(val.is_empty())
195}
196
197fn equal<S>(_: &mut EState<S>, a: LogoValue, b: LogoValue) -> Result<bool, String> {
198 Ok(a == b)
199}
200
201fn first<S>(_: &mut EState<S>, val: Vec<LogoValue>) -> Result<LogoValue, String> {
202 if val.len() == 0 {
203 return Err("Can't get an element from an empty list".to_string());
204 }
205 Ok(val.first().unwrap().clone())
206}
207
208fn fput<S>(_: &mut EState<S>, a: LogoValue, mut b: Vec<LogoValue>) -> Result<Vec<LogoValue>, String> {
209 b.insert(0, a);
210 Ok(b)
211}
212
213fn item<S>(_: &mut EState<S>, idx: i32, val: Vec<LogoValue>) -> Result<LogoValue, String> {
214 if idx < 0 || idx >= val.len() as i32 {
215 return Err("No such item".to_string());
216 }
217 Ok(val[idx as usize].clone())
218}
219
220fn last<S>(_: &mut EState<S>, val: Vec<LogoValue>) -> Result<LogoValue, String> {
221 if val.len() == 0 {
222 return Err("Can't get an element from an empty list".to_string());
223 }
224 Ok(val.last().unwrap().clone())
225}
226
227fn list<S>(_: &mut EState<S>, mut a: Vec<LogoValue>, mut b: Vec<LogoValue>) -> Result<Vec<LogoValue>, String> {
228 a.append(&mut b);
229 Ok(a)
230}
231
232fn is_list<S>(_: &mut EState<S>, a: LogoValue) -> Result<bool, String> {
233 if let LogoValue::List(_) = a {
234 Ok(true)
235 }
236 else {
237 Ok(false)
238 }
239}
240
241fn lput<S>(_: &mut EState<S>, a: LogoValue, mut b: Vec<LogoValue>) -> Result<Vec<LogoValue>, String> {
242 b.push(a);
243 Ok(b)
244}
245
246fn member<S>(_: &mut EState<S>, a: LogoValue, b: Vec<LogoValue>) -> Result<bool, String> {
247 for b_el in b {
248 if a == b_el {
249 return Ok(true)
250 }
251 }
252 Ok(false)
253}
254
255fn number<S>(_: &mut EState<S>, a: LogoValue) -> Result<bool, String> {
256 if let LogoValue::Word(word) = a {
257 if let Ok(_) = word.0.parse::<f32>() {
258 Ok(true)
259 }
260 else {
261 Ok(false)
262 }
263 }
264 else {
265 Ok(false)
266 }
267}
268
269fn pick<S>(_: &mut EState<S>, val: Vec<LogoValue>) -> Result<LogoValue, String> {
270 if val.len() == 0 {
271 return Err("Can't get an element from an empty list".to_string());
272 }
273 Ok(val[thread_rng().gen::<usize>() % val.len()].clone())
274}
275
276fn word<S>(_: &mut EState<S>, a: LogoValue) -> Result<bool, String> {
277 if let LogoValue::Word(_) = a {
278 Ok(true)
279 }
280 else {
281 Ok(false)
282 }
283}
284
285
286fn and<S>(_: &mut EState<S>, a: bool, b: bool) -> Result<bool, String> {
287 Ok(a && b)
288}
289
290fn or<S>(_: &mut EState<S>, a: bool, b: bool) -> Result<bool, String> {
291 Ok(a || b)
292}
293
294fn not<S>(_: &mut EState<S>, a: bool) -> Result<bool, String> {
295 Ok(!a)
296}
297
298fn if_fn<S>(state: &mut EState<S>, a: bool, cmd: Vec<LogoValue>) -> Result<(), String> {
299 if a {
300 execute(state, cmd)?;
301 }
302 Ok(())
303}
304
305fn if_else_fn<S>(state: &mut EState<S>, a: bool, cmd_true: Vec<LogoValue>, cmd_false: Vec<LogoValue>) -> Result<(), String> {
306 if a {
307 execute(state, cmd_true)?;
308 }
309 else {
310 execute(state, cmd_false)?;
311 }
312 Ok(())
313}
314
315
316fn make<S>(state: &mut EState<S>, name: String, val: LogoValue) -> Result<(), String> {
317 state.vars.insert(name.to_lowercase(), val);
318 Ok(())
319}
320
321fn clearname<S>(state: &mut EState<S>, name: String) -> Result<(), String> {
322 state.vars.remove(name.to_lowercase().as_str());
323 Ok(())
324}
325
326fn clearnames<S>(state: &mut EState<S>) -> Result<(), String> {
327 state.vars.clear();
328 Ok(())
329}
330
331fn name<S>(state: &mut EState<S>, name: String) -> Result<bool, String> {
332 Ok(state.vars.contains_key(name.to_lowercase().as_str()))
333}
334
335fn names<S>(state: &mut EState<S>) -> Result<Vec<LogoValue>, String> {
336 let mut result = Vec::with_capacity(state.vars.len());
337 for key in state.vars.keys() {
338 result.push(LogoValue::String(key.clone()));
339 }
340 Ok(result)
341}
342
343fn thing<S>(state: &mut EState<S>, name: String) -> Result<LogoValue, String> {
344 let name = name.to_lowercase();
345 if !state.vars.contains_key(name.as_str()) {
346 return Err("No such variable".to_string());
347 }
348 Ok(state.vars[name.as_str()].clone())
349}
350
351
352fn output<S>(state: &mut EState<S>, val: LogoValue) -> Result<(), String> {
353 state.output = Some(val);
354 Err("Output".to_string())
355}