diff --git a/src/interpreter/functions.rs b/src/interpreter/functions.rs index e69de29..682eaa9 100644 --- a/src/interpreter/functions.rs +++ b/src/interpreter/functions.rs @@ -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, + body: Vec, +} + +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, + ) -> Result { + 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(¶m_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!("", self.name.lexeme) + } +}