Files
regorus/tests/rvm/vm/suites/serialization.yaml
Anand Krishnamoorthi 49bd3c22f3 feat!: add Rego Virtual Machine (RVM) implementation (#495)
* 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>
2025-11-14 11:43:19 -06:00

424 lines
12 KiB
YAML

# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
# Serialization Test Suite
# Tests round-trip serialization of compiled RVM programs
# Covers all instruction types, large programs, and edge cases
cases:
- note: serialization_basic_arithmetic
description: Serialize and deserialize simple arithmetic program
example_rego: "5 + 3"
literals:
- 5
- 3
instructions:
- "Load { dest: 0, literal_idx: 0 }"
- "Load { dest: 1, literal_idx: 1 }"
- "Add { dest: 2, left: 0, right: 1 }"
- "Return { value: 2 }"
want_result: 8
- note: serialization_comparisons
description: Serialize comparison instructions
example_rego: "10 > 5 && 3 < 7"
literals:
- 10
- 5
- 3
- 7
instructions:
- "Load { dest: 0, literal_idx: 0 }"
- "Load { dest: 1, literal_idx: 1 }"
- "Gt { dest: 2, left: 0, right: 1 }"
- "Load { dest: 3, literal_idx: 2 }"
- "Load { dest: 4, literal_idx: 3 }"
- "Lt { dest: 5, left: 3, right: 4 }"
- "And { dest: 6, left: 2, right: 5 }"
- "Return { value: 6 }"
want_result: true
- note: serialization_array_create
description: Serialize ArrayCreate with instruction_params
example_rego: "[1, 2, 3]"
literals:
- 1
- 2
- 3
instruction_params:
array_create_params:
- dest: 0
elements: [1, 2, 3]
instructions:
- "Load { dest: 1, literal_idx: 0 }"
- "Load { dest: 2, literal_idx: 1 }"
- "Load { dest: 3, literal_idx: 2 }"
- "ArrayCreate { params_index: 0 }"
- "Return { value: 0 }"
want_result: [1, 2, 3]
- note: serialization_object_create
description: Serialize ObjectCreate with complex params
example_rego: "{\"a\": 1, \"b\": 2}"
literals:
- "a"
- 1
- "b"
- 2
- {}
instruction_params:
object_create_params:
- dest: 0
template_literal_idx: 4
literal_key_fields: []
fields:
- [1, 2]
- [3, 4]
instructions:
- "Load { dest: 1, literal_idx: 0 }"
- "Load { dest: 2, literal_idx: 1 }"
- "Load { dest: 3, literal_idx: 2 }"
- "Load { dest: 4, literal_idx: 3 }"
- "ObjectCreate { params_index: 0 }"
- "Return { value: 0 }"
want_result: {"a": 1, "b": 2}
- note: serialization_set_operations
description: Serialize set creation and operations
example_rego: "{1, 2, 3}"
literals:
- 1
- 2
- 3
instructions:
- "SetNew { dest: 0 }"
- "Load { dest: 1, literal_idx: 0 }"
- "SetAdd { set: 0, value: 1 }"
- "Load { dest: 2, literal_idx: 1 }"
- "SetAdd { set: 0, value: 2 }"
- "Load { dest: 3, literal_idx: 2 }"
- "SetAdd { set: 0, value: 3 }"
- "Return { value: 0 }"
want_result:
set!:
- 1
- 2
- 3
- note: serialization_loop_foreach
description: Serialize ForEach loop with params
example_rego: "[x | x = [1, 2, 3][_]]"
literals:
- 1
- 2
- 3
instruction_params:
array_create_params:
- dest: 0
elements: [1, 2, 3]
loop_params:
- mode: "ForEach"
collection: 0
key_reg: 4
value_reg: 5
result_reg: 9
body_start: 6
loop_end: 8
instructions:
- "Load { dest: 1, literal_idx: 0 }"
- "Load { dest: 2, literal_idx: 1 }"
- "Load { dest: 3, literal_idx: 2 }"
- "ArrayCreate { params_index: 0 }"
- "ArrayNew { dest: 6 }"
- "LoopStart { params_index: 0 }"
- "ArrayPush { arr: 6, value: 5 }"
- "LoopNext { body_start: 6, loop_end: 8 }"
- "Return { value: 6 }"
want_result: [1, 2, 3]
- note: serialization_loop_any
description: Serialize Any loop
example_rego: "some x in [1, 2, 3]; x > 2"
literals:
- 1
- 2
- 3
instruction_params:
array_create_params:
- dest: 0
elements: [1, 2, 3]
loop_params:
- mode: "Existential"
collection: 0
key_reg: 4
value_reg: 5
result_reg: 6
body_start: 5
loop_end: 8
instructions:
- "Load { dest: 1, literal_idx: 0 }"
- "Load { dest: 2, literal_idx: 1 }"
- "Load { dest: 3, literal_idx: 2 }"
- "ArrayCreate { params_index: 0 }"
- "LoopStart { params_index: 0 }"
- "Gt { dest: 8, left: 5, right: 2 }"
- "AssertCondition { condition: 8 }"
- "LoopNext { body_start: 5, loop_end: 8 }"
- "Return { value: 6 }"
want_result: true
- note: serialization_comprehension_array
description: Serialize array comprehension
example_rego: "[x * 2 | x = [1, 2, 3][_]]"
literals:
- 1
- 2
- 3
instruction_params:
array_create_params:
- dest: 0
elements: [1, 2, 3]
loop_params:
- mode: "ForEach"
collection: 0
key_reg: 4
value_reg: 5
result_reg: 9
body_start: 6
loop_end: 9
instructions:
- "Load { dest: 1, literal_idx: 0 }"
- "Load { dest: 2, literal_idx: 1 }"
- "Load { dest: 3, literal_idx: 2 }"
- "ArrayCreate { params_index: 0 }"
- "ArrayNew { dest: 7 }"
- "LoopStart { params_index: 0 }"
- "Mul { dest: 6, left: 5, right: 2 }"
- "ArrayPush { arr: 7, value: 6 }"
- "LoopNext { body_start: 6, loop_end: 9 }"
- "Return { value: 7 }"
want_result: [2, 4, 6]
- note: serialization_indexed_access
description: Serialize indexing instructions
example_rego: "data.users[0].name"
literals:
- {"users": [{"name": "Alice"}, {"name": "Bob"}]}
- "users"
- 0
- "name"
instruction_params:
chained_index_params:
- dest: 4
root: 0
path_components:
- literal_idx: 1
- literal_idx: 2
- literal_idx: 3
instructions:
- "Load { dest: 0, literal_idx: 0 }"
- "Load { dest: 1, literal_idx: 1 }"
- "Load { dest: 2, literal_idx: 2 }"
- "Load { dest: 3, literal_idx: 3 }"
- "ChainedIndex { params_index: 0 }"
- "Return { value: 4 }"
want_result: "Alice"
- note: serialization_conditional_branching
description: Serialize conditional instructions
example_rego: "if true then 1 else 2"
literals:
- 1
- 2
instructions:
- "LoadTrue { dest: 0 }"
- "AssertCondition { condition: 0 }"
- "Load { dest: 1, literal_idx: 0 }"
- "Return { value: 1 }"
want_result: 1
- note: serialization_null_and_undefined
description: Serialize null and undefined handling
example_rego: "null"
literals: []
instructions:
- "LoadNull { dest: 0 }"
- "Return { value: 0 }"
want_result: null
- note: serialization_mixed_types
description: Serialize program with all value types
example_rego: "[1, \"text\", true, false, null, [2, 3], {\"k\": \"v\"}]"
literals:
- 1
- "text"
- 2
- 3
- "k"
- "v"
- {}
instruction_params:
array_create_params:
- dest: 6
elements: [3, 4]
- dest: 0
elements: [1, 2, 7, 8, 9, 6, 10]
object_create_params:
- dest: 10
template_literal_idx: 6
literal_key_fields: []
fields:
- [5, 11]
instructions:
- "Load { dest: 1, literal_idx: 0 }"
- "Load { dest: 2, literal_idx: 1 }"
- "Load { dest: 3, literal_idx: 2 }"
- "Load { dest: 4, literal_idx: 3 }"
- "ArrayCreate { params_index: 0 }"
- "LoadTrue { dest: 7 }"
- "LoadFalse { dest: 8 }"
- "LoadNull { dest: 9 }"
- "Load { dest: 5, literal_idx: 4 }"
- "Load { dest: 11, literal_idx: 5 }"
- "ObjectCreate { params_index: 0 }"
- "ArrayCreate { params_index: 1 }"
- "Return { value: 0 }"
want_result: [1, "text", true, false, null, [2, 3], {"k": "v"}]
- note: serialization_large_program_50_instructions
description: Large program with many instructions (stress test)
example_rego: "Complex computation chain"
literals:
- 1
- 2
- 3
- 4
- 5
instructions:
- "Load { dest: 0, literal_idx: 0 }"
- "Load { dest: 1, literal_idx: 1 }"
- "Add { dest: 2, left: 0, right: 1 }"
- "Load { dest: 3, literal_idx: 2 }"
- "Mul { dest: 4, left: 2, right: 3 }"
- "Load { dest: 5, literal_idx: 3 }"
- "Sub { dest: 6, left: 4, right: 5 }"
- "Load { dest: 7, literal_idx: 4 }"
- "Div { dest: 8, left: 6, right: 7 }"
- "Load { dest: 9, literal_idx: 0 }"
- "Add { dest: 10, left: 8, right: 9 }"
- "Load { dest: 11, literal_idx: 1 }"
- "Mul { dest: 12, left: 10, right: 11 }"
- "Load { dest: 13, literal_idx: 2 }"
- "Add { dest: 14, left: 12, right: 13 }"
- "Load { dest: 15, literal_idx: 3 }"
- "Sub { dest: 16, left: 14, right: 15 }"
- "Load { dest: 17, literal_idx: 4 }"
- "Mul { dest: 18, left: 16, right: 17 }"
- "Load { dest: 19, literal_idx: 0 }"
- "Div { dest: 20, left: 18, right: 19 }"
- "Load { dest: 21, literal_idx: 1 }"
- "Add { dest: 22, left: 20, right: 21 }"
- "Load { dest: 23, literal_idx: 2 }"
- "Mul { dest: 24, left: 22, right: 23 }"
- "Load { dest: 25, literal_idx: 3 }"
- "Sub { dest: 26, left: 24, right: 25 }"
- "Load { dest: 27, literal_idx: 4 }"
- "Add { dest: 28, left: 26, right: 27 }"
- "Load { dest: 29, literal_idx: 0 }"
- "Mul { dest: 30, left: 28, right: 29 }"
- "Load { dest: 31, literal_idx: 1 }"
- "Div { dest: 32, left: 30, right: 31 }"
- "Load { dest: 33, literal_idx: 2 }"
- "Add { dest: 34, left: 32, right: 33 }"
- "Load { dest: 35, literal_idx: 3 }"
- "Sub { dest: 36, left: 34, right: 35 }"
- "Load { dest: 37, literal_idx: 4 }"
- "Mul { dest: 38, left: 36, right: 37 }"
- "Load { dest: 39, literal_idx: 0 }"
- "Add { dest: 40, left: 38, right: 39 }"
- "Load { dest: 41, literal_idx: 1 }"
- "Sub { dest: 42, left: 40, right: 41 }"
- "Load { dest: 43, literal_idx: 2 }"
- "Mul { dest: 44, left: 42, right: 43 }"
- "Load { dest: 45, literal_idx: 3 }"
- "Div { dest: 46, left: 44, right: 45 }"
- "Load { dest: 47, literal_idx: 4 }"
- "Add { dest: 48, left: 46, right: 47 }"
- "Return { value: 48 }"
want_result: 98
- note: serialization_large_literal_table
description: Program with many literal values
literals:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- "a"
- "b"
- "c"
- "d"
- "e"
- [1, 2, 3]
- {"key": "value"}
- true
- false
- null
instructions:
- "Load { dest: 0, literal_idx: 0 }"
- "Load { dest: 1, literal_idx: 5 }"
- "Add { dest: 2, left: 0, right: 1 }"
- "Load { dest: 3, literal_idx: 10 }"
- "Load { dest: 4, literal_idx: 15 }"
- "Return { value: 2 }"
want_result: 7
- note: serialization_nested_structures
description: Serialize deeply nested data structures
example_rego: "[{\"a\": [1, {\"b\": [2, 3]}]}]"
literals:
- 1
- 2
- 3
- "b"
- "a"
- {}
instruction_params:
array_create_params:
- dest: 3
elements: [2, 4]
- dest: 1
elements: [5, 6]
- dest: 0
elements: [7]
object_create_params:
- dest: 6
template_literal_idx: 5
literal_key_fields: []
fields:
- [8, 3]
- dest: 7
template_literal_idx: 5
literal_key_fields: []
fields:
- [9, 1]
instructions:
- "Load { dest: 5, literal_idx: 0 }"
- "Load { dest: 2, literal_idx: 1 }"
- "Load { dest: 4, literal_idx: 2 }"
- "ArrayCreate { params_index: 0 }"
- "Load { dest: 8, literal_idx: 3 }"
- "ObjectCreate { params_index: 0 }"
- "ArrayCreate { params_index: 1 }"
- "Load { dest: 9, literal_idx: 4 }"
- "ObjectCreate { params_index: 1 }"
- "ArrayCreate { params_index: 2 }"
- "Return { value: 0 }"
want_result: [{"a": [1, {"b": [2, 3]}]}]