diff options
Diffstat (limited to 'users')
-rw-r--r-- | users/tazjin/rlox/src/errors.rs | 1 | ||||
-rw-r--r-- | users/tazjin/rlox/src/interpreter.rs | 35 |
2 files changed, 34 insertions, 2 deletions
diff --git a/users/tazjin/rlox/src/errors.rs b/users/tazjin/rlox/src/errors.rs index 64dc7a92072f..484b06bdf6ab 100644 --- a/users/tazjin/rlox/src/errors.rs +++ b/users/tazjin/rlox/src/errors.rs @@ -12,6 +12,7 @@ pub enum ErrorKind { UndefinedVariable(String), InternalError(String), InvalidAssignmentTarget(String), + RuntimeError(String), } #[derive(Debug)] diff --git a/users/tazjin/rlox/src/interpreter.rs b/users/tazjin/rlox/src/interpreter.rs index 5e2eba02d460..2ddbab7e1f29 100644 --- a/users/tazjin/rlox/src/interpreter.rs +++ b/users/tazjin/rlox/src/interpreter.rs @@ -33,8 +33,9 @@ impl Callable { // Representation of an in-language value. #[derive(Clone, Debug)] -enum Value { +pub enum Value { Literal(Literal), + Callable(Callable), } impl From<Literal> for Value { @@ -235,7 +236,7 @@ impl Interpreter { Expr::Binary(binary) => self.eval_binary(binary), Expr::Variable(var) => self.get_var(var), Expr::Logical(log) => self.eval_logical(log), - Expr::Call(_) => unimplemented!(), + Expr::Call(call) => self.eval_call(call), } } @@ -321,6 +322,36 @@ impl Interpreter { }), } } + + fn eval_call<'a>(&mut self, call: &parser::Call<'a>) -> Result<Value, Error> { + let callable = match self.eval(&call.callee)? { + Value::Callable(c) => c, + Value::Literal(v) => { + return Err(Error { + line: call.paren.line, + kind: ErrorKind::RuntimeError(format!("not callable: {:?}", v)), + }) + } + }; + + let mut args = vec![]; + for arg in &call.args { + args.push(self.eval(arg)?); + } + + if callable.arity() != args.len() { + return Err(Error { + line: call.paren.line, + kind: ErrorKind::RuntimeError(format!( + "Expected {} arguments, but got {}", + callable.arity(), + args.len(), + )), + }); + } + + callable.call(args) + } } // Interpreter functions not dependent on interpreter-state. |