1use super::*;
3use zirql::{ValueExpression as E, ValueExpressionKind as K};
4
5pub type ProgramValue = E<zirql::Expression<ProgramNative, zirql::NativeSetOperator, ()>>;
8pub type ProgramFunction = zirql::UnresolvedPatternFunctionDeclaration<
10 zirql::Expression<ProgramNative, zirql::NativeSetOperator, ()>,
11>;
12
13#[derive(Debug)]
15pub enum ProgramNative {
16 Query(Query),
17 Ordering(zirql::NativeOrdering<zirql::Expression<Self, zirql::NativeSetOperator, ()>>),
18 Mapping(zirql::NativeMap<zirql::Expression<Self, zirql::NativeSetOperator, ()>>),
20 MapSorting,
22 Exists(Box<zirql::Expression<Self, zirql::NativeSetOperator, ()>>),
24 FixedPoint(Box<zirql::Expression<Self, zirql::NativeSetOperator, ()>>),
26}
27
28impl ProgramNative {
29 fn take_selectors(
30 &mut self,
31 pending: &mut Vec<zirql::Expression<Self, zirql::NativeSetOperator, ()>>,
32 ) {
33 match self {
34 Self::Ordering(ordering) => pending.extend(ordering.selector.take()),
35 Self::Mapping(mapping) => {
36 pending.push(std::mem::replace(
37 &mut mapping.key,
38 Located::new(ExpressionKind::Input, 0..0),
39 ));
40 pending.push(std::mem::replace(
41 &mut mapping.value,
42 Located::new(ExpressionKind::Input, 0..0),
43 ));
44 }
45 Self::Exists(body) | Self::FixedPoint(body) => pending.push(*std::mem::replace(
46 body,
47 Box::new(Located::new(ExpressionKind::Input, 0..0)),
48 )),
49 Self::Query(_) | Self::MapSorting => {}
50 }
51 }
52}
53
54impl Drop for ProgramNative {
55 fn drop(&mut self) {
56 let mut pending = Vec::new();
57 self.take_selectors(&mut pending);
58 while let Some(expression) = pending.pop() {
59 match expression.value {
60 ExpressionKind::Input | ExpressionKind::Binding(_) => {}
61 ExpressionKind::Group(value) | ExpressionKind::Field { value, .. } => {
62 pending.push(*value)
63 }
64 ExpressionKind::Record(fields) => {
65 pending.extend(fields.into_iter().map(|(_, value)| value))
66 }
67 ExpressionKind::Set { left, right, .. } => {
68 pending.push(*left);
69 pending.push(*right);
70 }
71 ExpressionKind::Sequence { input, steps } => {
72 pending.push(*input);
73 for mut step in steps {
74 if let ExpressionStep::Stage(stage) = &mut step.value {
75 stage.take_selectors(&mut pending);
76 }
77 }
78 }
79 }
80 }
81 }
82}
83
84struct Inputs {
85 functions: Vec<ProgramFunction>,
86 bindings: Vec<(zirql::Pattern, ProgramValue)>,
87 report: Option<ProgramValue>,
88}
89impl Drop for Inputs {
90 fn drop(&mut self) {
91 for mut function in std::mem::take(&mut self.functions) {
92 for parameter in &mut function.parameters {
93 dispose_signature(std::mem::replace(
94 &mut parameter.value.declaration.value,
95 zirql::SignatureType::Integer,
96 ));
97 }
98 dispose_signature(std::mem::replace(
99 &mut function.result.value,
100 zirql::SignatureType::Integer,
101 ));
102 zirql::dispose_unresolved_pattern_functions(vec![function]);
103 }
104 for (pattern, value) in std::mem::take(&mut self.bindings) {
105 zirql::dispose_pattern(pattern);
106 zirql::dispose_native_value(value);
107 }
108 if let Some(value) = self.report.take() {
109 zirql::dispose_native_value(value);
110 }
111 }
112}
113impl Program {
114 pub fn from_values(
127 functions: Vec<ProgramFunction>,
128 bindings: Vec<(zirql::Pattern, ProgramValue)>,
129 final_report: ProgramValue,
130 limits: ProgramLimits,
131 ) -> Result<Self, QueryError> {
132 let mut inputs = Inputs {
133 functions,
134 bindings,
135 report: Some(final_report),
136 };
137 let mut budget = Budget::for_program(limits.core());
138 let range = inputs.report.as_ref().unwrap().range.clone();
139 let mut names = std::collections::BTreeSet::new();
140 for function in &inputs.functions {
141 functions::check_signature(&function.result, &mut budget, limits.nesting)?;
142 for parameter in &function.parameters {
143 functions::check_signature(
144 ¶meter.value.declaration,
145 &mut budget,
146 limits.nesting,
147 )?;
148 }
149 for query in functions::check_value(&function.value, &mut budget, limits.nesting)? {
150 check_native(query, &mut budget, limits.nesting)?;
151 }
152 }
153 let mut binding_names = Vec::new();
154 for (pattern, value) in &inputs.bindings {
155 let selected =
156 zirql::pattern_names(pattern, &mut budget).map_err(pipeline::core_error)?;
157 for name in &selected {
158 if !names.insert(name.value.clone()) {
159 return Err(QueryError::query(
160 name.range.clone(),
161 "binding is already defined",
162 ));
163 }
164 }
165 binding_names.push(selected.into_iter().cloned().collect());
166 for query in functions::check_value(value, &mut budget, limits.nesting)? {
167 check_native(query, &mut budget, limits.nesting)?;
168 }
169 }
170 for query in
171 functions::check_value(inputs.report.as_ref().unwrap(), &mut budget, limits.nesting)?
172 {
173 check_native(query, &mut budget, limits.nesting)?;
174 }
175 let mut queries = Vec::new();
176 let mut lower = |query, range: Range<usize>| {
177 let index = queries.len();
178 queries.push(ProgramQuery {
179 query,
180 arguments: Rc::new(Vec::new()),
181 copy_units: range.len() + 1,
182 });
183 value_stage(Stage::Query(index, Rc::new(Vec::new())), range)
184 };
185 let mut functions = std::mem::take(&mut inputs.functions)
186 .into_iter()
187 .map(|function| zirql::UnresolvedPatternFunctionDeclaration {
188 name: function.name,
189 parameters: function.parameters,
190 result: function.result,
191 value: map_queries(function.value, &mut |query| map_native(query, &mut lower)),
192 })
193 .collect::<Vec<_>>();
194 let mut statements = Vec::new();
195 for ((pattern, value), names) in std::mem::take(&mut inputs.bindings)
196 .into_iter()
197 .zip(binding_names)
198 {
199 let range = value.range.clone();
200 statements.push(Located::new(
201 zirql::Statement::BindFields {
202 names,
203 expression: value_stage(
204 Stage::PatternBinding(
205 pattern,
206 map_queries(value, &mut |query| map_native(query, &mut lower)),
207 ),
208 range.clone(),
209 ),
210 },
211 range,
212 ));
213 }
214 statements.push(Located::new(
215 zirql::Statement::Evaluate {
216 expression: value_stage(
217 Stage::FunctionValue(map_queries(
218 inputs.report.take().unwrap(),
219 &mut |query| map_native(query, &mut lower),
220 )),
221 range.clone(),
222 ),
223 implicit_output: Some(Emitter::Json),
224 },
225 range.clone(),
226 ));
227 for function in &mut functions {
228 functions::lower_primitives(
229 &mut function.value,
230 &BTreeMap::new(),
231 &queries,
232 &Default::default(),
233 );
234 }
235 for statement in &mut statements {
236 let expression = match &mut statement.value {
237 zirql::Statement::Bind { expression, .. }
238 | zirql::Statement::BindFields { expression, .. }
239 | zirql::Statement::Evaluate { expression, .. } => expression,
240 };
241 if let ExpressionKind::Sequence { steps, .. } = &mut expression.value {
242 for step in steps {
243 if let ExpressionStep::Stage(
244 Stage::FunctionValue(value) | Stage::PatternBinding(_, value),
245 ) = &mut step.value
246 {
247 functions::lower_primitives(
248 value,
249 &BTreeMap::new(),
250 &queries,
251 &Default::default(),
252 );
253 }
254 }
255 }
256 }
257 let report_model_demand = queries
258 .iter()
259 .any(|query| query.query.requires_model_facts())
260 || functions.iter().any(|function| {
261 functions::signature_needs_model(&function.result.value)
262 || function.parameters.iter().any(|parameter| {
263 functions::signature_needs_model(¶meter.value.declaration.value)
264 })
265 });
266 Ok(Self {
267 parameters: Vec::new(),
268 program: zirql::Program::new(statements, range.clone()),
269 preflight_work: limits.work - budget.remaining_work(),
270 preflight_results: limits.results - budget.remaining_results().unwrap(),
271 preflight_range: Some(range),
272 queries,
273 functions,
274 function_limits: zirql::FunctionLimits { active_depth: 64 },
275 report_model_demand,
276 editing: false,
277 prepared: true,
278 prepared_values: false,
279 })
280 }
281}
282
283fn map_native(
284 query: zirql::Expression<ProgramNative, zirql::NativeSetOperator, ()>,
285 lower: &mut impl FnMut(Query, Range<usize>) -> Expression,
286) -> Expression {
287 let range = query.range;
288 Located::new(
289 match query.value {
290 ExpressionKind::Input => ExpressionKind::Input,
291 ExpressionKind::Binding(name) => ExpressionKind::Binding(name),
292 ExpressionKind::Group(value) => {
293 ExpressionKind::Group(Box::new(map_native(*value, lower)))
294 }
295 ExpressionKind::Field { value, field } => ExpressionKind::Field {
296 value: Box::new(map_native(*value, lower)),
297 field,
298 },
299 ExpressionKind::Record(fields) => ExpressionKind::Record(
300 fields
301 .into_iter()
302 .map(|(name, value)| (name, map_native(value, lower)))
303 .collect(),
304 ),
305 ExpressionKind::Set {
306 operator,
307 left,
308 right,
309 } => ExpressionKind::Set {
310 operator,
311 left: Box::new(map_native(*left, lower)),
312 right: Box::new(map_native(*right, lower)),
313 },
314 ExpressionKind::Sequence { input, steps } => {
315 let mut input = map_native(*input, lower);
316 for step in steps {
317 match step.value {
318 ExpressionStep::Stage(mut stage) => {
319 let mut leaf = match &mut stage {
320 ProgramNative::Query(query) => lower(
321 std::mem::replace(
322 query,
323 Query {
324 stages: Vec::new(),
325 range: 0..0,
326 nesting_limit: 1,
327 },
328 ),
329 step.range.clone(),
330 ),
331 ProgramNative::Mapping(mapping) => value_stage(
332 Stage::Mapping(native::MappingStage::new(zirql::NativeMap {
333 key: map_native(
334 std::mem::replace(
335 &mut mapping.key,
336 Located::new(ExpressionKind::Input, 0..0),
337 ),
338 lower,
339 ),
340 value: map_native(
341 std::mem::replace(
342 &mut mapping.value,
343 Located::new(ExpressionKind::Input, 0..0),
344 ),
345 lower,
346 ),
347 })),
348 step.range.clone(),
349 ),
350 ProgramNative::Exists(body) | ProgramNative::FixedPoint(body) => {
351 let body = map_native(
352 *std::mem::replace(
353 body,
354 Box::new(Located::new(ExpressionKind::Input, 0..0)),
355 ),
356 lower,
357 );
358 let body = native::BodyStage::new(body);
359 let stage = if matches!(stage, ProgramNative::Exists(_)) {
360 Stage::WhereExists(body)
361 } else {
362 Stage::FixedPoint(body)
363 };
364 value_stage(stage, step.range.clone())
365 }
366 ProgramNative::MapSorting => {
367 value_stage(Stage::MapSorting, step.range.clone())
368 }
369 ProgramNative::Ordering(ordering) => value_stage(
370 Stage::Ordering(native::OrderingStage::new(
371 zirql::NativeOrdering {
372 order: ordering.order,
373 selector: ordering
374 .selector
375 .take()
376 .map(|selector| map_native(selector, lower)),
377 },
378 )),
379 step.range.clone(),
380 ),
381 };
382 let ExpressionKind::Sequence { steps, .. } = &mut leaf.value else {
383 unreachable!()
384 };
385 input = Located::new(
386 ExpressionKind::Sequence {
387 input: Box::new(input),
388 steps: std::mem::take(steps),
389 },
390 step.range,
391 );
392 }
393 ExpressionStep::Emit { .. } => {
394 unreachable!("typed emission rejected before lowering")
395 }
396 }
397 }
398 return input;
399 }
400 },
401 range,
402 )
403}
404
405pub(crate) fn map_queries<Q, R>(value: E<Q>, lower: &mut impl FnMut(Q) -> R) -> E<R> {
406 let range = value.range;
407 let value = match value.value {
408 K::CurrentInput => K::CurrentInput,
409 K::Literal(value) => K::Literal(value),
410 K::Name(name) => K::Name(name),
411 K::NativeQuery(query) => K::NativeQuery(Box::new(lower(*query))),
412 K::NativeValue(query) => K::NativeValue(Box::new(lower(*query))),
413 K::Call {
414 function,
415 arguments,
416 } => K::Call {
417 function,
418 arguments: arguments
419 .into_iter()
420 .map(|value| map_queries(value, lower))
421 .collect(),
422 },
423 K::Array(values) => K::Array(values.into_iter().map(|v| map_queries(v, lower)).collect()),
424 K::Tuple(values) => K::Tuple(values.into_iter().map(|v| map_queries(v, lower)).collect()),
425 K::Set(values) => K::Set(values.into_iter().map(|v| map_queries(v, lower)).collect()),
426 K::Dictionary(entries) => K::Dictionary(
427 entries
428 .into_iter()
429 .map(|(key, value)| (map_queries(key, lower), map_queries(value, lower)))
430 .collect(),
431 ),
432 K::DictionaryComprehension { clauses, key, head } => K::DictionaryComprehension {
433 clauses: map_clauses(clauses, lower),
434 key: Box::new(map_queries(*key, lower)),
435 head: Box::new(map_queries(*head, lower)),
436 },
437 K::Record(fields) => K::Record(
438 fields
439 .into_iter()
440 .map(|(n, v)| (n, map_queries(v, lower)))
441 .collect(),
442 ),
443 K::Block { bindings, value } => K::Block {
444 bindings: bindings
445 .into_iter()
446 .map(|(p, v)| (p, map_queries(v, lower)))
447 .collect(),
448 value: Box::new(map_queries(*value, lower)),
449 },
450 K::ValueMatch { subject, arms } => K::ValueMatch {
451 subject: Box::new(map_queries(*subject, lower)),
452 arms: arms
453 .into_iter()
454 .map(|arm| zirql::ValueMatchArm {
455 pattern: arm.pattern,
456 guard: arm.guard.map(|v| map_queries(v, lower)),
457 value: map_queries(arm.value, lower),
458 })
459 .collect(),
460 },
461 K::Conditional {
462 branches,
463 otherwise,
464 } => K::Conditional {
465 branches: branches
466 .into_iter()
467 .map(|(a, b)| (map_queries(a, lower), map_queries(b, lower)))
468 .collect(),
469 otherwise: Box::new(map_queries(*otherwise, lower)),
470 },
471 K::KeyedArray {
472 axes,
473 declared_axis_sources,
474 entries,
475 } => K::KeyedArray {
476 axes,
477 declared_axis_sources: declared_axis_sources
478 .map(|values| values.into_iter().map(|v| map_queries(v, lower)).collect()),
479 entries: entries
480 .into_iter()
481 .map(|(a, b)| (map_queries(a, lower), map_queries(b, lower)))
482 .collect(),
483 },
484 K::Comprehension {
485 constructor,
486 clauses,
487 head,
488 } => K::Comprehension {
489 constructor,
490 clauses: map_clauses(clauses, lower),
491 head: Box::new(map_queries(*head, lower)),
492 },
493 K::KeyedComprehension {
494 clauses,
495 key,
496 head,
497 declared_axis_sources,
498 empty_axis_sources,
499 } => K::KeyedComprehension {
500 declared_axis_sources: declared_axis_sources
501 .map(|values| values.into_iter().map(|v| map_queries(v, lower)).collect()),
502 clauses: map_clauses(clauses, lower),
503 key: Box::new(map_queries(*key, lower)),
504 head: Box::new(map_queries(*head, lower)),
505 empty_axis_sources: empty_axis_sources
506 .map(|values| values.into_iter().map(|v| map_queries(v, lower)).collect()),
507 },
508 K::Unique(value) => K::Unique(Box::new(map_queries(*value, lower))),
509 K::Tally(value) => K::Tally(Box::new(map_queries(*value, lower))),
510 K::Occurs(value) => K::Occurs(Box::new(map_queries(*value, lower))),
511 K::Absent(value) => K::Absent(Box::new(map_queries(*value, lower))),
512 K::One(value) => K::One(Box::new(map_queries(*value, lower))),
513 K::IndexSet(value) => K::IndexSet(Box::new(map_queries(*value, lower))),
514 K::Entries(value) => K::Entries(Box::new(map_queries(*value, lower))),
515 K::Unary { operator, operand } => K::Unary {
516 operator,
517 operand: Box::new(map_queries(*operand, lower)),
518 },
519 K::Binary {
520 operator,
521 left,
522 right,
523 } => K::Binary {
524 operator,
525 left: Box::new(map_queries(*left, lower)),
526 right: Box::new(map_queries(*right, lower)),
527 },
528 K::Field { value, field } => K::Field {
529 value: Box::new(map_queries(*value, lower)),
530 field,
531 },
532 K::TupleAccess { value, position } => K::TupleAccess {
533 value: Box::new(map_queries(*value, lower)),
534 position,
535 },
536 K::ArrayAccess { array, index } => K::ArrayAccess {
537 array: Box::new(map_queries(*array, lower)),
538 index: Box::new(map_queries(*index, lower)),
539 },
540 K::Lookup { value, key } => K::Lookup {
541 value: Box::new(map_queries(*value, lower)),
542 key: Box::new(map_queries(*key, lower)),
543 },
544 K::HasKey { value, key } => K::HasKey {
545 value: Box::new(map_queries(*value, lower)),
546 key: Box::new(map_queries(*key, lower)),
547 },
548 K::Default { value, fallback } => K::Default {
549 value: Box::new(map_queries(*value, lower)),
550 fallback: Box::new(map_queries(*fallback, lower)),
551 },
552 K::ZipExact { left, right } => K::ZipExact {
553 left: Box::new(map_queries(*left, lower)),
554 right: Box::new(map_queries(*right, lower)),
555 },
556 K::Reduce { operator, array } => K::Reduce {
557 operator,
558 array: Box::new(map_queries(*array, lower)),
559 },
560 K::PredicateSubject => K::PredicateSubject,
561 K::SubjectScope { subject, argument } => K::SubjectScope {
562 subject: Box::new(map_queries(*subject, lower)),
563 argument: zirql::PredicateArgument {
564 argument: argument.argument,
565 body: Box::new(map_queries(*argument.body, lower)),
566 },
567 },
568 K::PredicateScope { subject, predicate } => K::PredicateScope {
569 subject: Box::new(map_queries(*subject, lower)),
570 predicate: zirql::PredicateArgument {
571 argument: predicate.argument,
572 body: Box::new(map_queries(*predicate.body, lower)),
573 },
574 },
575 K::Filter { array, predicate } => K::Filter {
576 array: Box::new(map_queries(*array, lower)),
577 predicate: zirql::PredicateArgument {
578 argument: predicate.argument,
579 body: Box::new(map_queries(*predicate.body, lower)),
580 },
581 },
582 K::Sort {
583 array,
584 selector,
585 descending,
586 } => K::Sort {
587 array: Box::new(map_queries(*array, lower)),
588 selector,
589 descending,
590 },
591 K::Extremum {
592 operator,
593 array,
594 field,
595 } => K::Extremum {
596 operator,
597 array: Box::new(map_queries(*array, lower)),
598 field,
599 },
600 K::GroupBy { rows, field } => K::GroupBy {
601 rows: Box::new(map_queries(*rows, lower)),
602 field,
603 },
604 K::Require {
605 condition,
606 value,
607 message,
608 } => K::Require {
609 condition: Box::new(map_queries(*condition, lower)),
610 value: Box::new(map_queries(*value, lower)),
611 message,
612 },
613 K::Range {
614 lower: start,
615 upper,
616 } => K::Range {
617 lower: Box::new(map_queries(*start, lower)),
618 upper: Box::new(map_queries(*upper, lower)),
619 },
620 K::Queue { items, element } => K::Queue {
621 items: Box::new(map_queries(*items, lower)),
622 element,
623 },
624 K::PopFront(value) => K::PopFront(Box::new(map_queries(*value, lower))),
625 K::Break(value) => K::Break(Box::new(map_queries(*value, lower))),
626 K::Continue(values) => {
627 K::Continue(values.into_iter().map(|v| map_queries(v, lower)).collect())
628 }
629 K::PushBackAll { queue, items } => K::PushBackAll {
630 queue: Box::new(map_queries(*queue, lower)),
631 items: Box::new(map_queries(*items, lower)),
632 },
633 K::IdentitySet { element } => K::IdentitySet { element },
634 K::Insert { set, item } => K::Insert {
635 set: Box::new(map_queries(*set, lower)),
636 item: Box::new(map_queries(*item, lower)),
637 },
638 K::Fold {
639 items,
640 initial,
641 step,
642 } => K::Fold {
643 items: Box::new(map_queries(*items, lower)),
644 initial: Box::new(map_queries(*initial, lower)),
645 step,
646 },
647 K::Scan {
648 items,
649 initial,
650 step,
651 } => K::Scan {
652 items: Box::new(map_queries(*items, lower)),
653 initial: Box::new(map_queries(*initial, lower)),
654 step,
655 },
656 K::Loop { states, body } => K::Loop {
657 states: states
658 .into_iter()
659 .map(|(n, v)| (n, map_queries(v, lower)))
660 .collect(),
661 body: Box::new(map_queries(*body, lower)),
662 },
663 };
664 Located::new(value, range)
665}
666fn map_clauses<Q, R>(
667 clauses: Vec<Located<zirql::ValueGenerator<Q>>>,
668 lower: &mut impl FnMut(Q) -> R,
669) -> Vec<Located<zirql::ValueGenerator<R>>> {
670 clauses
671 .into_iter()
672 .map(|clause| {
673 Located::new(
674 match clause.value {
675 zirql::ValueGenerator::In {
676 binders,
677 source,
678 filter,
679 } => zirql::ValueGenerator::In {
680 binders,
681 source: map_queries(source, lower),
682 filter: filter.map(|v| map_queries(v, lower)),
683 },
684 zirql::ValueGenerator::Bind {
685 binder,
686 value,
687 filter,
688 } => zirql::ValueGenerator::Bind {
689 binder,
690 value: map_queries(value, lower),
691 filter: filter.map(|v| map_queries(v, lower)),
692 },
693 },
694 clause.range,
695 )
696 })
697 .collect()
698}
699
700fn check_native(
701 query: &zirql::Expression<ProgramNative, zirql::NativeSetOperator, ()>,
702 budget: &mut Budget,
703 nesting: usize,
704) -> Result<(), QueryError> {
705 let mut pending = vec![(query, 0)];
706 while let Some((query, depth)) = pending.pop() {
707 if depth >= nesting.min(64) {
708 return Err(QueryError::query(
709 query.range.clone(),
710 "native expression nesting limit exceeded",
711 ));
712 }
713 budget
714 .charge(1, zirql::Location::Query(query.range.clone()))
715 .map_err(pipeline::core_error)?;
716 match &query.value {
717 ExpressionKind::Input | ExpressionKind::Binding(_) => {}
718 ExpressionKind::Group(value) | ExpressionKind::Field { value, .. } => {
719 pending.push((value, depth + 1))
720 }
721 ExpressionKind::Record(fields) => {
722 let location = zirql::Location::Query(query.range.clone());
723 budget
724 .charge(fields.len(), location.clone())
725 .map_err(pipeline::core_error)?;
726 budget
727 .charge_results(fields.len(), location)
728 .map_err(pipeline::core_error)?;
729 pending.extend(fields.iter().map(|(_, v)| (v, depth + 1)))
730 }
731 ExpressionKind::Set { left, right, .. } => {
732 pending.push((left, depth + 1));
733 pending.push((right, depth + 1));
734 }
735 ExpressionKind::Sequence { input, steps } => {
736 pending.push((input, depth + 1));
737 for step in steps {
738 budget
739 .charge_results(1, zirql::Location::Query(step.range.clone()))
740 .map_err(pipeline::core_error)?;
741 match &step.value {
742 ExpressionStep::Stage(ProgramNative::Query(query))
743 if !query.is_editing()
744 && !query.stages.iter().any(|stage| {
745 matches!(
746 stage.kind,
747 language::StageKind::Emit
748 | language::StageKind::Json
749 | language::StageKind::EmitDocument
750 )
751 }) =>
752 {
753 budget
754 .charge(
755 query.range.len() + query.stages.len(),
756 zirql::Location::Query(step.range.clone()),
757 )
758 .map_err(pipeline::core_error)?;
759 budget
760 .charge_results(
761 query.stages.len(),
762 zirql::Location::Query(step.range.clone()),
763 )
764 .map_err(pipeline::core_error)?;
765 }
766 ExpressionStep::Stage(ProgramNative::Mapping(mapping)) => {
767 pending.push((&mapping.key, depth + 1));
768 pending.push((&mapping.value, depth + 1));
769 }
770 ExpressionStep::Stage(
771 ProgramNative::Exists(body) | ProgramNative::FixedPoint(body),
772 ) => pending.push((body, depth + 1)),
773 ExpressionStep::Stage(ProgramNative::MapSorting) => {}
774 ExpressionStep::Stage(ProgramNative::Ordering(ordering)) => {
775 if let Some(selector) = &ordering.selector {
776 pending.push((selector, depth + 1));
777 }
778 }
779 ExpressionStep::Stage(_) | ExpressionStep::Emit { .. } => {
780 return Err(QueryError::query(
781 step.range.clone(),
782 "typed report values must be pure",
783 ));
784 }
785 }
786 }
787 }
788 }
789 }
790 Ok(())
791}
792
793fn dispose_signature(signature: zirql::SignatureType) {
794 use zirql::SignatureType as S;
795 let mut pending = vec![signature];
796 while let Some(signature) = pending.pop() {
797 match signature {
798 S::Optional(value)
799 | S::Sequence(value)
800 | S::Set(value)
801 | S::Keyed(value)
802 | S::Queue(value)
803 | S::IdentitySet(value) => pending.push(value.value),
804 S::Tuple(values) => pending.extend(values.into_iter().map(|value| value.value)),
805 S::Record(fields) => pending.extend(fields.into_iter().map(|(_, value)| value.value)),
806 S::Boolean | S::Integer | S::Float | S::String | S::Named(_) => {}
807 }
808 }
809}