Skip to main content

kronk_core/
eval.rs

1//! Interpretter
2
3use std::{
4    collections::HashMap,
5    error::Error,
6    fmt::Display,
7    ops::{Add, Div, Mul, Sub},
8};
9
10use crate::parser::{BinaryOperator, Expr, Literal, UnaryOperator};
11
12/// An AST interpretter
13#[derive(Debug, Default, Clone)]
14pub struct Interpretter<'a> {
15    /// Local variables
16    context: HashMap<String, Literal<'a>>,
17}
18
19/// An error during execution
20#[derive(Debug, Clone, Copy)]
21pub struct RuntimeError;
22
23impl Display for RuntimeError {
24    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
25        write!(f, "Runtime Error Occured :(")
26    }
27}
28
29impl Error for RuntimeError {}
30
31impl<'a> Interpretter<'a> {
32    /// Interprets an AST
33    pub fn eval(&mut self, ast: Expr<'a>) -> Result<Literal<'a>, RuntimeError> {
34        match ast {
35            Expr::Index { item, index } => {
36                let idx = self.eval(*index)?.uint()?;
37                let item = self.eval(*item)?;
38
39                match item {
40                    Literal::String(s) => Ok(Literal::String(&s[idx..=idx])),
41                    Literal::List(l) => Ok(l[idx].clone()),
42                    _ => Err(RuntimeError),
43                }
44            }
45            Expr::List(items) => {
46                let mut literals = vec![];
47
48                for item in items {
49                    literals.push(self.eval(item)?);
50                }
51
52                Ok(Literal::List(literals))
53            }
54            Expr::Inc(name, before) => {
55                if let Some(inc) = self.context.get_mut(name) {
56                    let prev = inc.clone();
57                    *inc = Literal::Number(inc.number()? + 1.0);
58
59                    if before { Ok(prev) } else { Ok(inc.clone()) }
60                } else {
61                    // TODO: Make this a more descriptive "variable does not exist" error
62                    Err(RuntimeError)
63                }
64            }
65            Expr::AddAssign { name, add } => {
66                let val = self.eval(*add)?;
67                if let Some(inc) = self.context.get_mut(name) {
68                    *inc = (inc.clone() + val)?;
69
70                    Ok(Literal::Void)
71                } else {
72                    // TODO: Make this a more descriptive "variable does not exist" error
73                    Err(RuntimeError)
74                }
75            }
76            Expr::Reassignment { name, val } => {
77                let val = self.eval(*val)?;
78                if let Some(set) = self.context.get_mut(name) {
79                    *set = val;
80                    Ok(Literal::Void)
81                } else {
82                    // TODO: Make this a more descriptive "variable does not exist" error
83                    Err(RuntimeError)
84                }
85            }
86            Expr::Roar(expr) => {
87                let mut stringified = format!("{}", self.eval(*expr)?);
88                stringified = stringified.to_uppercase();
89                println!("{stringified}!!!");
90
91                Ok(Literal::Void)
92            }
93            Expr::ForLoop {
94                init,
95                check,
96                update,
97                exec,
98            } => {
99                self.eval(*init)?;
100                while self.eval(*check.clone())?.bool()? {
101                    self.eval(*exec.clone())?;
102                    self.eval(*update.clone())?;
103                }
104
105                Ok(Literal::Void)
106            }
107
108            Expr::WhileLoop { condition, exec } => {
109                while self.eval(*condition.clone())?.bool()? {
110                    self.eval(*exec.clone())?;
111                }
112
113                Ok(Literal::Void)
114            }
115            Expr::Conditional {
116                condition,
117                true_branch,
118                else_branch,
119            } => {
120                let cond_check = self.eval(*condition)?.bool()?;
121
122                if cond_check {
123                    self.eval(*true_branch)
124                } else if let Some(elb) = else_branch {
125                    self.eval(*elb)
126                } else {
127                    Ok(Literal::Void)
128                }
129            }
130
131            Expr::Block(exprs) => {
132                for expr in exprs {
133                    self.eval(expr)?;
134                }
135
136                Ok(Literal::Void)
137            }
138            Expr::Variable(var) => Ok(self.context[var].clone()),
139            Expr::Print(node) => {
140                println!("{}", self.eval(*node)?);
141                Ok(Literal::Void)
142            }
143            Expr::Assignment { name, val } => {
144                let val = self.eval(*val)?;
145                self.context.insert(name.to_string(), val);
146                Ok(Literal::Void)
147            }
148            Expr::Literal(l) => Ok(l),
149            Expr::Grouping(inner) => self.eval(*inner),
150            Expr::Binary { op, left, right } => op.eval(self.eval(*left)?, self.eval(*right)?),
151            Expr::Unary { op, node } => op.eval(self.eval(*node)?),
152        }
153    }
154}
155
156impl BinaryOperator {
157    /// Evaluates a binary operation
158    pub fn eval<'a>(
159        &self,
160        left: Literal<'a>,
161        right: Literal<'a>,
162    ) -> Result<Literal<'a>, RuntimeError> {
163        match self {
164            Self::Add => left + right,
165            Self::Sub => left - right,
166            Self::Mul => left * right,
167            Self::Div => left / right,
168
169            Self::Gt => Ok((left.number()? > right.number()?).into()),
170            Self::Gte => Ok((left.number()? >= right.number()?).into()),
171            Self::Lt => Ok((left.number()? < right.number()?).into()),
172            Self::Lte => Ok((left.number()? <= right.number()?).into()),
173
174            Self::Eq => left.equals(&right),
175            Self::Neq => left.not_equals(&right),
176        }
177    }
178}
179
180impl UnaryOperator {
181    /// Evaluates a unary operation
182    pub fn eval<'a>(&self, node: Literal<'a>) -> Result<Literal<'a>, RuntimeError> {
183        match self {
184            Self::Neg => Ok(Literal::Number(-node.number()?)),
185            Self::Not => Ok(Literal::from(!node.bool()?)),
186        }
187    }
188}
189
190impl Add for Literal<'_> {
191    type Output = Result<Self, RuntimeError>;
192
193    fn add(self, rhs: Self) -> Self::Output {
194        match (self, rhs) {
195            (Self::Number(n1), Self::Number(n2)) => Ok(Literal::Number(n1 + n2)),
196
197            (Self::String(s1), Self::String(s2)) => Ok(Literal::Concat(
198                Box::new(Literal::String(s1)),
199                Box::new(Literal::String(s2)),
200            )),
201
202            (Self::Number(n1), Self::String(s2)) => Ok(Literal::Concat(
203                Box::new(Literal::Number(n1)),
204                Box::new(Literal::String(s2)),
205            )),
206
207            (Self::String(s1), Self::Number(n2)) => Ok(Literal::Concat(
208                Box::new(Literal::String(s1)),
209                Box::new(Literal::Number(n2)),
210            )),
211            _ => Err(RuntimeError),
212        }
213    }
214}
215
216impl Sub for Literal<'_> {
217    type Output = Result<Self, RuntimeError>;
218    fn sub(self, rhs: Self) -> Self::Output {
219        match (self, rhs) {
220            (Self::Number(n1), Self::Number(n2)) => Ok(Self::Number(n1 - n2)),
221
222            _ => Err(RuntimeError),
223        }
224    }
225}
226
227impl Mul for Literal<'_> {
228    type Output = Result<Self, RuntimeError>;
229    fn mul(self, rhs: Self) -> Self::Output {
230        match (self, rhs) {
231            (Self::Number(n1), Self::Number(n2)) => Ok(Self::Number(n1 * n2)),
232
233            _ => Err(RuntimeError),
234        }
235    }
236}
237
238impl Div for Literal<'_> {
239    type Output = Result<Self, RuntimeError>;
240    fn div(self, rhs: Self) -> Self::Output {
241        match (self, rhs) {
242            (Self::Number(n1), Self::Number(n2)) => Ok(Self::Number(n1 / n2)),
243            _ => Err(RuntimeError),
244        }
245    }
246}
247
248impl From<bool> for Literal<'_> {
249    fn from(value: bool) -> Self {
250        if value { Literal::True } else { Literal::False }
251    }
252}
253
254impl<'a> Literal<'a> {
255    /// Returns the inner literal if it's a proper unsigned integer truly, asserting a runtime
256    /// error if not
257    pub fn uint(&self) -> Result<usize, RuntimeError> {
258        match self {
259            Self::Number(n) if *n >= 0.0 && n.round() == *n => Ok(*n as usize),
260            _ => Err(RuntimeError),
261        }
262    }
263    /// Returns the inner literal if it's numeric, asserting a runtime error if not
264    pub fn number(&self) -> Result<f64, RuntimeError> {
265        match self {
266            Self::Number(n) => Ok(*n),
267            _ => Err(RuntimeError),
268        }
269    }
270
271    /// Returns the inner literal if it's boolean, asserting a runtime error if not
272    pub fn bool(&self) -> Result<bool, RuntimeError> {
273        match self {
274            Self::True => Ok(true),
275            Self::False => Ok(false),
276            Self::Number(0.0) => Ok(false),
277            Self::Number(_) => Ok(true),
278            _ => Err(RuntimeError),
279        }
280    }
281
282    /// Returns the True literal if the two literals are losely equal
283    pub fn equals(&self, other: &Self) -> Result<Literal<'a>, RuntimeError> {
284        match (self, other) {
285            (Self::Number(n1), Self::Number(n2)) => Ok((n1 == n2).into()),
286            (Self::True, Self::True) => Ok(Self::True),
287            (Self::False, Self::False) => Ok(Self::True),
288
289            (Self::False, Self::True) => Ok(Self::False),
290            (Self::True, Self::False) => Ok(Self::False),
291
292            (Self::Void, Self::Void) => Ok(Self::True),
293
294            (crazy1, crazy2) => Ok((crazy1.to_string() == crazy2.to_string()).into()),
295        }
296    }
297
298    /// Returns the True literal if the two literals are not losely equal
299    pub fn not_equals(&self, other: &Self) -> Result<Literal<'a>, RuntimeError> {
300        match (self, other) {
301            (Self::Number(n1), Self::Number(n2)) => Ok((n1 != n2).into()),
302            (Self::True, Self::True) => Ok(Self::False),
303            (Self::False, Self::False) => Ok(Self::False),
304
305            (Self::False, Self::True) => Ok(Self::True),
306            (Self::True, Self::False) => Ok(Self::True),
307
308            (Self::Void, Self::Void) => Ok(Self::False),
309
310            (crazy1, crazy2) => Ok((crazy1.to_string() != crazy2.to_string()).into()),
311        }
312    }
313}
314
315impl Display for Expr<'_> {
316    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
317        match self {
318            Expr::Index { item, index } => write!(f, "{item}[{index}]"),
319            Expr::List(items) => write!(f, "{items:?}"),
320            Expr::AddAssign { name, add } => write!(f, "{name} += {add}"),
321            Expr::Inc(name, before) => {
322                if *before {
323                    write!(f, "++{name}")
324                } else {
325                    write!(f, "{name}++")
326                }
327            }
328            Expr::Roar(r) => write!(f, "roar {r}!"),
329            Expr::ForLoop {
330                init,
331                check,
332                update,
333                exec,
334            } => {
335                writeln!(f, "for ({init}; {check}; {update}) {exec}")
336            }
337
338            Expr::WhileLoop { condition, exec } => {
339                writeln!(f, "while ({condition}) {{\n\t{exec}\n}}")
340            }
341
342            Expr::Conditional {
343                condition,
344                true_branch,
345                else_branch,
346            } => {
347                if let Some(elb) = else_branch {
348                    writeln!(
349                        f,
350                        "if ({}) {{\n\t{}\n}} else {{\n\t{}\n}}",
351                        condition, true_branch, elb
352                    )
353                } else {
354                    writeln!(f, "if ({}) {{\n\t{}\n}}", condition, true_branch)
355                }
356            }
357            Self::Block(b) => {
358                writeln!(f, "{{")?;
359
360                for expr in b {
361                    writeln!(f, "\t{expr}")?;
362                }
363
364                write!(f, "}}")
365            }
366            Self::Variable(v) => write!(f, "{v}"),
367            Self::Print(node) => write!(f, "print {node}"),
368            Self::Assignment { name, val } => write!(f, "var {name} = {val}"),
369            Self::Reassignment { name, val } => write!(f, "{name} = {val}"),
370            Self::Literal(l) => write!(f, "{l}"),
371            Self::Unary { op, node } => match op {
372                UnaryOperator::Neg => write!(f, "-{node}"),
373                UnaryOperator::Not => write!(f, "!{node}"),
374            },
375            Self::Binary { op, left, right } => match op {
376                BinaryOperator::Add => write!(f, "{left} + {right}"),
377                BinaryOperator::Sub => write!(f, "{left} - {right}"),
378                BinaryOperator::Mul => write!(f, "{left} * {right}"),
379                BinaryOperator::Div => write!(f, "{left} / {right}"),
380
381                BinaryOperator::Eq => write!(f, "{left} == {right}"),
382                BinaryOperator::Neq => write!(f, "{left} != {right}"),
383                BinaryOperator::Gt => write!(f, "{left} > {right}"),
384                BinaryOperator::Gte => write!(f, "{left} >= {right}"),
385                BinaryOperator::Lt => write!(f, "{left} < {right}"),
386                BinaryOperator::Lte => write!(f, "{left} <= {right}"),
387            },
388            Self::Grouping(e) => write!(f, "({e})"),
389        }
390    }
391}
392
393#[cfg(test)]
394mod tests {
395    use crate::{
396        parser::{Literal, Parser},
397        tokenizer::Tokenizable,
398    };
399
400    use super::Interpretter;
401
402    #[test]
403    fn for_looping() {
404        let tokens = r#"
405            var foo = 10;
406            for (var i = 0; i < 10; var i = i + 1) {
407                var foo = foo + 1;
408            }
409            foo;
410            "#
411        .tokenize()
412        .expect("Tokenize");
413
414        let mut parser = Parser::with_tokens(&tokens);
415
416        let ast = parser.parse_many().expect("Failed to parse");
417        let mut interp = Interpretter::default();
418
419        let mut val = None;
420        for expr in ast {
421            val = Some(interp.eval(expr).expect("Interpret result"));
422        }
423
424        assert_eq!(val.unwrap(), Literal::Number(20.0))
425    }
426
427    #[test]
428    fn use_variables_later() {
429        let tokens = "var foo = 100;".tokenize().expect("Tokenize");
430        let mut parser = Parser::with_tokens(&tokens);
431
432        let ast = parser.parse().expect("Failed to parse");
433        let mut interp = Interpretter::default();
434        interp.eval(ast).expect("Interpret result");
435
436        let tokens = "foo + 1;".tokenize().expect("Tokenize");
437        let mut parser = Parser::with_tokens(&tokens);
438
439        let ast = parser.parse().expect("Failed to parse");
440
441        assert_eq!(interp.eval(ast).expect("Eval"), Literal::Number(101.0))
442    }
443
444    #[test]
445    fn simple_eval() {
446        let tokens = "var foo = 100;".tokenize().expect("Tokenize");
447        let mut parser = Parser::with_tokens(&tokens);
448
449        let ast = parser.parse().expect("Failed to parse");
450        let mut interp = Interpretter::default();
451        interp.eval(ast).expect("Interpret result");
452
453        assert_eq!(interp.context["foo"], Literal::Number(100.0))
454    }
455
456    #[test]
457    fn notting() {
458        let tokens = "!true;".tokenize().expect("Tokenize");
459        let mut parser = Parser::with_tokens(&tokens);
460
461        let ast = parser.parse().expect("Failed to parse");
462        let mut interp = Interpretter::default();
463        let res = interp.eval(ast).expect("Interpret result");
464        assert_eq!(res, Literal::False)
465    }
466
467    #[test]
468    fn negation() {
469        let tokens = "-100;".tokenize().expect("Tokenize");
470        let mut parser = Parser::with_tokens(&tokens);
471
472        let ast = parser.parse().expect("Failed to parse");
473        let mut interp = Interpretter::default();
474        let res = interp.eval(ast).expect("Interpret result");
475        assert_eq!(res, Literal::Number(-100.0))
476    }
477
478    #[test]
479    fn eval_addition() {
480        let tokens = "100 + 100;".tokenize().expect("Tokenize");
481        let mut parser = Parser::with_tokens(&tokens);
482
483        let ast = parser.parse().expect("Failed to parse");
484        let mut eval = Interpretter::default();
485
486        assert_eq!(eval.eval(ast).expect("Evaluate"), Literal::Number(200.0))
487    }
488
489    #[test]
490    fn eval_string_concat() {
491        let tokens = r#""100" + 100;"#.tokenize().expect("Tokenize");
492        let mut parser = Parser::with_tokens(&tokens);
493
494        let ast = parser.parse().expect("Failed to parse");
495        let mut eval = Interpretter::default();
496        let result = eval.eval(ast).expect("Eval").to_string();
497
498        assert_eq!(result, "100100");
499    }
500
501    #[test]
502    fn eval_string_concat_otherway() {
503        let tokens = r#"10 + "20";"#.tokenize().expect("Tokenize");
504        let mut parser = Parser::with_tokens(&tokens);
505
506        let ast = parser.parse().expect("Failed to parse");
507        let mut eval = Interpretter::default();
508        let result = eval.eval(ast).expect("Eval").to_string();
509
510        assert_eq!(result, "1020");
511    }
512
513    #[test]
514    fn loose_equality() {
515        let tokens = r#"1 == "1";"#.tokenize().expect("Tokenize");
516        let mut parser = Parser::with_tokens(&tokens);
517
518        let ast = parser.parse().expect("Failed to parse");
519        let mut eval = Interpretter::default();
520        assert_eq!(eval.eval(ast).expect("Eval"), Literal::True)
521    }
522
523    #[test]
524    fn pure_inequality() {
525        let tokens = "1 + 1 != 100 * 10;".tokenize().expect("Tokenize");
526        let mut parser = Parser::with_tokens(&tokens);
527
528        let ast = parser.parse().expect("Failed to parse");
529        let mut eval = Interpretter::default();
530        assert_eq!(eval.eval(ast).expect("Eval"), Literal::True)
531    }
532
533    #[test]
534    fn list() {
535        let tokens = r#"[12 == 1, 10 * 10, "hi"];"#.tokenize().expect("Tokenize");
536        let mut parser = Parser::with_tokens(&tokens);
537
538        let ast = parser.parse().expect("Failed to parse");
539        let mut eval = Interpretter::default();
540        assert_eq!(
541            eval.eval(ast).expect("Eval"),
542            Literal::List(vec![
543                Literal::False,
544                Literal::Number(100.0),
545                Literal::String("hi")
546            ])
547        )
548    }
549
550    #[test]
551    fn pure_equality() {
552        let tokens = "1 + 1 == 2;".tokenize().expect("Tokenize");
553        let mut parser = Parser::with_tokens(&tokens);
554
555        let ast = parser.parse().expect("Failed to parse");
556        let mut eval = Interpretter::default();
557        assert_eq!(eval.eval(ast).expect("Eval"), Literal::True)
558    }
559
560    #[test]
561    fn eval_pure_string_concat() {
562        let tokens = r#""Hello " + "World!";"#.tokenize().expect("Tokenize");
563        let mut parser = Parser::with_tokens(&tokens);
564
565        let ast = parser.parse().expect("Failed to parse");
566        let mut eval = Interpretter::default();
567        let result = eval.eval(ast).expect("Eval").to_string();
568
569        assert_eq!(result, "Hello World!");
570    }
571}