From 26544aa5f05021ed95eca77966738a84d8be902e Mon Sep 17 00:00:00 2001 From: Vincent Ambo Date: Thu, 14 Jan 2021 03:14:59 +0300 Subject: feat(tazjin/rlox): Implement function call evaluation Change-Id: I6767c3a1a9654475b4066415f8c026b9c5b5907a Reviewed-on: https://cl.tvl.fyi/c/depot/+/2382 Reviewed-by: tazjin Tested-by: BuildkiteCI --- users/tazjin/rlox/src/errors.rs | 1 + users/tazjin/rlox/src/interpreter.rs | 35 +++++++++++++++++++++++++++++++++-- 2 files changed, 34 insertions(+), 2 deletions(-) (limited to 'users/tazjin/rlox') 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 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 { + 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. -- cgit 1.4.1