- Document arithmetic safety assumptions and add explicit lexer limits for columns, file size (1 MiB), and line count.
Realistic policies will be well within these bounds.
- Use checked arithmetic to prevent overflow underflow.
- Avoid var name shadowing.
- Misc clippy lints
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
- Made the lookup module crate-visible to address clippy’s redundant visibility lint.
- Replaced unchecked as casts with a fallible usize_from_u32 helper and propagate conversion errors in lookup accessors.
- Switched LookupIndexError to implement core::error::Error for no_std correctness.
- Fixed the pattern type mismatch by matching on the value in the Display impl.
- Promoted trivial helpers to const fn (new, module_len) per clippy suggestions.
- Centralized bounds-checked slot access via slot_ref/slot_mut to keep getters/clearers lint-clean and avoid unchecked indexing.
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
Lints are added (deny) at crate level.
In each offending file, the failing lints are explicitly allowed.
Each file will be fixed in subsequent PRs.
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
In case all the statements of a query don't execute,
skip reordering the result expressions to match the
source order. Doing so requires maintaining additional
data structures not worth the complexity for now.
Additionally we want to discourage queries and encourage
evaluating rules. Queries are inherently less performant
than rules which can be precompiled.
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
- ensure both run-to-completion and suspendable rule execution stop evaluating
bodies once one succeeds so later else branches are skipped
- test cases
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
RVM does not plan to support the `with` keyword which is mainly used
for testing.
- introduce CompilerError::WithKeywordUnsupported and fail query compilation
when any literal carries with_mods
- skip OPA test cases that hit the error
The "withkeyword" folder is retained in the TODO list to indicate its
lack of support.
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
- treat set subtraction in RVM the same as the interpreter by supporting
Value::Set operands in sub_values
- emit internal-only builtin names for set union/intersection and register
handlers so compiled bytecode resolves without exposing new Rego builtins
- add regression coverage for literal set difference/intersection
(x/y from failure.rego) in tests/rvm/rego/cases/sets.yaml
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
- emit AssertCondition for equality-only assignment plans (outside soft-assert mode) so rules like `0 = 1` fail under the VM just like the interpreter
- let comprehension bodies consume assertion failures by advancing or exiting their iteration context, both in run-to-completion and suspendable execution
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
Allow compile_chained_ref to fall back to “evaluate root expression → chain access”
so literal arrays, comprehensions, and other computed roots no longer raise NotSimpleReferenceChain.
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
Mirror interpreter implementation:
- use builtins::must_cache to determine whether builtin must be cached.
- reuse cached value when applicable
- clear the VM’s builtin cache whenever execution state resets to avoid leaking values across runs
- add a YAML regression for rand.intn set comprehensions and re-enable the rand cases in the OPA test suite
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
- Add a scoped soft_assert_mode to the compiler so `not` statements compile their subexpressions without emitting hard AssertCondition/AssertNotUndefined instructions.
- Teach binding-plan application to return an optional result register; equality plans now yield a boolean in soft mode, allowing not abs(-5 , 3) to succeed instead of aborting.
- Update function-call, loop, and rule plumbing to consume the new binding-plan outcome, including copying the produced register when an out-parameter equality is used.
- Trim the OPA TODO list to the remaining troublesome folders.
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
- Teach the hoister/destructuring planner to respect parent scope when building binding plans for extra arguments, so already-bound vars yield equality checks.
- Update the compiler’s function-call path to drop the trailing out-argument, run its binding plan after the call, and share call-target resolution logic.
- Add regression suites for builtin and user-defined out-parameter scenarios plus align the CLI example output when RVM returns undefined.
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
- fixes:
- ensure loop hoist lookups reserve query capacity and keep loop-var tables sized when compiling default rules
- rebuild hoisting tables with the analyzer’s schedule when available so statement order matches evaluation
- OPA test
- Also test using RVM workflow in OPA suite
- Maintain a list of test folders that don't yet pass and skip them
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
code fixes:
- compiler: add `is_var_bound_in_current_scope` and use it in destructuring so
only the innermost scope blocks rebinding while still catching duplicates
within that block.
- rvm: treat `not` over undefined operands as a successful negation to match
interpreter semantics.
tests/aci:
migrate YAML cases to `data.policy.rule` queries with `{x: …}`
bindings, expand the harness to run interpreter plus RVM (with optional
skipping), align results to the binding format, add readable timing output,
and support a `--filter` flag for targeting cases.
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
- Supply chain: Use the popular num-bigint crate for handling large integers
- Optimization: Handle f64, i64, u64 directly. These will be the most common instances of a number.
OPA number semantics isn't clear.
https://github.com/open-policy-agent/opa/issues/6281
As part of this change, we update the following failing tests:
- A local test that relies on what 15.3/3 evaluates to.
With our current change, we round in a different direction than what OPA does, but consistent
with Rust. We produce 5.1000000000000005 where as the OPA test expects 5.1.
There is no clear definition in Rego of what the right answer is. Moreover, policies should not
rely on exact floating point value comparison. Therefore this deviations is justified.
The test is patched to pass.
- Another local vm test that exercised 1.1 + 2.2
- Another local vm test that exercises 5.5 - 2.2
- An OPA test that expects that a large integer number say 10e308 is printed in exponent notation.
num-bigint does not print using scientific notation and instead prints all the digits.
The benefit of preserving this compatibility is not clear. We skip this test.
- Doc tests that exercised handling floating point numbers with more than 15 (what f64 supports)
digits of precision. There is no usecase for this scenario. The tests are updated to reflect
the behavior.
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
* feat: Add Azure RBAC condition parser
- declare an `azure-rbac` feature and expose the Azure RBAC module with parser, AST, and YAML-driven tests
- extend the shared lexer with RBAC-specific tokens, single-quoted strings, and corrected raw-string spans
- verify the parser via comprehensive test cases covering every operator and complex chaining
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
---------
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
* feat!: add Rego Virtual Machine (RVM) implementation
This commit introduces a register-based virtual machine for executing Rego
policies with bytecode-style instructions. Unlike the existing tree-walking
interpreter, the RVM compiles policies into instruction sequences that operate
on virtual registers, offering better performance and optimization potential.
Core Components:
Instruction Set Architecture:
- Define instruction types for data operations, control flow, and builtins
- Implement instruction parameter encoding and display formatting
- Add instruction parser with comprehensive test coverage
Virtual Machine Engine:
- Register-based execution model with program counter management
- Loop execution supporting iterators, comprehensions, and quantifiers
- Function call handling with argument evaluation and context management
- Rule evaluation with default value resolution and virtual data support
- Arithmetic and comparison operation implementations
Program Representation:
- Program listing builder with instruction sequencing
- Rule tree construction for organizing policy rules
- Binary and JSON serialization for compiled programs
- Recompilation support for program modification
Testing Infrastructure:
- Extensive YAML test suites covering all VM features
- Rust unit tests for VM execution and instruction parsing
- Test suites for loops, comprehensions, builtins, and control flow
BREAKING CHANGE: Introduces new VM execution path alongside interpreter
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
* docs: add detailed RVM architecture references
Introduce architecture.md explaining program artifacts, serialization, and runtime subsystems.
Document the full opcode catalog in instruction-set.md, including operands, parameter tables, and outcomes.
Walk through execution flow, stacks, and operational guidance in vm-runtime.md, tying the runtime to the new architecture docs.
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
---------
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
- add a dedicated `compiler/destructuring_planner` feature that precomputes binding plans for assignments, parameters, and `some in` expressions
- enrich `ScopeContext` with same-scope tracking, local scheduling hints, and module globals so the planner enforces := shadowing rules without blocking parent scopes
- wire the planner through compiler, hoist, interpreter, and engine paths while updating binding plan variants and adding query traversal helpers for dependency analysis
- document the new planner architecture and ship interpreter regressions that exercise nested destructuring, shadowing, and error reporting
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
Introduce a compiler pass that analyzes and pre-computes loop hoisting information
during policy compilation. This hoisted metadata is stored in lookup tables and made
available to downstream consumers:
- interpreter: use HoistedLoop entries during evaluation (replaces runtime scanning)
- type inference: can leverage pre-computed loop structure for type propagation
- RVM compiler: will consume hoisting metadata for optimized bytecode generation
Changes:
- populate loop hoisting tables during engine preparation and query snippet execution
- refactor eval_stmts_in_loop and eval_output_expr_in_loop to consume HoistedLoop directly
- add helper methods for accessing loop expressions, collections, and indices from HoistedLoop
- extend Lookup with get_checked and into_slots for safe query context access and merging
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
Major changes:
- Implement the `net.cidr_contains` builtin
- Enable the v0 and v1 test for `net.cidr_contains`
- Add the `netip` crate to standardize CIDR searching and other
operations
Key Concept:
- Allow users to leverage the `net.cidr_contains` builtin to check
whether an IPv4 or IPv6 CIDR contains a specified IP address or
subnet.
Testing:
- All tests passing.
Signed-off-by: tjons <tylerschade99@gmail.com>
Major Changes:
- Add generic Lookup<T> structure for efficient O(1) module-level data access
- Combine separate scope and order lookups into unified QuerySchedule structure
- Add query_schedule field to Interpreter for dedicated user query scheduling
- Refactor loop hoising to separate module
- Use efficient lookup for loop vars
- Also added more tests for loops
Key Concept:
- Ensure module context and indexing stay synchronized during function calls
Testing:
- All scheduler and interpreter tests passing
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
This commit introduces a complete multi-threaded evaluation benchmark suite for both Rust and C# implementations of Regorus.
- Implemented engine evaluation benchmark with input and engine cloning strategies
- Implemented compiled policy evaluation benchmark with input cloning and shared compiled policy strategies.
- Created EngineEvaluationBenchmark.cs and CompiledPolicyEvaluationBenchmark.cs with time-based execution (3s warmup + 3s evaluation)
- Implemented configuration options matching Rust implementation (useClonedEngines, useSharedPolicies parameters)
- Created markdown analysis documentation with cross-platform performance analysis
- C# seems to achieve 58-89% of Rust performance on test machine.
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
Details:
- Implement complete Type enum with 12 variants: Any, Integer, Number, Boolean,
Null, String, Array, Set, Object, Enum, Const, AnyOf
- Add Schema wrapper struct with reference counting for efficient sharing
- Support JSON Schema-compatible deserialization with serde
- Implement discriminated subobjects for polymorphic type definitions
- Add comprehensive test suite covering all type variants
- Include Azure resource schema examples (Storage, VM, Key Vault, App Service)
- Create meta-schema validation system with lazy static validator
- Add extensive edge case and corner case test coverage
- Implement custom deserializers for complex schema patterns
This establishes the foundation for type checking and validation of Rego
policies, particularly useful for cloud resource schemas and policy validation.
Regorus's type system is a first of many features intended to
enable type checking and various other constraints on Rego policies.
The type system is inspired from:
- JSON schema
- Bicep
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
The clone optimization PR didn't have the latest changes for "azure_policy".
Integration resulted in compile errors.
Also fix errors due to updated clippy lints.
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
Introduce the notion of CompiledPolicy to hold stuff that
remains immutable during evaluation - e.g. rules, function,
schedules etc
Cloning takes about 60 nano seconds for an engine loaded with
ACI policies. Earlier it used to take 40 microseconds.
Thus there is easily more than 100x speedup.
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
* fix: use early exit in 'some in' statements
Update kata tests:
Since 'early return' now works with 'some in' statement, interpreter
does not do any evaluation after it found match for rule, therefore
we don't have other rule checks after interpreter found match