Builds on #57. Swap Value::Object's payload from Rc<BTreeMap<Value, Value>>
to Rc<Object> and migrate all call sites to the Object API.
as_object / as_object_mut keep their names but return &Object / &mut Object.
The mutable accessor handles Rc::make_mut internally, so callers no longer
do it themselves. Object grows into_value() and From<Object> for Value.
Value's serializer now delegates to Object::serialize, dropping a duplicate
non-string-key stringification path.
RVM IterationState::Object is rewritten around ObjectCursor: O(log n)
steps over a shared Rc<Object>, no eager pair snapshot. Snapshot
independence is preserved by Rc copy-on-write; setup_next_iteration
advances the cursor inline and advance() becomes a no-op for this variant.
A new iteration_state_object_is_snapshot_independent_of_source test
covers CoW against a mutated alias.
Value::Set still wraps Rc<BTreeSet<Value>>; the matching Set abstraction
and its swap ship in follow-up PRs.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace the compiler's two cloned BTreeMap fields (alias_map and
alias_modifiable) with a single Option<Rc<AliasRegistry>>. This
eliminates cloning two 73K-entry maps on every compilation by sharing
the registry through a reference-counted pointer.
Additional improvements:
- alias_map()/alias_modifiable_map() return &BTreeMap (zero-copy)
- Safe .get() indexing in ingest_alias_entries and build_object_from_keys
- Null-tolerant deserialization for AliasEntry.paths (~97% of real
Azure catalog entries emit "paths": null)
All changes are within the azure_policy feature gate.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Adds the YAML test runner that exercises the companion test data PRs, plus
several compiler fixes surfaced during testing:
- Removed parameter register caching that produced wrong results inside
short-circuiting allOf/anyOf blocks; added literal-index caching for
parameter defaults to avoid repeated O(n) literal-table scans
- Simplified cross-resource effect details to only emit roleDefinitionIds
and type (deployment templates are not evaluated for compliance)
- Replaced guid/uniqueString builtins with clear "unsupported" errors
- Normalized datetime output to ISO 8601 with Z suffix
- Added azure_policy parser MAX_COL constant (8192) for long template
expressions, keeping the global DEFAULT_MAX_COL at 1024
- Added rvm to azure_policy feature dependencies since the compiler
targets RVM bytecode
Also restructures the example binary into examples/regorus/ with new
azure-policy-eval and azure-policy-aliases subcommands, adds C# alias
normalization tests, and documents Azure Policy support in the README.
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace the stub implementations in effects.rs, effects_modify_append.rs,
and metadata.rs with full working code.
Effect compilation dispatches all effect kinds (Deny, Audit, Modify, Append,
AuditIfNotExists, DeployIfNotExists, etc.) including parameterized effects
that resolve at runtime via [parameters('effect')]. Cross-resource effects
(AINE/DINE) emit a HostAwait to fetch the related resource and evaluate an
optional existenceCondition against it. Modify and Append effects compile
their operation/detail arrays, including template expressions in values.
Metadata recording tracks which policy features are used during compilation
(field kinds, aliases, operators, resource types, count, wildcards) and
writes them into the program annotations so the runtime can inspect
capabilities without re-analyzing the AST. Definition-level metadata
(display name, category, version, parameter names, etc.) is also extracted.
Detail field values in AINE/DINE (type, name, resourceGroupName) are compiled
as expressions rather than frozen as literals, so template expressions like
[field('name')] are properly evaluated at runtime.
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
Implement the full count loop compiler, replacing the stubs in count.rs,
count_any.rs, and count_bindings.rs with a single consolidated module.
Handles both field-based and value-based count nodes. Field counts walk
the resource via resolve_alias_path then iterate the wildcard array;
value counts operate on an arbitrary collection expression.
For nested wildcard paths like A[*].B[*].C, the compiler emits recursive
ForEach loops, drilling one wildcard level at a time. When an outer
count binding already covers a prefix, the inner loop starts from the
bound element register instead of re-walking from the resource root.
Existence patterns (count > 0, count == 0) are recognized and lowered
to LoopMode::Any, which exits on the first match rather than counting
every element.
Count-binding resolution threads the current-element register through
inner field references and current() calls so that nested conditions
can address fields relative to the loop variable.
Also fixes the bound_len arithmetic in conditions_wildcard.rs with a
cleaner strip_prefix call, and removes the nested-wildcard bail in
split_count_wildcard_path since the compiler now handles them.
Fill in the compiler stubs for the evaluation layer.
Condition and wildcard compilation:
- Compile allOf/anyOf/not constraints, operator conditions with
value-condition guards, and implicit allOf for unbound [*] fields
via recursive Every loops.
- Defensively lowercase prefix/suffix path segments in wildcard
handling for consistency with the collect path.
Expression and field compilation:
- Parse ARM template expressions and dispatch calls to parameters,
field, current, resourceGroup, subscription, and others.
- Compile all FieldKind variants (type, id, name, location, tags,
aliases, dynamic if/concat), resolve resource paths, and collect
wildcard values via ForEach loops.
Template function dispatch:
- Wire up 50+ ARM template functions covering string, numeric,
encoding, collection, date/time, logical, and comparison categories.
Compiler infrastructure (core.rs):
- Add emit helpers: load_literal, emit_builtin_call,
emit_chained_index_literal_path, load_input, load_context,
emit_coalesce_undefined_to_null, add_literal_u16, and
get_or_add_builtin_index.
- Add alias resolution via resolve_alias_path and strip_fq_prefix.
Misc cleanup:
- Handle ARM template `[[` escape sequences in json_value_to_runtime
and add a test for it.
- Tighten module visibility (pub -> pub(crate)/pub(super)) where
appropriate.
- Add span context to bail errors in stubs so diagnostics carry
source locations.
- Take CountBinding by reference in compile_from_binding.
- Suppress clippy warnings on the no-op memory_check stub.