use crate::ast::Stmt;
use crate::value::Value;
use indexmap::IndexMap;
use std::collections::{HashMap, HashSet};
use std::sync::Arc;
pub type BuiltinFn = Box<dyn Fn(&[Value], Option<&BuiltinCallback>) -> Result<Value, String> + Send + Sync>;
pub type BuiltinCallback = Box<dyn Fn(&[Value]) -> Result<Value, String>>;
#[derive(Clone)]
pub struct UserFunction {
pub name: String,
pub param_names: Vec<String>,
pub body: Vec<Stmt>,
}
pub struct EventHandler {
pub event_name: String,
pub body: Vec<Stmt>,
}
pub struct Environment {
pub variables: IndexMap<String, Value>,
pub functions: HashMap<String, UserFunction>,
pub builtins: HashMap<String, Arc<BuiltinFn>>,
pub constants: HashSet<String>,
pub current_module: Option<String>,
pub used_modules: HashSet<String>,
pub output: Vec<String>,
pub event_handlers: Vec<EventHandler>,
pub metadata: HashMap<String, IndexMap<String, Value>>,
}
impl Environment {
pub fn new() -> Self {
Self {
variables: IndexMap::new(),
functions: HashMap::new(),
builtins: HashMap::new(),
constants: HashSet::new(),
current_module: None,
used_modules: HashSet::new(),
output: Vec::new(),
event_handlers: Vec::new(),
metadata: HashMap::new(),
}
}
pub fn register_builtin(
&mut self,
name: &str,
func: impl Fn(&[Value], Option<&BuiltinCallback>) -> Result<Value, String> + Send + Sync + 'static,
) {
self.builtins.insert(name.to_string(), Arc::new(Box::new(func)));
}
pub fn register_function(&mut self, func: UserFunction) {
self.functions.insert(func.name.clone(), func);
}
pub fn resolve_function_name(&self, name: &str) -> Option<String> {
if self.builtins.contains_key(name) || self.functions.contains_key(name) {
return Some(name.to_string());
}
if let Some(ref module) = self.current_module {
let qualified = format!("{}.{}", module, name);
if self.builtins.contains_key(&qualified) {
return Some(qualified);
}
}
for module in &self.used_modules {
let qualified = format!("{}.{}", module, name);
if self.builtins.contains_key(&qualified) {
return Some(qualified);
}
}
None
}
}
impl Default for Environment {
fn default() -> Self {
Self::new()
}
}