feat(tazjin/rlox): Implement function call evaluation

Change-Id: I6767c3a1a9654475b4066415f8c026b9c5b5907a
Reviewed-on: https://cl.tvl.fyi/c/depot/+/2382
Reviewed-by: tazjin <mail@tazj.in>
Tested-by: BuildkiteCI
This commit is contained in:
Vincent Ambo 2021-01-14 03:14:59 +03:00 committed by tazjin
parent 090c96eae9
commit 26544aa5f0
2 changed files with 34 additions and 2 deletions

View file

@ -12,6 +12,7 @@ pub enum ErrorKind {
UndefinedVariable(String),
InternalError(String),
InvalidAssignmentTarget(String),
RuntimeError(String),
}
#[derive(Debug)]

View file

@ -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.