Skip to main content

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 {
40            argument,
41            ..
42        }) => {
43            let val = eval_expression(argument, env)?;
44            return Ok(Rc::new(Object::ReturnValue(val)));
45        }
46        Statement::Let(Let {
47            identifier: id,
48            expr,
49            ..
50        }) => {
51            let val = eval_expression(expr, &Rc::clone(env))?;
52            let obj: Rc<Object> = Rc::clone(&val);
53            if let TokenKind::IDENTIFIER {
54                name,
55            } = &id.kind
56            {
57                env.borrow_mut().set(name.clone(), obj);
58            }
59            return Ok(Rc::new(Object::Null));
60        }
61    }
62}
63
64fn is_truthy(obj: &Object) -> bool {
65    match obj {
66        Object::Null => return false,
67        Object::Boolean(false) => return false,
68        _ => true,
69    }
70}
71
72fn eval_expression(expression: &Expression, env: &Env) -> Result<Rc<Object>, EvalError> {
73    match expression {
74        Expression::LITERAL(literal) => eval_literal(literal, env),
75        Expression::PREFIX(UnaryExpression {
76            op,
77            operand: expr,
78            ..
79        }) => {
80            let right = eval_expression(expr, &Rc::clone(env))?;
81            return eval_prefix(op, &right);
82        }
83        Expression::INFIX(BinaryExpression {
84            op,
85            left,
86            right,
87            ..
88        }) => {
89            let left = eval_expression(left, &Rc::clone(env))?;
90            let right = eval_expression(right, &Rc::clone(env))?;
91            return eval_infix(op, &left, &right);
92        }
93        Expression::IF(IF {
94            condition,
95            consequent,
96            alternate,
97            ..
98        }) => {
99            let condition = eval_expression(condition, &Rc::clone(env))?;
100            if is_truthy(&condition) {
101                eval_block_statements(&(consequent.body), env)
102            } else {
103                match alternate {
104                    Some(alt) => eval_block_statements(&(alt.body), env),
105                    None => Ok(Rc::new(Object::Null)),
106                }
107            }
108        }
109        Expression::IDENTIFIER(IDENTIFIER {
110            name: id,
111            ..
112        }) => eval_identifier(&id, env),
113        Expression::FUNCTION(FunctionDeclaration {
114            params,
115            body,
116            ..
117        }) => {
118            return Ok(Rc::new(Object::Function(params.clone(), body.clone(), Rc::clone(env))));
119        }
120        Expression::FunctionCall(FunctionCall {
121            callee,
122            arguments,
123            ..
124        }) => {
125            let func = eval_expression(callee, &Rc::clone(env))?;
126            let args = eval_expressions(arguments, env)?;
127            apply_function(&func, &args)
128        }
129        Expression::Index(Index {
130            object: left,
131            index,
132            ..
133        }) => {
134            let literal = eval_expression(left, &Rc::clone(env))?;
135            let index = eval_expression(index, env)?;
136            eval_index_expression(&literal, &index)
137        }
138    }
139}
140
141fn eval_index_expression(left: &Rc<Object>, index: &Rc<Object>) -> Result<Rc<Object>, EvalError> {
142    match (&**left, &**index) {
143        (Object::Array(arr), Object::Integer(idx)) => match arr.get(*idx as usize) {
144            Some(obj) => return Ok(Rc::clone(obj)),
145            None => return Ok(Rc::new(Object::Null)),
146        },
147        (Object::Hash(map), key) => {
148            if !(key.is_hashable()) {
149                return Err(format!("not a valid hash key"));
150            }
151
152            match map.get(key) {
153                Some(obj) => return Ok(Rc::clone(obj)),
154                None => return Ok(Rc::new(Object::Null)),
155            }
156        }
157        _ => return Err(format!("index operator not supported for {}", left)),
158    }
159}
160
161fn apply_function(function: &Rc<Object>, args: &Vec<Rc<Object>>) -> Result<Rc<Object>, EvalError> {
162    match &**function {
163        Object::Function(params, body, env) => {
164            let mut env = Environment::new_enclosed_environment(&env);
165
166            params.iter().enumerate().for_each(|(i, param)| {
167                env.set(param.name.clone(), args[i].clone());
168            });
169
170            let evaluated = eval_block_statements(&body.body, &Rc::new(RefCell::new(env)))?;
171            return unwrap_return(evaluated);
172        }
173        Object::Builtin(b) => Ok(b(args.to_vec())),
174        f => Err(format!("expected {} to be a function", f)),
175    }
176}
177
178fn unwrap_return(obj: Rc<Object>) -> Result<Rc<Object>, EvalError> {
179    if let Object::ReturnValue(val) = &*obj {
180        Ok(Rc::clone(&val))
181    } else {
182        Ok(obj)
183    }
184}
185
186fn eval_expressions(exprs: &Vec<Expression>, env: &Env) -> Result<Vec<Rc<Object>>, EvalError> {
187    let mut list = Vec::new();
188    for expr in exprs {
189        let val = eval_expression(expr, &Rc::clone(env))?;
190        list.push(val);
191    }
192
193    Ok(list)
194}
195
196fn eval_identifier(identifier: &str, env: &Env) -> Result<Rc<Object>, EvalError> {
197    match env.borrow().get(identifier) {
198        Some(obj) => Ok(obj.clone()),
199        None => match BuiltIns.iter().find(|&&b| b.0 == identifier) {
200            Some(obj) => Ok(Rc::new(Object::Builtin(obj.1))),
201            None => Err(format!("unknown identifier {}", identifier)),
202        },
203    }
204}
205
206fn eval_prefix(op: &Token, right: &Object) -> Result<Rc<Object>, EvalError> {
207    match op.kind {
208        TokenKind::BANG => eval_prefix_bang(right),
209        TokenKind::MINUS => eval_prefix_minus(right),
210        _ => Err(format!("unknown prefix operator: {}", op)),
211    }
212}
213
214fn eval_prefix_bang(expr: &Object) -> Result<Rc<Object>, EvalError> {
215    match *expr {
216        Object::Null => Ok(Rc::new(Object::Boolean(true))),
217        Object::Boolean(b) => Ok(Rc::new(Object::Boolean(!b))),
218        _ => Ok(Rc::new(Object::Boolean(false))),
219    }
220}
221
222fn eval_prefix_minus(expr: &Object) -> Result<Rc<Object>, EvalError> {
223    match *expr {
224        Object::Integer(i) => Ok(Rc::from(Object::Integer(-i))),
225        _ => Err(format!("can't apply prefix minus operator: {}", expr)),
226    }
227}
228
229fn eval_infix(op: &Token, left: &Object, right: &Object) -> Result<Rc<Object>, EvalError> {
230    match (left, right) {
231        (Object::Integer(left), Object::Integer(right)) => {
232            return eval_integer_infix(op, *left, *right);
233        }
234        (Object::Boolean(left), Object::Boolean(right)) => {
235            return eval_boolean_infix(op, *left, *right);
236        }
237        (Object::String(left), Object::String(right)) => {
238            return eval_string_infix(op, left.to_string(), right.to_string());
239        }
240        _ => Err(format!("eval infix error for op: {}, left: {}, right: {}", op, left, right)),
241    }
242}
243
244fn eval_integer_infix(op: &Token, left: i64, right: i64) -> Result<Rc<Object>, EvalError> {
245    let result = match &op.kind {
246        TokenKind::PLUS => Object::Integer(left + right),
247        TokenKind::MINUS => Object::Integer(left - right),
248        TokenKind::ASTERISK => Object::Integer(left * right),
249        TokenKind::SLASH => Object::Integer(left / right),
250        TokenKind::LT => Object::Boolean(left < right),
251        TokenKind::GT => Object::Boolean(left > right),
252        TokenKind::EQ => Object::Boolean(left == right),
253        TokenKind::NotEq => Object::Boolean(left != right),
254        op => return Err(format!("Invalid infix operator {} for int", op)),
255    };
256
257    Ok(Rc::from(result))
258}
259
260fn eval_boolean_infix(op: &Token, left: bool, right: bool) -> Result<Rc<Object>, EvalError> {
261    let result = match &op.kind {
262        TokenKind::EQ => Object::Boolean(left == right),
263        TokenKind::NotEq => Object::Boolean(left != right),
264        op => return Err(format!("Invalid infix operator for boolean: {}", op)),
265    };
266
267    Ok(Rc::from(result))
268}
269
270fn eval_string_infix(op: &Token, left: String, right: String) -> Result<Rc<Object>, EvalError> {
271    let result = match &op.kind {
272        TokenKind::EQ => Object::Boolean(left == right),
273        TokenKind::NotEq => Object::Boolean(left != right),
274        TokenKind::PLUS => Object::String(format!("{}{}", left, right)),
275        op => return Err(format!("Invalid infix {} operator for string", op)),
276    };
277
278    Ok(Rc::from(result))
279}
280
281fn eval_literal(literal: &Literal, env: &Env) -> Result<Rc<Object>, EvalError> {
282    match literal {
283        Literal::Integer(Integer {
284            raw: i,
285            ..
286        }) => Ok(Rc::from(Object::Integer(*i))),
287        Literal::Boolean(Boolean {
288            raw: b,
289            ..
290        }) => Ok(Rc::from(Object::Boolean(*b))),
291        Literal::String(StringType {
292            raw: s,
293            ..
294        }) => Ok(Rc::from(Object::String(s.clone()))),
295        Literal::Array(Array {
296            elements,
297            ..
298        }) => {
299            let list = eval_expressions(elements, env)?;
300            return Ok(Rc::from(Object::Array(list)));
301        }
302        Literal::Hash(Hash {
303            elements: map,
304            ..
305        }) => {
306            let mut hash_map = HashMap::new();
307
308            for (k, v) in map {
309                let key = eval_expression(k, env)?;
310                if !key.is_hashable() {
311                    return Err(format!("key {} is not hashable", key));
312                }
313                let value = eval_expression(v, env)?;
314                hash_map.insert(key, value);
315            }
316
317            return Ok(Rc::new(Object::Hash(hash_map)));
318        } // l => return Err(format!("unknown literal: {}", *l))
319    }
320}