mirror of
https://github.com/microsoft/regorus.git
synced 2026-08-05 02:16:11 +00:00
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:
committed by
GitHub
parent
8f740e2f6f
commit
e5ac9a2734
@@ -54,6 +54,16 @@ pub enum Instruction {
|
||||
dest: u8,
|
||||
},
|
||||
|
||||
/// Load host-supplied context value into register
|
||||
LoadContext {
|
||||
dest: u8,
|
||||
},
|
||||
|
||||
/// Load program metadata value into register
|
||||
LoadMetadata {
|
||||
dest: u8,
|
||||
},
|
||||
|
||||
/// Move value from one register to another
|
||||
Move {
|
||||
dest: u8,
|
||||
@@ -206,6 +216,16 @@ pub enum Instruction {
|
||||
value: u8,
|
||||
},
|
||||
|
||||
/// Push element to array, but skip if the value is undefined.
|
||||
///
|
||||
/// Used by Azure Policy's `field('alias[*].property')` wildcard collection
|
||||
/// so that absent nested properties are excluded from the collected array
|
||||
/// rather than producing undefined entries.
|
||||
ArrayPushDefined {
|
||||
arr: u8,
|
||||
value: u8,
|
||||
},
|
||||
|
||||
/// Create array from registers - returns undefined if any element is undefined
|
||||
ArrayCreate {
|
||||
/// Index into program's instruction_data.array_create_params table
|
||||
@@ -254,6 +274,25 @@ pub enum Instruction {
|
||||
mode: GuardMode,
|
||||
},
|
||||
|
||||
/// Return undefined immediately when the condition register is not exactly
|
||||
/// `Bool(true)`. Any other value — including `false`, `Undefined`, `Null`,
|
||||
/// numbers, strings, etc. — causes an immediate return of `Undefined`.
|
||||
///
|
||||
/// This is used by Azure Policy compilation to model "condition does not match"
|
||||
/// without treating it as a VM assertion failure.
|
||||
ReturnUndefinedIfNotTrue {
|
||||
condition: u8,
|
||||
},
|
||||
|
||||
/// Replace Undefined with Null in a register.
|
||||
///
|
||||
/// Azure Policy treats missing fields as null rather than undefined.
|
||||
/// This instruction prevents the RVM's undefined-propagation from
|
||||
/// short-circuiting subsequent builtin calls.
|
||||
CoalesceUndefinedToNull {
|
||||
register: u8,
|
||||
},
|
||||
|
||||
/// Start a loop over a collection with specified semantics - uses parameter table
|
||||
LoopStart {
|
||||
/// Index into program's instruction_data.loop_params table
|
||||
|
||||
Reference in New Issue
Block a user