regorus/rvm/instructions/
params.rs1use alloc::vec::Vec;
4use serde::{Deserialize, Serialize};
5
6use super::types::{ComprehensionMode, LiteralOrRegister, LoopMode};
7
8#[repr(C)]
10#[derive(Debug, Clone, Serialize, Deserialize)]
11pub struct LoopStartParams {
12 pub mode: LoopMode,
14 pub collection: u8,
16 pub key_reg: u8,
18 pub value_reg: u8,
20 pub result_reg: u8,
22 pub body_start: u16,
24 pub loop_end: u16,
26}
27
28#[repr(C)]
30#[derive(Debug, Clone, Serialize, Deserialize)]
31pub struct BuiltinCallParams {
32 pub dest: u8,
34 pub builtin_index: u16,
36 pub num_args: u8,
38 pub args: [u8; 8],
40}
41
42impl BuiltinCallParams {
43 pub fn arg_count(&self) -> usize {
45 usize::from(self.num_args)
46 }
47
48 pub fn arg_registers(&self) -> &[u8] {
50 let count = usize::from(self.num_args).min(self.args.len());
51 self.args.get(..count).unwrap_or(&[])
52 }
53}
54
55#[repr(C)]
57#[derive(Debug, Clone, Serialize, Deserialize)]
58pub struct FunctionCallParams {
59 pub dest: u8,
61 pub func_rule_index: u16,
63 pub num_args: u8,
65 pub args: [u8; 8],
67}
68
69impl FunctionCallParams {
70 pub fn arg_count(&self) -> usize {
72 usize::from(self.num_args)
73 }
74
75 pub fn arg_registers(&self) -> &[u8] {
77 let count = usize::from(self.num_args).min(self.args.len());
78 self.args.get(..count).unwrap_or(&[])
79 }
80}
81
82#[repr(C)]
84#[derive(Debug, Clone, Serialize, Deserialize)]
85pub struct ObjectCreateParams {
86 pub dest: u8,
88 pub template_literal_idx: u16,
91 pub literal_key_fields: Vec<(u16, u8)>,
93 pub fields: Vec<(u8, u8)>,
95}
96
97impl ObjectCreateParams {
98 pub const fn field_count(&self) -> usize {
100 self.literal_key_fields
101 .len()
102 .saturating_add(self.fields.len())
103 }
104
105 pub fn literal_key_field_pairs(&self) -> &[(u16, u8)] {
107 &self.literal_key_fields
108 }
109
110 pub fn field_pairs(&self) -> &[(u8, u8)] {
112 &self.fields
113 }
114}
115
116#[repr(C)]
118#[derive(Debug, Clone, Serialize, Deserialize)]
119pub struct ArrayCreateParams {
120 pub dest: u8,
122 pub elements: Vec<u8>,
124}
125
126impl ArrayCreateParams {
127 pub const fn element_count(&self) -> usize {
129 self.elements.len()
130 }
131
132 pub fn element_registers(&self) -> &[u8] {
134 &self.elements
135 }
136}
137
138#[repr(C)]
140#[derive(Debug, Clone, Serialize, Deserialize)]
141pub struct SetCreateParams {
142 pub dest: u8,
144 pub elements: Vec<u8>,
146}
147
148impl SetCreateParams {
149 pub const fn element_count(&self) -> usize {
151 self.elements.len()
152 }
153
154 pub fn element_registers(&self) -> &[u8] {
156 &self.elements
157 }
158}
159
160#[repr(C)]
162#[derive(Debug, Clone, Serialize, Deserialize)]
163pub struct VirtualDataDocumentLookupParams {
164 pub dest: u8,
166 pub path_components: Vec<LiteralOrRegister>,
170}
171
172impl VirtualDataDocumentLookupParams {
173 pub const fn component_count(&self) -> usize {
175 self.path_components.len()
176 }
177
178 pub fn all_literals(&self) -> bool {
180 self.path_components
181 .iter()
182 .all(|c| matches!(c, LiteralOrRegister::Literal(_)))
183 }
184
185 pub fn literal_indices(&self) -> Vec<u16> {
187 self.path_components
188 .iter()
189 .filter_map(|c| match *c {
190 LiteralOrRegister::Literal(idx) => Some(idx),
191 _ => None,
192 })
193 .collect()
194 }
195
196 pub fn register_numbers(&self) -> Vec<u8> {
198 self.path_components
199 .iter()
200 .filter_map(|c| match *c {
201 LiteralOrRegister::Register(reg) => Some(reg),
202 _ => None,
203 })
204 .collect()
205 }
206}
207
208#[repr(C)]
210#[derive(Debug, Clone, Serialize, Deserialize)]
211pub struct ChainedIndexParams {
212 pub dest: u8,
214 pub root: u8,
216 pub path_components: Vec<LiteralOrRegister>,
218}
219
220impl ChainedIndexParams {
221 pub const fn component_count(&self) -> usize {
223 self.path_components.len()
224 }
225
226 pub fn all_literals(&self) -> bool {
228 self.path_components
229 .iter()
230 .all(|c| matches!(c, LiteralOrRegister::Literal(_)))
231 }
232
233 pub fn literal_indices(&self) -> Vec<u16> {
235 self.path_components
236 .iter()
237 .filter_map(|c| match *c {
238 LiteralOrRegister::Literal(idx) => Some(idx),
239 _ => None,
240 })
241 .collect()
242 }
243
244 pub fn register_numbers(&self) -> Vec<u8> {
246 self.path_components
247 .iter()
248 .filter_map(|c| match *c {
249 LiteralOrRegister::Register(reg) => Some(reg),
250 _ => None,
251 })
252 .collect()
253 }
254}
255
256#[repr(C)]
258#[derive(Debug, Clone, Serialize, Deserialize)]
259pub struct ComprehensionBeginParams {
260 pub mode: ComprehensionMode,
262 pub collection_reg: u8,
264 pub result_reg: u8,
267 pub key_reg: u8,
269 pub value_reg: u8,
271 pub body_start: u16,
273 pub comprehension_end: u16,
275}
276
277#[derive(Debug, Clone, Serialize, Deserialize)]
279pub struct InstructionData {
280 pub loop_params: Vec<LoopStartParams>,
282 pub builtin_call_params: Vec<BuiltinCallParams>,
284 pub function_call_params: Vec<FunctionCallParams>,
286 pub object_create_params: Vec<ObjectCreateParams>,
288 pub array_create_params: Vec<ArrayCreateParams>,
290 pub set_create_params: Vec<SetCreateParams>,
292 pub virtual_data_document_lookup_params: Vec<VirtualDataDocumentLookupParams>,
294 pub chained_index_params: Vec<ChainedIndexParams>,
296 pub comprehension_begin_params: Vec<ComprehensionBeginParams>,
298}
299
300impl InstructionData {
301 fn ensure_u16_index(len: usize) -> u16 {
302 debug_assert!(len <= usize::from(u16::MAX));
303 u16::try_from(len).unwrap_or(u16::MAX)
304 }
305
306 pub const fn new() -> Self {
308 Self {
309 loop_params: Vec::new(),
310 builtin_call_params: Vec::new(),
311 function_call_params: Vec::new(),
312 object_create_params: Vec::new(),
313 array_create_params: Vec::new(),
314 set_create_params: Vec::new(),
315 virtual_data_document_lookup_params: Vec::new(),
316 chained_index_params: Vec::new(),
317 comprehension_begin_params: Vec::new(),
318 }
319 }
320
321 pub fn add_loop_params(&mut self, params: LoopStartParams) -> u16 {
323 let index = Self::ensure_u16_index(self.loop_params.len());
324 self.loop_params.push(params);
325 index
326 }
327
328 pub fn add_builtin_call_params(&mut self, params: BuiltinCallParams) -> u16 {
330 let index = Self::ensure_u16_index(self.builtin_call_params.len());
331 self.builtin_call_params.push(params);
332 index
333 }
334
335 pub fn add_function_call_params(&mut self, params: FunctionCallParams) -> u16 {
337 let index = Self::ensure_u16_index(self.function_call_params.len());
338 self.function_call_params.push(params);
339 index
340 }
341
342 pub fn add_object_create_params(&mut self, params: ObjectCreateParams) -> u16 {
344 let index = Self::ensure_u16_index(self.object_create_params.len());
345 self.object_create_params.push(params);
346 index
347 }
348
349 pub fn add_array_create_params(&mut self, params: ArrayCreateParams) -> u16 {
351 let index = Self::ensure_u16_index(self.array_create_params.len());
352 self.array_create_params.push(params);
353 index
354 }
355
356 pub fn add_set_create_params(&mut self, params: SetCreateParams) -> u16 {
358 let index = Self::ensure_u16_index(self.set_create_params.len());
359 self.set_create_params.push(params);
360 index
361 }
362
363 pub fn get_loop_params(&self, index: u16) -> Option<&LoopStartParams> {
365 self.loop_params.get(usize::from(index))
366 }
367
368 pub fn get_builtin_call_params(&self, index: u16) -> Option<&BuiltinCallParams> {
370 self.builtin_call_params.get(usize::from(index))
371 }
372
373 pub fn get_function_call_params(&self, index: u16) -> Option<&FunctionCallParams> {
375 self.function_call_params.get(usize::from(index))
376 }
377
378 pub fn get_object_create_params(&self, index: u16) -> Option<&ObjectCreateParams> {
380 self.object_create_params.get(usize::from(index))
381 }
382
383 pub fn get_array_create_params(&self, index: u16) -> Option<&ArrayCreateParams> {
385 self.array_create_params.get(usize::from(index))
386 }
387
388 pub fn get_set_create_params(&self, index: u16) -> Option<&SetCreateParams> {
390 self.set_create_params.get(usize::from(index))
391 }
392
393 pub fn add_virtual_data_document_lookup_params(
395 &mut self,
396 params: VirtualDataDocumentLookupParams,
397 ) -> u16 {
398 let index = Self::ensure_u16_index(self.virtual_data_document_lookup_params.len());
399 self.virtual_data_document_lookup_params.push(params);
400 index
401 }
402
403 pub fn get_virtual_data_document_lookup_params(
405 &self,
406 index: u16,
407 ) -> Option<&VirtualDataDocumentLookupParams> {
408 self.virtual_data_document_lookup_params
409 .get(usize::from(index))
410 }
411
412 pub fn add_chained_index_params(&mut self, params: ChainedIndexParams) -> u16 {
414 let index = Self::ensure_u16_index(self.chained_index_params.len());
415 self.chained_index_params.push(params);
416 index
417 }
418
419 pub fn get_chained_index_params(&self, index: u16) -> Option<&ChainedIndexParams> {
421 self.chained_index_params.get(usize::from(index))
422 }
423
424 pub fn get_loop_params_mut(&mut self, index: u16) -> Option<&mut LoopStartParams> {
426 self.loop_params.get_mut(usize::from(index))
427 }
428
429 pub fn add_comprehension_begin_params(&mut self, params: ComprehensionBeginParams) -> u16 {
431 let index = Self::ensure_u16_index(self.comprehension_begin_params.len());
432 self.comprehension_begin_params.push(params);
433 index
434 }
435
436 pub fn get_comprehension_begin_params(&self, index: u16) -> Option<&ComprehensionBeginParams> {
438 self.comprehension_begin_params.get(usize::from(index))
439 }
440
441 pub fn get_comprehension_begin_params_mut(
443 &mut self,
444 index: u16,
445 ) -> Option<&mut ComprehensionBeginParams> {
446 self.comprehension_begin_params.get_mut(usize::from(index))
447 }
448}
449
450impl Default for InstructionData {
451 fn default() -> Self {
452 Self::new()
453 }
454}