Interpreter - Data structure for functions

This commit is contained in:
Emmanuel BENOîT 2023-01-02 19:50:55 +01:00
parent f02d15fa83
commit ca3ec46bdc

View file

@ -0,0 +1,65 @@
use itertools::izip;
use crate::{
ast,
errors::InterpreterError,
interpreter::{Environment, Interpretable},
tokens::Token,
};
use super::{Callable, EnvironmentRef, Value};
/// A function implemented in the Lox-ish language.
#[derive(Debug)]
pub(crate) struct Function {
name: Token,
params: Vec<Token>,
body: Vec<ast::StmtNode>,
}
impl From<&ast::StmtNode> for Function {
fn from(node: &ast::StmtNode) -> Self {
if let ast::StmtNode::FunDecl { name, params, body } = node {
Self {
name: name.clone(),
params: params.clone(),
body: body.clone(),
}
} else {
panic!("initializing Function from non-function statement");
}
}
}
impl Callable for Function {
fn arity(&self) -> usize {
self.params.len()
}
fn call(
&self,
environment: &EnvironmentRef,
arguments: Vec<Value>,
) -> Result<Value, InterpreterError> {
assert_eq!(arguments.len(), self.arity());
let param_env = Environment::create_child(environment);
for (arg, value) in izip!(self.params.iter(), arguments.into_iter()) {
param_env.borrow_mut().define(&arg, Some(value));
}
let child = Environment::create_child(&param_env);
for stmt in self.body.iter() {
let result = stmt.interpret(&child)?;
if result.is_flow_control() {
panic!("unexpected flow control");
}
}
Ok(Value::Nil)
}
}
impl ToString for Function {
fn to_string(&self) -> String {
format!("<fun {}>", self.name.lexeme)
}
}