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                ValueRef::duration(idx.as_u32())
149            }
150
151            LiteralValue::Int(i) => {
152                // Try to use small int optimization
153                if let Some(vref) = ValueRef::small_int(i as i32) {
154                    vref
155                } else {
156                    // Store as large integer
157                    let idx = self.scalars.insert_integer(i);
158                    ValueRef::large_int(idx.as_u32())
159                }
160            }
161
162            LiteralValue::Pending => ValueRef::pending(),
163        }
164    }
165
166    /// Retrieve a LiteralValue from a ValueRef
167    pub fn retrieve_value(&self, value_ref: ValueRef) -> LiteralValue {
168        use super::value_ref::ValueType;
169
170        match value_ref.value_type() {
171            ValueType::Empty => LiteralValue::Empty,
172
173            ValueType::SmallInt => {
174                // Small integers are inlined
175                if let Some(i) = value_ref.as_small_int() {
176                    LiteralValue::Int(i as i64)
177                } else {
178                    LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
179                }
180            }
181
182            ValueType::LargeInt => {
183                if let Some(idx) = value_ref.arena_index() {
184                    let scalar_ref = super::scalar::ScalarRef::from_raw(idx | (1 << 31));
185                    if let Some(i) = self.scalars.get_integer(scalar_ref) {
186                        LiteralValue::Int(i)
187                    } else {
188                        LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
189                    }
190                } else {
191                    LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
192                }
193            }
194
195            ValueType::Number => {
196                if let Some(idx) = value_ref.arena_index() {
197                    let scalar_ref = super::scalar::ScalarRef::from_raw(idx);
198                    if let Some(f) = self.scalars.get_float(scalar_ref) {
199                        LiteralValue::Number(f)
200                    } else {
201                        LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
202                    }
203                } else {
204                    LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
205                }
206            }
207
208            ValueType::String => {
209                if let Some(idx) = value_ref.arena_index() {
210                    let string_id = StringId::from_raw(idx);
211                    let s = self.strings.resolve(string_id);
212                    LiteralValue::Text(s.to_string())
213                } else {
214                    LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
215                }
216            }
217
218            ValueType::Boolean => {
219                if let Some(b) = value_ref.as_boolean() {
220                    LiteralValue::Boolean(b)
221                } else {
222                    LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
223                }
224            }
225
226            ValueType::Error => {
227                if let Some(error_ref_raw) = value_ref.as_error_ref() {
228                    let error_ref = ErrorRef::from_raw(error_ref_raw);
229                    if let Some(error) = self.errors.get(error_ref) {
230                        LiteralValue::Error(error)
231                    } else {
232                        LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
233                    }
234                } else {
235                    LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
236                }
237            }
238
239            ValueType::Array => {
240                if let Some(idx) = value_ref.arena_index() {
241                    let array_ref = super::array::ArrayRef::from_raw(idx);
242                    if let Some(array_2d) = self.arrays.get_2d(array_ref) {
243                        // Convert back to LiteralValue array
244                        let result: Vec<Vec<LiteralValue>> = array_2d
245                            .into_iter()
246                            .map(|row| row.into_iter().map(|v| self.retrieve_value(v)).collect())
247                            .collect();
248                        LiteralValue::Array(result)
249                    } else {
250                        LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
251                    }
252                } else {
253                    LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
254                }
255            }
256
257            ValueType::DateTime => {
258                if let Some(idx) = value_ref.arena_index() {
259                    let scalar_ref = super::scalar::ScalarRef::from_raw(idx);
260                    if let Some(serial) = self.scalars.get_float(scalar_ref) {
261                        let dt = formualizer_common::serial_to_datetime(serial);
262                        LiteralValue::DateTime(dt)
263                    } else {
264                        LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
265                    }
266                } else {
267                    LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
268                }
269            }
270
271            ValueType::Duration => {
272                if let Some(idx) = value_ref.arena_index() {
273                    let scalar_ref = super::scalar::ScalarRef::from_raw(idx | (1 << 31));
274                    if let Some(secs) = self.scalars.get_integer(scalar_ref) {
275                        let dur = chrono::Duration::seconds(secs);
276                        LiteralValue::Duration(dur)
277                    } else {
278                        LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
279                    }
280                } else {
281                    LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
282                }
283            }
284
285            ValueType::Pending => LiteralValue::Pending,
286
287            ValueType::FormulaAst => {
288                // Formula ASTs shouldn't be returned as values
289                LiteralValue::Error(ExcelError::new(ExcelErrorKind::Value))
290            }
291        }
292    }
293
294    /// Store an AST node and return its ID
295    pub fn store_ast(&mut self, ast: &ASTNode, sheet_registry: &SheetRegistry) -> AstNodeId {
296        self.convert_ast_node(ast, sheet_registry)
297    }
298
299    /// Retrieve an AST node from its ID
300    pub fn retrieve_ast(&self, id: AstNodeId, sheet_registry: &SheetRegistry) -> Option<ASTNode> {
301        self.reconstruct_ast_node(id, sheet_registry)
302    }
303
304    /// Convert ASTNode to arena representation
305    fn convert_ast_node(&mut self, node: &ASTNode, sheet_registry: &SheetRegistry) -> AstNodeId {
306        match &node.node_type {
307            ASTNodeType::Literal(lit) => {
308                let value_ref = self.store_value(lit.clone());
309                self.asts.insert_literal(value_ref)
310            }
311
312            ASTNodeType::Reference {
313                original,
314                reference,
315            } => {
316                let ref_type = self.convert_reference_type(reference, sheet_registry);
317                self.asts.insert_reference(original, ref_type)
318            }
319
320            ASTNodeType::UnaryOp { op, expr } => {
321                let expr_id = self.convert_ast_node(expr, sheet_registry);
322                self.asts.insert_unary_op(op, expr_id)
323            }
324
325            ASTNodeType::BinaryOp { op, left, right } => {
326                let left_id = self.convert_ast_node(left, sheet_registry);
327                let right_id = self.convert_ast_node(right, sheet_registry);
328                self.asts.insert_binary_op(op, left_id, right_id)
329            }
330
331            ASTNodeType::Function { name, args } => {
332                let arg_ids: Vec<AstNodeId> = args
333                    .iter()
334                    .map(|arg| self.convert_ast_node(arg, sheet_registry))
335                    .collect();
336                self.asts.insert_function(name, arg_ids)
337            }
338
339            ASTNodeType::Array(rows) => {
340                let total_elements = rows.iter().map(|r| r.len()).sum();
341                let mut elements = Vec::with_capacity(total_elements);
342
343                let rows_count = rows.len() as u16;
344                let cols_count = rows.first().map(|r| r.len()).unwrap_or(0) as u16;
345
346                for row in rows {
347                    for elem in row {
348                        elements.push(self.convert_ast_node(elem, sheet_registry));
349                    }
350                }
351
352                self.asts.insert_array(rows_count, cols_count, elements)
353            }
354        }
355    }
356
357    /// Convert ReferenceType to CompactRefType
358    fn convert_reference_type(
359        &mut self,
360        ref_type: &ReferenceType,
361        sheet_registry: &SheetRegistry,
362    ) -> CompactRefType {
363        match ref_type {
364            ReferenceType::Cell { sheet, row, col } => {
365                let sheet = match sheet.as_ref() {
366                    Some(s) => match sheet_registry.get_id(s) {
367                        Some(id) => Some(SheetKey::Id(id)),
368                        None => Some(SheetKey::Name(self.asts.strings_mut().intern(s))),
369                    },
370                    None => None,
371                };
372                CompactRefType::Cell {
373                    sheet,
374                    row: *row,
375                    col: *col,
376                }
377            }
378
379            ReferenceType::Range {
380                sheet,
381                start_row,
382                start_col,
383                end_row,
384                end_col,
385            } => {
386                let sheet = match sheet.as_ref() {
387                    Some(s) => match sheet_registry.get_id(s) {
388                        Some(id) => Some(SheetKey::Id(id)),
389                        None => Some(SheetKey::Name(self.asts.strings_mut().intern(s))),
390                    },
391                    None => None,
392                };
393                // For optional range bounds, use 0/u32::MAX as sentinels for unbounded
394                CompactRefType::Range {
395                    sheet,
396                    start_row: start_row.unwrap_or(0),
397                    start_col: start_col.unwrap_or(0),
398                    end_row: end_row.unwrap_or(u32::MAX),
399                    end_col: end_col.unwrap_or(u32::MAX),
400                }
401            }
402
403            ReferenceType::NamedRange(name) => {
404                let string_id = self.asts.strings_mut().intern(name);
405                CompactRefType::NamedRange(string_id)
406            }
407
408            ReferenceType::Table(table_ref) => {
409                // For now, just store the table name
410                let string_id = self.asts.strings_mut().intern(&table_ref.name);
411                CompactRefType::Table(string_id)
412            }
413        }
414    }
415
416    /// Reconstruct an ASTNode from arena representation
417    fn reconstruct_ast_node(
418        &self,
419        id: AstNodeId,
420        sheet_registry: &SheetRegistry,
421    ) -> Option<ASTNode> {
422        use super::ast::AstNodeData;
423
424        let node_data = self.asts.get(id)?;
425
426        let node_type = match node_data {
427            AstNodeData::Literal(value_ref) => {
428                let lit = self.retrieve_value(*value_ref);
429                ASTNodeType::Literal(lit)
430            }
431
432            AstNodeData::Reference {
433                original_id,
434                ref_type,
435            } => {
436                let original = self.asts.resolve_string(*original_id).to_string();
437                // If this looks like a table reference, prefer reparsing the original string to
438                // preserve structured specifiers that CompactRefType::Table doesn't encode.
439                let reference = match ref_type {
440                    super::ast::CompactRefType::Table(_) => {
441                        formualizer_parse::parser::ReferenceType::from_string(&original)
442                            .unwrap_or_else(|_| {
443                                // Fallback to name-only reconstruction if parse fails
444                                self.reconstruct_reference_type(ref_type, sheet_registry)
445                            })
446                    }
447                    _ => self.reconstruct_reference_type(ref_type, sheet_registry),
448                };
449                ASTNodeType::Reference {
450                    original,
451                    reference,
452                }
453            }
454
455            AstNodeData::UnaryOp { op_id, expr_id } => {
456                let op = self.asts.resolve_string(*op_id).to_string();
457                let expr = Box::new(self.reconstruct_ast_node(*expr_id, sheet_registry)?);
458                ASTNodeType::UnaryOp { op, expr }
459            }
460
461            AstNodeData::BinaryOp {
462                op_id,
463                left_id,
464                right_id,
465            } => {
466                let op = self.asts.resolve_string(*op_id).to_string();
467                let left = Box::new(self.reconstruct_ast_node(*left_id, sheet_registry)?);
468                let right = Box::new(self.reconstruct_ast_node(*right_id, sheet_registry)?);
469                ASTNodeType::BinaryOp { op, left, right }
470            }
471
472            AstNodeData::Function { name_id, .. } => {
473                let name = self.asts.resolve_string(*name_id).to_string();
474                let arg_ids = self.asts.get_function_args(id)?;
475                let args: Vec<ASTNode> = arg_ids
476                    .iter()
477                    .filter_map(|&arg_id| self.reconstruct_ast_node(arg_id, sheet_registry))
478                    .collect();
479                ASTNodeType::Function { name, args }
480            }
481
482            AstNodeData::Array { rows, cols, .. } => {
483                let elements = self.asts.get_array_elements(id)?;
484                let mut result = Vec::with_capacity(*rows as usize);
485
486                for r in 0..*rows {
487                    let mut row = Vec::with_capacity(*cols as usize);
488                    for c in 0..*cols {
489                        let idx = (r * *cols + c) as usize;
490                        if let Some(&elem_id) = elements.get(idx) {
491                            if let Some(node) = self.reconstruct_ast_node(elem_id, sheet_registry) {
492                                row.push(node);
493                            }
494                        }
495                    }
496                    result.push(row);
497                }
498
499                ASTNodeType::Array(result)
500            }
501        };
502
503        Some(ASTNode {
504            node_type,
505            source_token: None, // Token information is not preserved in arena
506            contains_volatile: false,
507        })
508    }
509
510    /// Reconstruct a ReferenceType from CompactRefType
511    fn reconstruct_reference_type(
512        &self,
513        ref_type: &CompactRefType,
514        sheet_registry: &SheetRegistry,
515    ) -> ReferenceType {
516        match ref_type {
517            CompactRefType::Cell { sheet, row, col } => {
518                let sheet = match sheet {
519                    Some(SheetKey::Id(id)) => Some(sheet_registry.name(*id).to_string()),
520                    Some(SheetKey::Name(name_id)) => {
521                        Some(self.asts.resolve_string(*name_id).to_string())
522                    }
523                    None => None,
524                };
525                ReferenceType::Cell {
526                    sheet,
527                    row: *row,
528                    col: *col,
529                }
530            }
531
532            CompactRefType::Range {
533                sheet,
534                start_row,
535                start_col,
536                end_row,
537                end_col,
538            } => {
539                let sheet = match sheet {
540                    Some(SheetKey::Id(id)) => Some(sheet_registry.name(*id).to_string()),
541                    Some(SheetKey::Name(name_id)) => {
542                        Some(self.asts.resolve_string(*name_id).to_string())
543                    }
544                    None => None,
545                };
546                // Convert sentinel values back to None
547                ReferenceType::Range {
548                    sheet,
549                    start_row: if *start_row == 0 {
550                        None
551                    } else {
552                        Some(*start_row)
553                    },
554                    start_col: if *start_col == 0 {
555                        None
556                    } else {
557                        Some(*start_col)
558                    },
559                    end_row: if *end_row == u32::MAX {
560                        None
561                    } else {
562                        Some(*end_row)
563                    },
564                    end_col: if *end_col == u32::MAX {
565                        None
566                    } else {
567                        Some(*end_col)
568                    },
569                }
570            }
571
572            CompactRefType::NamedRange(string_id) => {
573                let name = self.asts.resolve_string(*string_id).to_string();
574                ReferenceType::NamedRange(name)
575            }
576
577            CompactRefType::Table(string_id) => {
578                let name = self.asts.resolve_string(*string_id).to_string();
579                ReferenceType::Table(TableReference {
580                    name,
581                    specifier: None, // Specifier not preserved
582                })
583            }
584        }
585    }
586
587    /// Store an error with message preservation
588    fn store_error(&mut self, error: &ExcelError) -> ValueRef {
589        let error_ref = self.errors.insert(error);
590        ValueRef::error(error_ref.as_u32())
591    }
592
593    /// Get memory usage statistics
594    pub fn memory_usage(&self) -> DataStoreStats {
595        DataStoreStats {
596            scalar_bytes: self.scalars.memory_usage(),
597            string_bytes: self.strings.memory_usage(),
598            array_bytes: self.arrays.memory_usage(),
599            ast_bytes: self.asts.memory_usage(),
600            error_bytes: self.errors.memory_usage(),
601            total_scalars: self.scalars.len(),
602            total_strings: self.strings.len(),
603            total_arrays: self.arrays.len(),
604            total_ast_nodes: self.asts.stats().node_count,
605            total_errors: self.errors.len(),
606        }
607    }
608
609    /// Clear all data from the store
610    pub fn clear(&mut self) {
611        self.scalars.clear();
612        self.strings.clear();
613        self.arrays.clear();
614        self.asts.clear();
615        self.errors.clear();
616    }
617}
618
619impl Default for DataStore {
620    fn default() -> Self {
621        Self::new()
622    }
623}
624
625/// Statistics about data store memory usage
626#[derive(Debug, Clone)]
627pub struct DataStoreStats {
628    pub scalar_bytes: usize,
629    pub string_bytes: usize,
630    pub array_bytes: usize,
631    pub ast_bytes: usize,
632    pub error_bytes: usize,
633    pub total_scalars: usize,
634    pub total_strings: usize,
635    pub total_arrays: usize,
636    pub total_ast_nodes: usize,
637    pub total_errors: usize,
638}
639
640impl DataStoreStats {
641    pub fn total_bytes(&self) -> usize {
642        self.scalar_bytes + self.string_bytes + self.array_bytes + self.ast_bytes + self.error_bytes
643    }
644}
645
646// Helper trait implementations for ArrayRef and ScalarRef
647impl super::array::ArrayRef {
648    pub fn from_raw(raw: u32) -> Self {
649        super::array::ArrayRef(raw)
650    }
651}
652
653impl super::scalar::ScalarRef {
654    pub fn from_raw(raw: u32) -> Self {
655        Self { raw }
656    }
657
658    pub fn as_u32(self) -> u32 {
659        self.raw
660    }
661}
662
663#[cfg(test)]
664mod tests {
665    use super::*;
666
667    #[test]
668    fn test_data_store_empty_value() {
669        let mut store = DataStore::new();
670        let value_ref = store.store_value(LiteralValue::Empty);
671        assert!(value_ref.is_empty());
672
673        let retrieved = store.retrieve_value(value_ref);
674        assert_eq!(retrieved, LiteralValue::Empty);
675    }
676
677    #[test]
678    fn test_data_store_number() {
679        let mut store = DataStore::new();
680        let value_ref = store.store_value(LiteralValue::Number(42.5));
681
682        let retrieved = store.retrieve_value(value_ref);
683        assert_eq!(retrieved, LiteralValue::Number(42.5));
684    }
685
686    #[test]
687    fn test_data_store_text() {
688        let mut store = DataStore::new();
689        let value_ref = store.store_value(LiteralValue::Text("Hello".to_string()));
690
691        let retrieved = store.retrieve_value(value_ref);
692        assert_eq!(retrieved, LiteralValue::Text("Hello".to_string()));
693    }
694
695    #[test]
696    fn test_data_store_boolean() {
697        let mut store = DataStore::new();
698
699        let true_ref = store.store_value(LiteralValue::Boolean(true));
700        let false_ref = store.store_value(LiteralValue::Boolean(false));
701
702        assert_eq!(store.retrieve_value(true_ref), LiteralValue::Boolean(true));
703        assert_eq!(
704            store.retrieve_value(false_ref),
705            LiteralValue::Boolean(false)
706        );
707    }
708
709    #[test]
710    fn test_data_store_error() {
711        let mut store = DataStore::new();
712
713        let error = ExcelError::new(ExcelErrorKind::Div);
714        let value_ref = store.store_value(LiteralValue::Error(error.clone()));
715
716        let retrieved = store.retrieve_value(value_ref);
717        match retrieved {
718            LiteralValue::Error(e) => assert_eq!(e.kind, ExcelErrorKind::Div),
719            _ => panic!("Expected error"),
720        }
721    }
722
723    #[test]
724    fn test_data_store_array() {
725        let mut store = DataStore::new();
726
727        let array = vec![
728            vec![LiteralValue::Number(1.0), LiteralValue::Number(2.0)],
729            vec![LiteralValue::Number(3.0), LiteralValue::Number(4.0)],
730        ];
731
732        let value_ref = store.store_value(LiteralValue::Array(array.clone()));
733        let retrieved = store.retrieve_value(value_ref);
734
735        assert_eq!(retrieved, LiteralValue::Array(array));
736    }
737
738    #[test]
739    fn test_data_store_ast_literal() {
740        let mut store = DataStore::new();
741        let mut sheet_registry = SheetRegistry::new();
742        sheet_registry.id_for("Sheet1");
743
744        let ast = ASTNode {
745            node_type: ASTNodeType::Literal(LiteralValue::Number(42.0)),
746            source_token: None,
747            contains_volatile: false,
748        };
749
750        let ast_id = store.store_ast(&ast, &sheet_registry);
751        let retrieved = store.retrieve_ast(ast_id, &sheet_registry).unwrap();
752
753        match retrieved.node_type {
754            ASTNodeType::Literal(lit) => assert_eq!(lit, LiteralValue::Number(42.0)),
755            _ => panic!("Expected literal"),
756        }
757    }
758
759    #[test]
760    fn test_data_store_ast_binary_op() {
761        let mut store = DataStore::new();
762        let mut sheet_registry = SheetRegistry::new();
763        sheet_registry.id_for("Sheet1");
764
765        let ast = ASTNode {
766            node_type: ASTNodeType::BinaryOp {
767                op: "+".to_string(),
768                left: Box::new(ASTNode {
769                    node_type: ASTNodeType::Literal(LiteralValue::Number(1.0)),
770                    source_token: None,
771                    contains_volatile: false,
772                }),
773                right: Box::new(ASTNode {
774                    node_type: ASTNodeType::Literal(LiteralValue::Number(2.0)),
775                    source_token: None,
776                    contains_volatile: false,
777                }),
778            },
779            source_token: None,
780            contains_volatile: false,
781        };
782
783        let ast_id = store.store_ast(&ast, &sheet_registry);
784        let retrieved = store.retrieve_ast(ast_id, &sheet_registry).unwrap();
785
786        match retrieved.node_type {
787            ASTNodeType::BinaryOp { op, left, right } => {
788                assert_eq!(op, "+");
789                match left.node_type {
790                    ASTNodeType::Literal(lit) => assert_eq!(lit, LiteralValue::Number(1.0)),
791                    _ => panic!("Expected literal"),
792                }
793                match right.node_type {
794                    ASTNodeType::Literal(lit) => assert_eq!(lit, LiteralValue::Number(2.0)),
795                    _ => panic!("Expected literal"),
796                }
797            }
798            _ => panic!("Expected binary op"),
799        }
800    }
801
802    #[test]
803    fn test_data_store_ast_function() {
804        let mut store = DataStore::new();
805        let mut sheet_registry = SheetRegistry::new();
806        sheet_registry.id_for("Sheet1");
807
808        let ast = ASTNode {
809            node_type: ASTNodeType::Function {
810                name: "SUM".to_string(),
811                args: vec![
812                    ASTNode {
813                        node_type: ASTNodeType::Literal(LiteralValue::Number(1.0)),
814                        source_token: None,
815                        contains_volatile: false,
816                    },
817                    ASTNode {
818                        node_type: ASTNodeType::Literal(LiteralValue::Number(2.0)),
819                        source_token: None,
820                        contains_volatile: false,
821                    },
822                ],
823            },
824            source_token: None,
825            contains_volatile: false,
826        };
827
828        let ast_id = store.store_ast(&ast, &sheet_registry);
829        let retrieved = store.retrieve_ast(ast_id, &sheet_registry).unwrap();
830
831        match retrieved.node_type {
832            ASTNodeType::Function { name, args } => {
833                assert_eq!(name, "SUM");
834                assert_eq!(args.len(), 2);
835            }
836            _ => panic!("Expected function"),
837        }
838    }
839
840    #[test]
841    fn test_data_store_memory_stats() {
842        let mut store = DataStore::new();
843
844        // Add some data
845        store.store_value(LiteralValue::Number(42.0));
846        store.store_value(LiteralValue::Text("Hello".to_string()));
847        store.store_value(LiteralValue::Array(vec![vec![LiteralValue::Number(1.0)]]));
848
849        let stats = store.memory_usage();
850        assert!(stats.total_bytes() > 0);
851        assert_eq!(stats.total_scalars, 2); // 42.0 and 1.0
852        assert_eq!(stats.total_strings, 1); // "Hello"
853        assert_eq!(stats.total_arrays, 1);
854    }
855
856    #[test]
857    fn test_data_store_clear() {
858        let mut store = DataStore::new();
859
860        store.store_value(LiteralValue::Number(42.0));
861        store.store_value(LiteralValue::Text("Hello".to_string()));
862
863        let stats = store.memory_usage();
864        assert!(stats.total_scalars > 0);
865        assert!(stats.total_strings > 0);
866
867        store.clear();
868
869        let stats = store.memory_usage();
870        assert_eq!(stats.total_scalars, 0);
871        assert_eq!(stats.total_strings, 0);
872    }
873}