formualizer_eval/engine/arena/
data_store.rs

1/// Unified data storage for all value types using arenas
2/// Provides conversion between LiteralValue and ValueRef
3use super::array::ArrayArena;
4use super::ast::{AstArena, AstNodeId, CompactRefType, SheetKey};
5use super::error_arena::{ErrorArena, ErrorRef};
6use super::scalar::ScalarArena;
7use super::string_interner::{StringId, StringInterner};
8use super::value_ref::ValueRef;
9use crate::engine::sheet_registry::SheetRegistry;
10use formualizer_common::{ExcelError, ExcelErrorKind, LiteralValue};
11use formualizer_parse::parser::{ASTNode, ASTNodeType, ReferenceType, TableReference};
12
13/// Centralized data storage using arenas
14#[derive(Debug)]
15pub struct DataStore {
16    /// Scalar values (floats and large integers)
17    scalars: ScalarArena,
18
19    /// String values
20    strings: StringInterner,
21
22    /// Array values
23    arrays: ArrayArena,
24
25    /// AST nodes for formulas
26    asts: AstArena,
27
28    /// Error storage with message preservation
29    errors: ErrorArena,
30}
31
32impl DataStore {
33    pub fn new() -> Self {
34        Self {
35            scalars: ScalarArena::new(),
36            strings: StringInterner::new(),
37            arrays: ArrayArena::new(),
38            asts: AstArena::new(),
39            errors: ErrorArena::new(),
40        }
41    }
42
43    /// Batch store literal values; returns ValueRefs in same order.
44    pub fn store_values_batch<I>(&mut self, values: I) -> Vec<ValueRef>
45    where
46        I: IntoIterator<Item = LiteralValue>,
47    {
48        let iter = values.into_iter();
49        let (lower, _) = iter.size_hint();
50        let mut out = Vec::with_capacity(lower);
51        for v in iter {
52            out.push(self.store_value(v));
53        }
54        out
55    }
56
57    /// Batch store ASTs; returns AstNodeIds in same order.
58    pub fn store_asts_batch<'a, I>(
59        &mut self,
60        asts: I,
61        sheet_registry: &SheetRegistry,
62    ) -> Vec<AstNodeId>
63    where
64        I: IntoIterator<Item = &'a ASTNode>,
65    {
66        let iter = asts.into_iter();
67        let (lower, _) = iter.size_hint();
68        let mut out = Vec::with_capacity(lower);
69        for ast in iter {
70            out.push(self.store_ast(ast, sheet_registry));
71        }
72        out
73    }
74
75    pub fn with_capacity(estimated_cells: usize) -> Self {
76        Self {
77            scalars: ScalarArena::with_capacity(estimated_cells),
78            strings: StringInterner::with_capacity(estimated_cells / 10),
79            arrays: ArrayArena::with_capacity(estimated_cells / 100),
80            asts: AstArena::with_capacity(estimated_cells / 2),
81            errors: ErrorArena::with_capacity(estimated_cells / 20),
82        }
83    }
84
85    /// Store a LiteralValue and return a ValueRef
86    pub fn store_value(&mut self, value: LiteralValue) -> ValueRef {
87        match value {
88            LiteralValue::Empty => ValueRef::empty(),
89
90            LiteralValue::Number(n) => {
91                // Store as float in scalar arena
92                let idx = self.scalars.insert_float(n);
93                ValueRef::number(idx.as_u32())
94            }
95
96            LiteralValue::Text(s) => {
97                let id = self.strings.intern(&s);
98                ValueRef::string(id.as_u32())
99            }
100
101            LiteralValue::Boolean(b) => ValueRef::boolean(b),
102
103            LiteralValue::Error(err) => self.store_error(&err),
104
105            LiteralValue::Array(array) => {
106                // Convert nested array to ValueRefs
107                let rows = array.len() as u32;
108                let cols = array.first().map(|r| r.len()).unwrap_or(0) as u32;
109
110                let elements: Vec<ValueRef> = array
111                    .into_iter()
112                    .flatten()
113                    .map(|v| self.store_value(v))
114                    .collect();
115
116                let array_ref = self.arrays.insert(rows, cols, elements);
117                ValueRef::array(array_ref.as_u32())
118            }
119
120            LiteralValue::DateTime(dt) => {
121                // Store serial number as float
122                let serial = formualizer_common::datetime_to_serial(&dt);
123                let idx = self.scalars.insert_float(serial);
124                ValueRef::date_time(idx.as_u32())
125            }
126
127            LiteralValue::Date(d) => {
128                // Convert date to datetime at midnight
129                let dt = d.and_hms_opt(0, 0, 0).unwrap();
130                let serial = formualizer_common::datetime_to_serial(&dt);
131                let idx = self.scalars.insert_float(serial);
132                ValueRef::date_time(idx.as_u32())
133            }
134
135            LiteralValue::Time(t) => {
136                // Store time as fractional day
137                use chrono::Timelike;
138                let seconds = (t.hour() * 3600 + t.minute() * 60 + t.second()) as f64;
139                let fraction = seconds / 86400.0;
140                let idx = self.scalars.insert_float(fraction);
141                ValueRef::date_time(idx.as_u32())
142            }
143
144            LiteralValue::Duration(dur) => {
145                // Store as integer seconds (chrono::Duration has num_seconds())
146                let secs = dur.num_seconds();
147                let idx = self.scalars.insert_integer(secs);
148                let raw_index = idx.as_u32() & 0x7FFF_FFFF;
149                ValueRef::duration(raw_index)
150            }
151
152            LiteralValue::Int(i) => {
153                // Try to use small int optimization
154                if let Some(vref) = ValueRef::small_int(i as i32) {
155                    vref
156                } else {
157                    // Store as large integer
158                    let idx = self.scalars.insert_integer(i);
159                    ValueRef::large_int(idx.as_u32())
160                }
161            }
162
163            LiteralValue::Pending => ValueRef::pending(),
164        }
165    }
166
167    /// Retrieve a LiteralValue from a ValueRef
168    pub fn retrieve_value(&self, value_ref: ValueRef) -> LiteralValue {
169        use super::value_ref::ValueType;
170
171        match value_ref.value_type() {
172            ValueType::Empty => LiteralValue::Empty,
173
174            ValueType::SmallInt => {
175                // Small integers are inlined
176                if let Some(i) = value_ref.as_small_int() {
177                    LiteralValue::Int(i as i64)
178                } else {
179                    LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
180                }
181            }
182
183            ValueType::LargeInt => {
184                if let Some(idx) = value_ref.arena_index() {
185                    let scalar_ref = super::scalar::ScalarRef::from_raw(idx | (1 << 31));
186                    if let Some(i) = self.scalars.get_integer(scalar_ref) {
187                        LiteralValue::Int(i)
188                    } else {
189                        LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
190                    }
191                } else {
192                    LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
193                }
194            }
195
196            ValueType::Number => {
197                if let Some(idx) = value_ref.arena_index() {
198                    let scalar_ref = super::scalar::ScalarRef::from_raw(idx);
199                    if let Some(f) = self.scalars.get_float(scalar_ref) {
200                        LiteralValue::Number(f)
201                    } else {
202                        LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
203                    }
204                } else {
205                    LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
206                }
207            }
208
209            ValueType::String => {
210                if let Some(idx) = value_ref.arena_index() {
211                    let string_id = StringId::from_raw(idx);
212                    let s = self.strings.resolve(string_id);
213                    LiteralValue::Text(s.to_string())
214                } else {
215                    LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
216                }
217            }
218
219            ValueType::Boolean => {
220                if let Some(b) = value_ref.as_boolean() {
221                    LiteralValue::Boolean(b)
222                } else {
223                    LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
224                }
225            }
226
227            ValueType::Error => {
228                if let Some(error_ref_raw) = value_ref.as_error_ref() {
229                    let error_ref = ErrorRef::from_raw(error_ref_raw);
230                    if let Some(error) = self.errors.get(error_ref) {
231                        LiteralValue::Error(error)
232                    } else {
233                        LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
234                    }
235                } else {
236                    LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
237                }
238            }
239
240            ValueType::Array => {
241                if let Some(idx) = value_ref.arena_index() {
242                    let array_ref = super::array::ArrayRef::from_raw(idx);
243                    if let Some(array_2d) = self.arrays.get_2d(array_ref) {
244                        // Convert back to LiteralValue array
245                        let result: Vec<Vec<LiteralValue>> = array_2d
246                            .into_iter()
247                            .map(|row| row.into_iter().map(|v| self.retrieve_value(v)).collect())
248                            .collect();
249                        LiteralValue::Array(result)
250                    } else {
251                        LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
252                    }
253                } else {
254                    LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
255                }
256            }
257
258            ValueType::DateTime => {
259                if let Some(idx) = value_ref.arena_index() {
260                    let scalar_ref = super::scalar::ScalarRef::from_raw(idx);
261                    if let Some(serial) = self.scalars.get_float(scalar_ref) {
262                        let dt = formualizer_common::serial_to_datetime(serial);
263                        LiteralValue::DateTime(dt)
264                    } else {
265                        LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
266                    }
267                } else {
268                    LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
269                }
270            }
271
272            ValueType::Duration => {
273                if let Some(idx) = value_ref.arena_index() {
274                    let scalar_ref = super::scalar::ScalarRef::from_raw(idx | (1 << 31));
275                    if let Some(secs) = self.scalars.get_integer(scalar_ref) {
276                        let dur = chrono::Duration::seconds(secs);
277                        LiteralValue::Duration(dur)
278                    } else {
279                        LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
280                    }
281                } else {
282                    LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
283                }
284            }
285
286            ValueType::Pending => LiteralValue::Pending,
287
288            ValueType::FormulaAst => {
289                // Formula ASTs shouldn't be returned as values
290                LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
291            }
292        }
293    }
294
295    /// Store an AST node and return its ID
296    pub fn store_ast(&mut self, ast: &ASTNode, sheet_registry: &SheetRegistry) -> AstNodeId {
297        self.convert_ast_node(ast, sheet_registry)
298    }
299
300    /// Retrieve an AST node from its ID
301    pub fn retrieve_ast(&self, id: AstNodeId, sheet_registry: &SheetRegistry) -> Option<ASTNode> {
302        self.reconstruct_ast_node(id, sheet_registry)
303    }
304
305    pub fn resolve_ast_string(&self, id: StringId) -> &str {
306        self.asts.resolve_string(id)
307    }
308
309    pub fn reconstruct_reference_type_for_eval(
310        &self,
311        ref_type: &CompactRefType,
312        sheet_registry: &SheetRegistry,
313    ) -> ReferenceType {
314        self.reconstruct_reference_type(ref_type, sheet_registry)
315    }
316
317    pub fn get_node(&self, id: AstNodeId) -> Option<&super::ast::AstNodeData> {
318        self.asts.get(id)
319    }
320
321    pub fn get_args(&self, id: AstNodeId) -> Option<&[AstNodeId]> {
322        self.asts.get_function_args(id)
323    }
324
325    pub fn get_array_elems(&self, id: AstNodeId) -> Option<(u16, u16, &[AstNodeId])> {
326        self.asts.get_array_elements_info(id)
327    }
328
329    /// Convert ASTNode to arena representation
330    fn convert_ast_node(&mut self, node: &ASTNode, sheet_registry: &SheetRegistry) -> AstNodeId {
331        match &node.node_type {
332            ASTNodeType::Literal(lit) => {
333                let value_ref = self.store_value(lit.clone());
334                self.asts.insert_literal(value_ref)
335            }
336
337            ASTNodeType::Reference {
338                original,
339                reference,
340            } => {
341                let ref_type = self.convert_reference_type(reference, sheet_registry);
342                self.asts.insert_reference(original, ref_type)
343            }
344
345            ASTNodeType::UnaryOp { op, expr } => {
346                let expr_id = self.convert_ast_node(expr, sheet_registry);
347                self.asts.insert_unary_op(op, expr_id)
348            }
349
350            ASTNodeType::BinaryOp { op, left, right } => {
351                let left_id = self.convert_ast_node(left, sheet_registry);
352                let right_id = self.convert_ast_node(right, sheet_registry);
353                self.asts.insert_binary_op(op, left_id, right_id)
354            }
355
356            ASTNodeType::Function { name, args } => {
357                let arg_ids: Vec<AstNodeId> = args
358                    .iter()
359                    .map(|arg| self.convert_ast_node(arg, sheet_registry))
360                    .collect();
361                self.asts.insert_function(name, arg_ids)
362            }
363
364            ASTNodeType::Array(rows) => {
365                let total_elements = rows.iter().map(|r| r.len()).sum();
366                let mut elements = Vec::with_capacity(total_elements);
367
368                let rows_count = rows.len() as u16;
369                let cols_count = rows.first().map(|r| r.len()).unwrap_or(0) as u16;
370
371                for row in rows {
372                    for elem in row {
373                        elements.push(self.convert_ast_node(elem, sheet_registry));
374                    }
375                }
376
377                self.asts.insert_array(rows_count, cols_count, elements)
378            }
379        }
380    }
381
382    /// Convert ReferenceType to CompactRefType
383    fn convert_reference_type(
384        &mut self,
385        ref_type: &ReferenceType,
386        sheet_registry: &SheetRegistry,
387    ) -> CompactRefType {
388        match ref_type {
389            ReferenceType::Cell { sheet, row, col } => {
390                let sheet = match sheet.as_ref() {
391                    Some(s) => match sheet_registry.get_id(s) {
392                        Some(id) => Some(SheetKey::Id(id)),
393                        None => Some(SheetKey::Name(self.asts.strings_mut().intern(s))),
394                    },
395                    None => None,
396                };
397                CompactRefType::Cell {
398                    sheet,
399                    row: *row,
400                    col: *col,
401                }
402            }
403
404            ReferenceType::Range {
405                sheet,
406                start_row,
407                start_col,
408                end_row,
409                end_col,
410            } => {
411                let sheet = match sheet.as_ref() {
412                    Some(s) => match sheet_registry.get_id(s) {
413                        Some(id) => Some(SheetKey::Id(id)),
414                        None => Some(SheetKey::Name(self.asts.strings_mut().intern(s))),
415                    },
416                    None => None,
417                };
418                // For optional range bounds, use 0/u32::MAX as sentinels for unbounded
419                CompactRefType::Range {
420                    sheet,
421                    start_row: start_row.unwrap_or(0),
422                    start_col: start_col.unwrap_or(0),
423                    end_row: end_row.unwrap_or(u32::MAX),
424                    end_col: end_col.unwrap_or(u32::MAX),
425                }
426            }
427
428            ReferenceType::NamedRange(name) => {
429                let string_id = self.asts.strings_mut().intern(name);
430                CompactRefType::NamedRange(string_id)
431            }
432
433            ReferenceType::Table(table_ref) => {
434                let name_id = self.asts.strings_mut().intern(&table_ref.name);
435                let specifier_id = table_ref
436                    .specifier
437                    .as_ref()
438                    .map(|specifier| self.asts.intern_table_specifier(specifier));
439                CompactRefType::Table {
440                    name_id,
441                    specifier_id,
442                }
443            }
444        }
445    }
446
447    /// Reconstruct an ASTNode from arena representation
448    fn reconstruct_ast_node(
449        &self,
450        id: AstNodeId,
451        sheet_registry: &SheetRegistry,
452    ) -> Option<ASTNode> {
453        use super::ast::AstNodeData;
454
455        let node_data = self.asts.get(id)?;
456
457        let node_type = match node_data {
458            AstNodeData::Literal(value_ref) => {
459                let lit = self.retrieve_value(*value_ref);
460                ASTNodeType::Literal(lit)
461            }
462
463            AstNodeData::Reference {
464                original_id,
465                ref_type,
466            } => {
467                let original = self.asts.resolve_string(*original_id).to_string();
468                let reference = self.reconstruct_reference_type(ref_type, sheet_registry);
469                ASTNodeType::Reference {
470                    original,
471                    reference,
472                }
473            }
474
475            AstNodeData::UnaryOp { op_id, expr_id } => {
476                let op = self.asts.resolve_string(*op_id).to_string();
477                let expr = Box::new(self.reconstruct_ast_node(*expr_id, sheet_registry)?);
478                ASTNodeType::UnaryOp { op, expr }
479            }
480
481            AstNodeData::BinaryOp {
482                op_id,
483                left_id,
484                right_id,
485            } => {
486                let op = self.asts.resolve_string(*op_id).to_string();
487                let left = Box::new(self.reconstruct_ast_node(*left_id, sheet_registry)?);
488                let right = Box::new(self.reconstruct_ast_node(*right_id, sheet_registry)?);
489                ASTNodeType::BinaryOp { op, left, right }
490            }
491
492            AstNodeData::Function { name_id, .. } => {
493                let name = self.asts.resolve_string(*name_id).to_string();
494                let arg_ids = self.asts.get_function_args(id)?;
495                let args: Vec<ASTNode> = arg_ids
496                    .iter()
497                    .filter_map(|&arg_id| self.reconstruct_ast_node(arg_id, sheet_registry))
498                    .collect();
499                ASTNodeType::Function { name, args }
500            }
501
502            AstNodeData::Array { rows, cols, .. } => {
503                let elements = self.asts.get_array_elements(id)?;
504                let mut result = Vec::with_capacity(*rows as usize);
505
506                for r in 0..*rows {
507                    let mut row = Vec::with_capacity(*cols as usize);
508                    for c in 0..*cols {
509                        let idx = (r * *cols + c) as usize;
510                        if let Some(&elem_id) = elements.get(idx)
511                            && let Some(node) = self.reconstruct_ast_node(elem_id, sheet_registry)
512                        {
513                            row.push(node);
514                        }
515                    }
516                    result.push(row);
517                }
518
519                ASTNodeType::Array(result)
520            }
521        };
522
523        Some(ASTNode {
524            node_type,
525            source_token: None, // Token information is not preserved in arena
526            contains_volatile: false,
527        })
528    }
529
530    /// Reconstruct a ReferenceType from CompactRefType
531    fn reconstruct_reference_type(
532        &self,
533        ref_type: &CompactRefType,
534        sheet_registry: &SheetRegistry,
535    ) -> ReferenceType {
536        match ref_type {
537            CompactRefType::Cell { sheet, row, col } => {
538                let sheet = match sheet {
539                    Some(SheetKey::Id(id)) => Some(sheet_registry.name(*id).to_string()),
540                    Some(SheetKey::Name(name_id)) => {
541                        Some(self.asts.resolve_string(*name_id).to_string())
542                    }
543                    None => None,
544                };
545                ReferenceType::Cell {
546                    sheet,
547                    row: *row,
548                    col: *col,
549                }
550            }
551
552            CompactRefType::Range {
553                sheet,
554                start_row,
555                start_col,
556                end_row,
557                end_col,
558            } => {
559                let sheet = match sheet {
560                    Some(SheetKey::Id(id)) => Some(sheet_registry.name(*id).to_string()),
561                    Some(SheetKey::Name(name_id)) => {
562                        Some(self.asts.resolve_string(*name_id).to_string())
563                    }
564                    None => None,
565                };
566                // Convert sentinel values back to None
567                ReferenceType::Range {
568                    sheet,
569                    start_row: if *start_row == 0 {
570                        None
571                    } else {
572                        Some(*start_row)
573                    },
574                    start_col: if *start_col == 0 {
575                        None
576                    } else {
577                        Some(*start_col)
578                    },
579                    end_row: if *end_row == u32::MAX {
580                        None
581                    } else {
582                        Some(*end_row)
583                    },
584                    end_col: if *end_col == u32::MAX {
585                        None
586                    } else {
587                        Some(*end_col)
588                    },
589                }
590            }
591
592            CompactRefType::NamedRange(string_id) => {
593                let name = self.asts.resolve_string(*string_id).to_string();
594                ReferenceType::NamedRange(name)
595            }
596
597            CompactRefType::Table {
598                name_id,
599                specifier_id,
600            } => {
601                let name = self.asts.resolve_string(*name_id).to_string();
602                let specifier = specifier_id
603                    .and_then(|id| self.asts.resolve_table_specifier(id))
604                    .cloned();
605                ReferenceType::Table(TableReference { name, specifier })
606            }
607        }
608    }
609
610    /// Store an error with message preservation
611    fn store_error(&mut self, error: &ExcelError) -> ValueRef {
612        let error_ref = self.errors.insert(error);
613        ValueRef::error(error_ref.as_u32())
614    }
615
616    /// Get memory usage statistics
617    pub fn memory_usage(&self) -> DataStoreStats {
618        DataStoreStats {
619            scalar_bytes: self.scalars.memory_usage(),
620            string_bytes: self.strings.memory_usage(),
621            array_bytes: self.arrays.memory_usage(),
622            ast_bytes: self.asts.memory_usage(),
623            error_bytes: self.errors.memory_usage(),
624            total_scalars: self.scalars.len(),
625            total_strings: self.strings.len(),
626            total_arrays: self.arrays.len(),
627            total_ast_nodes: self.asts.stats().node_count,
628            total_errors: self.errors.len(),
629        }
630    }
631
632    /// Clear all data from the store
633    pub fn clear(&mut self) {
634        self.scalars.clear();
635        self.strings.clear();
636        self.arrays.clear();
637        self.asts.clear();
638        self.errors.clear();
639    }
640}
641
642impl Default for DataStore {
643    fn default() -> Self {
644        Self::new()
645    }
646}
647
648/// Statistics about data store memory usage
649#[derive(Debug, Clone)]
650pub struct DataStoreStats {
651    pub scalar_bytes: usize,
652    pub string_bytes: usize,
653    pub array_bytes: usize,
654    pub ast_bytes: usize,
655    pub error_bytes: usize,
656    pub total_scalars: usize,
657    pub total_strings: usize,
658    pub total_arrays: usize,
659    pub total_ast_nodes: usize,
660    pub total_errors: usize,
661}
662
663impl DataStoreStats {
664    pub fn total_bytes(&self) -> usize {
665        self.scalar_bytes + self.string_bytes + self.array_bytes + self.ast_bytes + self.error_bytes
666    }
667}
668
669// Helper trait implementations for ArrayRef and ScalarRef
670impl super::array::ArrayRef {
671    pub fn from_raw(raw: u32) -> Self {
672        super::array::ArrayRef(raw)
673    }
674}
675
676impl super::scalar::ScalarRef {
677    pub fn from_raw(raw: u32) -> Self {
678        Self { raw }
679    }
680
681    pub fn as_u32(self) -> u32 {
682        self.raw
683    }
684}
685
686#[cfg(test)]
687mod tests {
688    use super::*;
689
690    #[test]
691    fn test_data_store_empty_value() {
692        let mut store = DataStore::new();
693        let value_ref = store.store_value(LiteralValue::Empty);
694        assert!(value_ref.is_empty());
695
696        let retrieved = store.retrieve_value(value_ref);
697        assert_eq!(retrieved, LiteralValue::Empty);
698    }
699
700    #[test]
701    fn test_data_store_number() {
702        let mut store = DataStore::new();
703        let value_ref = store.store_value(LiteralValue::Number(42.5));
704
705        let retrieved = store.retrieve_value(value_ref);
706        assert_eq!(retrieved, LiteralValue::Number(42.5));
707    }
708
709    #[test]
710    fn test_data_store_text() {
711        let mut store = DataStore::new();
712        let value_ref = store.store_value(LiteralValue::Text("Hello".to_string()));
713
714        let retrieved = store.retrieve_value(value_ref);
715        assert_eq!(retrieved, LiteralValue::Text("Hello".to_string()));
716    }
717
718    #[test]
719    fn test_data_store_boolean() {
720        let mut store = DataStore::new();
721
722        let true_ref = store.store_value(LiteralValue::Boolean(true));
723        let false_ref = store.store_value(LiteralValue::Boolean(false));
724
725        assert_eq!(store.retrieve_value(true_ref), LiteralValue::Boolean(true));
726        assert_eq!(
727            store.retrieve_value(false_ref),
728            LiteralValue::Boolean(false)
729        );
730    }
731
732    #[test]
733    fn test_data_store_error() {
734        let mut store = DataStore::new();
735
736        let error = ExcelError::new(ExcelErrorKind::Div);
737        let value_ref = store.store_value(LiteralValue::Error(error.clone()));
738
739        let retrieved = store.retrieve_value(value_ref);
740        match retrieved {
741            LiteralValue::Error(e) => assert_eq!(e.kind, ExcelErrorKind::Div),
742            _ => panic!("Expected error"),
743        }
744    }
745
746    #[test]
747    fn test_data_store_array() {
748        let mut store = DataStore::new();
749
750        let array = vec![
751            vec![LiteralValue::Number(1.0), LiteralValue::Number(2.0)],
752            vec![LiteralValue::Number(3.0), LiteralValue::Number(4.0)],
753        ];
754
755        let value_ref = store.store_value(LiteralValue::Array(array.clone()));
756        let retrieved = store.retrieve_value(value_ref);
757
758        assert_eq!(retrieved, LiteralValue::Array(array));
759    }
760
761    #[test]
762    fn test_data_store_ast_literal() {
763        let mut store = DataStore::new();
764        let mut sheet_registry = SheetRegistry::new();
765        sheet_registry.id_for("Sheet1");
766
767        let ast = ASTNode {
768            node_type: ASTNodeType::Literal(LiteralValue::Number(42.0)),
769            source_token: None,
770            contains_volatile: false,
771        };
772
773        let ast_id = store.store_ast(&ast, &sheet_registry);
774        let retrieved = store.retrieve_ast(ast_id, &sheet_registry).unwrap();
775
776        match retrieved.node_type {
777            ASTNodeType::Literal(lit) => assert_eq!(lit, LiteralValue::Number(42.0)),
778            _ => panic!("Expected literal"),
779        }
780    }
781
782    #[test]
783    fn test_data_store_ast_binary_op() {
784        let mut store = DataStore::new();
785        let mut sheet_registry = SheetRegistry::new();
786        sheet_registry.id_for("Sheet1");
787
788        let ast = ASTNode {
789            node_type: ASTNodeType::BinaryOp {
790                op: "+".to_string(),
791                left: Box::new(ASTNode {
792                    node_type: ASTNodeType::Literal(LiteralValue::Number(1.0)),
793                    source_token: None,
794                    contains_volatile: false,
795                }),
796                right: Box::new(ASTNode {
797                    node_type: ASTNodeType::Literal(LiteralValue::Number(2.0)),
798                    source_token: None,
799                    contains_volatile: false,
800                }),
801            },
802            source_token: None,
803            contains_volatile: false,
804        };
805
806        let ast_id = store.store_ast(&ast, &sheet_registry);
807        let retrieved = store.retrieve_ast(ast_id, &sheet_registry).unwrap();
808
809        match retrieved.node_type {
810            ASTNodeType::BinaryOp { op, left, right } => {
811                assert_eq!(op, "+");
812                match left.node_type {
813                    ASTNodeType::Literal(lit) => assert_eq!(lit, LiteralValue::Number(1.0)),
814                    _ => panic!("Expected literal"),
815                }
816                match right.node_type {
817                    ASTNodeType::Literal(lit) => assert_eq!(lit, LiteralValue::Number(2.0)),
818                    _ => panic!("Expected literal"),
819                }
820            }
821            _ => panic!("Expected binary op"),
822        }
823    }
824
825    #[test]
826    fn test_data_store_ast_function() {
827        let mut store = DataStore::new();
828        let mut sheet_registry = SheetRegistry::new();
829        sheet_registry.id_for("Sheet1");
830
831        let ast = ASTNode {
832            node_type: ASTNodeType::Function {
833                name: "SUM".to_string(),
834                args: vec![
835                    ASTNode {
836                        node_type: ASTNodeType::Literal(LiteralValue::Number(1.0)),
837                        source_token: None,
838                        contains_volatile: false,
839                    },
840                    ASTNode {
841                        node_type: ASTNodeType::Literal(LiteralValue::Number(2.0)),
842                        source_token: None,
843                        contains_volatile: false,
844                    },
845                ],
846            },
847            source_token: None,
848            contains_volatile: false,
849        };
850
851        let ast_id = store.store_ast(&ast, &sheet_registry);
852        let retrieved = store.retrieve_ast(ast_id, &sheet_registry).unwrap();
853
854        match retrieved.node_type {
855            ASTNodeType::Function { name, args } => {
856                assert_eq!(name, "SUM");
857                assert_eq!(args.len(), 2);
858            }
859            _ => panic!("Expected function"),
860        }
861    }
862
863    #[test]
864    fn test_data_store_memory_stats() {
865        let mut store = DataStore::new();
866
867        // Add some data
868        store.store_value(LiteralValue::Number(42.0));
869        store.store_value(LiteralValue::Text("Hello".to_string()));
870        store.store_value(LiteralValue::Array(vec![vec![LiteralValue::Number(1.0)]]));
871
872        let stats = store.memory_usage();
873        assert!(stats.total_bytes() > 0);
874        assert_eq!(stats.total_scalars, 2); // 42.0 and 1.0
875        assert_eq!(stats.total_strings, 1); // "Hello"
876        assert_eq!(stats.total_arrays, 1);
877    }
878
879    #[test]
880    fn test_data_store_clear() {
881        let mut store = DataStore::new();
882
883        store.store_value(LiteralValue::Number(42.0));
884        store.store_value(LiteralValue::Text("Hello".to_string()));
885
886        let stats = store.memory_usage();
887        assert!(stats.total_scalars > 0);
888        assert!(stats.total_strings > 0);
889
890        store.clear();
891
892        let stats = store.memory_usage();
893        assert_eq!(stats.total_scalars, 0);
894        assert_eq!(stats.total_strings, 0);
895    }
896}