ruso_runtime/runtime/bytecode.rs
1//! Executable bytecode produced from the script AST.
2
3use crate::contract::{EvidenceKind, ExtractSource, QualifiedMatch};
4use crate::runtime::spec::ProgramSpec;
5
6/// Compiled script ready for the executor (probes, metadata, and instruction stream).
7#[derive(Debug, Clone)]
8pub struct BytecodeProgram {
9 /// Probe table and finding metadata (the non-executable part).
10 pub spec: ProgramSpec,
11 /// The instruction stream the executor walks.
12 pub code: Vec<Instr>,
13 /// String pool. Instruction operands index into this.
14 pub strings: Vec<String>,
15 /// Binary payloads referenced by `Send.payload` (override bytes).
16 pub payloads: Vec<Vec<u8>>,
17 /// Matcher pool, indexed by `Match`/`Assert`/`IfMatch` operands.
18 pub matchers: Vec<QualifiedMatch>,
19 /// Extract-rule pool, indexed by `Extract` operands.
20 pub extracts: Vec<ExtractSource>,
21 /// Evidence-rule pool, indexed by `Evidence` operands.
22 pub evidence: Vec<EvidenceKind>,
23}
24
25/// Instruction pointer index into `BytecodeProgram::code`.
26pub type Pc = u32;
27
28/// A single VM instruction. Operands are `u32`/`u16` indices into the
29/// program's pools (`strings`, `matchers`, `extracts`, `evidence`) or program
30/// counters ([`Pc`]) into `code` — never inline data.
31#[derive(Debug, Clone, PartialEq)]
32pub enum Instr {
33 /// Set a string variable: `name` and `value` index the string pool.
34 Set {
35 /// String-pool index of the variable name.
36 name: u32,
37 /// String-pool index of the value.
38 value: u32,
39 },
40 /// Set a list variable from `len` consecutive strings starting at `start`.
41 SetList {
42 /// String-pool index of the variable name.
43 name: u32,
44 /// String-pool index of the first element.
45 start: u32,
46 /// Number of elements.
47 len: u16,
48 },
49 /// Perform a probe's request. `payload`, if set, overrides the probe's
50 /// payload (string-pool or payload-pool index, per probe kind).
51 Send {
52 /// String-pool index of the probe name.
53 probe: u32,
54 /// Optional payload-override index.
55 payload: Option<u32>,
56 },
57 /// Evaluate one matcher (matcher-pool index); on failure, latch the match
58 /// chain false.
59 Match(u32),
60 /// Evaluate `len` matchers starting at `start`; all must pass.
61 MatchAll {
62 /// Matcher-pool index of the first matcher.
63 start: u32,
64 /// Number of matchers.
65 len: u16,
66 },
67 /// Evaluate `len` matchers starting at `start`; any one passing succeeds.
68 MatchAny {
69 /// Matcher-pool index of the first matcher.
70 start: u32,
71 /// Number of matchers.
72 len: u16,
73 },
74 /// Like `Match`, but a failure aborts the run with an error.
75 Assert(u32),
76 /// Extract a value into a variable. `name` is a string-pool index; `source`
77 /// indexes the extract pool.
78 Extract {
79 /// String-pool index of the destination variable name.
80 name: u32,
81 /// Extract-pool index of the source rule.
82 source: u32,
83 },
84 /// If the matcher holds, fall through; otherwise jump to `else_pc`.
85 IfMatch {
86 /// Matcher-pool index of the condition.
87 matcher: u32,
88 /// Program counter to jump to when the condition is false.
89 else_pc: Pc,
90 },
91 /// Begin a `for` over a literal list (`len` strings from `start`), binding
92 /// each to `item`. `end_pc` is the instruction after the loop.
93 ForList {
94 /// String-pool index of the loop variable name.
95 item: u32,
96 /// String-pool index of the first value.
97 start: u32,
98 /// Number of values.
99 len: u16,
100 /// Program counter just past the loop.
101 end_pc: Pc,
102 },
103 /// Begin a `for` over a list variable (`list`), binding each to `item`.
104 ForVar {
105 /// String-pool index of the loop variable name.
106 item: u32,
107 /// String-pool index of the list variable name.
108 list: u32,
109 /// Program counter just past the loop.
110 end_pc: Pc,
111 },
112 /// End-of-loop-body marker: advance the loop or exit it.
113 LoopBack,
114 /// Exit the innermost loop.
115 Break,
116 /// Snapshot a probe's response under another name (`from`/`to` index the
117 /// string pool).
118 Save {
119 /// String-pool index of the source probe name.
120 from: u32,
121 /// String-pool index of the destination name.
122 to: u32,
123 },
124 /// Attach evidence (evidence-pool index) when the match chain is true.
125 Evidence(u32),
126 /// Re-send a probe up to `count` times, stopping on first success.
127 Retry {
128 /// String-pool index of the probe name.
129 probe: u32,
130 /// Maximum attempts.
131 count: u32,
132 },
133 /// Set the delay between `Retry` attempts (string-pool index of a duration).
134 RetryDelay(u32),
135 /// Sleep for a duration (string-pool index of a duration literal).
136 Sleep(u32),
137 /// Stop the run, emitting no finding.
138 Stop,
139 /// Abort the run with an error.
140 Fail,
141 /// Skip to the next iteration of the innermost loop.
142 Continue,
143 /// Stop the run, emitting the finding if the match chain held.
144 Exit,
145}
146
147impl BytecodeProgram {
148 /// Number of instructions in the program's `code` stream.
149 pub fn instr_count(&self) -> usize {
150 self.code.len()
151 }
152}