use std::collections::HashMap;
use std::sync::Arc;
use fusevm::Chunk;
use crate::runtime::TclError;
pub const DEFAULT_CAPACITY: usize = 1024;
#[derive(Debug)]
pub struct ChunkCache {
entries: HashMap<String, Arc<Chunk>>,
capacity: usize,
hits: u64,
misses: u64,
}
impl ChunkCache {
pub fn new() -> Self {
Self::with_capacity(DEFAULT_CAPACITY)
}
pub fn with_capacity(capacity: usize) -> Self {
Self {
entries: HashMap::new(),
capacity: capacity.max(1),
hits: 0,
misses: 0,
}
}
pub fn compile(&mut self, src: &str) -> Result<Arc<Chunk>, TclError> {
if let Some(chunk) = self.entries.get(src) {
self.hits += 1;
return Ok(Arc::clone(chunk));
}
self.misses += 1;
let rewritten = crate::rust_ffi::desugar(src);
let script = crate::parser::parse(&rewritten).map_err(|e| TclError {
msg: e.msg,
line: Some(e.line),
})?;
let chunk = Arc::new(crate::compiler::compile(&script).map_err(|e| TclError {
msg: e.msg,
line: Some(e.line),
})?);
if self.entries.len() >= self.capacity {
self.entries.clear();
}
self.entries.insert(src.to_string(), Arc::clone(&chunk));
Ok(chunk)
}
pub fn len(&self) -> usize {
self.entries.len()
}
pub fn is_empty(&self) -> bool {
self.entries.is_empty()
}
pub fn stats(&self) -> (u64, u64) {
(self.hits, self.misses)
}
pub fn clear(&mut self) {
self.entries.clear();
}
}
impl Default for ChunkCache {
fn default() -> Self {
Self::new()
}
}