lci/
eval.rs

1use parser::{AST, Expr, Operation};
2use std::{
3    cell::RefCell,
4    collections::HashMap,
5    io,
6    result::Result as StdResult
7};
8use types::Value;
9
10#[derive(Debug, Fail)]
11pub enum Error {
12    #[fail(display = "attempt to divide by zero")]
13    DivideByZero,
14    #[fail(display = "cannot cast value to that type")]
15    InvalidCast,
16    #[fail(display = "loop variable cannot be casted to numbr")]
17    InvalidCastLoop,
18    #[fail(display = "function {:?} expected {} parameters", _0, _1)]
19    InvalidUsage(String, usize),
20    #[fail(display = "io error: {}", _0)]
21    IoError(io::Error),
22    #[fail(display = "recursion limit reached: can't go more than {} levels deep", _0)]
23    RecursionLimit(usize),
24    #[fail(display = "can't shadow variable from the same scope: {:?}", _0)]
25    ShadowVar(String),
26    #[fail(display = "undefined function {:?}", _0)]
27    UndefinedFunc(String),
28    #[fail(display = "undefined variable {:?}", _0)]
29    UndefinedVar(String)
30}
31
32type Result<T> = StdResult<T, Error>;
33
34pub enum Return {
35    None,
36    Gtfo,
37    Value(Value)
38}
39
40struct Function {
41    args: Vec<String>,
42    block: Vec<AST>
43}
44
45/// Parameters global to the whole evaluation
46pub struct EvalParams<R: io::BufRead, W: io::Write> {
47    stdin: R,
48    stdout: W,
49
50    funcs: HashMap<String, (Option<usize>, Box<FnMut(Vec<Value>) -> Value>)>,
51    recursion_limit: usize,
52    recursion: usize
53}
54impl<R: io::BufRead, W: io::Write> EvalParams<R, W> {
55    pub fn new(stdin: R, stdout: W) -> Self {
56        Self {
57            stdin: stdin,
58            stdout: stdout,
59
60            funcs: HashMap::new(),
61            recursion_limit: 64,
62            recursion: 0
63        }
64    }
65    /// Set the recursion limit
66    pub fn set_recursion_limit(&mut self, limit: usize) {
67        self.recursion_limit = limit;
68    }
69    /// Bind a LOLCODE function to a rust closure
70    pub fn bind_func<S, F>(&mut self, name: S, args: Option<usize>, func: F)
71        where S: Into<String>,
72              F: FnMut(Vec<Value>) -> Value + 'static
73    {
74        self.funcs.insert(name.into(), (args, Box::new(func)));
75    }
76    /// Create a new top-level scope with this evaluator.
77    /// Use the return value of this to evaluate AST.
78    pub fn scope<'a>(self) -> Scope<'a, R, W> {
79        Scope {
80            params: Some(RefCell::new(self)),
81
82            it: RefCell::new(Value::Noob),
83            vars: RefCell::new(HashMap::new()),
84            funcs: RefCell::new(HashMap::new()),
85            parent: None
86        }
87    }
88}
89
90/// Parameters local to the current scope
91pub struct Scope<'a, R: io::BufRead + 'a, W: io::Write + 'a> {
92    params: Option<RefCell<EvalParams<R, W>>>,
93
94    it: RefCell<Value>,
95    vars: RefCell<HashMap<String, Value>>,
96    funcs: RefCell<HashMap<String, Function>>,
97    parent: Option<&'a Scope<'a, R, W>>
98}
99impl<'a, R: io::BufRead, W: io::Write> Scope<'a, R, W> {
100    pub fn params(&self) -> &RefCell<EvalParams<R, W>> {
101        let mut me = self;
102        while let Some(parent) = me.parent {
103            me = parent;
104        }
105        me.params.as_ref().expect("Missing 'params' on top-level scope")
106    }
107    pub fn find_var<F, T>(&self, name: &str, apply: F) -> Option<T>
108        where F: FnOnce(&mut Value) -> T
109    {
110        let mut me = self;
111        loop {
112            let mut vars = me.vars.borrow_mut();
113            if let Some(var) = vars.get_mut(name) {
114                break Some(apply(var));
115            } else if let Some(parent) = me.parent {
116                me = parent;
117            } else {
118                break None;
119            }
120        }
121    }
122    pub fn call_func(&self, name: &str, args: Vec<Value>) -> Result<Value> {
123        {
124            let params = self.params();
125            let params = &mut params.borrow_mut();
126
127            // Check for any library defined functions
128            if let Some(&mut (nargs, ref mut func)) = params.funcs.get_mut(name) {
129                if let Some(nargs) = nargs {
130                    if args.len() != nargs {
131                        return Err(Error::InvalidUsage(name.to_string(), nargs));
132                    }
133                }
134                return Ok(func(args));
135            }
136
137            // Prevent stack overflow
138            params.recursion += 1;
139            if params.recursion > params.recursion_limit {
140                return Err(Error::RecursionLimit(params.recursion_limit));
141            }
142        }
143        // Traverse down scopes
144        let mut me = self;
145        Ok(loop {
146            let block = match me.funcs.borrow_mut().get_mut(name) {
147                None => None,
148                Some(the_func) => {
149                    if args.len() != the_func.args.len() {
150                        return Err(Error::InvalidUsage(name.to_string(), the_func.args.len()));
151                    }
152
153                    let mut vars = me.vars.borrow_mut();
154                    for (i, arg) in args.iter().enumerate() {
155                        vars.insert(the_func.args[i].clone(), arg.clone());
156                    }
157                    Some(the_func.block.clone())
158                }
159            };
160            if let Some(block) = block {
161                let scope = me.scope();
162                let val = match scope.eval_all(block)? {
163                    Return::None => scope.it.borrow().clone(),
164                    Return::Gtfo => Value::Noob,
165                    Return::Value(val) => val
166                };
167                {
168                    let params = &mut me.params();
169                    params.borrow_mut().recursion -= 1;
170                }
171                break val;
172            } else if let Some(parent) = me.parent {
173                me = parent;
174            } else {
175                return Err(Error::UndefinedFunc(name.to_string()));
176            }
177        })
178    }
179    pub fn scope(&'a self) -> Self {
180        Self {
181            params: None,
182
183            it: self.it.clone(),
184            vars: RefCell::new(HashMap::new()),
185            funcs: RefCell::new(HashMap::new()),
186            parent: Some(self)
187        }
188    }
189
190    fn apply_num<F1, F2>(&self, one: Expr, two: Expr, if_numbr: F1, if_numbar: F2) -> Result<Value>
191        where F1: FnOnce(i64, i64) -> Result<i64>,
192              F2: FnOnce(f64, f64) -> f64
193    {
194        let one = self.eval_expr(one)?;
195        let two = self.eval_expr(two)?;
196        if one.is_numbar() || two.is_numbar() {
197            Ok(Value::Numbar(if_numbar(
198                one.cast_numbar().ok_or(Error::InvalidCast)?,
199                two.cast_numbar().ok_or(Error::InvalidCast)?
200            )))
201        } else {
202            Ok(Value::Numbr(if_numbr(
203                one.cast_numbr().ok_or(Error::InvalidCast)?,
204                two.cast_numbr().ok_or(Error::InvalidCast)?
205            )?))
206        }
207    }
208    fn apply_any<F>(&self, one: Expr, two: Expr, apply: F) -> Result<Value>
209        where F: FnOnce(Value, Value) -> bool
210    {
211        Ok(Value::Troof(apply(self.eval_expr(one)?, self.eval_expr(two)?)))
212    }
213    fn apply_bool<F>(&self, one: Expr, two: Expr, apply: F) -> Result<Value>
214        where F: FnOnce(bool, bool) -> bool
215    {
216        self.apply_any(one, two, |x, y| apply(x.cast_troof(), y.cast_troof()))
217    }
218    pub fn eval_expr(&self, expr: Expr) -> Result<Value> {
219        macro_rules! apply_num {
220            ($one:expr, $two:expr, $func:ident, $op:tt) => {
221                self.apply_num(*$one, *$two, |x, y| Ok(x.$func(y)), |x, y| x $op y)
222            }
223        }
224        match expr {
225            Expr::It => Ok(self.it.borrow().clone()),
226            Expr::Value(mut val) => {
227                if let Some(missing) = val.interpolate(|var| self.find_var(var, |var| var.clone())) {
228                    return Err(Error::UndefinedVar(missing));
229                }
230                Ok(val)
231            },
232            Expr::Var(ident) => {
233                if let Some(val) = self.find_var(&ident, |var| var.clone()) {
234                    return Ok(val);
235                } else {
236                    return Err(Error::UndefinedVar(ident));
237                }
238            },
239            Expr::IIz(name, args) => {
240                let mut args_val = Vec::with_capacity(args.len());
241                for arg in args {
242                    args_val.push(self.eval_expr(arg)?);
243                }
244                self.call_func(&name, args_val)
245            },
246
247            Expr::SumOf(one, two) => apply_num!(one, two, wrapping_add, +),
248            Expr::DiffOf(one, two) => apply_num!(one, two, wrapping_sub, -),
249            Expr::ProduktOf(one, two) => apply_num!(one, two, wrapping_mul, *),
250            Expr::QuoshuntOf(one, two) => self.apply_num(*one, *two, |x, y| {
251                if y == 0 {
252                    return Err(Error::DivideByZero);
253                }
254                Ok(x / y)
255            }, |x, y| x / y),
256            Expr::ModOf(one, two) => self.apply_num(*one, *two, |x, y| {
257                if y == 0 {
258                    return Err(Error::DivideByZero);
259                }
260                Ok(x % y)
261            }, |x, y| x % y),
262            Expr::BiggrOf(one, two) => self.apply_num(*one, *two, |x, y| Ok(x.max(y)), |x, y| x.max(y)),
263            Expr::SmallrOf(one, two) => self.apply_num(*one, *two, |x, y| Ok(x.min(y)), |x, y| x.min(y)),
264
265            Expr::BothOf(one, two) => self.apply_bool(*one, *two, |x, y| x && y),
266            Expr::EitherOf(one, two) => self.apply_bool(*one, *two, |x, y| x || y),
267            Expr::WonOf(one, two) => self.apply_bool(*one, *two, |x, y| x ^ y),
268            Expr::Not(inner) => Ok(Value::Troof(!self.eval_expr(*inner)?.cast_troof())),
269            Expr::AllOf(values) => {
270                for value in values {
271                    if !self.eval_expr(value)?.cast_troof() {
272                        return Ok(Value::Troof(false))
273                    }
274                }
275                Ok(Value::Troof(true))
276            },
277            Expr::AnyOf(values) => {
278                for value in values {
279                    if self.eval_expr(value)?.cast_troof() {
280                        return Ok(Value::Troof(true))
281                    }
282                }
283                Ok(Value::Troof(false))
284            },
285
286            Expr::BothSaem(one, two) => self.apply_any(*one, *two, |x, y| x.equals(&y)),
287            Expr::Diffrint(one, two) => self.apply_any(*one, *two, |x, y| !x.equals(&y)),
288
289            Expr::Smoosh(exprs) => {
290                let mut result = String::new();
291                for expr in exprs {
292                    result.push_str(&self.eval_expr(expr)?.cast_yarn().ok_or(Error::InvalidCast)?);
293                }
294                Ok(Value::Yarn(result))
295            }
296        }
297    }
298    pub fn eval(&self, ast: AST) -> Result<Return> {
299        match ast {
300            AST::IHasA(ident, expr) => {
301                let val = self.eval_expr(expr)?;
302                {
303                    let mut vars = self.vars.borrow_mut();
304                    if vars.contains_key(&ident) {
305                        return Err(Error::ShadowVar(ident));
306                    }
307                    vars.insert(ident, val);
308                }
309            },
310            AST::R(ident, expr) => {
311                let val = self.eval_expr(expr)?;
312                if self.find_var(&ident, |var| *var = val).is_none() {
313                    return Err(Error::UndefinedVar(ident));
314                }
315            },
316            AST::It(expr) => {
317                let expr = self.eval_expr(expr)?;
318                *self.it.borrow_mut() = expr;
319            },
320            AST::ORly(yarly, mebbe, nowai) => {
321                if self.it.borrow().cast_troof() {
322                    return self.eval_scope(yarly);
323                }
324                for (condition, block) in mebbe {
325                    if self.eval_expr(condition)?.cast_troof() {
326                        return self.eval_scope(block);
327                    }
328                }
329                return self.eval_scope(nowai);
330            },
331            AST::Wtf(omg, omgwtf) => {
332                let mut matched = false;
333                let it = self.it.borrow();
334                for (condition, block) in omg {
335                    if matched || *it == self.eval_expr(condition)? {
336                        matched = true;
337                        match self.eval_scope(block)? {
338                            Return::None => (),
339                            Return::Gtfo => return Ok(Return::None),
340                            val @ Return::Value(_) => return Ok(val)
341                        }
342                    }
343                }
344                return self.eval_scope(omgwtf);
345            },
346            AST::ImInYr(operation, var, condition, block) => {
347                let mut scope = self.scope();
348                scope.vars.borrow_mut().insert(var.clone(), Value::Numbr(0));
349                while condition.is_none() || scope.eval_expr(condition.clone().unwrap())?.cast_troof() {
350                    match scope.eval_scope(block.clone())? {
351                        Return::None => (),
352                        Return::Gtfo => return Ok(Return::None),
353                        val @ Return::Value(_) => return Ok(val)
354                    }
355                    let val = scope.vars.borrow_mut()[&var].clone();
356                    let val = match operation {
357                        Operation::Uppin => Value::Numbr(val.cast_numbr().ok_or(Error::InvalidCastLoop)? + 1),
358                        Operation::Nerfin => Value::Numbr(val.cast_numbr().ok_or(Error::InvalidCastLoop)? - 1),
359                        Operation::IIz(ref name) => scope.call_func(&name, vec![val])?
360                    };
361                    *scope.vars.borrow_mut().get_mut(&var).unwrap() = val;
362                }
363            },
364            AST::HowIzI(name, args, block) => {
365                self.funcs.borrow_mut().insert(name, Function {
366                    args: args,
367                    block: block
368                });
369            },
370
371            AST::Gtfo => return Ok(Return::Gtfo),
372            AST::FoundYr(expr) => return Ok(Return::Value(self.eval_expr(expr)?)),
373
374            AST::Visible(exprs, newline) => {
375                let mut result = String::new();
376                for expr in exprs {
377                    result.push_str(&self.eval_expr(expr)?.cast_yarn().ok_or(Error::InvalidCast)?);
378                }
379                let stdout = &mut self.params().borrow_mut().stdout;
380                stdout.write_all(result.as_bytes()).map_err(|err| Error::IoError(err))?;
381                if newline {
382                    stdout.write_all(b"\n").map_err(|err| Error::IoError(err))?;
383                } else {
384                    stdout.flush().map_err(|err| Error::IoError(err))?;
385                }
386            },
387            AST::Gimmeh(ident) => {
388                let stdin = &mut self.params().borrow_mut().stdin;
389
390                let mut text = String::new();
391                stdin.read_line(&mut text).map_err(|err| Error::IoError(err))?;
392
393                let text = text.trim().to_string();
394                self.vars.borrow_mut().insert(ident, Value::Yarn(text));
395            }
396        }
397        Ok(Return::None)
398    }
399    /// Evaluate all lines of ASTs. You probably want to use this for running code.
400    pub fn eval_all<I: IntoIterator<Item = AST>>(&self, asts: I) -> Result<Return> {
401        for line in asts.into_iter() {
402            match self.eval(line)? {
403                Return::None => (),
404                val => return Ok(val)
405            }
406        }
407        Ok(Return::None)
408    }
409    /// Evaluate all lines of ASTs in a new child scope. Convenience function.
410    pub fn eval_scope<I: IntoIterator<Item = AST>>(&self, asts: I) -> Result<Return> {
411        self.scope().eval_all(asts)
412    }
413}