1use std::collections::HashMap;
2
3use crate::types::Error;
4use crate::types::Error::*;
5use std::cell::RefCell;
6
7use crate::functions;
8use crate::functions::num::to_int;
9
10#[derive(Debug, PartialEq, Clone)]
11pub struct Value {
12 pub val: String,
13 pub cond: bool,
14}
15
16pub fn value_string(s: &str, c: bool) -> Value {
17 Value {
18 val: String::from(s),
19 cond: c,
20 }
21}
22
23#[derive(Clone)]
24pub enum FuncValue {
25 NativeFn(fn(Vec<String>) -> String),
26 NativeFnError(fn(Vec<String>) -> Result<String, Error>),
27 NativeCondFnError(fn(Vec<Value>) -> Result<Value, Error>),
28 NativeEnvFnError(fn(&Environment, Vec<Value>) -> Result<Value, Error>),
29}
30
31#[derive(Clone)]
34pub struct Environment {
35 vars: RefCell<HashMap<String, String>>,
36 metadata: HashMap<String, Vec<String>>,
37 funcs: HashMap<String, FuncValue>,
38}
39
40impl Environment {
41 fn add_default_functions(&mut self) {
42 self.funcs.insert(
43 String::from("add"),
44 FuncValue::NativeFnError(functions::num::add::add),
45 );
46 self.funcs.insert(
47 String::from("sub"),
48 FuncValue::NativeFnError(functions::num::sub::sub),
49 );
50 self.funcs.insert(
51 String::from("mul"),
52 FuncValue::NativeFnError(functions::num::mul::mul),
53 );
54 self.funcs.insert(
55 String::from("div"),
56 FuncValue::NativeFnError(functions::num::div::div),
57 );
58 self.funcs.insert(
59 String::from("min"),
60 FuncValue::NativeFnError(functions::num::min::min),
61 );
62 self.funcs.insert(
63 String::from("max"),
64 FuncValue::NativeFnError(functions::num::max::max),
65 );
66
67 self.funcs.insert(
68 String::from("eq"),
69 FuncValue::NativeCondFnError(functions::num::control::eq),
70 );
71 self.funcs.insert(
72 String::from("ne"),
73 FuncValue::NativeCondFnError(functions::num::control::ne),
74 );
75 self.funcs.insert(
76 String::from("gt"),
77 FuncValue::NativeCondFnError(functions::num::control::gt),
78 );
79 self.funcs.insert(
80 String::from("gte"),
81 FuncValue::NativeCondFnError(functions::num::control::gte),
82 );
83 self.funcs.insert(
84 String::from("lt"),
85 FuncValue::NativeCondFnError(functions::num::control::lt),
86 );
87 self.funcs.insert(
88 String::from("lte"),
89 FuncValue::NativeCondFnError(functions::num::control::lte),
90 );
91
92 self.funcs.insert(
93 String::from("if"),
94 FuncValue::NativeCondFnError(functions::control::if_::if_),
95 );
96 self.funcs.insert(
97 String::from("if2"),
98 FuncValue::NativeCondFnError(functions::control::if2::if2),
99 );
100 self.funcs.insert(
101 String::from("if3"),
102 FuncValue::NativeCondFnError(functions::control::if3::if3),
103 );
104 self.funcs.insert(
105 String::from("ifequal"),
106 FuncValue::NativeCondFnError(functions::control::ifequal::ifequal),
107 );
108 self.funcs.insert(
109 String::from("ifgreater"),
110 FuncValue::NativeCondFnError(functions::control::ifgreater::ifgreater),
111 );
112 self.funcs.insert(
113 String::from("iflonger"),
114 FuncValue::NativeCondFnError(functions::control::iflonger::iflonger),
115 );
116 self.funcs.insert(
117 String::from("select"),
118 FuncValue::NativeCondFnError(functions::control::select::select),
119 );
120 self.funcs.insert(
121 String::from("and"),
122 FuncValue::NativeCondFnError(functions::control::and::and),
123 );
124 self.funcs.insert(
125 String::from("or"),
126 FuncValue::NativeCondFnError(functions::control::or::or),
127 );
128 self.funcs.insert(
129 String::from("xor"),
130 FuncValue::NativeCondFnError(functions::control::xor::xor),
131 );
132 self.funcs.insert(
133 String::from("not"),
134 FuncValue::NativeCondFnError(functions::control::not::not),
135 );
136
137 self.funcs.insert(
138 String::from("crlf"),
139 FuncValue::NativeCondFnError(functions::str::constants::crlf),
140 );
141 self.funcs.insert(
142 String::from("tab"),
143 FuncValue::NativeCondFnError(functions::str::constants::tab),
144 );
145 self.funcs.insert(
146 String::from("noop"),
147 FuncValue::NativeCondFnError(functions::str::constants::noop),
148 );
149
150 self.funcs.insert(
151 String::from("upper"),
152 FuncValue::NativeCondFnError(functions::str::case::upper),
153 );
154 self.funcs.insert(
155 String::from("lower"),
156 FuncValue::NativeCondFnError(functions::str::case::lower),
157 );
158 self.funcs.insert(
159 String::from("firstalphachar"),
160 FuncValue::NativeCondFnError(functions::str::case::firstalphachar),
161 );
162
163 self.funcs.insert(
164 String::from("len"),
165 FuncValue::NativeCondFnError(functions::str::size::len),
166 );
167 self.funcs.insert(
168 String::from("longer"),
169 FuncValue::NativeCondFnError(functions::str::size::longer),
170 );
171
172 self.funcs.insert(
173 String::from("stripprefix"),
174 FuncValue::NativeCondFnError(functions::str::modify::stripprefix),
175 );
176 self.funcs.insert(
177 String::from("swapprefix"),
178 FuncValue::NativeCondFnError(functions::str::modify::swapprefix),
179 );
180 self.funcs.insert(
181 String::from("cut"),
182 FuncValue::NativeCondFnError(functions::str::modify::cut),
183 );
184 self.funcs.insert(
185 String::from("left"),
186 FuncValue::NativeCondFnError(functions::str::modify::left),
187 );
188 self.funcs.insert(
189 String::from("num"),
190 FuncValue::NativeCondFnError(functions::str::format::num),
191 );
192
193 self.funcs.insert(
194 String::from("meta"),
195 FuncValue::NativeEnvFnError(Environment::meta_value),
196 );
197 self.funcs.insert(
198 String::from("meta_sep"),
199 FuncValue::NativeEnvFnError(Environment::meta_sep_value),
200 );
201 self.funcs.insert(
202 String::from("meta_num"),
203 FuncValue::NativeEnvFnError(Environment::meta_num_value),
204 );
205 self.funcs.insert(
206 String::from("meta_test"),
207 FuncValue::NativeEnvFnError(Environment::meta_test_value),
208 );
209 self.funcs.insert(
210 String::from("get"),
211 FuncValue::NativeEnvFnError(Environment::get_value),
212 );
213 self.funcs.insert(
214 String::from("put"),
215 FuncValue::NativeEnvFnError(Environment::put_value),
216 );
217 self.funcs.insert(
218 String::from("puts"),
219 FuncValue::NativeEnvFnError(Environment::puts_value),
220 );
221
222 self.funcs.insert(
223 String::from("year"),
224 FuncValue::NativeCondFnError(functions::str::datetime::year),
225 );
226 }
227
228 pub fn new(metadata: HashMap<String, Vec<String>>) -> Self {
250 let mut env = Environment {
251 vars: RefCell::new(HashMap::new()),
252 metadata: metadata.clone(),
253 funcs: HashMap::new(),
254 };
255 Self::add_default_functions(&mut env);
256 env
257 }
258
259 fn put_value(&self, args: Vec<Value>) -> Result<Value, Error> {
260 match args.len() {
261 2 => Ok(value_string(&self.put(&args[0].val, &args[1].val), true)),
262 _ => Err(InvalidNativeFunctionArgs(String::from("put"), args.len())),
263 }
264 }
265
266 fn put(&self, key: &str, val: &str) -> String {
268 let s = String::from(val);
269 self.vars.borrow_mut().insert(String::from(key), s.clone());
270 s
271 }
272
273 fn puts_value(&self, args: Vec<Value>) -> Result<Value, Error> {
274 match args.len() {
275 2 => Ok(value_string(
276 {
277 self.puts(&args[0].val, &args[1].val);
278 ""
279 },
280 true,
281 )),
282 _ => Err(InvalidNativeFunctionArgs(String::from("puts"), args.len())),
283 }
284 }
285
286 fn puts(&self, key: &str, val: &str) {
288 self.vars
289 .borrow_mut()
290 .insert(String::from(key), String::from(val));
291 }
292
293 fn get_value(&self, args: Vec<Value>) -> Result<Value, Error> {
294 match args.len() {
295 1 => Ok(self.get(&args[0].val)),
296 _ => Err(InvalidNativeFunctionArgs(String::from("get"), args.len())),
297 }
298 }
299
300 fn get(&self, key: &str) -> Value {
302 match self.vars.borrow().get(key) {
303 Some(v) => Value {
304 val: v.clone(),
305 cond: true,
306 },
307 None => Value {
308 val: String::from("?"),
309 cond: false,
310 },
311 }
312 }
313
314 pub fn get_variable(&self, key: &str) -> Value {
315 self.meta_i(key, 0)
316 }
317
318 fn meta_i(&self, key: &str, i: usize) -> Value {
320 match self.metadata.get(key) {
321 Some(v) => {
322 if i >= v.len() {
323 value_string("?", false)
324 } else {
325 value_string(&v[i], true)
326 }
327 }
328 None => value_string("?", false),
329 }
330 }
331
332 fn meta(&self, key: &str) -> Value {
334 self.meta_sep(key, ", ")
335 }
336
337 fn meta_sep(&self, key: &str, sep: &str) -> Value {
339 self.meta_sep_with_last(key, sep, sep)
340 }
341
342 fn meta_sep_with_last(&self, key: &str, sep: &str, last_sep: &str) -> Value {
344 match self.metadata.get(key) {
345 Some(v) => {
346 let mut s = String::from("");
347 for (i, val) in v.iter().enumerate() {
348 if i > 0 && i + 1 >= v.len() {
349 s.push_str(last_sep);
350 } else if i > 0 {
351 s.push_str(sep);
352 }
353 s.push_str(val);
354 }
355 value_string(&s, true)
356 }
357 None => value_string("?", false),
358 }
359 }
360
361 fn meta_num(&self, key: &str) -> usize {
362 match self.metadata.get(key) {
363 Some(v) => v.len(),
364 None => 0,
365 }
366 }
367
368 fn meta_value(&self, args: Vec<Value>) -> Result<Value, Error> {
379 match args.len() {
380 1 => Ok(self.meta(&args[0].val)),
381 2 => Ok(self.meta_i(&args[0].val, to_int(&args[1].val) as usize)),
382 _ => Err(InvalidNativeFunctionArgs(String::from("meta"), args.len())),
383 }
384 }
385
386 fn meta_sep_value(&self, args: Vec<Value>) -> Result<Value, Error> {
398 match args.len() {
399 2 => Ok(self.meta_sep(&args[0].val, &args[1].val)),
400 3 => Ok(self.meta_sep_with_last(&args[0].val, &args[1].val, &args[2].val)),
401 _ => Err(InvalidNativeFunctionArgs(
402 String::from("meta_sep"),
403 args.len(),
404 )),
405 }
406 }
407
408 fn meta_test_value(&self, args: Vec<Value>) -> Result<Value, Error> {
414 match args.len() {
415 0 => Err(InvalidNativeFunctionArgs(
416 String::from("meta_num"),
417 args.len(),
418 )),
419 _ => Ok(value_string(
420 "",
421 args.iter().all(|i| self.meta_num(&i.val) > 0),
422 )),
423 }
424 }
425
426 fn meta_num_value(&self, args: Vec<Value>) -> Result<Value, Error> {
432 match args.len() {
433 1 => Ok(value_string(&self.meta_num(&args[0].val).to_string(), true)),
434 _ => Err(InvalidNativeFunctionArgs(
435 String::from("meta_num"),
436 args.len(),
437 )),
438 }
439 }
440
441 pub fn call(&self, name: &str, args: Vec<Value>) -> Result<Value, Error> {
442 let f = { self.funcs.get(name) };
443 match f {
444 Some(func_val) => match func_val {
445 FuncValue::NativeFn(func) => {
446 let c = args.iter().all(|val| val.cond);
448 Ok(Value {
449 val: func(args.iter().map(|a| a.val.clone()).collect()),
450 cond: c,
451 })
452 }
453 FuncValue::NativeFnError(func) => {
454 let c = args.iter().all(|val| val.cond);
456 Ok(Value {
457 val: func(args.iter().map(|a| a.val.clone()).collect())?,
458 cond: c,
459 })
460 }
461 FuncValue::NativeCondFnError(func) => Ok(func(args)?),
462 FuncValue::NativeEnvFnError(func) => Ok(func(self, args)?),
463 },
464 None => Err(Error::UndefinedFunction(String::from(name))),
465 }
466 }
467}
468
469#[cfg(test)]
470mod tests {
471 use super::*;
472
473 #[test]
474 fn test_put_get() {
475 let env = Environment::new(HashMap::new());
476 assert_eq!(env.put("a", "val"), String::from("val"));
477 assert_eq!(env.get("a"), value_string("val", true));
478 }
479
480 #[test]
481 fn test_put_get_value() {
482 let env = Environment::new(HashMap::new());
483
484 assert_eq!(
485 env.put_value(vec![value_string("a", true), value_string("val", true)])
486 .unwrap(),
487 value_string("val", true)
488 );
489 assert_eq!(
490 env.get_value(vec![value_string("a", true)]).unwrap(),
491 value_string("val", true)
492 );
493
494 assert_eq!(
495 env.puts_value(vec![value_string("b", true), value_string("bar", true)])
496 .unwrap(),
497 value_string("", true)
498 );
499 assert_eq!(
500 env.get_value(vec![value_string("b", true)]).unwrap(),
501 value_string("bar", true)
502 );
503 }
504
505 #[test]
506 fn test_puts_get() {
507 let env = Environment::new(HashMap::new());
508 env.puts("a", "val");
509 assert_eq!(env.get("a"), value_string("val", true));
510 }
511
512 #[test]
513 fn test_get_unknown() {
514 let env = Environment::new(HashMap::new());
515 assert_eq!(env.get("invalid"), value_string("?", false));
516 }
517
518 #[test]
519 fn test_call() {
520 let env = Environment::new(HashMap::new());
521 assert_eq!(
522 env.call(
523 "add",
524 vec![value_string("2", true), value_string("2", true)]
525 )
526 .unwrap(),
527 value_string("4", true)
528 );
529 }
530
531 #[test]
532 fn test_call_unknown() {
533 let env = Environment::new(HashMap::new());
534 assert_eq!(
535 env.call("unknown", vec![]).err().unwrap(),
536 Error::UndefinedFunction(String::from("unknown"))
537 );
538 }
539
540 #[test]
541 fn wrong_n_arguments() {
542 let env = Environment::new(HashMap::new());
543 assert_eq!(
544 env.meta_value(vec![]).err().unwrap(),
545 InvalidNativeFunctionArgs(String::from("meta"), 0)
546 );
547 assert_eq!(
548 env.meta_sep_value(vec![]).err().unwrap(),
549 InvalidNativeFunctionArgs(String::from("meta_sep"), 0)
550 );
551 assert_eq!(
552 env.meta_num_value(vec![]).err().unwrap(),
553 InvalidNativeFunctionArgs(String::from("meta_num"), 0)
554 );
555 assert_eq!(
556 env.put_value(vec![]).err().unwrap(),
557 InvalidNativeFunctionArgs(String::from("put"), 0)
558 );
559 assert_eq!(
560 env.puts_value(vec![]).err().unwrap(),
561 InvalidNativeFunctionArgs(String::from("puts"), 0)
562 );
563 assert_eq!(
564 env.get_value(vec![]).err().unwrap(),
565 InvalidNativeFunctionArgs(String::from("get"), 0)
566 );
567 }
568
569 #[test]
570 fn test_meta() {
571 let mut m = HashMap::new();
572 m.insert(
573 String::from("a"),
574 vec![
575 String::from("0"),
576 String::from("1"),
577 String::from("2"),
578 String::from("3"),
579 ],
580 );
581 let env = Environment::new(m);
582 assert_eq!(
583 env.meta_value(vec![value_string("a", true)]).unwrap(),
584 value_string("0, 1, 2, 3", true)
585 );
586 assert_eq!(
587 env.meta_value(vec![value_string("a", true), value_string("1", true)])
588 .unwrap(),
589 value_string("1", true)
590 );
591 assert_eq!(
592 env.meta_value(vec![value_string("a", true), value_string("1000", true)])
593 .unwrap(),
594 value_string("?", false)
595 );
596 }
597
598 #[test]
599 fn test_meta_sep() {
600 let mut m = HashMap::new();
601 m.insert(
602 String::from("a"),
603 vec![
604 String::from("0"),
605 String::from("1"),
606 String::from("2"),
607 String::from("3"),
608 ],
609 );
610 let env = Environment::new(m);
611 assert_eq!(
612 env.meta_sep_value(vec![value_string("a", true), value_string("|", true)])
613 .unwrap(),
614 value_string("0|1|2|3", true)
615 );
616 assert_eq!(
617 env.meta_sep_value(vec![
618 value_string("a", true),
619 value_string("|", true),
620 value_string("^", true)
621 ])
622 .unwrap(),
623 value_string("0|1|2^3", true)
624 );
625 }
626
627 #[test]
628 fn test_meta_num() {
629 let mut m = HashMap::new();
630 m.insert(
631 String::from("a"),
632 vec![
633 String::from("0"),
634 String::from("1"),
635 String::from("2"),
636 String::from("3"),
637 ],
638 );
639 let env = Environment::new(m);
640 assert_eq!(
641 env.meta_num_value(vec![value_string("a", true)]).unwrap(),
642 value_string("4", true)
643 );
644 assert_eq!(
645 env.meta_num_value(vec![value_string("unknown", true)])
646 .unwrap(),
647 value_string("0", true)
648 );
649 }
650
651 #[test]
652 fn test_meta_test() {
653 let mut m = HashMap::new();
654 m.insert(
655 String::from("a"),
656 vec![
657 String::from("0"),
658 String::from("1"),
659 String::from("2"),
660 String::from("3"),
661 ],
662 );
663 m.insert(String::from("b"), vec![String::from("4")]);
664 let env = Environment::new(m);
665 assert_eq!(
666 env.meta_test_value(vec![value_string("a", true), value_string("b", true)])
667 .unwrap(),
668 value_string("", true)
669 );
670 assert_eq!(
671 env.meta_test_value(vec![value_string("unknown", true),])
672 .unwrap(),
673 value_string("", false)
674 );
675 }
676}