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::{BoundMethodObject, ClassObject, EvalError, InstanceObject, InstanceRef, Object};
8use parser::ast::*;
9use parser::lexer::token::{Token, TokenKind};
10use parser::validation::validate_program;
11
12mod interpreter_test;
13
14pub fn eval(node: Node, env: &Env) -> Result<Rc<Object>, EvalError> {
15    match node {
16        Node::Program(p) => {
17            let mut predefined_names = env.borrow().visible_names();
18            predefined_names.extend(BuiltIns.iter().map(|builtin| builtin.name.to_string()));
19            let predefined_names = predefined_names
20                .iter()
21                .map(String::as_str)
22                .collect::<Vec<_>>();
23            validate_program(&p, &predefined_names).map_err(|error| error.message)?;
24            eval_block_statements(&p.body, env)
25        }
26        Node::Statement(statements) => eval_statement(&statements, env),
27        Node::Expression(expression) => eval_expression(&expression, env),
28    }
29}
30
31fn eval_block_statements(statements: &Vec<Statement>, env: &Env) -> Result<Rc<Object>, EvalError> {
32    let mut result = Rc::new(Object::Null);
33    for statement in statements {
34        let val = eval_statement(statement, &Rc::clone(env))?;
35        match *val {
36            Object::ReturnValue(_) => return Ok(val),
37            _ => {
38                result = val;
39            }
40        }
41    }
42
43    return Ok(result);
44}
45
46fn eval_statement(statement: &Statement, env: &Env) -> Result<Rc<Object>, EvalError> {
47    match statement {
48        Statement::Expr(expr) => eval_expression(expr, env),
49        Statement::Return(ReturnStatement {
50            argument,
51            ..
52        }) => {
53            let val = eval_expression(argument, env)?;
54            return Ok(Rc::new(Object::ReturnValue(val)));
55        }
56        Statement::Let(Let {
57            identifier: id,
58            expr,
59            ..
60        }) => {
61            let val = eval_expression(expr, &Rc::clone(env))?;
62            let obj: Rc<Object> = Rc::clone(&val);
63            if let TokenKind::IDENTIFIER {
64                name,
65            } = &id.kind
66            {
67                env.borrow_mut().set(name.clone(), obj);
68            }
69            return Ok(Rc::new(Object::Null));
70        }
71        Statement::Class(class) => eval_class_declaration(class, env),
72        Statement::SetProperty(statement) => {
73            let receiver = eval_expression(&statement.object, env)?;
74            let value = eval_expression(&statement.value, env)?;
75            set_property(&receiver, statement.property.name.clone(), value)?;
76            Ok(Rc::new(Object::Null))
77        }
78    }
79}
80
81fn eval_class_declaration(
82    declaration: &ClassDeclaration,
83    env: &Env,
84) -> Result<Rc<Object>, EvalError> {
85    let mut constructor = None;
86    let mut methods = HashMap::new();
87    for method in &declaration.methods {
88        let function =
89            Rc::new(Object::Function(method.params.clone(), method.body.clone(), Rc::clone(env)));
90        match method.kind {
91            MethodKind::Constructor => constructor = Some(function),
92            MethodKind::Method => {
93                methods.insert(method.name.name.clone(), function);
94            }
95        }
96    }
97
98    let class = Rc::new(RefCell::new(ClassObject {
99        name: declaration.name.name.clone(),
100        constructor,
101        methods,
102    }));
103    env.borrow_mut()
104        .set(declaration.name.name.clone(), Rc::new(Object::Class(class)));
105    Ok(Rc::new(Object::Null))
106}
107
108fn is_truthy(obj: &Object) -> bool {
109    match obj {
110        Object::Null => return false,
111        Object::Boolean(false) => return false,
112        _ => true,
113    }
114}
115
116fn eval_expression(expression: &Expression, env: &Env) -> Result<Rc<Object>, EvalError> {
117    match expression {
118        Expression::LITERAL(literal) => eval_literal(literal, env),
119        Expression::PREFIX(UnaryExpression {
120            op,
121            operand: expr,
122            ..
123        }) => {
124            let right = eval_expression(expr, &Rc::clone(env))?;
125            return eval_prefix(op, &right);
126        }
127        Expression::INFIX(BinaryExpression {
128            op,
129            left,
130            right,
131            ..
132        }) => {
133            let left = eval_expression(left, &Rc::clone(env))?;
134            let right = eval_expression(right, &Rc::clone(env))?;
135            return eval_infix(op, &left, &right);
136        }
137        Expression::IF(IF {
138            condition,
139            consequent,
140            alternate,
141            ..
142        }) => {
143            let condition = eval_expression(condition, &Rc::clone(env))?;
144            if is_truthy(&condition) {
145                eval_block_statements(&(consequent.body), env)
146            } else {
147                match alternate {
148                    Some(alt) => eval_block_statements(&(alt.body), env),
149                    None => Ok(Rc::new(Object::Null)),
150                }
151            }
152        }
153        Expression::IDENTIFIER(IDENTIFIER {
154            name: id,
155            ..
156        }) => eval_identifier(id, env),
157        Expression::FUNCTION(FunctionDeclaration {
158            params,
159            body,
160            ..
161        }) => {
162            return Ok(Rc::new(Object::Function(params.clone(), body.clone(), Rc::clone(env))));
163        }
164        Expression::FunctionCall(FunctionCall {
165            callee,
166            arguments,
167            ..
168        }) => {
169            let func = eval_expression(callee, &Rc::clone(env))?;
170            let args = eval_expressions(arguments, env)?;
171            apply_function(&func, &args)
172        }
173        Expression::Index(Index {
174            object: left,
175            index,
176            ..
177        }) => {
178            let literal = eval_expression(left, &Rc::clone(env))?;
179            let index = eval_expression(index, env)?;
180            eval_index_expression(&literal, &index)
181        }
182        Expression::This(_) => eval_identifier("this", env),
183        Expression::Property(property) => {
184            let receiver = eval_expression(&property.object, env)?;
185            get_property(&receiver, &property.property.name)
186        }
187        Expression::New(new_expression) => {
188            let class = eval_identifier(&new_expression.callee.name, env)?;
189            let arguments = eval_expressions(&new_expression.arguments, env)?;
190            construct_instance(&class, &arguments)
191        }
192    }
193}
194
195fn get_property(receiver: &Rc<Object>, name: &str) -> Result<Rc<Object>, EvalError> {
196    let Object::Instance(instance) = &**receiver else {
197        return Err(format!("cannot read property '{}' of {}", name, receiver));
198    };
199
200    if let Some(value) = instance.borrow().fields.get(name).cloned() {
201        return Ok(value);
202    }
203
204    let (class_name, method) = {
205        let instance = instance.borrow();
206        let class = instance.class.borrow();
207        (class.name.clone(), class.methods.get(name).cloned())
208    };
209    if let Some(method) = method {
210        return Ok(Rc::new(Object::BoundMethod(Rc::new(BoundMethodObject {
211            receiver: Rc::clone(instance),
212            method,
213            name: name.to_string(),
214        }))));
215    }
216
217    Err(format!("property '{}' does not exist on {}", name, class_name))
218}
219
220fn set_property(receiver: &Rc<Object>, name: String, value: Rc<Object>) -> Result<(), EvalError> {
221    let Object::Instance(instance) = &**receiver else {
222        return Err(format!("cannot set property '{}' of {}", name, receiver));
223    };
224    instance.borrow_mut().fields.insert(name, value);
225    Ok(())
226}
227
228fn construct_instance(
229    class_value: &Rc<Object>,
230    args: &[Rc<Object>],
231) -> Result<Rc<Object>, EvalError> {
232    let Object::Class(class) = &**class_value else {
233        return Err(format!("cannot construct {}", class_value));
234    };
235    let instance = Rc::new(RefCell::new(InstanceObject {
236        class: Rc::clone(class),
237        fields: HashMap::new(),
238    }));
239    let instance_value = Rc::new(Object::Instance(Rc::clone(&instance)));
240    let constructor = class.borrow().constructor.clone();
241    if let Some(constructor) = constructor {
242        apply_method(
243            &constructor,
244            &instance,
245            args,
246            &format!("{}.constructor", class.borrow().name),
247        )?;
248    } else if !args.is_empty() {
249        return Err(format!(
250            "wrong number of arguments for {}.constructor: want=0, got={}",
251            class.borrow().name,
252            args.len()
253        ));
254    }
255    Ok(instance_value)
256}
257
258fn eval_index_expression(left: &Rc<Object>, index: &Rc<Object>) -> Result<Rc<Object>, EvalError> {
259    match (&**left, &**index) {
260        (Object::Array(arr), Object::Integer(idx)) => match arr.get(*idx as usize) {
261            Some(obj) => return Ok(Rc::clone(obj)),
262            None => return Ok(Rc::new(Object::Null)),
263        },
264        (Object::Hash(map), key) => {
265            if !(key.is_hashable()) {
266                return Err("not a valid hash key".to_string());
267            }
268
269            match map.get(key) {
270                Some(obj) => return Ok(Rc::clone(obj)),
271                None => return Ok(Rc::new(Object::Null)),
272            }
273        }
274        _ => return Err(format!("index operator not supported for {}", left)),
275    }
276}
277
278fn apply_function(function: &Rc<Object>, args: &[Rc<Object>]) -> Result<Rc<Object>, EvalError> {
279    match &**function {
280        Object::Function(params, body, env) => {
281            if params.len() != args.len() {
282                return Err(format!(
283                    "wrong number of arguments: want={}, got={}",
284                    params.len(),
285                    args.len()
286                ));
287            }
288            let mut env = Environment::new_enclosed_environment(env);
289
290            params.iter().enumerate().for_each(|(i, param)| {
291                env.set(param.name.clone(), args[i].clone());
292            });
293
294            let evaluated = eval_block_statements(&body.body, &Rc::new(RefCell::new(env)))?;
295            return unwrap_return(evaluated);
296        }
297        Object::Builtin(b) => Ok(b(args.to_vec())),
298        Object::BoundMethod(bound) => {
299            apply_method(&bound.method, &bound.receiver, args, &bound.name)
300        }
301        Object::Class(class) => {
302            Err(format!("class {} must be constructed with new", class.borrow().name))
303        }
304        f => Err(format!("expected {} to be a function", f)),
305    }
306}
307
308fn apply_method(
309    method: &Rc<Object>,
310    receiver: &InstanceRef,
311    args: &[Rc<Object>],
312    display_name: &str,
313) -> Result<Rc<Object>, EvalError> {
314    let Object::Function(params, body, declaration_env) = &**method else {
315        return Err(format!("{} is not a method", display_name));
316    };
317    if params.len() != args.len() {
318        return Err(format!(
319            "wrong number of arguments for {}: want={}, got={}",
320            display_name,
321            params.len(),
322            args.len()
323        ));
324    }
325
326    let mut call_env = Environment::new_enclosed_environment(declaration_env);
327    call_env.set("this".to_string(), Rc::new(Object::Instance(Rc::clone(receiver))));
328    for (parameter, argument) in params.iter().zip(args) {
329        call_env.set(parameter.name.clone(), Rc::clone(argument));
330    }
331    let evaluated = eval_block_statements(&body.body, &Rc::new(RefCell::new(call_env)))?;
332    unwrap_return(evaluated)
333}
334
335fn unwrap_return(obj: Rc<Object>) -> Result<Rc<Object>, EvalError> {
336    if let Object::ReturnValue(val) = &*obj {
337        Ok(Rc::clone(val))
338    } else {
339        Ok(obj)
340    }
341}
342
343fn eval_expressions(exprs: &Vec<Expression>, env: &Env) -> Result<Vec<Rc<Object>>, EvalError> {
344    let mut list = Vec::new();
345    for expr in exprs {
346        let val = eval_expression(expr, &Rc::clone(env))?;
347        list.push(val);
348    }
349
350    Ok(list)
351}
352
353fn eval_identifier(identifier: &str, env: &Env) -> Result<Rc<Object>, EvalError> {
354    match env.borrow().get(identifier) {
355        Some(obj) => Ok(obj.clone()),
356        None => match BuiltIns.iter().find(|builtin| builtin.name == identifier) {
357            Some(obj) => Ok(Rc::new(Object::Builtin(obj.function))),
358            None => Err(format!("unknown identifier {}", identifier)),
359        },
360    }
361}
362
363fn eval_prefix(op: &Token, right: &Object) -> Result<Rc<Object>, EvalError> {
364    match op.kind {
365        TokenKind::BANG => eval_prefix_bang(right),
366        TokenKind::MINUS => eval_prefix_minus(right),
367        _ => Err(format!("unknown prefix operator: {}", op)),
368    }
369}
370
371fn eval_prefix_bang(expr: &Object) -> Result<Rc<Object>, EvalError> {
372    match *expr {
373        Object::Null => Ok(Rc::new(Object::Boolean(true))),
374        Object::Boolean(b) => Ok(Rc::new(Object::Boolean(!b))),
375        _ => Ok(Rc::new(Object::Boolean(false))),
376    }
377}
378
379fn eval_prefix_minus(expr: &Object) -> Result<Rc<Object>, EvalError> {
380    match *expr {
381        Object::Integer(i) => Ok(Rc::from(Object::Integer(-i))),
382        _ => Err(format!("can't apply prefix minus operator: {}", expr)),
383    }
384}
385
386fn eval_infix(op: &Token, left: &Object, right: &Object) -> Result<Rc<Object>, EvalError> {
387    if op.kind == TokenKind::EQ || op.kind == TokenKind::NotEq {
388        let equal = left == right;
389        return Ok(Rc::new(Object::Boolean(if op.kind == TokenKind::EQ { equal } else { !equal })));
390    }
391    match (left, right) {
392        (Object::Integer(left), Object::Integer(right)) => {
393            return eval_integer_infix(op, *left, *right);
394        }
395        (Object::Boolean(left), Object::Boolean(right)) => {
396            return eval_boolean_infix(op, *left, *right);
397        }
398        (Object::String(left), Object::String(right)) => {
399            return eval_string_infix(op, left.to_string(), right.to_string());
400        }
401        _ => Err(format!("eval infix error for op: {}, left: {}, right: {}", op, left, right)),
402    }
403}
404
405fn eval_integer_infix(op: &Token, left: i64, right: i64) -> Result<Rc<Object>, EvalError> {
406    let result = match &op.kind {
407        TokenKind::PLUS => Object::Integer(left + right),
408        TokenKind::MINUS => Object::Integer(left - right),
409        TokenKind::ASTERISK => Object::Integer(left * right),
410        TokenKind::SLASH => Object::Integer(left / right),
411        TokenKind::LT => Object::Boolean(left < right),
412        TokenKind::GT => Object::Boolean(left > right),
413        TokenKind::EQ => Object::Boolean(left == right),
414        TokenKind::NotEq => Object::Boolean(left != right),
415        op => return Err(format!("Invalid infix operator {} for int", op)),
416    };
417
418    Ok(Rc::from(result))
419}
420
421fn eval_boolean_infix(op: &Token, left: bool, right: bool) -> Result<Rc<Object>, EvalError> {
422    let result = match &op.kind {
423        TokenKind::EQ => Object::Boolean(left == right),
424        TokenKind::NotEq => Object::Boolean(left != right),
425        op => return Err(format!("Invalid infix operator for boolean: {}", op)),
426    };
427
428    Ok(Rc::from(result))
429}
430
431fn eval_string_infix(op: &Token, left: String, right: String) -> Result<Rc<Object>, EvalError> {
432    let result = match &op.kind {
433        TokenKind::EQ => Object::Boolean(left == right),
434        TokenKind::NotEq => Object::Boolean(left != right),
435        TokenKind::PLUS => Object::String(format!("{}{}", left, right)),
436        op => return Err(format!("Invalid infix {} operator for string", op)),
437    };
438
439    Ok(Rc::from(result))
440}
441
442fn eval_literal(literal: &Literal, env: &Env) -> Result<Rc<Object>, EvalError> {
443    match literal {
444        Literal::Integer(Integer {
445            raw: i,
446            ..
447        }) => Ok(Rc::from(Object::Integer(*i))),
448        Literal::Boolean(Boolean {
449            raw: b,
450            ..
451        }) => Ok(Rc::from(Object::Boolean(*b))),
452        Literal::String(StringType {
453            raw: s,
454            ..
455        }) => Ok(Rc::from(Object::String(s.clone()))),
456        Literal::Array(Array {
457            elements,
458            ..
459        }) => {
460            let list = eval_expressions(elements, env)?;
461            return Ok(Rc::from(Object::Array(list)));
462        }
463        Literal::Hash(Hash {
464            elements: map,
465            ..
466        }) => {
467            // Object's Hash impl only covers Integer/Boolean/String, which have no
468            // interior mutability; keys are checked with is_hashable() before insert.
469            #[allow(clippy::mutable_key_type)]
470            let mut hash_map = HashMap::new();
471
472            for (k, v) in map {
473                let key = eval_expression(k, env)?;
474                if !key.is_hashable() {
475                    return Err(format!("key {} is not hashable", key));
476                }
477                let value = eval_expression(v, env)?;
478                hash_map.insert(key, value);
479            }
480
481            return Ok(Rc::new(Object::Hash(hash_map)));
482        } // l => return Err(format!("unknown literal: {}", *l))
483    }
484}