use crate::ast::utils::{NativeFnSchema, Type, Value};
use crate::error::Result;
use std::collections::HashMap;
use std::sync::Arc;
#[derive(Debug, Clone)]
pub struct Library {
pub(crate) name: String,
pub(crate) items: Vec<LibraryItem>,
}
impl Library {
pub fn new(name: String, items: Vec<LibraryItem>) -> Self {
Self { name, items }
}
pub fn name(&self) -> String {
self.name.clone()
}
pub fn set_name(&mut self, name: String) {
self.name = name;
}
pub fn items(&self) -> Vec<LibraryItem> {
self.items.clone()
}
pub fn get_item(&self, name: String) -> Option<LibraryItem> {
self.items.iter().find(|&i| i.name == name).cloned()
}
pub fn add_item(&mut self, item: LibraryItem) {
let position = self.items.iter().position(|existing| existing.name == item.name);
match position {
Some(index) => {
self.items[index] = item;
}
None => {
self.items.push(item);
}
}
}
}
#[derive(Debug, Clone)]
pub struct LibraryItem {
pub(crate) name: String,
pub(crate) native_functions: HashMap<String, NativeFnSchema>,
pub(crate) globals: HashMap<String, Value>,
}
impl LibraryItem {
fn new(name: String) -> Self {
Self { name, native_functions: HashMap::new(), globals: HashMap::new() }
}
pub fn define(name: impl Into<String>) -> Self {
Self::new(name.into())
}
pub fn with_fn<F>(mut self, name: &str, params: Vec<Type>, ret: Type, f: F) -> Self
where
F: Fn(Vec<Value>) -> Result<Value> + Send + Sync + 'static,
{
self.add_native_fn(name, params, ret, f);
self
}
pub fn with_global(mut self, name: &str, value: Value) -> Self {
self.set_global(name, value);
self
}
pub fn name(&self) -> String {
self.name.clone()
}
pub fn set_name(&mut self, name: String) {
self.name = name;
}
pub fn add_native_fn<F>(&mut self, name: &str, params: Vec<Type>, return_type: Type, f: F)
where
F: Fn(Vec<Value>) -> Result<Value> + Send + Sync + 'static,
{
let schema =
NativeFnSchema { name: name.to_string(), params, return_type, body: Arc::new(f) };
self.native_functions.insert(name.to_string(), schema);
}
pub fn set_global(&mut self, name: &str, value: Value) {
self.globals.insert(name.to_string(), value);
}
}