logo_interp/
executor_state.rs

1use std::collections::HashMap;
2use std::rc::Rc;
3use crate::core::*;
4
5
6#[derive(Clone)]
7pub struct Function<S> {
8    pub f: Rc<dyn Fn(&mut EState<S>, Vec<LogoValue>) -> Result<Option<LogoValue>, String>>,
9    pub args: i32
10}
11
12pub struct EState<S> {
13    pub functions: HashMap<String, Function<S>>,
14    pub logo_procedures: HashMap<String, LogoProcedure>,
15    pub vars: HashMap<String, LogoValue>,
16    pub output: Option<LogoValue>,
17    pub state: S
18}
19
20impl<S: 'static> Function<S> {
21    pub fn from_proc(f: fn(&mut EState<S>) -> Result<(), String>) -> Self {
22        return Function{f: Rc::new(
23            move |state: &mut EState<S>, _: Vec<LogoValue>| -> Result<Option<LogoValue>, String> {
24                f(state)?;
25                return Ok(None);
26        }), args: 0};
27    }
28    pub fn from_fn<Out: LogoConvertible + 'static>(f: fn(&mut EState<S>) -> Result<Out, String>) -> Self {
29        return Function{f: Rc::new(move |state: &mut EState<S>, _: Vec<LogoValue>| -> Result<Option<LogoValue>, String> {
30            return Ok(Some(f(state)?.to_logo()));
31        }), args: 0};
32    }
33
34    pub fn from_proc1<T1: LogoConvertible + 'static>
35    (f: fn(&mut EState<S>, T1) -> Result<(), String>) -> Self {
36        return Function{f: Rc::new(move |state: &mut EState<S>, mut args: Vec<LogoValue>| -> Result<Option<LogoValue>, String> {
37            let arg1 = T1::from_logo(args.pop().unwrap())?;
38            f(state, arg1)?;
39            return Ok(None);
40        }), args: 1};
41    }
42    pub fn from_fn1<T1: LogoConvertible + 'static, Out: LogoConvertible + 'static>
43    (f: fn(&mut EState<S>, T1) -> Result<Out, String>) -> Self {
44        return Function{f: Rc::new(move |state: &mut EState<S>, mut args: Vec<LogoValue>| -> Result<Option<LogoValue>, String> {
45            let arg1 = T1::from_logo(args.pop().unwrap())?;
46            return Ok(Some(f(state, arg1)?.to_logo()));
47        }), args: 1};
48    }
49
50    pub fn from_proc2<T1: LogoConvertible + 'static, T2: LogoConvertible + 'static>
51    (f: fn(&mut EState<S>, T1, T2) -> Result<(), String>) -> Self {
52        return Function{f: Rc::new(move |state: &mut EState<S>, mut args: Vec<LogoValue>| -> Result<Option<LogoValue>, String> {
53            let arg2 = T2::from_logo(args.pop().unwrap())?;
54            let arg1 = T1::from_logo(args.pop().unwrap())?;
55            f(state, arg1, arg2)?;
56            return Ok(None);
57        }), args: 2};
58    }
59    pub fn from_fn2<T1: LogoConvertible + 'static, T2: LogoConvertible + 'static, Out: LogoConvertible + 'static>
60    (f: fn(&mut EState<S>, T1, T2) -> Result<Out, String>) -> Self {
61        return Function{f: Rc::new(move |state: &mut EState<S>, mut args: Vec<LogoValue>| -> Result<Option<LogoValue>, String> {
62            let arg2 = T2::from_logo(args.pop().unwrap())?;
63            let arg1 = T1::from_logo(args.pop().unwrap())?;
64            return Ok(Some(f(state, arg1, arg2)?.to_logo()));
65        }), args: 2};
66    }
67
68    pub fn from_proc3<T1: LogoConvertible + 'static, T2: LogoConvertible + 'static, T3: LogoConvertible + 'static>
69    (f: fn(&mut EState<S>, T1, T2, T3) -> Result<(), String>) -> Self {
70        return Function{f: Rc::new(move |state: &mut EState<S>, mut args: Vec<LogoValue>| -> Result<Option<LogoValue>, String> {
71            let arg3 = T3::from_logo(args.pop().unwrap())?;
72            let arg2 = T2::from_logo(args.pop().unwrap())?;
73            let arg1 = T1::from_logo(args.pop().unwrap())?;
74            f(state, arg1, arg2, arg3)?;
75            return Ok(None);
76        }), args: 3};
77    }
78    pub fn from_fn3<T1: LogoConvertible + 'static, T2: LogoConvertible + 'static, T3: LogoConvertible + 'static, Out: LogoConvertible + 'static>
79    (f: fn(&mut EState<S>, T1, T2, T3) -> Result<Out, String>) -> Self {
80        return Function{f: Rc::new(move |state: &mut EState<S>, mut args: Vec<LogoValue>| -> Result<Option<LogoValue>, String> {
81            let arg3 = T3::from_logo(args.pop().unwrap())?;
82            let arg2 = T2::from_logo(args.pop().unwrap())?;
83            let arg1 = T1::from_logo(args.pop().unwrap())?;
84            return Ok(Some(f(state, arg1, arg2, arg3)?.to_logo()));
85        }), args: 3};
86    }
87}
88
89impl<S> EState<S> {
90    pub fn new(state: S) -> Self {
91        return EState {
92            functions: HashMap::new(),
93            logo_procedures: HashMap::new(),
94            vars: HashMap::new(),
95            output: None,
96            state
97        };
98    }
99}
100
101#[test]
102fn test_executor_function() {
103    let mut state = EState::new(5);
104
105    let sum = |_: &mut EState<i32>, x: f64, y: f64| -> Result<f64, String> {
106        Ok(x + y)
107    };
108    state.functions.insert("sum".to_string(), Function::from_fn2(sum));
109
110    let sum_fn = state.functions[&"sum".to_string()].clone();
111    assert_eq!(sum_fn.args, 2);
112    let res = (sum_fn.f)(&mut state,
113                         vec![LogoValue::Word(Word("2".to_string())), LogoValue::Word(Word("3".to_string()))]);
114    assert!(res.is_ok());
115    assert!(res.as_ref().unwrap().is_some());
116    assert_eq!(res.unwrap().unwrap(), LogoValue::Word(Word("5".to_string())));
117}