diff options
author | Vincent Ambo <mail@tazj.in> | 2021-01-14T00·14+0300 |
---|---|---|
committer | tazjin <mail@tazj.in> | 2021-01-14T00·31+0000 |
commit | 26544aa5f05021ed95eca77966738a84d8be902e (patch) | |
tree | e6a1b464d7006c40402cb7c3cb60d7e3a0aacaa2 /users/tazjin | |
parent | 090c96eae998fd399975e85321189a136a7dbddd (diff) |
feat(tazjin/rlox): Implement function call evaluation r/2096
Change-Id: I6767c3a1a9654475b4066415f8c026b9c5b5907a Reviewed-on: https://cl.tvl.fyi/c/depot/+/2382 Reviewed-by: tazjin <mail@tazj.in> Tested-by: BuildkiteCI
Diffstat (limited to '')
-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. |