feat(rvm): new instructions and loop semantics for Azure Policy support (#659)

The Rego VM was designed around Rego's semantics, but Azure Policy needs
a few things Rego doesn't: host-supplied context alongside input/data,
undefined-to-null coercion for missing fields, skip-undefined collection
behavior for wildcard aliases, and non-vacuous iteration over non-array
values.

This commit adds five new instructions to bridge those gaps:

  LoadContext / LoadMetadata — give programs access to host-supplied
  evaluation context and cached program metadata at runtime.

  ArrayPushDefined — like ArrayPush but silently drops undefined values,
  so wildcard alias collection (field[*].property) excludes absent
  nested properties instead of leaking undefined entries into the array.

  ReturnUndefinedIfNotTrue — early return with Undefined when a guard
  condition isn't satisfied, without tripping a VM assertion failure.
  This models "condition doesn't match" cleanly.

  CoalesceUndefinedToNull — turns Undefined into Null in-place so that
  downstream builtins see null rather than short-circuiting on undefined.

The loop engine also gains an Azure Policy mode: when the source language
is "azure_policy", an Every loop over a non-array value (scalars, null,
objects) iterates once over a virtual Null element instead of being
vacuously true.  This matches how field[*] behaves on non-array fields
in Azure Policy — the condition body runs once against Null, which
typically evaluates to false.

On the plumbing side: the VM gets a context field with set_context(),
metadata is cached as a Value on program load, and map_limit_error is
inlined into memory_check since it had only one call site.

Four new YAML test suites (~880 lines) cover the new instructions and
context/metadata loading, along with instruction parser, display, and
assembly listing support for everything added here.
This commit is contained in:
Anand Krishnamoorthi
2026-04-06 15:40:41 -05:00
committed by GitHub
parent 8f740e2f6f
commit e5ac9a2734
15 changed files with 1215 additions and 25 deletions
+3 -3
View File
@@ -312,7 +312,7 @@ impl RegoVM {
*current_item =
Some(self.get_register(comprehension_context.value_reg)?.clone());
}
IterationState::Array { .. } => {}
IterationState::Array { .. } | IterationState::Single { .. } => {}
}
iter_state.advance();
@@ -468,7 +468,7 @@ impl RegoVM {
} => {
*current_item = Some(iteration_value.clone());
}
IterationState::Array { .. } => {}
IterationState::Array { .. } | IterationState::Single { .. } => {}
}
iter_state.advance();
@@ -599,7 +599,7 @@ impl RegoVM {
} => {
*current_item = Some(self.get_register(value_reg)?.clone());
}
IterationState::Array { .. } => {}
IterationState::Array { .. } | IterationState::Single { .. } => {}
}
Ok(())