1use std::collections::HashSet;
7
8use serde_json::{Map, Number, Value};
9
10use crate::ast::Ast;
11use crate::functions::{Function, custom_error, number_value};
12use crate::interpreter::{SearchResult, interpret};
13use crate::registry::register_if_enabled;
14use crate::value_ext::ValueExt;
15use crate::{Context, Runtime, arg, defn, get_expref_id};
16
17fn get_expref_ast<'a>(value: &Value, ctx: &'a Context<'_>) -> Option<&'a Ast> {
19 get_expref_id(value).and_then(|id| ctx.get_expref(id))
20}
21
22fn value_to_string(value: &Value) -> String {
24 match value {
25 Value::String(s) => s.clone(),
26 Value::Number(n) => n.to_string(),
27 Value::Bool(b) => b.to_string(),
28 Value::Null => "null".to_string(),
29 _ => serde_json::to_string(value).unwrap_or_default(),
30 }
31}
32
33fn compare_values(a: &Value, b: &Value) -> std::cmp::Ordering {
35 use std::cmp::Ordering;
36 match (a, b) {
37 (Value::Number(an), Value::Number(bn)) => {
38 let a_f = an.as_f64().unwrap_or(0.0);
39 let b_f = bn.as_f64().unwrap_or(0.0);
40 a_f.partial_cmp(&b_f).unwrap_or(Ordering::Equal)
41 }
42 (Value::String(a_s), Value::String(b_s)) => a_s.cmp(b_s),
43 (Value::Null, Value::Null) => Ordering::Equal,
44 (Value::Null, _) => Ordering::Less,
45 (_, Value::Null) => Ordering::Greater,
46 _ => Ordering::Equal,
47 }
48}
49
50pub fn register_filtered(runtime: &mut Runtime, enabled: &HashSet<&str>) {
52 register_if_enabled(runtime, "map_expr", enabled, Box::new(MapExprFn::new()));
53 register_if_enabled(
54 runtime,
55 "filter_expr",
56 enabled,
57 Box::new(FilterExprFn::new()),
58 );
59 register_if_enabled(runtime, "any_expr", enabled, Box::new(AnyExprFn::new()));
60 register_if_enabled(runtime, "all_expr", enabled, Box::new(AllExprFn::new()));
61 register_if_enabled(runtime, "find_expr", enabled, Box::new(FindExprFn::new()));
62 register_if_enabled(
63 runtime,
64 "find_index_expr",
65 enabled,
66 Box::new(FindIndexExprFn::new()),
67 );
68 register_if_enabled(runtime, "count_expr", enabled, Box::new(CountExprFn::new()));
69 register_if_enabled(
70 runtime,
71 "sort_by_expr",
72 enabled,
73 Box::new(SortByExprFn::new()),
74 );
75 register_if_enabled(
76 runtime,
77 "group_by_expr",
78 enabled,
79 Box::new(GroupByExprFn::new()),
80 );
81 register_if_enabled(
82 runtime,
83 "partition_expr",
84 enabled,
85 Box::new(PartitionExprFn::new()),
86 );
87 register_if_enabled(
88 runtime,
89 "min_by_expr",
90 enabled,
91 Box::new(MinByExprFn::new()),
92 );
93 register_if_enabled(
94 runtime,
95 "max_by_expr",
96 enabled,
97 Box::new(MaxByExprFn::new()),
98 );
99 register_if_enabled(
100 runtime,
101 "unique_by_expr",
102 enabled,
103 Box::new(UniqueByExprFn::new()),
104 );
105 register_if_enabled(
106 runtime,
107 "flat_map_expr",
108 enabled,
109 Box::new(FlatMapExprFn::new()),
110 );
111
112 register_if_enabled(runtime, "mapcat", enabled, Box::new(FlatMapExprFn::new()));
114
115 register_if_enabled(runtime, "some", enabled, Box::new(AnyExprFn::new()));
117 register_if_enabled(runtime, "every", enabled, Box::new(AllExprFn::new()));
118 register_if_enabled(runtime, "reject", enabled, Box::new(RejectFn::new()));
119 register_if_enabled(runtime, "map_keys", enabled, Box::new(MapKeysFn::new()));
120 register_if_enabled(runtime, "map_values", enabled, Box::new(MapValuesFn::new()));
121 register_if_enabled(runtime, "order_by", enabled, Box::new(OrderByFn::new()));
122 register_if_enabled(
123 runtime,
124 "reduce_expr",
125 enabled,
126 Box::new(ReduceExprFn::new()),
127 );
128 register_if_enabled(runtime, "scan_expr", enabled, Box::new(ScanExprFn::new()));
129 register_if_enabled(runtime, "fold", enabled, Box::new(ReduceExprFn::new()));
131 register_if_enabled(runtime, "reductions", enabled, Box::new(ScanExprFn::new()));
133 register_if_enabled(runtime, "none", enabled, Box::new(NoneFn::new()));
135 register_if_enabled(runtime, "count_by", enabled, Box::new(CountByFn::new()));
136
137 register_if_enabled(runtime, "partial", enabled, Box::new(PartialFn::new()));
139 register_if_enabled(runtime, "apply", enabled, Box::new(ApplyFn::new()));
140
141 register_if_enabled(runtime, "take_while", enabled, Box::new(TakeWhileFn::new()));
143 register_if_enabled(runtime, "drop_while", enabled, Box::new(DropWhileFn::new()));
144 register_if_enabled(runtime, "zip_with", enabled, Box::new(ZipWithFn::new()));
145
146 register_if_enabled(runtime, "walk", enabled, Box::new(WalkFn::new()));
148
149 register_if_enabled(runtime, "recurse", enabled, Box::new(RecurseFn::new()));
151 register_if_enabled(
152 runtime,
153 "recurse_with",
154 enabled,
155 Box::new(RecurseWithFn::new()),
156 );
157
158 register_if_enabled(runtime, "while_expr", enabled, Box::new(WhileExprFn::new()));
160 register_if_enabled(runtime, "until_expr", enabled, Box::new(UntilExprFn::new()));
161}
162
163defn!(MapExprFn, vec![arg!(expref), arg!(array)], None);
168
169impl Function for MapExprFn {
170 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
171 self.signature.validate(args, ctx)?;
172
173 let ast = get_expref_ast(&args[0], ctx)
174 .ok_or_else(|| custom_error(ctx, "Expected expref"))?
175 .clone();
176 let arr = args[1].as_array().unwrap();
177
178 let mut results = Vec::with_capacity(arr.len());
179 for item in arr {
180 results.push(interpret(item, &ast, ctx)?);
181 }
182
183 Ok(Value::Array(results))
184 }
185}
186
187defn!(FilterExprFn, vec![arg!(expref), arg!(array)], None);
192
193impl Function for FilterExprFn {
194 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
195 self.signature.validate(args, ctx)?;
196
197 let ast = get_expref_ast(&args[0], ctx)
198 .ok_or_else(|| custom_error(ctx, "Expected expref"))?
199 .clone();
200 let arr = args[1].as_array().unwrap();
201
202 let mut results = Vec::new();
203 for item in arr {
204 let result = interpret(item, &ast, ctx)?;
205 if result.is_truthy() {
206 results.push(item.clone());
207 }
208 }
209
210 Ok(Value::Array(results))
211 }
212}
213
214defn!(AnyExprFn, vec![arg!(expref), arg!(array)], None);
219
220impl Function for AnyExprFn {
221 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
222 self.signature.validate(args, ctx)?;
223
224 let ast = get_expref_ast(&args[0], ctx)
225 .ok_or_else(|| custom_error(ctx, "Expected expref"))?
226 .clone();
227 let arr = args[1].as_array().unwrap();
228
229 for item in arr {
230 let result = interpret(item, &ast, ctx)?;
231 if result.is_truthy() {
232 return Ok(Value::Bool(true));
233 }
234 }
235
236 Ok(Value::Bool(false))
237 }
238}
239
240defn!(NoneFn, vec![arg!(expref), arg!(array)], None);
245
246impl Function for NoneFn {
247 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
248 self.signature.validate(args, ctx)?;
249
250 let ast = get_expref_ast(&args[0], ctx)
251 .ok_or_else(|| custom_error(ctx, "Expected expref"))?
252 .clone();
253 let arr = args[1].as_array().unwrap();
254
255 if arr.is_empty() {
257 return Ok(Value::Bool(true));
258 }
259
260 for item in arr {
261 let result = interpret(item, &ast, ctx)?;
262 if result.is_truthy() {
263 return Ok(Value::Bool(false));
264 }
265 }
266
267 Ok(Value::Bool(true))
268 }
269}
270
271defn!(AllExprFn, vec![arg!(expref), arg!(array)], None);
276
277impl Function for AllExprFn {
278 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
279 self.signature.validate(args, ctx)?;
280
281 let ast = get_expref_ast(&args[0], ctx)
282 .ok_or_else(|| custom_error(ctx, "Expected expref"))?
283 .clone();
284 let arr = args[1].as_array().unwrap();
285
286 if arr.is_empty() {
288 return Ok(Value::Bool(true));
289 }
290
291 for item in arr {
292 let result = interpret(item, &ast, ctx)?;
293 if !result.is_truthy() {
294 return Ok(Value::Bool(false));
295 }
296 }
297
298 Ok(Value::Bool(true))
299 }
300}
301
302defn!(FindExprFn, vec![arg!(expref), arg!(array)], None);
307
308impl Function for FindExprFn {
309 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
310 self.signature.validate(args, ctx)?;
311
312 let ast = get_expref_ast(&args[0], ctx)
313 .ok_or_else(|| custom_error(ctx, "Expected expref"))?
314 .clone();
315 let arr = args[1].as_array().unwrap();
316
317 for item in arr {
318 let result = interpret(item, &ast, ctx)?;
319 if result.is_truthy() {
320 return Ok(item.clone());
321 }
322 }
323
324 Ok(Value::Null)
325 }
326}
327
328defn!(FindIndexExprFn, vec![arg!(expref), arg!(array)], None);
333
334impl Function for FindIndexExprFn {
335 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
336 self.signature.validate(args, ctx)?;
337
338 let ast = get_expref_ast(&args[0], ctx)
339 .ok_or_else(|| custom_error(ctx, "Expected expref"))?
340 .clone();
341 let arr = args[1].as_array().unwrap();
342
343 for (i, item) in arr.iter().enumerate() {
344 let result = interpret(item, &ast, ctx)?;
345 if result.is_truthy() {
346 return Ok(number_value(i as f64));
347 }
348 }
349
350 Ok(number_value(-1.0))
351 }
352}
353
354defn!(CountExprFn, vec![arg!(expref), arg!(array)], None);
359
360impl Function for CountExprFn {
361 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
362 self.signature.validate(args, ctx)?;
363
364 let ast = get_expref_ast(&args[0], ctx)
365 .ok_or_else(|| custom_error(ctx, "Expected expref"))?
366 .clone();
367 let arr = args[1].as_array().unwrap();
368
369 let mut count = 0i64;
370 for item in arr {
371 let result = interpret(item, &ast, ctx)?;
372 if result.is_truthy() {
373 count += 1;
374 }
375 }
376
377 Ok(Value::Number(Number::from(count)))
378 }
379}
380
381defn!(SortByExprFn, vec![arg!(expref), arg!(array)], None);
386
387impl Function for SortByExprFn {
388 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
389 self.signature.validate(args, ctx)?;
390
391 let ast = get_expref_ast(&args[0], ctx)
392 .ok_or_else(|| custom_error(ctx, "Expected expref"))?
393 .clone();
394 let arr = args[1].as_array().unwrap();
395
396 if arr.is_empty() {
397 return Ok(Value::Array(vec![]));
398 }
399
400 let mut keyed: Vec<(Value, Value)> = Vec::with_capacity(arr.len());
402 for item in arr {
403 let key = interpret(item, &ast, ctx)?;
404 keyed.push((item.clone(), key));
405 }
406
407 keyed.sort_by(|a, b| compare_values(&a.1, &b.1));
409
410 let results: Vec<Value> = keyed.into_iter().map(|(item, _)| item).collect();
411 Ok(Value::Array(results))
412 }
413}
414
415defn!(GroupByExprFn, vec![arg!(expref), arg!(array)], None);
420
421impl Function for GroupByExprFn {
422 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
423 self.signature.validate(args, ctx)?;
424
425 let ast = get_expref_ast(&args[0], ctx)
426 .ok_or_else(|| custom_error(ctx, "Expected expref"))?
427 .clone();
428 let arr = args[1].as_array().unwrap();
429
430 let mut group_keys: Vec<String> = Vec::new();
432 let mut group_map: std::collections::HashMap<String, Vec<Value>> =
433 std::collections::HashMap::new();
434
435 for item in arr {
436 let key_val = interpret(item, &ast, ctx)?;
437 let key = value_to_string(&key_val);
438 if !group_map.contains_key(&key) {
439 group_keys.push(key.clone());
440 }
441 group_map.entry(key).or_default().push(item.clone());
442 }
443
444 let mut result = Map::new();
445 for key in group_keys {
446 if let Some(items) = group_map.remove(&key) {
447 result.insert(key, Value::Array(items));
448 }
449 }
450
451 Ok(Value::Object(result))
452 }
453}
454
455defn!(CountByFn, vec![arg!(expref), arg!(array)], None);
460
461impl Function for CountByFn {
462 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
463 self.signature.validate(args, ctx)?;
464
465 let ast = get_expref_ast(&args[0], ctx)
466 .ok_or_else(|| custom_error(ctx, "Expected expref"))?
467 .clone();
468 let arr = args[1].as_array().unwrap();
469
470 let mut count_keys: Vec<String> = Vec::new();
471 let mut counts: std::collections::HashMap<String, i64> = std::collections::HashMap::new();
472
473 for item in arr {
474 let key_val = interpret(item, &ast, ctx)?;
475 let key = value_to_string(&key_val);
476 if !counts.contains_key(&key) {
477 count_keys.push(key.clone());
478 }
479 *counts.entry(key).or_insert(0) += 1;
480 }
481
482 let mut result = Map::new();
483 for key in count_keys {
484 if let Some(&count) = counts.get(&key) {
485 result.insert(key, Value::Number(Number::from(count)));
486 }
487 }
488
489 Ok(Value::Object(result))
490 }
491}
492
493defn!(PartitionExprFn, vec![arg!(expref), arg!(array)], None);
498
499impl Function for PartitionExprFn {
500 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
501 self.signature.validate(args, ctx)?;
502
503 let ast = get_expref_ast(&args[0], ctx)
504 .ok_or_else(|| custom_error(ctx, "Expected expref"))?
505 .clone();
506 let arr = args[1].as_array().unwrap();
507
508 let mut matches = Vec::new();
509 let mut non_matches = Vec::new();
510
511 for item in arr {
512 let result = interpret(item, &ast, ctx)?;
513 if result.is_truthy() {
514 matches.push(item.clone());
515 } else {
516 non_matches.push(item.clone());
517 }
518 }
519
520 Ok(Value::Array(vec![
521 Value::Array(matches),
522 Value::Array(non_matches),
523 ]))
524 }
525}
526
527defn!(MinByExprFn, vec![arg!(expref), arg!(array)], None);
532
533impl Function for MinByExprFn {
534 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
535 self.signature.validate(args, ctx)?;
536
537 let ast = get_expref_ast(&args[0], ctx)
538 .ok_or_else(|| custom_error(ctx, "Expected expref"))?
539 .clone();
540 let arr = args[1].as_array().unwrap();
541
542 if arr.is_empty() {
543 return Ok(Value::Null);
544 }
545
546 let mut min_item = arr[0].clone();
547 let mut min_key = interpret(&arr[0], &ast, ctx)?;
548
549 for item in arr.iter().skip(1) {
550 let key = interpret(item, &ast, ctx)?;
551 if compare_values(&key, &min_key) == std::cmp::Ordering::Less {
552 min_item = item.clone();
553 min_key = key;
554 }
555 }
556
557 Ok(min_item)
558 }
559}
560
561defn!(MaxByExprFn, vec![arg!(expref), arg!(array)], None);
566
567impl Function for MaxByExprFn {
568 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
569 self.signature.validate(args, ctx)?;
570
571 let ast = get_expref_ast(&args[0], ctx)
572 .ok_or_else(|| custom_error(ctx, "Expected expref"))?
573 .clone();
574 let arr = args[1].as_array().unwrap();
575
576 if arr.is_empty() {
577 return Ok(Value::Null);
578 }
579
580 let mut max_item = arr[0].clone();
581 let mut max_key = interpret(&arr[0], &ast, ctx)?;
582
583 for item in arr.iter().skip(1) {
584 let key = interpret(item, &ast, ctx)?;
585 if compare_values(&key, &max_key) == std::cmp::Ordering::Greater {
586 max_item = item.clone();
587 max_key = key;
588 }
589 }
590
591 Ok(max_item)
592 }
593}
594
595defn!(UniqueByExprFn, vec![arg!(expref), arg!(array)], None);
600
601impl Function for UniqueByExprFn {
602 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
603 self.signature.validate(args, ctx)?;
604
605 let ast = get_expref_ast(&args[0], ctx)
606 .ok_or_else(|| custom_error(ctx, "Expected expref"))?
607 .clone();
608 let arr = args[1].as_array().unwrap();
609
610 let mut seen: HashSet<String> = HashSet::new();
611 let mut results = Vec::new();
612
613 for item in arr {
614 let key_val = interpret(item, &ast, ctx)?;
615 let key = value_to_string(&key_val);
616 if seen.insert(key) {
617 results.push(item.clone());
618 }
619 }
620
621 Ok(Value::Array(results))
622 }
623}
624
625defn!(FlatMapExprFn, vec![arg!(expref), arg!(array)], None);
630
631impl Function for FlatMapExprFn {
632 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
633 self.signature.validate(args, ctx)?;
634
635 let ast = get_expref_ast(&args[0], ctx)
636 .ok_or_else(|| custom_error(ctx, "Expected expref"))?
637 .clone();
638 let arr = args[1].as_array().unwrap();
639
640 let mut results = Vec::new();
641 for item in arr {
642 let result = interpret(item, &ast, ctx)?;
643 match result {
644 Value::Array(inner) => {
645 results.extend(inner);
646 }
647 Value::Null => {
648 }
650 _ => {
651 results.push(result);
652 }
653 }
654 }
655
656 Ok(Value::Array(results))
657 }
658}
659
660defn!(RejectFn, vec![arg!(expref), arg!(array)], None);
665
666impl Function for RejectFn {
667 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
668 self.signature.validate(args, ctx)?;
669
670 let ast = get_expref_ast(&args[0], ctx)
671 .ok_or_else(|| custom_error(ctx, "Expected expref"))?
672 .clone();
673 let arr = args[1].as_array().unwrap();
674
675 let mut results = Vec::new();
676 for item in arr {
677 let result = interpret(item, &ast, ctx)?;
678 if !result.is_truthy() {
680 results.push(item.clone());
681 }
682 }
683
684 Ok(Value::Array(results))
685 }
686}
687
688defn!(MapKeysFn, vec![arg!(expref), arg!(object)], None);
693
694impl Function for MapKeysFn {
695 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
696 self.signature.validate(args, ctx)?;
697
698 let ast = get_expref_ast(&args[0], ctx)
699 .ok_or_else(|| custom_error(ctx, "Expected expref"))?
700 .clone();
701 let obj = args[1].as_object().unwrap();
702
703 let mut result = Map::new();
704 for (key, value) in obj.iter() {
705 let key_val = Value::String(key.clone());
707 let new_key_val = interpret(&key_val, &ast, ctx)?;
708
709 let new_key_str = match &new_key_val {
710 Value::String(s) => s.clone(),
711 Value::Number(n) => n.to_string(),
712 _ => key.clone(), };
714
715 result.insert(new_key_str, value.clone());
716 }
717
718 Ok(Value::Object(result))
719 }
720}
721
722defn!(MapValuesFn, vec![arg!(expref), arg!(object)], None);
727
728impl Function for MapValuesFn {
729 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
730 self.signature.validate(args, ctx)?;
731
732 let ast = get_expref_ast(&args[0], ctx)
733 .ok_or_else(|| custom_error(ctx, "Expected expref"))?
734 .clone();
735 let obj = args[1].as_object().unwrap();
736
737 let mut result = Map::new();
738 for (key, value) in obj.iter() {
739 let new_value = interpret(value, &ast, ctx)?;
740 result.insert(key.clone(), new_value);
741 }
742
743 Ok(Value::Object(result))
744 }
745}
746
747defn!(OrderByFn, vec![arg!(array), arg!(array)], None);
752
753impl Function for OrderByFn {
754 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
755 self.signature.validate(args, ctx)?;
756
757 let arr = args[0].as_array().unwrap();
758 let criteria = args[1].as_array().unwrap();
759
760 if arr.is_empty() {
761 return Ok(Value::Array(vec![]));
762 }
763
764 let mut sort_specs: Vec<(String, bool)> = Vec::new(); for criterion in criteria {
767 let crit_arr = criterion.as_array().ok_or_else(|| {
768 custom_error(ctx, "Each criterion must be an array [field, direction]")
769 })?;
770
771 if crit_arr.len() < 2 {
772 return Err(custom_error(
773 ctx,
774 "Each criterion must have [field, direction]",
775 ));
776 }
777
778 let field = crit_arr[0]
779 .as_str()
780 .ok_or_else(|| custom_error(ctx, "Field name must be a string"))?;
781
782 let direction = crit_arr[1]
783 .as_str()
784 .ok_or_else(|| custom_error(ctx, "Direction must be 'asc' or 'desc'"))?;
785
786 let ascending = match direction.to_lowercase().as_str() {
787 "asc" | "ascending" => true,
788 "desc" | "descending" => false,
789 _ => {
790 return Err(custom_error(ctx, "Direction must be 'asc' or 'desc'"));
791 }
792 };
793
794 sort_specs.push((field.to_string(), ascending));
795 }
796
797 let mut result: Vec<Value> = arr.clone();
799 result.sort_by(|a, b| {
800 for (field, ascending) in &sort_specs {
801 let a_val = a
802 .as_object()
803 .and_then(|o| o.get(field.as_str()))
804 .unwrap_or(&Value::Null);
805 let b_val = b
806 .as_object()
807 .and_then(|o| o.get(field.as_str()))
808 .unwrap_or(&Value::Null);
809
810 let cmp = compare_values(a_val, b_val);
811 if cmp != std::cmp::Ordering::Equal {
812 return if *ascending { cmp } else { cmp.reverse() };
813 }
814 }
815 std::cmp::Ordering::Equal
816 });
817
818 Ok(Value::Array(result))
819 }
820}
821
822defn!(
827 ReduceExprFn,
828 vec![arg!(expref), arg!(array), arg!(any)],
829 None
830);
831
832impl Function for ReduceExprFn {
833 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
834 self.signature.validate(args, ctx)?;
835
836 let ast = get_expref_ast(&args[0], ctx)
837 .ok_or_else(|| custom_error(ctx, "Expected expref"))?
838 .clone();
839 let arr = args[1].as_array().unwrap();
840 let initial = args[2].clone();
841
842 if arr.is_empty() {
843 return Ok(initial);
844 }
845
846 let mut accumulator = initial;
847
848 for (idx, item) in arr.iter().enumerate() {
849 let mut context_map = Map::new();
851 context_map.insert("accumulator".to_string(), accumulator.clone());
852 context_map.insert("current".to_string(), item.clone());
853 context_map.insert("index".to_string(), Value::Number(Number::from(idx as i64)));
854 let context_val = Value::Object(context_map);
855
856 accumulator = interpret(&context_val, &ast, ctx)?;
857 }
858
859 Ok(accumulator)
860 }
861}
862
863defn!(ScanExprFn, vec![arg!(expref), arg!(array), arg!(any)], None);
868
869impl Function for ScanExprFn {
870 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
871 self.signature.validate(args, ctx)?;
872
873 let ast = get_expref_ast(&args[0], ctx)
874 .ok_or_else(|| custom_error(ctx, "Expected expref"))?
875 .clone();
876 let arr = args[1].as_array().unwrap();
877 let initial = args[2].clone();
878
879 if arr.is_empty() {
880 return Ok(Value::Array(vec![]));
881 }
882
883 let mut accumulator = initial;
884 let mut results: Vec<Value> = Vec::with_capacity(arr.len());
885
886 for (idx, item) in arr.iter().enumerate() {
887 let mut context_map = Map::new();
889 context_map.insert("accumulator".to_string(), accumulator.clone());
890 context_map.insert("current".to_string(), item.clone());
891 context_map.insert("index".to_string(), Value::Number(Number::from(idx as i64)));
892 let context_val = Value::Object(context_map);
893
894 accumulator = interpret(&context_val, &ast, ctx)?;
895 results.push(accumulator.clone());
896 }
897
898 Ok(Value::Array(results))
899 }
900}
901
902defn!(PartialFn, vec![arg!(string)], Some(arg!(any)));
907
908impl Function for PartialFn {
909 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
910 self.signature.validate(args, ctx)?;
911
912 let fn_name = args[0].as_str().ok_or_else(|| {
913 custom_error(
914 ctx,
915 "partial() first argument must be a function name string",
916 )
917 })?;
918
919 let prefilled_args: Vec<Value> = args[1..].to_vec();
921
922 let mut partial_obj = Map::new();
924 partial_obj.insert("__partial__".to_string(), Value::Bool(true));
925 partial_obj.insert("fn".to_string(), Value::String(fn_name.to_string()));
926 partial_obj.insert("args".to_string(), Value::Array(prefilled_args));
927
928 Ok(Value::Object(partial_obj))
929 }
930}
931
932defn!(ApplyFn, vec![arg!(any)], Some(arg!(any)));
937
938impl Function for ApplyFn {
939 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
940 self.signature.validate(args, ctx)?;
941
942 let first_arg = &args[0];
943 let additional_args = &args[1..];
944
945 if let Some(obj) = first_arg.as_object()
947 && obj.get("__partial__").and_then(|v| v.as_bool()) == Some(true)
948 {
949 let fn_name = obj
951 .get("fn")
952 .and_then(|v| v.as_str())
953 .ok_or_else(|| custom_error(ctx, "Invalid partial object: missing 'fn' field"))?;
954
955 let prefilled = obj
956 .get("args")
957 .and_then(|v| v.as_array())
958 .ok_or_else(|| custom_error(ctx, "Invalid partial object: missing 'args' field"))?;
959
960 return invoke_function(fn_name, prefilled, additional_args, ctx);
961 }
962
963 if let Some(fn_name) = first_arg.as_str() {
965 return invoke_function(fn_name, &[], additional_args, ctx);
966 }
967
968 Err(custom_error(
969 ctx,
970 "apply() first argument must be a partial object or function name string",
971 ))
972 }
973}
974
975fn invoke_function(
977 fn_name: &str,
978 prefilled: &[Value],
979 additional: &[Value],
980 ctx: &mut Context<'_>,
981) -> SearchResult {
982 let mut all_args_json: Vec<String> = Vec::new();
984
985 for a in prefilled {
987 all_args_json.push(format!("`{}`", serde_json::to_string(a).unwrap()));
988 }
989
990 for a in additional {
992 all_args_json.push(format!("`{}`", serde_json::to_string(a).unwrap()));
993 }
994
995 let expr_str = format!("{}({})", fn_name, all_args_json.join(", "));
997
998 let compiled = ctx.runtime.compile(&expr_str).map_err(|_| {
999 custom_error(
1000 ctx,
1001 &format!("Failed to compile function call '{}'", expr_str),
1002 )
1003 })?;
1004
1005 compiled
1006 .search(&Value::Null)
1007 .map_err(|_| custom_error(ctx, &format!("Failed to execute '{}'", fn_name)))
1008}
1009
1010defn!(TakeWhileFn, vec![arg!(expref), arg!(array)], None);
1015
1016impl Function for TakeWhileFn {
1017 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
1018 self.signature.validate(args, ctx)?;
1019
1020 let ast = get_expref_ast(&args[0], ctx)
1021 .ok_or_else(|| custom_error(ctx, "Expected expref"))?
1022 .clone();
1023 let arr = args[1].as_array().unwrap();
1024
1025 let mut results = Vec::new();
1026 for item in arr {
1027 let result = interpret(item, &ast, ctx)?;
1028 if result.is_truthy() {
1029 results.push(item.clone());
1030 } else {
1031 break;
1032 }
1033 }
1034
1035 Ok(Value::Array(results))
1036 }
1037}
1038
1039defn!(DropWhileFn, vec![arg!(expref), arg!(array)], None);
1044
1045impl Function for DropWhileFn {
1046 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
1047 self.signature.validate(args, ctx)?;
1048
1049 let ast = get_expref_ast(&args[0], ctx)
1050 .ok_or_else(|| custom_error(ctx, "Expected expref"))?
1051 .clone();
1052 let arr = args[1].as_array().unwrap();
1053
1054 let mut dropping = true;
1055 let mut results = Vec::new();
1056 for item in arr {
1057 if dropping {
1058 let result = interpret(item, &ast, ctx)?;
1059 if !result.is_truthy() {
1060 dropping = false;
1061 results.push(item.clone());
1062 }
1063 } else {
1064 results.push(item.clone());
1065 }
1066 }
1067
1068 Ok(Value::Array(results))
1069 }
1070}
1071
1072defn!(
1077 ZipWithFn,
1078 vec![arg!(expref), arg!(array), arg!(array)],
1079 None
1080);
1081
1082impl Function for ZipWithFn {
1083 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
1084 self.signature.validate(args, ctx)?;
1085
1086 let ast = get_expref_ast(&args[0], ctx)
1087 .ok_or_else(|| custom_error(ctx, "Expected expref"))?
1088 .clone();
1089 let arr1 = args[1].as_array().unwrap();
1090 let arr2 = args[2].as_array().unwrap();
1091
1092 let min_len = arr1.len().min(arr2.len());
1093 let mut results = Vec::with_capacity(min_len);
1094
1095 for i in 0..min_len {
1096 let pair = Value::Array(vec![arr1[i].clone(), arr2[i].clone()]);
1098 let result = interpret(&pair, &ast, ctx)?;
1099 results.push(result);
1100 }
1101
1102 Ok(Value::Array(results))
1103 }
1104}
1105
1106defn!(WalkFn, vec![arg!(expref), arg!(any)], None);
1111
1112fn walk_value(value: &Value, ast: &Ast, ctx: &mut Context<'_>) -> SearchResult {
1114 match value {
1115 Value::Array(arr) => {
1116 let walked_elements: Result<Vec<Value>, _> =
1118 arr.iter().map(|elem| walk_value(elem, ast, ctx)).collect();
1119 let new_array = Value::Array(walked_elements?);
1120 interpret(&new_array, ast, ctx)
1122 }
1123 Value::Object(obj) => {
1124 let mut walked_obj = Map::new();
1126 for (k, v) in obj.iter() {
1127 walked_obj.insert(k.clone(), walk_value(v, ast, ctx)?);
1128 }
1129 let new_object = Value::Object(walked_obj);
1130 interpret(&new_object, ast, ctx)
1132 }
1133 _ => interpret(value, ast, ctx),
1135 }
1136}
1137
1138impl Function for WalkFn {
1139 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
1140 self.signature.validate(args, ctx)?;
1141
1142 let ast = get_expref_ast(&args[0], ctx)
1143 .ok_or_else(|| custom_error(ctx, "Expected expref"))?
1144 .clone();
1145
1146 walk_value(&args[1], &ast, ctx)
1147 }
1148}
1149
1150defn!(RecurseFn, vec![arg!(any)], None);
1155
1156fn collect_recursive(value: &Value, results: &mut Vec<Value>) {
1158 results.push(value.clone());
1159 match value {
1160 Value::Array(arr) => {
1161 for elem in arr {
1162 collect_recursive(elem, results);
1163 }
1164 }
1165 Value::Object(obj) => {
1166 for (_, v) in obj.iter() {
1167 collect_recursive(v, results);
1168 }
1169 }
1170 _ => {}
1171 }
1172}
1173
1174impl Function for RecurseFn {
1175 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
1176 self.signature.validate(args, ctx)?;
1177
1178 let mut results = Vec::new();
1179 collect_recursive(&args[0], &mut results);
1180
1181 Ok(Value::Array(results))
1182 }
1183}
1184
1185defn!(RecurseWithFn, vec![arg!(any), arg!(expref)], None);
1190
1191impl Function for RecurseWithFn {
1192 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
1193 self.signature.validate(args, ctx)?;
1194
1195 let ast = get_expref_ast(&args[1], ctx)
1196 .ok_or_else(|| custom_error(ctx, "Expected expref"))?
1197 .clone();
1198
1199 let mut results = Vec::new();
1200 let mut queue = vec![args[0].clone()];
1201 let max_iterations = 10000; let mut iterations = 0;
1203
1204 while let Some(current) = queue.pop() {
1205 if iterations >= max_iterations {
1206 return Err(custom_error(
1207 ctx,
1208 "recurse_with exceeded maximum iterations",
1209 ));
1210 }
1211 iterations += 1;
1212
1213 if current.is_null() {
1215 continue;
1216 }
1217
1218 results.push(current.clone());
1219
1220 let next = interpret(¤t, &ast, ctx)?;
1222
1223 match next {
1224 Value::Null => {}
1225 Value::Array(arr) => {
1226 for elem in arr.into_iter().rev() {
1228 if !elem.is_null() {
1229 queue.push(elem);
1230 }
1231 }
1232 }
1233 _ => {
1234 queue.push(next);
1235 }
1236 }
1237 }
1238
1239 Ok(Value::Array(results))
1240 }
1241}
1242
1243defn!(
1248 WhileExprFn,
1249 vec![arg!(any), arg!(expref), arg!(expref)],
1250 None
1251);
1252
1253impl Function for WhileExprFn {
1254 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
1255 self.signature.validate(args, ctx)?;
1256
1257 let cond_ast = get_expref_ast(&args[1], ctx)
1258 .ok_or_else(|| custom_error(ctx, "Expected expref for condition"))?
1259 .clone();
1260 let update_ast = get_expref_ast(&args[2], ctx)
1261 .ok_or_else(|| custom_error(ctx, "Expected expref for update"))?
1262 .clone();
1263
1264 let mut current = args[0].clone();
1265 let max_iterations = 100000; let mut iterations = 0;
1267
1268 loop {
1269 if iterations >= max_iterations {
1270 return Err(custom_error(ctx, "while_expr exceeded maximum iterations"));
1271 }
1272 iterations += 1;
1273
1274 let cond_result = interpret(¤t, &cond_ast, ctx)?;
1276 if !cond_result.is_truthy() {
1277 break;
1278 }
1279
1280 current = interpret(¤t, &update_ast, ctx)?;
1282 }
1283
1284 Ok(current)
1285 }
1286}
1287
1288defn!(
1293 UntilExprFn,
1294 vec![arg!(any), arg!(expref), arg!(expref)],
1295 None
1296);
1297
1298impl Function for UntilExprFn {
1299 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
1300 self.signature.validate(args, ctx)?;
1301
1302 let cond_ast = get_expref_ast(&args[1], ctx)
1303 .ok_or_else(|| custom_error(ctx, "Expected expref for condition"))?
1304 .clone();
1305 let update_ast = get_expref_ast(&args[2], ctx)
1306 .ok_or_else(|| custom_error(ctx, "Expected expref for update"))?
1307 .clone();
1308
1309 let mut current = args[0].clone();
1310 let max_iterations = 100000; let mut iterations = 0;
1312
1313 loop {
1314 if iterations >= max_iterations {
1315 return Err(custom_error(ctx, "until_expr exceeded maximum iterations"));
1316 }
1317 iterations += 1;
1318
1319 let cond_result = interpret(¤t, &cond_ast, ctx)?;
1321 if cond_result.is_truthy() {
1322 break;
1323 }
1324
1325 current = interpret(¤t, &update_ast, ctx)?;
1327 }
1328
1329 Ok(current)
1330 }
1331}