interpreter/
lib.rs

1use std::cell::RefCell;
2use std::collections::HashMap;
3use std::rc::Rc;
4
5use object::builtins::*;
6use object::environment::*;
7use object::{EvalError, Object};
8use parser::ast::*;
9use parser::lexer::token::{Token, TokenKind};
10
11mod interpreter_test;
12
13pub fn eval(node: Node, env: &Env) -> Result<Rc<Object>, EvalError> {
14    match node {
15        Node::Program(p) => eval_block_statements(&p.body, env),
16        Node::Statement(statements) => eval_statement(&statements, env),
17        Node::Expression(expression) => eval_expression(&expression, env),
18    }
19}
20
21fn eval_block_statements(statements: &Vec<Statement>, env: &Env) -> Result<Rc<Object>, EvalError> {
22    let mut result = Rc::new(Object::Null);
23    for statement in statements {
24        let val = eval_statement(statement, &Rc::clone(env))?;
25        match *val {
26            Object::ReturnValue(_) => return Ok(val),
27            _ => {
28                result = val;
29            }
30        }
31    }
32
33    return Ok(result);
34}
35
36fn eval_statement(statement: &Statement, env: &Env) -> Result<Rc<Object>, EvalError> {
37    match statement {
38        Statement::Expr(expr) => eval_expression(expr, env),
39        Statement::Return(ReturnStatement { argument, .. }) => {
40            let val = eval_expression(argument, env)?;
41            return Ok(Rc::new(Object::ReturnValue(val)));
42        }
43        Statement::Let(Let { identifier: id, expr, .. }) => {
44            let val = eval_expression(expr, &Rc::clone(env))?;
45            let obj: Rc<Object> = Rc::clone(&val);
46            if let TokenKind::IDENTIFIER { name } = &id.kind {
47                env.borrow_mut().set(name.clone(), obj);
48            }
49            return Ok(Rc::new(Object::Null));
50        }
51    }
52}
53
54fn is_truthy(obj: &Object) -> bool {
55    match obj {
56        Object::Null => return false,
57        Object::Boolean(false) => return false,
58        _ => true,
59    }
60}
61
62fn eval_expression(expression: &Expression, env: &Env) -> Result<Rc<Object>, EvalError> {
63    match expression {
64        Expression::LITERAL(literal) => eval_literal(literal, env),
65        Expression::PREFIX(UnaryExpression { op, operand: expr, .. }) => {
66            let right = eval_expression(expr, &Rc::clone(env))?;
67            return eval_prefix(op, &right);
68        }
69        Expression::INFIX(BinaryExpression { op, left, right, .. }) => {
70            let left = eval_expression(left, &Rc::clone(env))?;
71            let right = eval_expression(right, &Rc::clone(env))?;
72            return eval_infix(op, &left, &right);
73        }
74        Expression::IF(IF { condition, consequent, alternate, .. }) => {
75            let condition = eval_expression(condition, &Rc::clone(env))?;
76            if is_truthy(&condition) {
77                eval_block_statements(&(consequent.body), env)
78            } else {
79                match alternate {
80                    Some(alt) => eval_block_statements(&(alt.body), env),
81                    None => Ok(Rc::new(Object::Null)),
82                }
83            }
84        }
85        Expression::IDENTIFIER(IDENTIFIER { name: id, .. }) => eval_identifier(&id, env),
86        Expression::FUNCTION(FunctionDeclaration { params, body, .. }) => {
87            return Ok(Rc::new(Object::Function(params.clone(), body.clone(), Rc::clone(env))));
88        }
89        Expression::FunctionCall(FunctionCall { callee, arguments, .. }) => {
90            let func = eval_expression(callee, &Rc::clone(env))?;
91            let args = eval_expressions(arguments, env)?;
92            apply_function(&func, &args)
93        }
94        Expression::Index(Index { object: left, index, .. }) => {
95            let literal = eval_expression(left, &Rc::clone(env))?;
96            let index = eval_expression(index, env)?;
97            eval_index_expression(&literal, &index)
98        }
99    }
100}
101
102fn eval_index_expression(left: &Rc<Object>, index: &Rc<Object>) -> Result<Rc<Object>, EvalError> {
103    match (&**left, &**index) {
104        (Object::Array(arr), Object::Integer(idx)) => match arr.get(*idx as usize) {
105            Some(obj) => return Ok(Rc::clone(obj)),
106            None => return Ok(Rc::new(Object::Null)),
107        },
108        (Object::Hash(map), key) => {
109            if !(key.is_hashable()) {
110                return Err(format!("not a valid hash key"));
111            }
112
113            match map.get(key) {
114                Some(obj) => return Ok(Rc::clone(obj)),
115                None => return Ok(Rc::new(Object::Null)),
116            }
117        }
118        _ => return Err(format!("index operator not supported for {}", left)),
119    }
120}
121
122fn apply_function(function: &Rc<Object>, args: &Vec<Rc<Object>>) -> Result<Rc<Object>, EvalError> {
123    match &**function {
124        Object::Function(params, body, env) => {
125            let mut env = Environment::new_enclosed_environment(&env);
126
127            params.iter().enumerate().for_each(|(i, param)| {
128                env.set(param.name.clone(), args[i].clone());
129            });
130
131            let evaluated = eval_block_statements(&body.body, &Rc::new(RefCell::new(env)))?;
132            return unwrap_return(evaluated);
133        }
134        Object::Builtin(b) => Ok(b(args.to_vec())),
135        f => Err(format!("expected {} to be a function", f)),
136    }
137}
138
139fn unwrap_return(obj: Rc<Object>) -> Result<Rc<Object>, EvalError> {
140    if let Object::ReturnValue(val) = &*obj {
141        Ok(Rc::clone(&val))
142    } else {
143        Ok(obj)
144    }
145}
146
147fn eval_expressions(exprs: &Vec<Expression>, env: &Env) -> Result<Vec<Rc<Object>>, EvalError> {
148    let mut list = Vec::new();
149    for expr in exprs {
150        let val = eval_expression(expr, &Rc::clone(env))?;
151        list.push(val);
152    }
153
154    Ok(list)
155}
156
157fn eval_identifier(identifier: &str, env: &Env) -> Result<Rc<Object>, EvalError> {
158    match env.borrow().get(identifier) {
159        Some(obj) => Ok(obj.clone()),
160        None => match BuiltIns.iter().find(|&&b| b.0 == identifier) {
161            Some(obj) => Ok(Rc::new(Object::Builtin(obj.1))),
162            None => Err(format!("unknown identifier {}", identifier)),
163        },
164    }
165}
166
167fn eval_prefix(op: &Token, right: &Object) -> Result<Rc<Object>, EvalError> {
168    match op.kind {
169        TokenKind::BANG => eval_prefix_bang(right),
170        TokenKind::MINUS => eval_prefix_minus(right),
171        _ => Err(format!("unknown prefix operator: {}", op)),
172    }
173}
174
175fn eval_prefix_bang(expr: &Object) -> Result<Rc<Object>, EvalError> {
176    match *expr {
177        Object::Null => Ok(Rc::new(Object::Boolean(true))),
178        Object::Boolean(b) => Ok(Rc::new(Object::Boolean(!b))),
179        _ => Ok(Rc::new(Object::Boolean(false))),
180    }
181}
182
183fn eval_prefix_minus(expr: &Object) -> Result<Rc<Object>, EvalError> {
184    match *expr {
185        Object::Integer(i) => Ok(Rc::from(Object::Integer(-i))),
186        _ => Err(format!("can't apply prefix minus operator: {}", expr)),
187    }
188}
189
190fn eval_infix(op: &Token, left: &Object, right: &Object) -> Result<Rc<Object>, EvalError> {
191    match (left, right) {
192        (Object::Integer(left), Object::Integer(right)) => {
193            return eval_integer_infix(op, *left, *right);
194        }
195        (Object::Boolean(left), Object::Boolean(right)) => {
196            return eval_boolean_infix(op, *left, *right);
197        }
198        (Object::String(left), Object::String(right)) => {
199            return eval_string_infix(op, left.to_string(), right.to_string());
200        }
201        _ => Err(format!("eval infix error for op: {}, left: {}, right: {}", op, left, right)),
202    }
203}
204
205fn eval_integer_infix(op: &Token, left: i64, right: i64) -> Result<Rc<Object>, EvalError> {
206    let result = match &op.kind {
207        TokenKind::PLUS => Object::Integer(left + right),
208        TokenKind::MINUS => Object::Integer(left - right),
209        TokenKind::ASTERISK => Object::Integer(left * right),
210        TokenKind::SLASH => Object::Integer(left / right),
211        TokenKind::LT => Object::Boolean(left < right),
212        TokenKind::GT => Object::Boolean(left > right),
213        TokenKind::EQ => Object::Boolean(left == right),
214        TokenKind::NotEq => Object::Boolean(left != right),
215        op => return Err(format!("Invalid infix operator {} for int", op)),
216    };
217
218    Ok(Rc::from(result))
219}
220
221fn eval_boolean_infix(op: &Token, left: bool, right: bool) -> Result<Rc<Object>, EvalError> {
222    let result = match &op.kind {
223        TokenKind::EQ => Object::Boolean(left == right),
224        TokenKind::NotEq => Object::Boolean(left != right),
225        op => return Err(format!("Invalid infix operator for int: {}", op)),
226    };
227
228    Ok(Rc::from(result))
229}
230
231fn eval_string_infix(op: &Token, left: String, right: String) -> Result<Rc<Object>, EvalError> {
232    let result = match &op.kind {
233        TokenKind::EQ => Object::Boolean(left == right),
234        TokenKind::NotEq => Object::Boolean(left != right),
235        TokenKind::PLUS => Object::String(format!("{}{}", left, right)),
236        op => return Err(format!("Invalid infix {} operator for string", op)),
237    };
238
239    Ok(Rc::from(result))
240}
241
242fn eval_literal(literal: &Literal, env: &Env) -> Result<Rc<Object>, EvalError> {
243    match literal {
244        Literal::Integer(Integer { raw: i, .. }) => Ok(Rc::from(Object::Integer(*i))),
245        Literal::Boolean(Boolean { raw: b, .. }) => Ok(Rc::from(Object::Boolean(*b))),
246        Literal::String(StringType { raw: s, .. }) => Ok(Rc::from(Object::String(s.clone()))),
247        Literal::Array(Array { elements, .. }) => {
248            let list = eval_expressions(elements, env)?;
249            return Ok(Rc::from(Object::Array(list)));
250        }
251        Literal::Hash(Hash { elements: map, .. }) => {
252            let mut hash_map = HashMap::new();
253
254            for (k, v) in map {
255                let key = eval_expression(k, env)?;
256                if !key.is_hashable() {
257                    return Err(format!("key {} is not hashable", key));
258                }
259                let value = eval_expression(v, env)?;
260                hash_map.insert(key, value);
261            }
262
263            return Ok(Rc::new(Object::Hash(hash_map)));
264        } // l => return Err(format!("unknown literal: {}", *l))
265    }
266}