1use crate::engine::lookup_index_cache::{LookupAxis, LookupIndex};
2use crate::engine::range_view::RangeView;
3use crate::engine::row_visibility::VisibilityMaskMode;
4pub use crate::function::Function;
5use crate::interpreter::Interpreter;
6use crate::reference::CellRef;
7use formualizer_common::{
8 LiteralValue,
9 error::{ExcelError, ExcelErrorKind},
10};
11use std::any::Any;
12use std::borrow::Cow;
13use std::fmt::Debug;
14use std::sync::Arc;
15
16use formualizer_parse::parser::{ASTNode, ASTNodeType, ReferenceType, TableSpecifier};
17
18#[derive(Clone, Debug, Eq, PartialEq)]
19pub struct ReferenceInfo {
20 pub first_sheet_index: Option<usize>,
22 pub sheet_count: Option<usize>,
24 pub first_cell: Option<CellRef>,
26}
27
28pub trait Range: Debug + Send + Sync {
31 fn get(&self, row: usize, col: usize) -> Result<LiteralValue, ExcelError>;
32 fn dimensions(&self) -> (usize, usize);
33
34 fn is_sparse(&self) -> bool {
35 false
36 }
37
38 fn is_infinite(&self) -> bool {
40 false
41 }
42
43 fn materialise(&self) -> Cow<'_, [Vec<LiteralValue>]> {
44 Cow::Owned(
45 (0..self.dimensions().0)
46 .map(|r| {
47 (0..self.dimensions().1)
48 .map(|c| self.get(r, c).unwrap_or(LiteralValue::Empty))
49 .collect()
50 })
51 .collect(),
52 )
53 }
54
55 fn iter_cells<'a>(&'a self) -> Box<dyn Iterator<Item = LiteralValue> + 'a> {
56 let (rows, cols) = self.dimensions();
57 Box::new((0..rows).flat_map(move |r| (0..cols).map(move |c| self.get(r, c).unwrap())))
58 }
59 fn iter_rows<'a>(&'a self) -> Box<dyn Iterator<Item = Vec<LiteralValue>> + 'a> {
60 let (rows, cols) = self.dimensions();
61 Box::new((0..rows).map(move |r| (0..cols).map(|c| self.get(r, c).unwrap()).collect()))
62 }
63
64 fn as_any(&self) -> &dyn Any;
66}
67
68impl Range for Box<dyn Range> {
70 fn get(&self, r: usize, c: usize) -> Result<LiteralValue, ExcelError> {
71 (**self).get(r, c)
72 }
73 fn dimensions(&self) -> (usize, usize) {
74 (**self).dimensions()
75 }
76 fn is_sparse(&self) -> bool {
77 (**self).is_sparse()
78 }
79 fn materialise(&self) -> Cow<'_, [Vec<LiteralValue>]> {
80 (**self).materialise()
81 }
82 fn iter_cells<'a>(&'a self) -> Box<dyn Iterator<Item = LiteralValue> + 'a> {
83 (**self).iter_cells()
84 }
85 fn iter_rows<'a>(&'a self) -> Box<dyn Iterator<Item = Vec<LiteralValue>> + 'a> {
86 (**self).iter_rows()
87 }
88 fn as_any(&self) -> &dyn Any {
89 (**self).as_any()
90 }
91}
92
93pub type CowValue<'a> = Cow<'a, LiteralValue>;
96
97pub trait CustomCallable: Send + Sync {
98 fn arity(&self) -> usize;
99
100 fn invoke<'ctx>(
101 &self,
102 interp: &Interpreter<'ctx>,
103 args: &[LiteralValue],
104 ) -> Result<CalcValue<'ctx>, ExcelError>;
105}
106
107#[derive(Clone)]
108pub enum CalcValue<'a> {
109 Scalar(LiteralValue),
110 Range(RangeView<'a>),
111 Callable(Arc<dyn CustomCallable>),
112}
113
114impl<'a> std::fmt::Debug for CalcValue<'a> {
115 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
116 match self {
117 CalcValue::Scalar(v) => f.debug_tuple("Scalar").field(v).finish(),
118 CalcValue::Range(rv) => {
119 let (r, c) = rv.dims();
120 f.debug_tuple("Range").field(&(r, c)).finish()
121 }
122 CalcValue::Callable(_) => f.write_str("Callable(<opaque>)"),
123 }
124 }
125}
126
127impl<'a> CalcValue<'a> {
128 pub fn into_literal(self) -> LiteralValue {
129 match self {
130 CalcValue::Scalar(s) => s,
131 CalcValue::Range(rv) => {
132 let (rows, cols) = rv.dims();
133 if rows == 1 && cols == 1 {
134 rv.get_cell(0, 0)
135 } else {
136 let mut data = Vec::with_capacity(rows);
137 let _ = rv.for_each_row(&mut |row| {
140 data.push(row.to_vec());
141 Ok(())
142 });
143 LiteralValue::Array(data)
144 }
145 }
146 CalcValue::Callable(_) => LiteralValue::Error(
147 ExcelError::new(ExcelErrorKind::Calc).with_message("LAMBDA value must be invoked"),
148 ),
149 }
150 }
151
152 pub fn as_scalar(&self) -> Option<&LiteralValue> {
153 match self {
154 CalcValue::Scalar(s) => Some(s),
155 _ => None,
156 }
157 }
158
159 pub fn as_range(&self) -> Option<&RangeView<'a>> {
160 match self {
161 CalcValue::Range(r) => Some(r),
162 _ => None,
163 }
164 }
165
166 pub fn as_callable(&self) -> Option<&Arc<dyn CustomCallable>> {
167 match self {
168 CalcValue::Callable(c) => Some(c),
169 _ => None,
170 }
171 }
172
173 pub fn into_owned(self) -> LiteralValue {
174 self.into_literal()
175 }
176}
177
178impl From<CalcValue<'_>> for LiteralValue {
179 fn from(val: CalcValue<'_>) -> Self {
180 val.into_literal()
181 }
182}
183
184impl<'a> PartialEq<LiteralValue> for CalcValue<'a> {
185 fn eq(&self, other: &LiteralValue) -> bool {
186 match self {
187 CalcValue::Scalar(s) => s == other,
188 CalcValue::Range(rv) => match other {
189 LiteralValue::Array(arr) => {
190 let (rows, cols) = rv.dims();
191 if arr.len() != rows {
192 return false;
193 }
194 for (r, row) in arr.iter().enumerate() {
195 if row.len() != cols {
196 return false;
197 }
198 for (c, cell) in row.iter().enumerate() {
199 if &rv.get_cell(r, c) != cell {
200 return false;
201 }
202 }
203 }
204 true
205 }
206 _ => {
207 let (rows, cols) = rv.dims();
208 rows == 1 && cols == 1 && &rv.get_cell(0, 0) == other
209 }
210 },
211 CalcValue::Callable(_) => false,
212 }
213 }
214}
215
216impl<'a> PartialEq<CalcValue<'a>> for LiteralValue {
217 fn eq(&self, other: &CalcValue<'a>) -> bool {
218 other == self
219 }
220}
221
222pub enum EvaluatedArg<'a> {
223 LiteralValue(CowValue<'a>),
224 Range(Box<dyn Range>),
225}
226
227enum ArgumentExpr<'a> {
228 Ast(&'a ASTNode),
229 Arena {
230 id: crate::engine::arena::AstNodeId,
231 data_store: &'a crate::engine::arena::DataStore,
232 sheet_registry: &'a crate::engine::sheet_registry::SheetRegistry,
233 },
234}
235
236pub struct ArgumentHandle<'a, 'b> {
237 expr: ArgumentExpr<'a>,
238 interp: &'a Interpreter<'b>,
239 cached_ast: std::cell::OnceCell<ASTNode>,
240 cached_ref: std::cell::OnceCell<ReferenceType>,
241 cached_value: std::cell::OnceCell<Result<crate::traits::CalcValue<'b>, ExcelError>>,
250}
251
252impl<'a, 'b> ArgumentHandle<'a, 'b> {
253 pub(crate) fn new(node: &'a ASTNode, interp: &'a Interpreter<'b>) -> Self {
254 Self {
255 expr: ArgumentExpr::Ast(node),
256 interp,
257 cached_ast: std::cell::OnceCell::new(),
258 cached_ref: std::cell::OnceCell::new(),
259 cached_value: std::cell::OnceCell::new(),
260 }
261 }
262
263 pub(crate) fn new_arena(
264 id: crate::engine::arena::AstNodeId,
265 interp: &'a Interpreter<'b>,
266 data_store: &'a crate::engine::arena::DataStore,
267 sheet_registry: &'a crate::engine::sheet_registry::SheetRegistry,
268 ) -> Self {
269 Self {
270 expr: ArgumentExpr::Arena {
271 id,
272 data_store,
273 sheet_registry,
274 },
275 interp,
276 cached_ast: std::cell::OnceCell::new(),
277 cached_ref: std::cell::OnceCell::new(),
278 cached_value: std::cell::OnceCell::new(),
279 }
280 }
281
282 pub fn value(&self) -> Result<crate::traits::CalcValue<'b>, ExcelError> {
283 self.cached_value
284 .get_or_init(|| self.compute_value())
285 .clone()
286 }
287
288 fn compute_value(&self) -> Result<crate::traits::CalcValue<'b>, ExcelError> {
289 match &self.expr {
290 ArgumentExpr::Ast(node) => {
291 if let ASTNodeType::Literal(ref v) = node.node_type {
292 return Ok(crate::traits::CalcValue::Scalar(v.clone()));
293 }
294 self.interp.evaluate_ast(node)
295 }
296 ArgumentExpr::Arena {
297 id,
298 data_store,
299 sheet_registry,
300 } => self
301 .interp
302 .evaluate_arena_ast(*id, data_store, sheet_registry),
303 }
304 }
305
306 pub fn value_with_env(
307 &self,
308 env: crate::interpreter::LocalEnv,
309 ) -> Result<crate::traits::CalcValue<'b>, ExcelError> {
310 let scoped = self.interp.with_local_env(env);
311 match &self.expr {
312 ArgumentExpr::Ast(node) => {
313 if let ASTNodeType::Literal(ref v) = node.node_type {
314 return Ok(crate::traits::CalcValue::Scalar(v.clone()));
315 }
316 scoped.evaluate_ast(node)
317 }
318 ArgumentExpr::Arena {
319 id,
320 data_store,
321 sheet_registry,
322 } => scoped.evaluate_arena_ast(*id, data_store, sheet_registry),
323 }
324 }
325
326 pub fn current_env(&self) -> crate::interpreter::LocalEnv {
327 self.interp.local_env().clone()
328 }
329
330 pub fn inline_array_literal(&self) -> Result<Option<Vec<Vec<LiteralValue>>>, ExcelError> {
331 match &self.expr {
332 ArgumentExpr::Ast(node) => match &node.node_type {
333 ASTNodeType::Literal(LiteralValue::Array(arr)) => Ok(Some(arr.clone())),
334 _ => Ok(None),
335 },
336 ArgumentExpr::Arena {
337 id,
338 data_store,
339 sheet_registry,
340 } => {
341 let node = data_store.get_node(*id).ok_or_else(|| {
342 ExcelError::new(ExcelErrorKind::Value).with_message("Missing AST node")
343 })?;
344 match node {
345 crate::engine::arena::AstNodeData::Literal(vref) => {
346 match data_store.retrieve_value(*vref) {
347 LiteralValue::Array(arr) => Ok(Some(arr)),
348 _ => Ok(None),
349 }
350 }
351 _ => {
352 let _ = sheet_registry;
355 Ok(None)
356 }
357 }
358 }
359 }
360 }
361
362 fn reference_for_eval(&self) -> Result<ReferenceType, ExcelError> {
363 match &self.expr {
364 ArgumentExpr::Ast(node) => match &node.node_type {
365 ASTNodeType::Reference { reference, .. } => {
366 self.interp.reference_for_current_offset(reference)
367 }
368 ASTNodeType::Function { .. } | ASTNodeType::BinaryOp { .. } => {
369 self.interp.evaluate_ast_as_reference(node)
370 }
371 _ => Err(ExcelError::new(ExcelErrorKind::Ref)
372 .with_message("Expected a reference (by-ref argument)")),
373 },
374 ArgumentExpr::Arena {
375 id,
376 data_store,
377 sheet_registry,
378 } => {
379 let node = data_store.get_node(*id).ok_or_else(|| {
380 ExcelError::new(ExcelErrorKind::Value).with_message("Missing AST node")
381 })?;
382 match node {
383 crate::engine::arena::AstNodeData::Reference { ref_type, .. } => {
384 let reference = data_store
385 .reconstruct_reference_type_for_eval(ref_type, sheet_registry);
386 self.interp.reference_for_current_offset(&reference)
387 }
388 crate::engine::arena::AstNodeData::Function { .. }
389 | crate::engine::arena::AstNodeData::BinaryOp { .. } => self
390 .interp
391 .evaluate_arena_ast_as_reference(*id, data_store, sheet_registry),
392 _ => Err(ExcelError::new(ExcelErrorKind::Ref)
393 .with_message("Expected a reference (by-ref argument)")),
394 }
395 }
396 }
397 }
398
399 pub fn range(&self) -> Result<Box<dyn Range>, ExcelError> {
400 match &self.expr {
401 ArgumentExpr::Ast(node) => match &node.node_type {
402 ASTNodeType::Reference { reference, .. } => {
403 let reference = self.interp.reference_for_current_offset(reference)?;
405 let view = self
406 .interp
407 .context
408 .resolve_range_view(&reference, self.interp.current_sheet())?;
409 let (rows, cols) = view.dims();
410 let mut out: Vec<Vec<LiteralValue>> = Vec::with_capacity(rows);
411 view.for_each_row(&mut |row| {
412 let row_data: Vec<LiteralValue> = (0..cols)
413 .map(|c| row.get(c).cloned().unwrap_or(LiteralValue::Empty))
414 .collect();
415 out.push(row_data);
416 Ok(())
417 })?;
418 Ok(Box::new(InMemoryRange::new(out)))
419 }
420 ASTNodeType::Function { .. } | ASTNodeType::BinaryOp { .. } => {
421 let reference = self.reference_for_eval()?;
422 let view = self
423 .interp
424 .context
425 .resolve_range_view(&reference, self.interp.current_sheet())?;
426 let (rows, cols) = view.dims();
427 let mut out: Vec<Vec<LiteralValue>> = Vec::with_capacity(rows);
428 view.for_each_row(&mut |row| {
429 let row_data: Vec<LiteralValue> = (0..cols)
430 .map(|c| row.get(c).cloned().unwrap_or(LiteralValue::Empty))
431 .collect();
432 out.push(row_data);
433 Ok(())
434 })?;
435 Ok(Box::new(InMemoryRange::new(out)))
436 }
437 ASTNodeType::Array(rows) => {
438 let mut materialized = Vec::new();
439 for row in rows {
440 let mut materialized_row = Vec::new();
441 for cell in row {
442 materialized_row.push(self.interp.evaluate_ast(cell)?.into_literal());
443 }
444 materialized.push(materialized_row);
445 }
446 Ok(Box::new(InMemoryRange::new(materialized)))
447 }
448 _ => Err(ExcelError::new(ExcelErrorKind::Ref)
449 .with_message(format!("Expected a range, got {:?}", node.node_type))),
450 },
451 ArgumentExpr::Arena { id, data_store, .. } => {
452 let node = data_store.get_node(*id).ok_or_else(|| {
453 ExcelError::new(ExcelErrorKind::Value).with_message("Missing AST node")
454 })?;
455
456 match node {
457 crate::engine::arena::AstNodeData::Reference { .. }
458 | crate::engine::arena::AstNodeData::Function { .. }
459 | crate::engine::arena::AstNodeData::BinaryOp { .. } => {
460 let reference = self.reference_for_eval()?;
461 let view = self
462 .interp
463 .context
464 .resolve_range_view(&reference, self.interp.current_sheet())?;
465 let (rows, cols) = view.dims();
466 let mut out: Vec<Vec<LiteralValue>> = Vec::with_capacity(rows);
467 view.for_each_row(&mut |row| {
468 let row_data: Vec<LiteralValue> = (0..cols)
469 .map(|c| row.get(c).cloned().unwrap_or(LiteralValue::Empty))
470 .collect();
471 out.push(row_data);
472 Ok(())
473 })?;
474 Ok(Box::new(InMemoryRange::new(out)))
475 }
476 crate::engine::arena::AstNodeData::Array { .. } => {
477 let (rows, cols, elements) =
478 data_store.get_array_elems(*id).ok_or_else(|| {
479 ExcelError::new(ExcelErrorKind::Value).with_message("Invalid array")
480 })?;
481 let rows_usize = rows as usize;
482 let cols_usize = cols as usize;
483 let mut materialized: Vec<Vec<LiteralValue>> =
484 Vec::with_capacity(rows_usize);
485 for r in 0..rows_usize {
486 let mut row = Vec::with_capacity(cols_usize);
487 for c in 0..cols_usize {
488 let idx = r * cols_usize + c;
489 let elem_id = elements.get(idx).copied().ok_or_else(|| {
490 ExcelError::new(ExcelErrorKind::Value)
491 .with_message("Invalid array")
492 })?;
493 let v = self.interp.evaluate_arena_ast(
494 elem_id,
495 data_store,
496 self.sheet_registry(),
497 )?;
498 row.push(v.into_literal());
499 }
500 materialized.push(row);
501 }
502 Ok(Box::new(InMemoryRange::new(materialized)))
503 }
504 _ => Err(ExcelError::new(ExcelErrorKind::Ref)
505 .with_message("Argument cannot be interpreted as a range.")),
506 }
507 }
508 }
509 }
510
511 fn sheet_registry(&self) -> &crate::engine::sheet_registry::SheetRegistry {
512 match &self.expr {
513 ArgumentExpr::Ast(_) => {
514 unreachable!("sheet_registry only used for arena ArgumentHandle")
516 }
517 ArgumentExpr::Arena { sheet_registry, .. } => sheet_registry,
518 }
519 }
520
521 pub fn range_view(&self) -> Result<RangeView<'b>, ExcelError> {
523 match &self.expr {
524 ArgumentExpr::Ast(node) => match &node.node_type {
525 ASTNodeType::Reference { reference, .. } => {
526 let reference = self.interp.reference_for_current_offset(reference)?;
527 self.interp
528 .context
529 .resolve_range_view(&reference, self.interp.current_sheet())
530 .map(|v| v.with_cancel_token(self.interp.context.cancellation_token()))
531 }
532 ASTNodeType::Literal(formualizer_common::LiteralValue::Array(arr)) => Ok(
534 RangeView::from_owned_rows(arr.clone(), self.interp.context.date_system())
535 .with_cancel_token(self.interp.context.cancellation_token()),
536 ),
537 ASTNodeType::Array(rows) => {
538 let mut out: Vec<Vec<LiteralValue>> = Vec::with_capacity(rows.len());
539 for r in rows {
540 let mut row_vals = Vec::with_capacity(r.len());
541 for cell in r {
542 row_vals.push(self.interp.evaluate_ast(cell)?.into_literal());
543 }
544 out.push(row_vals);
545 }
546 Ok(
547 RangeView::from_owned_rows(out, self.interp.context.date_system())
548 .with_cancel_token(self.interp.context.cancellation_token()),
549 )
550 }
551 ASTNodeType::Function { .. } | ASTNodeType::BinaryOp { .. } => {
552 let reference = self.reference_for_eval()?;
553 self.interp
554 .context
555 .resolve_range_view(&reference, self.interp.current_sheet())
556 .map(|v| v.with_cancel_token(self.interp.context.cancellation_token()))
557 }
558 _ => Err(ExcelError::new(ExcelErrorKind::Ref)
559 .with_message("Argument cannot be interpreted as a range.")),
560 },
561 ArgumentExpr::Arena {
562 id,
563 data_store,
564 sheet_registry,
565 } => {
566 let node = data_store.get_node(*id).ok_or_else(|| {
567 ExcelError::new(ExcelErrorKind::Value).with_message("Missing AST node")
568 })?;
569
570 match node {
571 crate::engine::arena::AstNodeData::Reference { .. }
572 | crate::engine::arena::AstNodeData::Function { .. }
573 | crate::engine::arena::AstNodeData::BinaryOp { .. } => {
574 let reference = self.reference_for_eval()?;
575 self.interp
576 .context
577 .resolve_range_view(&reference, self.interp.current_sheet())
578 .map(|v| v.with_cancel_token(self.interp.context.cancellation_token()))
579 }
580 crate::engine::arena::AstNodeData::Literal(vref) => {
581 match data_store.retrieve_value(*vref) {
582 LiteralValue::Array(arr) => Ok(RangeView::from_owned_rows(
583 arr,
584 self.interp.context.date_system(),
585 )
586 .with_cancel_token(self.interp.context.cancellation_token())),
587 _ => Err(ExcelError::new(ExcelErrorKind::Ref)
588 .with_message("Argument cannot be interpreted as a range.")),
589 }
590 }
591 crate::engine::arena::AstNodeData::Array { .. } => {
592 let (rows, cols, elements) =
593 data_store.get_array_elems(*id).ok_or_else(|| {
594 ExcelError::new(ExcelErrorKind::Value).with_message("Invalid array")
595 })?;
596
597 let rows_usize = rows as usize;
598 let cols_usize = cols as usize;
599 let mut out: Vec<Vec<LiteralValue>> = Vec::with_capacity(rows_usize);
600 for r in 0..rows_usize {
601 let mut row = Vec::with_capacity(cols_usize);
602 for c in 0..cols_usize {
603 let idx = r * cols_usize + c;
604 let elem_id = elements.get(idx).copied().ok_or_else(|| {
605 ExcelError::new(ExcelErrorKind::Value)
606 .with_message("Invalid array")
607 })?;
608 let v = self.interp.evaluate_arena_ast(
609 elem_id,
610 data_store,
611 sheet_registry,
612 )?;
613 row.push(v.into_literal());
614 }
615 out.push(row);
616 }
617 Ok(
618 RangeView::from_owned_rows(out, self.interp.context.date_system())
619 .with_cancel_token(self.interp.context.cancellation_token()),
620 )
621 }
622 _ => Err(ExcelError::new(ExcelErrorKind::Ref)
623 .with_message("Argument cannot be interpreted as a range.")),
624 }
625 }
626 }
627 }
628
629 pub fn value_or_range(&self) -> Result<EvaluatedArg<'_>, ExcelError> {
630 self.range().map(EvaluatedArg::Range).or_else(|_| {
631 self.value()
632 .map(|cv| EvaluatedArg::LiteralValue(Cow::Owned(cv.into_literal())))
633 })
634 }
635
636 pub fn lazy_values_owned(
641 &'a self,
642 ) -> Result<Box<dyn Iterator<Item = LiteralValue> + 'a>, ExcelError> {
643 match &self.expr {
644 ArgumentExpr::Ast(node) => match &node.node_type {
645 ASTNodeType::Reference { .. } => {
646 let view = self.range_view()?;
647 let mut values: Vec<LiteralValue> = Vec::new();
648 view.for_each_cell(&mut |v| {
649 values.push(v.clone());
650 Ok(())
651 })?;
652 Ok(Box::new(values.into_iter()))
653 }
654 ASTNodeType::Array(rows) => {
655 struct ArrayEvalIter<'a, 'b> {
656 rows: &'a [Vec<ASTNode>],
657 r: usize,
658 c: usize,
659 interp: &'a Interpreter<'b>,
660 }
661 impl<'a, 'b> Iterator for ArrayEvalIter<'a, 'b> {
662 type Item = LiteralValue;
663 fn next(&mut self) -> Option<Self::Item> {
664 if self.rows.is_empty() {
665 return None;
666 }
667 let rows = self.rows;
668 let mut r = self.r;
669 let mut c = self.c;
670 if r >= rows.len() {
671 return None;
672 }
673 let node = &rows[r][c];
674 c += 1;
676 if c >= rows[r].len() {
677 r += 1;
678 c = 0;
679 }
680 self.r = r;
681 self.c = c;
682 match self.interp.evaluate_ast(node) {
683 Ok(cv) => Some(cv.into_literal()),
684 Err(e) => Some(LiteralValue::Error(e)),
685 }
686 }
687 }
688 let it = ArrayEvalIter {
689 rows,
690 r: 0,
691 c: 0,
692 interp: self.interp,
693 };
694 Ok(Box::new(it))
695 }
696 _ => {
697 let v = self.value()?.into_literal();
699 Ok(Box::new(std::iter::once(v)))
700 }
701 },
702 ArgumentExpr::Arena {
703 id,
704 data_store,
705 sheet_registry,
706 } => {
707 let node = data_store.get_node(*id).ok_or_else(|| {
708 ExcelError::new(ExcelErrorKind::Value).with_message("Missing AST node")
709 })?;
710
711 match node {
712 crate::engine::arena::AstNodeData::Reference { .. } => {
713 let view = self.range_view()?;
714 let mut values: Vec<LiteralValue> = Vec::new();
715 view.for_each_cell(&mut |v| {
716 values.push(v.clone());
717 Ok(())
718 })?;
719 Ok(Box::new(values.into_iter()))
720 }
721 crate::engine::arena::AstNodeData::Array { .. } => {
722 let (rows, cols, elements) =
723 data_store.get_array_elems(*id).ok_or_else(|| {
724 ExcelError::new(ExcelErrorKind::Value).with_message("Invalid array")
725 })?;
726
727 struct ArenaArrayEvalIter<'a, 'b> {
728 elements: &'a [crate::engine::arena::AstNodeId],
729 idx: usize,
730 interp: &'a Interpreter<'b>,
731 data_store: &'a crate::engine::arena::DataStore,
732 sheet_registry: &'a crate::engine::sheet_registry::SheetRegistry,
733 }
734
735 impl<'a, 'b> Iterator for ArenaArrayEvalIter<'a, 'b> {
736 type Item = LiteralValue;
737
738 fn next(&mut self) -> Option<Self::Item> {
739 let id = self.elements.get(self.idx).copied()?;
740 self.idx += 1;
741 match self.interp.evaluate_arena_ast(
742 id,
743 self.data_store,
744 self.sheet_registry,
745 ) {
746 Ok(cv) => Some(cv.into_literal()),
747 Err(e) => Some(LiteralValue::Error(e)),
748 }
749 }
750 }
751
752 let _ = (rows, cols);
753 let it = ArenaArrayEvalIter {
754 elements,
755 idx: 0,
756 interp: self.interp,
757 data_store,
758 sheet_registry,
759 };
760 Ok(Box::new(it))
761 }
762 _ => {
763 let v = self
764 .interp
765 .evaluate_arena_ast(*id, data_store, sheet_registry)?;
766 Ok(Box::new(std::iter::once(v.into_literal())))
767 }
768 }
769 }
770 }
771 }
772
773 pub fn ast(&self) -> &ASTNode {
774 match &self.expr {
775 ArgumentExpr::Ast(node) => node,
776 ArgumentExpr::Arena {
777 id,
778 data_store,
779 sheet_registry,
780 } => self.cached_ast.get_or_init(|| {
781 data_store
782 .retrieve_ast(*id, sheet_registry)
783 .unwrap_or_else(|| ASTNode {
784 node_type: ASTNodeType::Literal(LiteralValue::Error(
785 ExcelError::new(ExcelErrorKind::Value)
786 .with_message("Missing formula AST"),
787 )),
788 source_token: None,
789 contains_volatile: false,
790 })
791 }),
792 }
793 }
794
795 pub fn as_reference(&self) -> Result<&ReferenceType, ExcelError> {
798 match &self.expr {
799 ArgumentExpr::Ast(node) => match &node.node_type {
800 ASTNodeType::Reference { reference, .. } => Ok(reference),
801 _ => Err(ExcelError::new(ExcelErrorKind::Ref)
802 .with_message("Expected a reference (by-ref argument)")),
803 },
804 ArgumentExpr::Arena { .. } => {
805 let reference = self.reference_for_eval()?;
806 Ok(self.cached_ref.get_or_init(|| reference))
807 }
808 }
809 }
810
811 pub fn as_reference_or_eval(&self) -> Result<ReferenceType, ExcelError> {
814 match &self.expr {
815 ArgumentExpr::Ast(node) => match &node.node_type {
816 ASTNodeType::Reference { reference, .. } => {
817 self.interp.reference_for_current_offset(reference)
818 }
819 ASTNodeType::Function { .. } | ASTNodeType::BinaryOp { .. } => {
820 self.interp.evaluate_ast_as_reference(node)
821 }
822 _ => Err(ExcelError::new(ExcelErrorKind::Ref)
823 .with_message("Argument is not a reference")),
824 },
825 ArgumentExpr::Arena {
826 id,
827 data_store,
828 sheet_registry,
829 } => {
830 let node = data_store.get_node(*id).ok_or_else(|| {
831 ExcelError::new(ExcelErrorKind::Value).with_message("Missing AST node")
832 })?;
833
834 match node {
835 crate::engine::arena::AstNodeData::Reference { .. } => {
836 self.reference_for_eval()
837 }
838 crate::engine::arena::AstNodeData::Function { .. }
839 | crate::engine::arena::AstNodeData::BinaryOp { .. } => self
840 .interp
841 .evaluate_arena_ast_as_reference(*id, data_store, sheet_registry),
842 _ => Err(ExcelError::new(ExcelErrorKind::Ref)
843 .with_message("Argument is not a reference")),
844 }
845 }
846 }
847 }
848
849 pub fn matches_kind(&self, k: formualizer_common::ArgKind) -> Result<bool, ExcelError> {
851 Ok(match k {
852 formualizer_common::ArgKind::Any => true,
853 formualizer_common::ArgKind::Range => self.range().is_ok(),
854 formualizer_common::ArgKind::Number => matches!(
855 self.value()?.into_literal(),
856 LiteralValue::Number(_) | LiteralValue::Int(_)
857 ),
858 formualizer_common::ArgKind::Text => {
859 matches!(self.value()?.into_literal(), LiteralValue::Text(_))
860 }
861 formualizer_common::ArgKind::Logical => {
862 matches!(self.value()?.into_literal(), LiteralValue::Boolean(_))
863 }
864 })
865 }
866}
867
868#[derive(Debug, Clone)]
870pub struct InMemoryRange {
871 data: Vec<Vec<LiteralValue>>,
872}
873impl InMemoryRange {
874 pub fn new(d: Vec<Vec<LiteralValue>>) -> Self {
875 Self { data: d }
876 }
877}
878impl Range for InMemoryRange {
879 fn get(&self, r: usize, c: usize) -> Result<LiteralValue, ExcelError> {
880 Ok(self
881 .data
882 .get(r)
883 .and_then(|row| row.get(c))
884 .cloned()
885 .unwrap_or(LiteralValue::Empty))
886 }
887 fn dimensions(&self) -> (usize, usize) {
888 (self.data.len(), self.data.first().map_or(0, |r| r.len()))
889 }
890 fn as_any(&self) -> &dyn Any {
891 self
892 }
893}
894
895pub trait Table: Debug + Send + Sync {
898 fn get_cell(&self, row: usize, column: &str) -> Result<LiteralValue, ExcelError>;
899 fn get_column(&self, column: &str) -> Result<Box<dyn Range>, ExcelError>;
900 fn columns(&self) -> Vec<String> {
902 vec![]
903 }
904 fn data_height(&self) -> usize {
906 0
907 }
908 fn has_headers(&self) -> bool {
910 false
911 }
912 fn has_totals(&self) -> bool {
914 false
915 }
916 fn headers_row(&self) -> Option<Box<dyn Range>> {
918 None
919 }
920 fn totals_row(&self) -> Option<Box<dyn Range>> {
922 None
923 }
924 fn data_body(&self) -> Option<Box<dyn Range>> {
926 None
927 }
928 fn clone_box(&self) -> Box<dyn Table>;
929}
930impl Table for Box<dyn Table> {
931 fn get_cell(&self, r: usize, c: &str) -> Result<LiteralValue, ExcelError> {
932 (**self).get_cell(r, c)
933 }
934 fn get_column(&self, c: &str) -> Result<Box<dyn Range>, ExcelError> {
935 (**self).get_column(c)
936 }
937 fn columns(&self) -> Vec<String> {
938 (**self).columns()
939 }
940 fn data_height(&self) -> usize {
941 (**self).data_height()
942 }
943 fn has_headers(&self) -> bool {
944 (**self).has_headers()
945 }
946 fn has_totals(&self) -> bool {
947 (**self).has_totals()
948 }
949 fn headers_row(&self) -> Option<Box<dyn Range>> {
950 (**self).headers_row()
951 }
952 fn totals_row(&self) -> Option<Box<dyn Range>> {
953 (**self).totals_row()
954 }
955 fn data_body(&self) -> Option<Box<dyn Range>> {
956 (**self).data_body()
957 }
958 fn clone_box(&self) -> Box<dyn Table> {
959 (**self).clone_box()
960 }
961}
962
963pub trait ReferenceResolver: Send + Sync {
966 fn resolve_cell_reference(
967 &self,
968 sheet: Option<&str>,
969 row: u32,
970 col: u32,
971 ) -> Result<LiteralValue, ExcelError>;
972}
973pub trait RangeResolver: Send + Sync {
974 fn resolve_range_reference(
975 &self,
976 sheet: Option<&str>,
977 sr: Option<u32>,
978 sc: Option<u32>,
979 er: Option<u32>,
980 ec: Option<u32>,
981 ) -> Result<Box<dyn Range>, ExcelError>;
982}
983pub trait NamedRangeResolver: Send + Sync {
984 fn resolve_named_range_reference(
985 &self,
986 name: &str,
987 ) -> Result<Vec<Vec<LiteralValue>>, ExcelError>;
988}
989pub trait TableResolver: Send + Sync {
990 fn resolve_table_reference(
991 &self,
992 tref: &formualizer_parse::parser::TableReference,
993 ) -> Result<Box<dyn Table>, ExcelError>;
994}
995
996pub trait SourceResolver: Send + Sync {
997 fn source_scalar_version(&self, _name: &str) -> Option<u64> {
998 None
999 }
1000
1001 fn resolve_source_scalar(&self, name: &str) -> Result<LiteralValue, ExcelError> {
1002 Err(ExcelError::new(ExcelErrorKind::NImpl)
1003 .with_message(format!("Source scalar not supported: {name}")))
1004 }
1005
1006 fn source_table_version(&self, _name: &str) -> Option<u64> {
1007 None
1008 }
1009
1010 fn resolve_source_table(&self, name: &str) -> Result<Box<dyn Table>, ExcelError> {
1011 Err(ExcelError::new(ExcelErrorKind::NImpl)
1012 .with_message(format!("Source table not supported: {name}")))
1013 }
1014}
1015
1016pub trait Resolver: ReferenceResolver + RangeResolver + NamedRangeResolver + TableResolver {
1017 fn resolve_range_like(&self, r: &ReferenceType) -> Result<Box<dyn Range>, ExcelError> {
1018 match r {
1019 ReferenceType::Range {
1020 sheet,
1021 start_row,
1022 start_col,
1023 end_row,
1024 end_col,
1025 ..
1026 } => self.resolve_range_reference(
1027 sheet.as_deref(),
1028 *start_row,
1029 *start_col,
1030 *end_row,
1031 *end_col,
1032 ),
1033 ReferenceType::External(_) => Err(ExcelError::new(ExcelErrorKind::NImpl)
1034 .with_message("External references are not supported by Resolver".to_string())),
1035 ReferenceType::Table(tref) => {
1036 let t = self.resolve_table_reference(tref)?;
1037 match &tref.specifier {
1038 Some(TableSpecifier::Column(c)) => t.get_column(c),
1039 Some(TableSpecifier::ColumnRange(start, end)) => {
1040 let cols = t.columns();
1042 let start_key = start.to_lowercase();
1043 let end_key = end.to_lowercase();
1044 let start_idx = cols.iter().position(|n| n.to_lowercase() == start_key);
1045 let end_idx = cols.iter().position(|n| n.to_lowercase() == end_key);
1046 if let (Some(mut si), Some(mut ei)) = (start_idx, end_idx) {
1047 if si > ei {
1048 std::mem::swap(&mut si, &mut ei);
1049 }
1050 let h = t.data_height();
1052 let w = ei - si + 1;
1053 let mut rows = vec![vec![LiteralValue::Empty; w]; h];
1054 for (offset, ci) in (si..=ei).enumerate() {
1055 let cname = &cols[ci];
1056 let col_range = t.get_column(cname)?;
1057 let (rh, _) = col_range.dimensions();
1058 for (r, row) in rows.iter_mut().enumerate().take(h.min(rh)) {
1059 row[offset] = col_range.get(r, 0)?;
1060 }
1061 }
1062 Ok(Box::new(InMemoryRange::new(rows)))
1063 } else {
1064 Err(ExcelError::new(ExcelErrorKind::Ref).with_message(
1065 "Column range refers to unknown column(s)".to_string(),
1066 ))
1067 }
1068 }
1069 Some(TableSpecifier::SpecialItem(
1070 formualizer_parse::parser::SpecialItem::Headers,
1071 )) => {
1072 if let Some(h) = t.headers_row() {
1073 Ok(h)
1074 } else {
1075 Ok(Box::new(InMemoryRange::new(vec![])))
1076 }
1077 }
1078 Some(TableSpecifier::SpecialItem(
1079 formualizer_parse::parser::SpecialItem::Totals,
1080 )) => {
1081 if let Some(tr) = t.totals_row() {
1082 Ok(tr)
1083 } else {
1084 Ok(Box::new(InMemoryRange::new(vec![])))
1085 }
1086 }
1087 Some(TableSpecifier::SpecialItem(
1088 formualizer_parse::parser::SpecialItem::Data,
1089 )) => {
1090 if let Some(body) = t.data_body() {
1091 Ok(body)
1092 } else {
1093 Ok(Box::new(InMemoryRange::new(vec![])))
1094 }
1095 }
1096 Some(TableSpecifier::SpecialItem(
1097 formualizer_parse::parser::SpecialItem::All,
1098 )) => {
1099 let mut out: Vec<Vec<LiteralValue>> = Vec::new();
1101 if let Some(h) = t.headers_row() {
1102 out.extend(h.iter_rows());
1103 }
1104 if let Some(body) = t.data_body() {
1105 out.extend(body.iter_rows());
1106 }
1107 if let Some(tr) = t.totals_row() {
1108 out.extend(tr.iter_rows());
1109 }
1110 Ok(Box::new(InMemoryRange::new(out)))
1111 }
1112 Some(TableSpecifier::SpecialItem(
1113 formualizer_parse::parser::SpecialItem::ThisRow,
1114 )) => Err(ExcelError::new(ExcelErrorKind::NImpl).with_message(
1115 "@ (This Row) requires table-aware context; not yet supported".to_string(),
1116 )),
1117 Some(TableSpecifier::All) => {
1118 let mut out: Vec<Vec<LiteralValue>> = Vec::new();
1120 if let Some(h) = t.headers_row() {
1121 out.extend(h.iter_rows());
1122 }
1123 if let Some(body) = t.data_body() {
1124 out.extend(body.iter_rows());
1125 }
1126 if let Some(tr) = t.totals_row() {
1127 out.extend(tr.iter_rows());
1128 }
1129 Ok(Box::new(InMemoryRange::new(out)))
1130 }
1131 Some(TableSpecifier::Data) => {
1132 if let Some(body) = t.data_body() {
1133 Ok(body)
1134 } else {
1135 Ok(Box::new(InMemoryRange::new(vec![])))
1136 }
1137 }
1138 Some(TableSpecifier::Combination(_)) => Err(ExcelError::new(
1140 ExcelErrorKind::NImpl,
1141 )
1142 .with_message("Complex structured references not yet supported".to_string())),
1143 Some(TableSpecifier::Row(_)) => Err(ExcelError::new(ExcelErrorKind::NImpl)
1144 .with_message("Row selectors (@/index) not yet supported".to_string())),
1145 Some(TableSpecifier::Headers) | Some(TableSpecifier::Totals) => {
1146 Err(ExcelError::new(ExcelErrorKind::NImpl).with_message(
1147 "Legacy Headers/Totals variants not used; use SpecialItem".to_string(),
1148 ))
1149 }
1150 None => Err(ExcelError::new(ExcelErrorKind::Ref).with_message(
1151 "Table reference without specifier is unsupported".to_string(),
1152 )),
1153 }
1154 }
1155 ReferenceType::NamedRange(n) => {
1156 let v = self.resolve_named_range_reference(n)?;
1157 Ok(Box::new(InMemoryRange::new(v)))
1158 }
1159 ReferenceType::Cell {
1160 sheet, row, col, ..
1161 } => {
1162 let v = self.resolve_cell_reference(sheet.as_deref(), *row, *col)?;
1163 Ok(Box::new(InMemoryRange::new(vec![vec![v]])))
1164 }
1165 ReferenceType::Cell3D { .. } | ReferenceType::Range3D { .. } => {
1166 Err(ExcelError::new(ExcelErrorKind::NImpl)
1167 .with_message("3D references are not yet supported".to_string()))
1168 }
1169 }
1170 }
1171}
1172
1173pub trait FunctionProvider: Send + Sync {
1176 fn get_function(&self, ns: &str, name: &str) -> Option<Arc<dyn Function>>;
1177}
1178
1179pub trait EvaluationContext: Resolver + FunctionProvider + SourceResolver {
1180 fn thread_pool(&self) -> Option<&Arc<rayon::ThreadPool>> {
1183 None
1184 }
1185
1186 fn cancellation_token(&self) -> Option<Arc<std::sync::atomic::AtomicBool>> {
1188 None
1189 }
1190
1191 fn chunk_hint(&self) -> Option<usize> {
1193 None
1194 }
1195
1196 fn resolve_range_view<'c>(
1199 &'c self,
1200 _reference: &ReferenceType,
1201 _current_sheet: &str,
1202 ) -> Result<RangeView<'c>, ExcelError> {
1203 Err(ExcelError::new(ExcelErrorKind::NImpl))
1204 }
1205
1206 fn resolve_cell_reference_value(
1211 &self,
1212 sheet: Option<&str>,
1213 row: u32,
1214 col: u32,
1215 current_sheet: &str,
1216 ) -> Result<LiteralValue, ExcelError> {
1217 let reference = ReferenceType::Cell {
1218 sheet: sheet.map(str::to_string),
1219 row,
1220 col,
1221 row_abs: true,
1222 col_abs: true,
1223 };
1224 let view = self.resolve_range_view(&reference, current_sheet)?;
1225 Ok(view.as_1x1().unwrap_or(LiteralValue::Empty))
1226 }
1227
1228 fn locale(&self) -> crate::locale::Locale {
1230 crate::locale::Locale::invariant()
1231 }
1232
1233 fn workbook_sheet_count(&self) -> Option<usize> {
1235 None
1236 }
1237
1238 fn sheet_index_by_name(&self, _sheet: &str) -> Option<usize> {
1240 None
1241 }
1242
1243 fn current_sheet_index(&self, current_sheet: &str) -> Option<usize> {
1245 self.sheet_index_by_name(current_sheet)
1246 }
1247
1248 fn inspect_reference(
1250 &self,
1251 _reference: &ReferenceType,
1252 _current_sheet: &str,
1253 ) -> Result<Option<ReferenceInfo>, ExcelError> {
1254 Ok(None)
1255 }
1256
1257 fn formula_text_at_cell(&self, _cell: CellRef) -> Result<Option<String>, ExcelError> {
1259 Ok(None)
1260 }
1261
1262 fn clock(&self) -> &dyn crate::timezone::ClockProvider {
1271 #[cfg(feature = "system-clock")]
1272 {
1273 static DEFAULT_CLOCK: std::sync::OnceLock<crate::timezone::SystemClock> =
1274 std::sync::OnceLock::new();
1275 DEFAULT_CLOCK.get_or_init(|| {
1276 crate::timezone::SystemClock::new(crate::timezone::TimeZoneSpec::default())
1277 })
1278 }
1279 #[cfg(not(feature = "system-clock"))]
1280 {
1281 static DEFAULT_CLOCK: std::sync::OnceLock<crate::timezone::FixedClock> =
1282 std::sync::OnceLock::new();
1283 DEFAULT_CLOCK.get_or_init(|| {
1284 crate::timezone::FixedClock::new(
1285 chrono::DateTime::UNIX_EPOCH,
1286 crate::timezone::TimeZoneSpec::Utc,
1287 )
1288 })
1289 }
1290 }
1291
1292 fn timezone(&self) -> &crate::timezone::TimeZoneSpec {
1296 self.clock().timezone()
1297 }
1298
1299 fn volatile_level(&self) -> VolatileLevel {
1301 VolatileLevel::Always
1302 }
1303
1304 fn workbook_seed(&self) -> u64 {
1306 0xF0F0_D0D0_AAAA_5555
1307 }
1308
1309 fn recalc_epoch(&self) -> u64 {
1311 0
1312 }
1313
1314 fn used_rows_for_columns(
1319 &self,
1320 _sheet: &str,
1321 _start_col: u32,
1322 _end_col: u32,
1323 ) -> Option<(u32, u32)> {
1324 None
1325 }
1326
1327 fn used_cols_for_rows(
1330 &self,
1331 _sheet: &str,
1332 _start_row: u32,
1333 _end_row: u32,
1334 ) -> Option<(u32, u32)> {
1335 None
1336 }
1337
1338 fn sheet_bounds(&self, _sheet: &str) -> Option<(u32, u32)> {
1340 None
1341 }
1342
1343 fn data_snapshot_id(&self) -> u64 {
1345 0
1346 }
1347
1348 fn backend_caps(&self) -> BackendCaps {
1350 BackendCaps::default()
1351 }
1352
1353 fn date_system(&self) -> crate::engine::DateSystem {
1358 crate::engine::DateSystem::Excel1900
1359 }
1360
1361 fn build_lookup_index(
1364 &self,
1365 _view: &RangeView<'_>,
1366 _axis: LookupAxis,
1367 ) -> Option<std::sync::Arc<LookupIndex>> {
1368 None
1369 }
1370
1371 fn build_criteria_mask(
1374 &self,
1375 _view: &RangeView<'_>,
1376 _col_in_view: usize,
1377 _pred: &crate::args::CriteriaPredicate,
1378 ) -> Option<std::sync::Arc<arrow_array::BooleanArray>> {
1379 None
1380 }
1381
1382 fn build_row_visibility_mask(
1385 &self,
1386 _view: &RangeView<'_>,
1387 _mode: VisibilityMaskMode,
1388 ) -> Option<std::sync::Arc<arrow_array::BooleanArray>> {
1389 None
1390 }
1391}
1392
1393#[derive(Copy, Clone, Debug, Default)]
1395pub struct BackendCaps {
1396 pub streaming: bool,
1398 pub used_region: bool,
1400 pub write: bool,
1402 pub tables: bool,
1404 pub async_stream: bool,
1406}
1407
1408#[derive(Copy, Clone, Debug, Eq, PartialEq)]
1411pub enum VolatileLevel {
1412 Always,
1414 OnRecalc,
1416 OnOpen,
1418}
1419
1420pub trait FunctionContext<'ctx> {
1422 fn locale(&self) -> crate::locale::Locale;
1423 fn timezone(&self) -> &crate::timezone::TimeZoneSpec;
1424 fn clock(&self) -> &dyn crate::timezone::ClockProvider;
1425 fn thread_pool(&self) -> Option<&std::sync::Arc<rayon::ThreadPool>>;
1426 fn cancellation_token(&self) -> Option<Arc<std::sync::atomic::AtomicBool>>;
1427 fn chunk_hint(&self) -> Option<usize>;
1428
1429 fn current_sheet(&self) -> &str;
1431
1432 fn workbook_sheet_count(&self) -> Option<usize> {
1433 None
1434 }
1435
1436 fn sheet_index_by_name(&self, _sheet: &str) -> Option<usize> {
1437 None
1438 }
1439
1440 fn current_sheet_index(&self) -> Option<usize> {
1441 self.sheet_index_by_name(self.current_sheet())
1442 }
1443
1444 fn inspect_reference(
1445 &self,
1446 _reference: &ReferenceType,
1447 ) -> Result<Option<ReferenceInfo>, ExcelError> {
1448 Ok(None)
1449 }
1450
1451 fn formula_text_at_cell(&self, _cell: CellRef) -> Result<Option<String>, ExcelError> {
1452 Ok(None)
1453 }
1454
1455 fn volatile_level(&self) -> VolatileLevel;
1456 fn workbook_seed(&self) -> u64;
1457 fn recalc_epoch(&self) -> u64;
1458 fn current_cell(&self) -> Option<CellRef>;
1459
1460 fn resolve_range_view(
1462 &self,
1463 _reference: &ReferenceType,
1464 _current_sheet: &str,
1465 ) -> Result<RangeView<'ctx>, ExcelError>;
1466
1467 fn rng_for_current(&self, fn_salt: u64) -> rand::rngs::SmallRng {
1471 use crate::rng::{compose_seed, small_rng_from_lanes};
1472 let (sheet_id, row, col) = self
1473 .current_cell()
1474 .map(|c| (c.sheet_id as u32, c.coord.row(), c.coord.col()))
1475 .unwrap_or((0, 0, 0));
1476 let epoch = match self.volatile_level() {
1478 VolatileLevel::OnRecalc => self.recalc_epoch(),
1479 _ => 0,
1480 };
1481 let (l0, l1) = compose_seed(self.workbook_seed(), sheet_id, row, col, fn_salt, epoch);
1482 small_rng_from_lanes(l0, l1)
1483 }
1484
1485 fn date_system(&self) -> crate::engine::DateSystem {
1487 crate::engine::DateSystem::Excel1900
1488 }
1489
1490 fn get_lookup_index(
1493 &self,
1494 _view: &RangeView<'_>,
1495 _axis: LookupAxis,
1496 ) -> Option<std::sync::Arc<LookupIndex>> {
1497 None
1498 }
1499
1500 fn get_criteria_mask(
1503 &self,
1504 _view: &RangeView<'_>,
1505 _col_in_view: usize,
1506 _pred: &crate::args::CriteriaPredicate,
1507 ) -> Option<std::sync::Arc<arrow_array::BooleanArray>> {
1508 None
1509 }
1510
1511 fn get_row_visibility_mask(
1513 &self,
1514 _view: &RangeView<'_>,
1515 _mode: VisibilityMaskMode,
1516 ) -> Option<std::sync::Arc<arrow_array::BooleanArray>> {
1517 None
1518 }
1519}
1520
1521pub struct DefaultFunctionContext<'a> {
1523 pub base: &'a dyn EvaluationContext,
1524 pub current: Option<CellRef>,
1525 pub current_sheet: &'a str,
1526}
1527
1528impl<'a> DefaultFunctionContext<'a> {
1529 pub fn new(
1530 base: &'a dyn EvaluationContext,
1531 current: Option<CellRef>,
1532 current_sheet: &'a str,
1533 ) -> Self {
1534 Self {
1535 base,
1536 current,
1537 current_sheet,
1538 }
1539 }
1540
1541 pub fn new_with_sheet(
1542 base: &'a dyn EvaluationContext,
1543 current: Option<CellRef>,
1544 current_sheet: &'a str,
1545 ) -> Self {
1546 Self::new(base, current, current_sheet)
1547 }
1548}
1549
1550impl<'a> FunctionContext<'a> for DefaultFunctionContext<'a> {
1551 fn locale(&self) -> crate::locale::Locale {
1552 self.base.locale()
1553 }
1554
1555 fn current_sheet(&self) -> &str {
1556 self.current_sheet
1557 }
1558
1559 fn workbook_sheet_count(&self) -> Option<usize> {
1560 self.base.workbook_sheet_count()
1561 }
1562
1563 fn sheet_index_by_name(&self, sheet: &str) -> Option<usize> {
1564 self.base.sheet_index_by_name(sheet)
1565 }
1566
1567 fn current_sheet_index(&self) -> Option<usize> {
1568 self.base.current_sheet_index(self.current_sheet)
1569 }
1570
1571 fn inspect_reference(
1572 &self,
1573 reference: &ReferenceType,
1574 ) -> Result<Option<ReferenceInfo>, ExcelError> {
1575 self.base.inspect_reference(reference, self.current_sheet)
1576 }
1577
1578 fn formula_text_at_cell(&self, cell: CellRef) -> Result<Option<String>, ExcelError> {
1579 self.base.formula_text_at_cell(cell)
1580 }
1581
1582 fn timezone(&self) -> &crate::timezone::TimeZoneSpec {
1583 self.base.timezone()
1584 }
1585
1586 fn clock(&self) -> &dyn crate::timezone::ClockProvider {
1587 self.base.clock()
1588 }
1589 fn thread_pool(&self) -> Option<&std::sync::Arc<rayon::ThreadPool>> {
1590 self.base.thread_pool()
1591 }
1592 fn cancellation_token(&self) -> Option<Arc<std::sync::atomic::AtomicBool>> {
1593 self.base.cancellation_token()
1594 }
1595 fn chunk_hint(&self) -> Option<usize> {
1596 self.base.chunk_hint()
1597 }
1598
1599 fn volatile_level(&self) -> VolatileLevel {
1600 self.base.volatile_level()
1601 }
1602 fn workbook_seed(&self) -> u64 {
1603 self.base.workbook_seed()
1604 }
1605 fn recalc_epoch(&self) -> u64 {
1606 self.base.recalc_epoch()
1607 }
1608 fn current_cell(&self) -> Option<CellRef> {
1609 self.current
1610 }
1611
1612 fn resolve_range_view(
1613 &self,
1614 reference: &ReferenceType,
1615 current_sheet: &str,
1616 ) -> Result<RangeView<'a>, ExcelError> {
1617 self.base.resolve_range_view(reference, current_sheet)
1618 }
1619
1620 fn date_system(&self) -> crate::engine::DateSystem {
1623 self.base.date_system()
1624 }
1625
1626 fn get_lookup_index(
1627 &self,
1628 view: &RangeView<'_>,
1629 axis: LookupAxis,
1630 ) -> Option<std::sync::Arc<LookupIndex>> {
1631 self.base.build_lookup_index(view, axis)
1632 }
1633
1634 fn get_criteria_mask(
1635 &self,
1636 view: &RangeView<'_>,
1637 col_in_view: usize,
1638 pred: &crate::args::CriteriaPredicate,
1639 ) -> Option<std::sync::Arc<arrow_array::BooleanArray>> {
1640 self.base.build_criteria_mask(view, col_in_view, pred)
1641 }
1642
1643 fn get_row_visibility_mask(
1644 &self,
1645 view: &RangeView<'_>,
1646 mode: VisibilityMaskMode,
1647 ) -> Option<std::sync::Arc<arrow_array::BooleanArray>> {
1648 self.base.build_row_visibility_mask(view, mode)
1649 }
1650}