1use crate::ast::Program;
5use serde::{Deserialize, Serialize};
6use std::collections::HashMap;
7use std::collections::hash_map::DefaultHasher;
8use std::hash::{Hash, Hasher};
9
10#[derive(Debug)]
12pub struct ASTCache {
13 cache: HashMap<u64, Program>,
15 max_size: usize,
17 hits: usize,
19 misses: usize,
21}
22
23impl ASTCache {
24 pub fn new() -> Self {
26 Self::with_capacity(100)
27 }
28
29 pub fn with_capacity(max_size: usize) -> Self {
31 ASTCache {
32 cache: HashMap::with_capacity(max_size.min(100)),
33 max_size,
34 hits: 0,
35 misses: 0,
36 }
37 }
38
39 fn hash_code(code: &str) -> u64 {
41 let mut hasher = DefaultHasher::new();
42 code.hash(&mut hasher);
43 hasher.finish()
44 }
45
46 pub fn get(&mut self, code: &str) -> Option<Program> {
48 let hash = Self::hash_code(code);
49 if let Some(program) = self.cache.get(&hash) {
50 self.hits += 1;
51 Some(program.clone())
52 } else {
53 self.misses += 1;
54 None
55 }
56 }
57
58 pub fn insert(&mut self, code: &str, program: Program) {
60 let hash = Self::hash_code(code);
61
62 if self.cache.len() >= self.max_size {
64 let to_remove = (self.max_size / 10).max(1);
66 let keys_to_remove: Vec<u64> = self.cache.keys().take(to_remove).copied().collect();
67 for key in keys_to_remove {
68 self.cache.remove(&key);
69 }
70 }
71
72 self.cache.insert(hash, program);
73 }
74
75 pub fn clear(&mut self) {
77 self.cache.clear();
78 self.hits = 0;
79 self.misses = 0;
80 }
81
82 pub fn stats(&self) -> CacheStats {
84 CacheStats {
85 size: self.cache.len(),
86 max_size: self.max_size,
87 hits: self.hits,
88 misses: self.misses,
89 hit_rate: if self.hits + self.misses > 0 {
90 self.hits as f64 / (self.hits + self.misses) as f64
91 } else {
92 0.0
93 },
94 }
95 }
96}
97
98impl Default for ASTCache {
99 fn default() -> Self {
100 Self::new()
101 }
102}
103
104#[derive(Debug, Clone, Serialize, Deserialize)]
106pub struct CacheStats {
107 pub size: usize,
109 pub max_size: usize,
111 pub hits: usize,
113 pub misses: usize,
115 pub hit_rate: f64,
117}
118
119impl std::fmt::Display for CacheStats {
120 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
121 write!(
122 f,
123 "Cache Stats: size={}/{}, hits={}, misses={}, hit_rate={:.2}%",
124 self.size,
125 self.max_size,
126 self.hits,
127 self.misses,
128 self.hit_rate * 100.0
129 )
130 }
131}