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) => {
298            let result = b(args.to_vec());
299            // Builtins report failures as Object::Error values. Every other runtime
300            // failure here is an Err, so lift them instead of letting an error keep
301            // flowing as an ordinary value.
302            match &*result {
303                Object::Error(message) => Err(message.clone()),
304                _ => Ok(result),
305            }
306        }
307        Object::BoundMethod(bound) => {
308            apply_method(&bound.method, &bound.receiver, args, &bound.name)
309        }
310        Object::Class(class) => {
311            Err(format!("class {} must be constructed with new", class.borrow().name))
312        }
313        f => Err(format!("expected {} to be a function", f)),
314    }
315}
316
317fn apply_method(
318    method: &Rc<Object>,
319    receiver: &InstanceRef,
320    args: &[Rc<Object>],
321    display_name: &str,
322) -> Result<Rc<Object>, EvalError> {
323    let Object::Function(params, body, declaration_env) = &**method else {
324        return Err(format!("{} is not a method", display_name));
325    };
326    if params.len() != args.len() {
327        return Err(format!(
328            "wrong number of arguments for {}: want={}, got={}",
329            display_name,
330            params.len(),
331            args.len()
332        ));
333    }
334
335    let mut call_env = Environment::new_enclosed_environment(declaration_env);
336    call_env.set("this".to_string(), Rc::new(Object::Instance(Rc::clone(receiver))));
337    for (parameter, argument) in params.iter().zip(args) {
338        call_env.set(parameter.name.clone(), Rc::clone(argument));
339    }
340    let evaluated = eval_block_statements(&body.body, &Rc::new(RefCell::new(call_env)))?;
341    unwrap_return(evaluated)
342}
343
344fn unwrap_return(obj: Rc<Object>) -> Result<Rc<Object>, EvalError> {
345    if let Object::ReturnValue(val) = &*obj {
346        Ok(Rc::clone(val))
347    } else {
348        Ok(obj)
349    }
350}
351
352fn eval_expressions(exprs: &Vec<Expression>, env: &Env) -> Result<Vec<Rc<Object>>, EvalError> {
353    let mut list = Vec::new();
354    for expr in exprs {
355        let val = eval_expression(expr, &Rc::clone(env))?;
356        list.push(val);
357    }
358
359    Ok(list)
360}
361
362fn eval_identifier(identifier: &str, env: &Env) -> Result<Rc<Object>, EvalError> {
363    match env.borrow().get(identifier) {
364        Some(obj) => Ok(obj.clone()),
365        None => match BuiltIns.iter().find(|builtin| builtin.name == identifier) {
366            Some(obj) => Ok(Rc::new(Object::Builtin(obj.function))),
367            None => Err(format!("unknown identifier {}", identifier)),
368        },
369    }
370}
371
372fn eval_prefix(op: &Token, right: &Object) -> Result<Rc<Object>, EvalError> {
373    match op.kind {
374        TokenKind::BANG => eval_prefix_bang(right),
375        TokenKind::MINUS => eval_prefix_minus(right),
376        _ => Err(format!("unknown prefix operator: {}", op)),
377    }
378}
379
380fn eval_prefix_bang(expr: &Object) -> Result<Rc<Object>, EvalError> {
381    match *expr {
382        Object::Null => Ok(Rc::new(Object::Boolean(true))),
383        Object::Boolean(b) => Ok(Rc::new(Object::Boolean(!b))),
384        _ => Ok(Rc::new(Object::Boolean(false))),
385    }
386}
387
388fn eval_prefix_minus(expr: &Object) -> Result<Rc<Object>, EvalError> {
389    match *expr {
390        Object::Integer(i) => Ok(Rc::from(Object::Integer(-i))),
391        _ => Err(format!("can't apply prefix minus operator: {}", expr)),
392    }
393}
394
395fn eval_infix(op: &Token, left: &Object, right: &Object) -> Result<Rc<Object>, EvalError> {
396    if op.kind == TokenKind::EQ || op.kind == TokenKind::NotEq {
397        let equal = left == right;
398        return Ok(Rc::new(Object::Boolean(if op.kind == TokenKind::EQ { equal } else { !equal })));
399    }
400    match (left, right) {
401        (Object::Integer(left), Object::Integer(right)) => {
402            return eval_integer_infix(op, *left, *right);
403        }
404        (Object::Boolean(left), Object::Boolean(right)) => {
405            return eval_boolean_infix(op, *left, *right);
406        }
407        (Object::String(left), Object::String(right)) => {
408            return eval_string_infix(op, left.to_string(), right.to_string());
409        }
410        _ => Err(format!("eval infix error for op: {}, left: {}, right: {}", op, left, right)),
411    }
412}
413
414fn eval_integer_infix(op: &Token, left: i64, right: i64) -> Result<Rc<Object>, EvalError> {
415    let result = match &op.kind {
416        TokenKind::PLUS => Object::Integer(left + right),
417        TokenKind::MINUS => Object::Integer(left - right),
418        TokenKind::ASTERISK => Object::Integer(left * right),
419        TokenKind::SLASH => Object::Integer(left / right),
420        TokenKind::LT => Object::Boolean(left < right),
421        TokenKind::GT => Object::Boolean(left > right),
422        TokenKind::EQ => Object::Boolean(left == right),
423        TokenKind::NotEq => Object::Boolean(left != right),
424        op => return Err(format!("Invalid infix operator {} for int", op)),
425    };
426
427    Ok(Rc::from(result))
428}
429
430fn eval_boolean_infix(op: &Token, left: bool, right: bool) -> Result<Rc<Object>, EvalError> {
431    let result = match &op.kind {
432        TokenKind::EQ => Object::Boolean(left == right),
433        TokenKind::NotEq => Object::Boolean(left != right),
434        op => return Err(format!("Invalid infix operator for boolean: {}", op)),
435    };
436
437    Ok(Rc::from(result))
438}
439
440fn eval_string_infix(op: &Token, left: String, right: String) -> Result<Rc<Object>, EvalError> {
441    let result = match &op.kind {
442        TokenKind::EQ => Object::Boolean(left == right),
443        TokenKind::NotEq => Object::Boolean(left != right),
444        TokenKind::PLUS => Object::String(format!("{}{}", left, right)),
445        op => return Err(format!("Invalid infix {} operator for string", op)),
446    };
447
448    Ok(Rc::from(result))
449}
450
451fn eval_literal(literal: &Literal, env: &Env) -> Result<Rc<Object>, EvalError> {
452    match literal {
453        Literal::Integer(Integer {
454            raw: i,
455            ..
456        }) => Ok(Rc::from(Object::Integer(*i))),
457        Literal::Boolean(Boolean {
458            raw: b,
459            ..
460        }) => Ok(Rc::from(Object::Boolean(*b))),
461        Literal::String(StringType {
462            raw: s,
463            ..
464        }) => Ok(Rc::from(Object::String(s.clone()))),
465        Literal::Array(Array {
466            elements,
467            ..
468        }) => {
469            let list = eval_expressions(elements, env)?;
470            return Ok(Rc::from(Object::Array(list)));
471        }
472        Literal::Hash(Hash {
473            elements: map,
474            ..
475        }) => {
476            // Object's Hash impl only covers Integer/Boolean/String, which have no
477            // interior mutability; keys are checked with is_hashable() before insert.
478            #[allow(clippy::mutable_key_type)]
479            let mut hash_map = HashMap::new();
480
481            for (k, v) in map {
482                let key = eval_expression(k, env)?;
483                if !key.is_hashable() {
484                    return Err(format!("key {} is not hashable", key));
485                }
486                let value = eval_expression(v, env)?;
487                hash_map.insert(key, value);
488            }
489
490            return Ok(Rc::new(Object::Hash(hash_map)));
491        } // l => return Err(format!("unknown literal: {}", *l))
492    }
493}