use std::fmt::{Debug, Display}; use rlox2_frontend::parser::Stmt; use super::environment::{Environment, Scope}; use super::interpret::EvalResult; use super::{Runtime, Value}; #[derive(Debug, Clone)] pub struct LoxFunction { name: String, closure: Scope, param_names: Vec, body: Box, } impl LoxFunction { pub fn new(name: impl Into, closure: Scope, param_names: Vec, body: Stmt) -> Self { let name = name.into(); let body = Box::new(body); LoxFunction { name, closure, param_names, body, } } pub fn arity(&self) -> usize { self.param_names.len() } pub fn name(&self) -> &str { &self.name } pub fn closure(&self) -> &Scope { &self.closure } pub fn param_names(&self) -> impl Iterator { self.param_names.iter() } pub fn body(&self) -> &Stmt { &self.body } } impl Display for LoxFunction { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "", self.name) } } /*====================================================================================================================*/ pub type ExternFunClosure = fn(Vec, &mut Environment) -> EvalResult; #[derive(Clone)] pub struct LoxExternFunction { name: String, closure: ExternFunClosure, } impl LoxExternFunction { pub fn new(name: impl Into, closure: ExternFunClosure) -> Self { let name = name.into(); LoxExternFunction { name, closure } } pub fn register(self, env: &mut Runtime) { let name = self.name.clone(); let fun = Value::extern_function(self); env.define_global(name, fun); } pub fn call(&self, args: Vec, env: &mut Environment) -> EvalResult { (self.closure)(args, env) } } impl Display for LoxExternFunction { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "", self.name) } } impl Debug for LoxExternFunction { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("LoxExternFunction") .field("name", &self.name) .field("closure", &"") .finish() } } impl PartialEq for LoxExternFunction { fn eq(&self, other: &Self) -> bool { self.name == other.name } }