Skip to main content

shape_vm/bytecode/
opcode_defs.rs

1//! Bytecode instruction set for Shape VM
2
3use serde::{Deserialize, Serialize};
4
5/// Re-export `StringId` from `shape-value` — the canonical definition.
6pub use shape_value::StringId;
7
8/// Opcode category for classification and tooling.
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub enum OpcodeCategory {
11    Stack,
12    Arithmetic,
13    Comparison,
14    Logical,
15    Control,
16    Variable,
17    Object,
18    Loop,
19    Builtin,
20    Exception,
21    DataFrame,
22    Async,
23    Trait,
24    Special,
25}
26
27/// Macro to define the OpCode enum with metadata (category, stack effects).
28///
29/// Generates:
30/// - `OpCode` enum with `#[repr(u8)]` and explicit byte values
31/// - `OpCode::category()` returning `OpcodeCategory`
32/// - `OpCode::stack_pops()` and `OpCode::stack_pushes()` returning `u8`
33///
34/// For opcodes with variable stack effects (Call, CallMethod, NewArray, etc.),
35/// use 0/0 since the actual effect depends on runtime arity.
36macro_rules! define_opcodes {
37    ($($(#[doc = $doc:expr])* $name:ident = $byte:literal, $cat:ident, pops: $pops:expr, pushes: $pushes:expr);* $(;)?) => {
38        #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
39        #[repr(u8)]
40        pub enum OpCode {
41            $(
42                $(#[doc = $doc])*
43                $name = $byte,
44            )*
45        }
46
47        impl OpCode {
48            /// Returns the category this opcode belongs to.
49            pub const fn category(self) -> OpcodeCategory {
50                match self {
51                    $( OpCode::$name => OpcodeCategory::$cat, )*
52                }
53            }
54
55            /// Returns the number of values this opcode pops from the stack.
56            /// Returns 0 for variable-arity opcodes (Call, CallMethod, NewArray, etc.).
57            pub const fn stack_pops(self) -> u8 {
58                match self {
59                    $( OpCode::$name => $pops, )*
60                }
61            }
62
63            /// Returns the number of values this opcode pushes onto the stack.
64            /// Returns 0 for variable-arity opcodes.
65            pub const fn stack_pushes(self) -> u8 {
66                match self {
67                    $( OpCode::$name => $pushes, )*
68                }
69            }
70        }
71    };
72}
73
74define_opcodes! {
75    // ===== Stack Operations =====
76    /// Push a constant onto the stack
77    PushConst = 0x00, Stack, pops: 0, pushes: 1;
78    /// Push null onto the stack
79    PushNull = 0x01, Stack, pops: 0, pushes: 1;
80    /// Pop value from stack
81    Pop = 0x02, Stack, pops: 1, pushes: 0;
82    /// Duplicate top of stack
83    Dup = 0x03, Stack, pops: 1, pushes: 2;
84    /// Swap top two values
85    Swap = 0x04, Stack, pops: 2, pushes: 2;
86
87    // ===== Arithmetic Operations =====
88    /// Add two numbers
89    Add = 0x10, Arithmetic, pops: 2, pushes: 1;
90    /// Subtract two numbers
91    Sub = 0x11, Arithmetic, pops: 2, pushes: 1;
92    /// Multiply two numbers
93    Mul = 0x12, Arithmetic, pops: 2, pushes: 1;
94    /// Divide two numbers
95    Div = 0x13, Arithmetic, pops: 2, pushes: 1;
96    /// Modulo operation
97    Mod = 0x14, Arithmetic, pops: 2, pushes: 1;
98    /// Negate number
99    Neg = 0x15, Arithmetic, pops: 1, pushes: 1;
100    /// Power operation
101    Pow = 0x16, Arithmetic, pops: 2, pushes: 1;
102    /// Bitwise AND
103    BitAnd = 0x17, Arithmetic, pops: 2, pushes: 1;
104    /// Bitwise OR
105    BitOr = 0x18, Arithmetic, pops: 2, pushes: 1;
106    /// Bitwise shift left
107    BitShl = 0x19, Arithmetic, pops: 2, pushes: 1;
108    /// Bitwise shift right
109    BitShr = 0x1A, Arithmetic, pops: 2, pushes: 1;
110    /// Bitwise NOT
111    BitNot = 0x1B, Arithmetic, pops: 1, pushes: 1;
112    /// Bitwise XOR
113    BitXor = 0x1C, Arithmetic, pops: 2, pushes: 1;
114
115    // ===== Comparison Operations =====
116    /// Greater than
117    Gt = 0x20, Comparison, pops: 2, pushes: 1;
118    /// Less than
119    Lt = 0x21, Comparison, pops: 2, pushes: 1;
120    /// Greater than or equal
121    Gte = 0x22, Comparison, pops: 2, pushes: 1;
122    /// Less than or equal
123    Lte = 0x23, Comparison, pops: 2, pushes: 1;
124    /// Equal
125    Eq = 0x24, Comparison, pops: 2, pushes: 1;
126    /// Not equal
127    Neq = 0x25, Comparison, pops: 2, pushes: 1;
128
129    // ===== Typed Comparison Operations (compiler-guaranteed types, zero dispatch) =====
130    /// Greater than (int × int → bool)
131    GtInt = 0x26, Comparison, pops: 2, pushes: 1;
132    /// Greater than (f64 × f64 → bool)
133    GtNumber = 0x27, Comparison, pops: 2, pushes: 1;
134    /// Greater than (decimal × decimal → bool)
135    GtDecimal = 0x28, Comparison, pops: 2, pushes: 1;
136    /// Less than (int × int → bool)
137    LtInt = 0x29, Comparison, pops: 2, pushes: 1;
138    /// Less than (f64 × f64 → bool)
139    LtNumber = 0x2A, Comparison, pops: 2, pushes: 1;
140    /// Less than (decimal × decimal → bool)
141    LtDecimal = 0x2B, Comparison, pops: 2, pushes: 1;
142    /// Greater than or equal (int × int → bool)
143    GteInt = 0x2C, Comparison, pops: 2, pushes: 1;
144    /// Greater than or equal (f64 × f64 → bool)
145    GteNumber = 0x2D, Comparison, pops: 2, pushes: 1;
146    /// Greater than or equal (decimal × decimal → bool)
147    GteDecimal = 0x2E, Comparison, pops: 2, pushes: 1;
148    /// Less than or equal (int × int → bool)
149    LteInt = 0x2F, Comparison, pops: 2, pushes: 1;
150
151    // ===== Logical Operations =====
152    /// Logical AND
153    And = 0x30, Logical, pops: 2, pushes: 1;
154    /// Logical OR
155    Or = 0x31, Logical, pops: 2, pushes: 1;
156    /// Logical NOT
157    Not = 0x32, Logical, pops: 1, pushes: 1;
158
159    // ===== Typed Arithmetic Operations (compiler-guaranteed types, zero dispatch) =====
160    /// Add (int × int → int)
161    AddInt = 0x33, Arithmetic, pops: 2, pushes: 1;
162    /// Add (f64 × f64 → f64)
163    AddNumber = 0x34, Arithmetic, pops: 2, pushes: 1;
164    /// Add (decimal × decimal → decimal)
165    AddDecimal = 0x35, Arithmetic, pops: 2, pushes: 1;
166    /// Subtract (int × int → int)
167    SubInt = 0x36, Arithmetic, pops: 2, pushes: 1;
168    /// Subtract (f64 × f64 → f64)
169    SubNumber = 0x37, Arithmetic, pops: 2, pushes: 1;
170    /// Subtract (decimal × decimal → decimal)
171    SubDecimal = 0x38, Arithmetic, pops: 2, pushes: 1;
172    /// Multiply (int × int → int)
173    MulInt = 0x39, Arithmetic, pops: 2, pushes: 1;
174    /// Multiply (f64 × f64 → f64)
175    MulNumber = 0x3A, Arithmetic, pops: 2, pushes: 1;
176    /// Multiply (decimal × decimal → decimal)
177    MulDecimal = 0x3B, Arithmetic, pops: 2, pushes: 1;
178    /// Divide (int × int → int)
179    DivInt = 0x3C, Arithmetic, pops: 2, pushes: 1;
180    /// Divide (f64 × f64 → f64)
181    DivNumber = 0x3D, Arithmetic, pops: 2, pushes: 1;
182    /// Divide (decimal × decimal → decimal)
183    DivDecimal = 0x3E, Arithmetic, pops: 2, pushes: 1;
184    /// Modulo (int × int → int)
185    ModInt = 0x3F, Arithmetic, pops: 2, pushes: 1;
186
187    // ===== Control Flow =====
188    /// Unconditional jump
189    Jump = 0x40, Control, pops: 0, pushes: 0;
190    /// Jump if false (pop condition)
191    JumpIfFalse = 0x41, Control, pops: 1, pushes: 0;
192    /// Jump if true (pop condition)
193    JumpIfTrue = 0x42, Control, pops: 1, pushes: 0;
194    /// Function call
195    Call = 0x43, Control, pops: 0, pushes: 0;
196    /// Return from function
197    Return = 0x44, Control, pops: 0, pushes: 0;
198    /// Return with value
199    ReturnValue = 0x45, Control, pops: 1, pushes: 0;
200    /// Call a value (function/closure) from the stack
201    CallValue = 0x46, Control, pops: 0, pushes: 0;
202
203    // ===== Variable Operations =====
204    /// Load local variable
205    LoadLocal = 0x50, Variable, pops: 0, pushes: 1;
206    /// Store local variable
207    StoreLocal = 0x51, Variable, pops: 1, pushes: 0;
208    /// Load module_binding variable
209    LoadModuleBinding = 0x52, Variable, pops: 0, pushes: 1;
210    /// Store module_binding variable
211    StoreModuleBinding = 0x53, Variable, pops: 1, pushes: 0;
212    /// Load from closure upvalue
213    LoadClosure = 0x54, Variable, pops: 0, pushes: 1;
214    /// Store to closure upvalue
215    StoreClosure = 0x55, Variable, pops: 1, pushes: 0;
216    /// Create a closure with captured upvalues
217    MakeClosure = 0x56, Variable, pops: 0, pushes: 1;
218    /// Close upvalue - moves stack local to heap when leaving scope
219    CloseUpvalue = 0x57, Variable, pops: 0, pushes: 0;
220    /// Create a reference to a local variable's stack slot
221    MakeRef = 0x58, Variable, pops: 0, pushes: 1;
222    /// Load the value that a reference points to
223    DerefLoad = 0x59, Variable, pops: 0, pushes: 1;
224    /// Store a value through a reference
225    DerefStore = 0x5A, Variable, pops: 1, pushes: 0;
226    /// Set an index on the array that a reference points to (in-place mutation)
227    SetIndexRef = 0x5B, Variable, pops: 2, pushes: 0;
228    /// Box a local variable into a SharedCell for mutable closure capture.
229    /// Converts the local slot to a SharedCell (if not already one), then pushes
230    /// the SharedCell ValueWord onto the stack for MakeClosure to consume.
231    BoxLocal = 0x5C, Variable, pops: 0, pushes: 1;
232    /// Box a module binding into a SharedCell for mutable closure capture.
233    /// Same as BoxLocal but operates on the module_bindings vector.
234    BoxModuleBinding = 0x5D, Variable, pops: 0, pushes: 1;
235
236    // ===== Object/Array Operations =====
237    /// Create new array
238    NewArray = 0x60, Object, pops: 0, pushes: 1;
239    /// Create new object
240    NewObject = 0x61, Object, pops: 0, pushes: 1;
241    /// Get property/index
242    GetProp = 0x62, Object, pops: 2, pushes: 1;
243    /// Set property/index
244    SetProp = 0x63, Object, pops: 3, pushes: 0;
245    /// Get array/object length
246    Length = 0x64, Object, pops: 1, pushes: 1;
247    /// Push value to array
248    ArrayPush = 0x65, Object, pops: 2, pushes: 0;
249    /// Pop value from array
250    ArrayPop = 0x66, Object, pops: 1, pushes: 1;
251    /// Merge object fields from stack into another object
252    MergeObject = 0x67, Object, pops: 2, pushes: 1;
253    /// Set index on a local array without loading/cloning through the stack
254    SetLocalIndex = 0x68, Object, pops: 2, pushes: 0;
255    /// Set index on a module_binding array without loading/cloning through the stack
256    SetModuleBindingIndex = 0x69, Object, pops: 2, pushes: 0;
257    /// Push value to array stored in a local variable, mutating in-place
258    ArrayPushLocal = 0x6A, Object, pops: 1, pushes: 0;
259    /// Create a new Matrix from rows*cols f64 values on the stack
260    NewMatrix = 0x6B, Object, pops: 0, pushes: 1;
261    /// Create a typed array (IntArray/FloatArray/BoolArray) from N homogeneous elements
262    /// Operand: Count(n) — number of elements to pop
263    /// At runtime, inspects element types and packs into the appropriate typed array
264    NewTypedArray = 0x6C, Object, pops: 0, pushes: 1;
265
266    // ===== Loop Operations =====
267    /// Start of loop (for break/continue)
268    LoopStart = 0x70, Loop, pops: 0, pushes: 0;
269    /// End of loop
270    LoopEnd = 0x71, Loop, pops: 0, pushes: 0;
271    /// Break from loop
272    Break = 0x72, Loop, pops: 0, pushes: 0;
273    /// Continue to next iteration
274    Continue = 0x73, Loop, pops: 0, pushes: 0;
275    /// Iterator next
276    IterNext = 0x74, Loop, pops: 1, pushes: 1;
277    /// Check if iterator done
278    IterDone = 0x75, Loop, pops: 1, pushes: 1;
279
280    // ===== Pattern and Comparison Operations =====
281    /// Pattern match (generic pattern matching, not domain-specific)
282    Pattern = 0x83, Builtin, pops: 0, pushes: 0;
283    /// Call method on value (series.mean(), etc.)
284    CallMethod = 0x88, Builtin, pops: 0, pushes: 0;
285    /// Push timeframe context
286    PushTimeframe = 0x89, Builtin, pops: 1, pushes: 0;
287    /// Pop timeframe context
288    PopTimeframe = 0x8A, Builtin, pops: 0, pushes: 0;
289    /// Execute simulation with config object on stack (generic state simulation)
290    RunSimulation = 0x8B, Builtin, pops: 0, pushes: 0;
291
292    // ===== Built-in Functions =====
293    /// Call built-in function
294    BuiltinCall = 0x90, Builtin, pops: 0, pushes: 0;
295    /// Type check
296    TypeCheck = 0x91, Builtin, pops: 1, pushes: 1;
297    /// Convert type
298    Convert = 0x92, Builtin, pops: 1, pushes: 1;
299
300    // ===== Typed Arithmetic (continued from 0x3F) =====
301    /// Modulo (f64 × f64 → f64)
302    ModNumber = 0x93, Arithmetic, pops: 2, pushes: 1;
303    /// Modulo (decimal × decimal → decimal)
304    ModDecimal = 0x94, Arithmetic, pops: 2, pushes: 1;
305    /// Power (int × int → int)
306    PowInt = 0x95, Arithmetic, pops: 2, pushes: 1;
307    /// Power (f64 × f64 → f64)
308    PowNumber = 0x96, Arithmetic, pops: 2, pushes: 1;
309    /// Power (decimal × decimal → decimal)
310    PowDecimal = 0x97, Arithmetic, pops: 2, pushes: 1;
311
312    // ===== Typed Comparison (continued from 0x2F) =====
313    /// Less than or equal (f64 × f64 → bool)
314    LteNumber = 0x98, Comparison, pops: 2, pushes: 1;
315    /// Less than or equal (decimal × decimal → bool)
316    LteDecimal = 0x99, Comparison, pops: 2, pushes: 1;
317    /// Equal (int × int → bool)
318    EqInt = 0x9A, Comparison, pops: 2, pushes: 1;
319    /// Equal (f64 × f64 → bool)
320    EqNumber = 0x9B, Comparison, pops: 2, pushes: 1;
321    /// Not equal (int × int → bool)
322    NeqInt = 0x9C, Comparison, pops: 2, pushes: 1;
323    /// Not equal (f64 × f64 → bool)
324    NeqNumber = 0x9D, Comparison, pops: 2, pushes: 1;
325
326    // ===== Exception Handling =====
327    /// Set up try/catch block (operand: offset to catch handler)
328    SetupTry = 0xA0, Exception, pops: 0, pushes: 0;
329    /// Pop exception handler (successful try block completion)
330    PopHandler = 0xA1, Exception, pops: 0, pushes: 0;
331    /// Throw an exception (push error value first)
332    Throw = 0xA2, Exception, pops: 1, pushes: 0;
333    /// Try operator: unified Result/Option propagation with early return on Err/None
334    TryUnwrap = 0xA3, Exception, pops: 1, pushes: 1;
335    /// Unwrap Option: extract inner value from Some, panic on None
336    UnwrapOption = 0xA4, Exception, pops: 1, pushes: 1;
337    /// Add context to Result/Option failures and lift success into Result
338    ErrorContext = 0xA5, Exception, pops: 1, pushes: 1;
339    /// Check whether Result is Ok(value)
340    IsOk = 0xA6, Exception, pops: 1, pushes: 1;
341    /// Check whether Result is Err(error)
342    IsErr = 0xA7, Exception, pops: 1, pushes: 1;
343    /// Extract inner payload from Ok(value)
344    UnwrapOk = 0xA8, Exception, pops: 1, pushes: 1;
345    /// Extract inner payload from Err(error)
346    UnwrapErr = 0xA9, Exception, pops: 1, pushes: 1;
347
348    // ===== Additional Operations =====
349    /// Slice access (array[start:end])
350    SliceAccess = 0xB0, Object, pops: 3, pushes: 1;
351    /// Null coalescing (a ?? b)
352    NullCoalesce = 0xB1, Logical, pops: 2, pushes: 1;
353    /// Range constructor (start..end)
354    MakeRange = 0xB2, Object, pops: 2, pushes: 1;
355
356    // ===== Compact Typed Arithmetic (width-parameterised, ABI-stable) =====
357    /// Width-typed add: Operand::Width selects I8..F64
358    AddTyped = 0xB3, Arithmetic, pops: 2, pushes: 1;
359    /// Width-typed subtract: Operand::Width selects I8..F64
360    SubTyped = 0xB4, Arithmetic, pops: 2, pushes: 1;
361    /// Width-typed multiply: Operand::Width selects I8..F64
362    MulTyped = 0xB5, Arithmetic, pops: 2, pushes: 1;
363    /// Width-typed divide: Operand::Width selects I8..F64
364    DivTyped = 0xB6, Arithmetic, pops: 2, pushes: 1;
365    /// Width-typed modulo: Operand::Width selects I8..F64
366    ModTyped = 0xB7, Arithmetic, pops: 2, pushes: 1;
367    /// Width-typed comparison (ordered): Operand::Width selects I8..F64
368    /// Result semantics: pushes -1 (a<b), 0 (a==b), or 1 (a>b)
369    CmpTyped = 0xB8, Comparison, pops: 2, pushes: 1;
370
371    // ===== DataFrame Operations =====
372    /// Get field from data row by column index (generic, industry-agnostic)
373    GetDataField = 0xC0, DataFrame, pops: 1, pushes: 1;
374    /// Get row reference (lightweight, no data copy)
375    GetDataRow = 0xC1, DataFrame, pops: 1, pushes: 1;
376
377    // ===== Type-Specialized Operations (JIT Optimization) =====
378    /// Get field from typed object using precomputed offset
379    GetFieldTyped = 0xD0, Object, pops: 1, pushes: 1;
380    /// Set field on typed object using precomputed offset
381    SetFieldTyped = 0xD1, Object, pops: 2, pushes: 0;
382    /// Create a new typed object with fields from stack
383    NewTypedObject = 0xD2, Object, pops: 0, pushes: 1;
384    /// Merge two typed objects into a new typed object
385    TypedMergeObject = 0xD3, Object, pops: 2, pushes: 1;
386    /// Wrap a value with a type annotation for meta formatting
387    WrapTypeAnnotation = 0xD4, Object, pops: 1, pushes: 1;
388
389    // ===== Async Operations (0xE0-0xEF) =====
390    /// Yield to event loop for cooperative scheduling
391    Yield = 0xE0, Async, pops: 0, pushes: 0;
392    /// Suspend until a condition is met
393    Suspend = 0xE1, Async, pops: 0, pushes: 0;
394    /// Resume from suspension (internal use)
395    Resume = 0xE2, Async, pops: 1, pushes: 0;
396    /// Poll event queue
397    Poll = 0xE3, Async, pops: 0, pushes: 1;
398    /// Await next data bar from a source
399    AwaitBar = 0xE4, Async, pops: 0, pushes: 1;
400    /// Await next timer tick
401    AwaitTick = 0xE5, Async, pops: 0, pushes: 0;
402    /// General-purpose await: suspends on Future values
403    Await = 0xE6, Async, pops: 1, pushes: 1;
404    /// Spawn an async task from the expression on top of stack
405    SpawnTask = 0xE7, Async, pops: 1, pushes: 1;
406
407    // ===== Event Emission Operations =====
408    /// Emit an alert to the alert pipeline
409    EmitAlert = 0xE8, Async, pops: 1, pushes: 0;
410    /// Emit a generic event to the event queue
411    EmitEvent = 0xE9, Async, pops: 1, pushes: 0;
412    /// Initialize a join group from spawned tasks on the stack
413    JoinInit = 0xEA, Async, pops: 0, pushes: 1;
414    /// Await a TaskGroup to completion according to its join strategy
415    JoinAwait = 0xEB, Async, pops: 1, pushes: 1;
416    /// Cancel a running task
417    CancelTask = 0xEC, Async, pops: 1, pushes: 0;
418    /// Enter an async scope (structured concurrency boundary)
419    AsyncScopeEnter = 0xED, Async, pops: 0, pushes: 0;
420    /// Exit an async scope (structured concurrency boundary)
421    AsyncScopeExit = 0xEE, Async, pops: 0, pushes: 0;
422
423    // ===== Typed Column Access (Arrow DataTable) =====
424    /// Load f64 from typed column on a RowView
425    LoadColF64 = 0xC2, DataFrame, pops: 1, pushes: 1;
426    /// Load i64 from typed column on a RowView
427    LoadColI64 = 0xC3, DataFrame, pops: 1, pushes: 1;
428    /// Load bool from typed column on a RowView
429    LoadColBool = 0xC4, DataFrame, pops: 1, pushes: 1;
430    /// Load string from typed column on a RowView
431    LoadColStr = 0xC5, DataFrame, pops: 1, pushes: 1;
432    /// Bind a DataTable to a TypeSchema at runtime (safety net for dynamic paths)
433    BindSchema = 0xC6, DataFrame, pops: 1, pushes: 1;
434
435    // ===== Trait Object Operations =====
436    /// Box a concrete value into a trait object with a vtable
437    BoxTraitObject = 0xEF, Trait, pops: 1, pushes: 1;
438    /// Call a method on a trait object via vtable dispatch
439    DynMethodCall = 0xC7, Trait, pops: 0, pushes: 0;
440    /// Call Drop::drop on the value at the top of stack (sync)
441    DropCall = 0xC8, Trait, pops: 1, pushes: 0;
442    /// Call Drop::drop on the value at the top of stack (async)
443    DropCallAsync = 0xC9, Trait, pops: 1, pushes: 0;
444
445    // ===== Trusted Arithmetic (compiler-proved types, zero guard) =====
446    /// Add (int x int -> int) -- trusted: skips runtime type guard
447    AddIntTrusted = 0xCA, Arithmetic, pops: 2, pushes: 1;
448    /// Sub (int x int -> int) -- trusted: skips runtime type guard
449    SubIntTrusted = 0xCB, Arithmetic, pops: 2, pushes: 1;
450    /// Mul (int x int -> int) -- trusted: skips runtime type guard
451    MulIntTrusted = 0xCC, Arithmetic, pops: 2, pushes: 1;
452    /// Div (int x int -> int) -- trusted: skips runtime type guard
453    DivIntTrusted = 0xCD, Arithmetic, pops: 2, pushes: 1;
454    /// Add (f64 x f64 -> f64) -- trusted: skips runtime type guard
455    AddNumberTrusted = 0xCE, Arithmetic, pops: 2, pushes: 1;
456    /// Sub (f64 x f64 -> f64) -- trusted: skips runtime type guard
457    SubNumberTrusted = 0xCF, Arithmetic, pops: 2, pushes: 1;
458    /// Mul (f64 x f64 -> f64) -- trusted: skips runtime type guard
459    MulNumberTrusted = 0xD5, Arithmetic, pops: 2, pushes: 1;
460    /// Div (f64 x f64 -> f64) -- trusted: skips runtime type guard
461    DivNumberTrusted = 0xD6, Arithmetic, pops: 2, pushes: 1;
462
463    // ===== Trusted Variable Operations (compiler-proved types, zero guard) =====
464    /// LoadLocal (trusted) -- skips tag validation, reads slot directly
465    LoadLocalTrusted = 0xD7, Variable, pops: 0, pushes: 1;
466
467    // ===== Trusted Control Flow (compiler-proved types, zero guard) =====
468    /// JumpIfFalse (trusted) -- condition is known bool, direct bool check
469    JumpIfFalseTrusted = 0xD8, Control, pops: 1, pushes: 0;
470
471    // ===== Trusted Comparison (compiler-proved types, zero guard) =====
472    /// Gt (int x int -> bool) -- trusted: skips runtime type guard
473    GtIntTrusted = 0xD9, Comparison, pops: 2, pushes: 1;
474    /// Lt (int x int -> bool) -- trusted: skips runtime type guard
475    LtIntTrusted = 0xDA, Comparison, pops: 2, pushes: 1;
476    /// Gte (int x int -> bool) -- trusted: skips runtime type guard
477    GteIntTrusted = 0xDB, Comparison, pops: 2, pushes: 1;
478    /// Lte (int x int -> bool) -- trusted: skips runtime type guard
479    LteIntTrusted = 0xDC, Comparison, pops: 2, pushes: 1;
480    /// Gt (f64 x f64 -> bool) -- trusted: skips runtime type guard
481    GtNumberTrusted = 0xDD, Comparison, pops: 2, pushes: 1;
482    /// Lt (f64 x f64 -> bool) -- trusted: skips runtime type guard
483    LtNumberTrusted = 0xDE, Comparison, pops: 2, pushes: 1;
484    /// Gte (f64 x f64 -> bool) -- trusted: skips runtime type guard
485    GteNumberTrusted = 0xDF, Comparison, pops: 2, pushes: 1;
486    /// Lte (f64 x f64 -> bool) -- trusted: skips runtime type guard
487    LteNumberTrusted = 0x9E, Comparison, pops: 2, pushes: 1;
488
489    // ===== Special Operations =====
490    /// No operation
491    Nop = 0xF0, Special, pops: 0, pushes: 0;
492    /// Halt execution
493    Halt = 0xF1, Special, pops: 0, pushes: 0;
494    /// Debug breakpoint
495    Debug = 0xF2, Special, pops: 0, pushes: 0;
496
497    // ===== Numeric Coercion Operations =====
498    /// Coerce int to number (i64 -> f64)
499    IntToNumber = 0xF3, Arithmetic, pops: 1, pushes: 1;
500    /// Coerce number to int (f64 -> i64, truncating)
501    NumberToInt = 0xF4, Arithmetic, pops: 1, pushes: 1;
502
503    // ===== Foreign Function Operations =====
504    /// Call a linked foreign function.
505    /// Dispatches through language runtime extensions or the VM native C ABI path.
506    /// Operand: ForeignFunction(u16) — index into program.foreign_functions
507    /// Stack: pops N args (count pushed as a constant by the stub), pushes 1 result
508    CallForeign = 0xF5, Control, pops: 0, pushes: 0;
509
510    /// Store a local with width truncation.
511    /// Operand: TypedLocal(u16, NumericWidth) — local index + width
512    /// Pops one value, truncates to declared width, stores to local.
513    StoreLocalTyped = 0xF6, Variable, pops: 1, pushes: 0;
514
515    /// Cast a value to a specific integer width (bit-truncation, Rust-style `as`).
516    /// Operand: Width(NumericWidth) — target width
517    /// Pops one value, truncates, pushes result.
518    CastWidth = 0xF7, Arithmetic, pops: 1, pushes: 1;
519}
520
521impl OpCode {
522    /// Returns true if this is a trusted opcode variant (compiler-proved types, no runtime guard).
523    pub const fn is_trusted(self) -> bool {
524        matches!(
525            self,
526            OpCode::AddIntTrusted
527                | OpCode::SubIntTrusted
528                | OpCode::MulIntTrusted
529                | OpCode::DivIntTrusted
530                | OpCode::AddNumberTrusted
531                | OpCode::SubNumberTrusted
532                | OpCode::MulNumberTrusted
533                | OpCode::DivNumberTrusted
534                | OpCode::LoadLocalTrusted
535                | OpCode::JumpIfFalseTrusted
536                | OpCode::GtIntTrusted
537                | OpCode::LtIntTrusted
538                | OpCode::GteIntTrusted
539                | OpCode::LteIntTrusted
540                | OpCode::GtNumberTrusted
541                | OpCode::LtNumberTrusted
542                | OpCode::GteNumberTrusted
543                | OpCode::LteNumberTrusted
544        )
545    }
546
547    /// Map a trusted opcode back to its guarded (runtime-checked) counterpart.
548    ///
549    /// This is the inverse of `trusted_variant()`: given a trusted opcode, it
550    /// returns the equivalent guarded opcode. Used for differential testing and
551    /// bytecode post-processing.
552    pub const fn guarded_variant(self) -> Option<OpCode> {
553        match self {
554            OpCode::AddIntTrusted => Some(OpCode::AddInt),
555            OpCode::SubIntTrusted => Some(OpCode::SubInt),
556            OpCode::MulIntTrusted => Some(OpCode::MulInt),
557            OpCode::DivIntTrusted => Some(OpCode::DivInt),
558            OpCode::AddNumberTrusted => Some(OpCode::AddNumber),
559            OpCode::SubNumberTrusted => Some(OpCode::SubNumber),
560            OpCode::MulNumberTrusted => Some(OpCode::MulNumber),
561            OpCode::DivNumberTrusted => Some(OpCode::DivNumber),
562            OpCode::GtIntTrusted => Some(OpCode::GtInt),
563            OpCode::LtIntTrusted => Some(OpCode::LtInt),
564            OpCode::GteIntTrusted => Some(OpCode::GteInt),
565            OpCode::LteIntTrusted => Some(OpCode::LteInt),
566            OpCode::GtNumberTrusted => Some(OpCode::GtNumber),
567            OpCode::LtNumberTrusted => Some(OpCode::LtNumber),
568            OpCode::GteNumberTrusted => Some(OpCode::GteNumber),
569            OpCode::LteNumberTrusted => Some(OpCode::LteNumber),
570            OpCode::LoadLocalTrusted => Some(OpCode::LoadLocal),
571            OpCode::JumpIfFalseTrusted => Some(OpCode::JumpIfFalse),
572            _ => None,
573        }
574    }
575
576    /// Map a guarded typed opcode to its trusted variant (if one exists).
577    pub const fn trusted_variant(self) -> Option<OpCode> {
578        match self {
579            OpCode::AddInt => Some(OpCode::AddIntTrusted),
580            OpCode::SubInt => Some(OpCode::SubIntTrusted),
581            OpCode::MulInt => Some(OpCode::MulIntTrusted),
582            OpCode::DivInt => Some(OpCode::DivIntTrusted),
583            OpCode::AddNumber => Some(OpCode::AddNumberTrusted),
584            OpCode::SubNumber => Some(OpCode::SubNumberTrusted),
585            OpCode::MulNumber => Some(OpCode::MulNumberTrusted),
586            OpCode::DivNumber => Some(OpCode::DivNumberTrusted),
587            OpCode::GtInt => Some(OpCode::GtIntTrusted),
588            OpCode::LtInt => Some(OpCode::LtIntTrusted),
589            OpCode::GteInt => Some(OpCode::GteIntTrusted),
590            OpCode::LteInt => Some(OpCode::LteIntTrusted),
591            OpCode::GtNumber => Some(OpCode::GtNumberTrusted),
592            OpCode::LtNumber => Some(OpCode::LtNumberTrusted),
593            OpCode::GteNumber => Some(OpCode::GteNumberTrusted),
594            OpCode::LteNumber => Some(OpCode::LteNumberTrusted),
595            OpCode::LoadLocal => Some(OpCode::LoadLocalTrusted),
596            OpCode::JumpIfFalse => Some(OpCode::JumpIfFalseTrusted),
597            _ => None,
598        }
599    }
600}
601
602/// Numeric width tag for compact typed opcodes (AddTyped, SubTyped, etc.).
603///
604/// Encodes the operand width so a single opcode family can handle all
605/// numeric types.  The discriminant values are part of the bytecode ABI
606/// and must remain stable.
607#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
608#[repr(u8)]
609pub enum NumericWidth {
610    I8 = 0,
611    I16 = 1,
612    I32 = 2,
613    I64 = 3,
614    U8 = 4,
615    U16 = 5,
616    U32 = 6,
617    U64 = 7,
618    F32 = 8,
619    F64 = 9,
620}
621
622impl NumericWidth {
623    pub const ALL: [Self; 10] = [
624        Self::I8,
625        Self::I16,
626        Self::I32,
627        Self::I64,
628        Self::U8,
629        Self::U16,
630        Self::U32,
631        Self::U64,
632        Self::F32,
633        Self::F64,
634    ];
635
636    #[inline(always)]
637    pub const fn is_integer(self) -> bool {
638        matches!(
639            self,
640            Self::I8
641                | Self::I16
642                | Self::I32
643                | Self::I64
644                | Self::U8
645                | Self::U16
646                | Self::U32
647                | Self::U64
648        )
649    }
650
651    #[inline(always)]
652    pub const fn is_float(self) -> bool {
653        matches!(self, Self::F32 | Self::F64)
654    }
655
656    /// Whether this is a signed integer type.
657    #[inline(always)]
658    pub const fn is_signed(self) -> bool {
659        matches!(self, Self::I8 | Self::I16 | Self::I32 | Self::I64)
660    }
661
662    /// Whether this is an unsigned integer type.
663    #[inline(always)]
664    pub const fn is_unsigned(self) -> bool {
665        matches!(self, Self::U8 | Self::U16 | Self::U32 | Self::U64)
666    }
667
668    /// Number of bits for this width.
669    #[inline(always)]
670    pub const fn bits(self) -> u32 {
671        match self {
672            Self::I8 | Self::U8 => 8,
673            Self::I16 | Self::U16 => 16,
674            Self::I32 | Self::U32 | Self::F32 => 32,
675            Self::I64 | Self::U64 | Self::F64 => 64,
676        }
677    }
678
679    /// Bit mask for the integer value range.
680    #[inline(always)]
681    pub const fn mask(self) -> u64 {
682        match self {
683            Self::I8 | Self::U8 => 0xFF,
684            Self::I16 | Self::U16 => 0xFFFF,
685            Self::I32 | Self::U32 | Self::F32 => 0xFFFF_FFFF,
686            Self::I64 | Self::U64 | Self::F64 => u64::MAX,
687        }
688    }
689
690    /// Convert from IntWidth (shape-ast) to NumericWidth.
691    #[inline]
692    pub fn from_int_width(w: shape_ast::IntWidth) -> Self {
693        match w {
694            shape_ast::IntWidth::I8 => Self::I8,
695            shape_ast::IntWidth::U8 => Self::U8,
696            shape_ast::IntWidth::I16 => Self::I16,
697            shape_ast::IntWidth::U16 => Self::U16,
698            shape_ast::IntWidth::I32 => Self::I32,
699            shape_ast::IntWidth::U32 => Self::U32,
700            shape_ast::IntWidth::U64 => Self::U64,
701        }
702    }
703
704    /// Convert to IntWidth (shape-ast). Returns None for F32/F64/I64.
705    #[inline]
706    pub fn to_int_width(self) -> Option<shape_ast::IntWidth> {
707        match self {
708            Self::I8 => Some(shape_ast::IntWidth::I8),
709            Self::U8 => Some(shape_ast::IntWidth::U8),
710            Self::I16 => Some(shape_ast::IntWidth::I16),
711            Self::U16 => Some(shape_ast::IntWidth::U16),
712            Self::I32 => Some(shape_ast::IntWidth::I32),
713            Self::U32 => Some(shape_ast::IntWidth::U32),
714            Self::U64 => Some(shape_ast::IntWidth::U64),
715            Self::I64 | Self::F32 | Self::F64 => None,
716        }
717    }
718}
719
720/// A bytecode instruction with its operands
721#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
722pub struct Instruction {
723    pub opcode: OpCode,
724    pub operand: Option<Operand>,
725}
726
727/// Instruction operands
728#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
729pub enum Operand {
730    /// Constant pool index
731    Const(u16),
732    /// Local variable index
733    Local(u16),
734    /// ModuleBinding variable index
735    ModuleBinding(u16),
736    /// Jump offset (can be negative)
737    Offset(i32),
738    /// Function index
739    Function(shape_value::FunctionId),
740    /// Built-in function ID
741    Builtin(BuiltinFunction),
742    /// Number of arguments/elements
743    Count(u16),
744    /// Property name index
745    Property(u16),
746    /// Column index for DataFrame field access (compile-time resolved)
747    ColumnIndex(u32),
748    /// Typed field access (type_id, field_idx, field_type_tag)
749    /// Used with GetFieldTyped/SetFieldTyped for optimized field access.
750    /// field_type_tag encodes the FieldType so the executor can read slots
751    /// without a runtime schema lookup.
752    TypedField {
753        type_id: u16,
754        field_idx: u16,
755        field_type_tag: u16,
756    },
757    /// Typed object allocation
758    /// Used with NewTypedObject for creating TypedObject instances
759    TypedObjectAlloc {
760        /// Schema ID identifying the type layout
761        schema_id: u16,
762        /// Number of fields to pop from stack
763        field_count: u16,
764    },
765    /// Typed object merge (compile-time registered intersection schema)
766    /// Used with TypedMergeObject for O(1) merge operations
767    TypedMerge {
768        /// Schema ID for the merged result (pre-registered at compile time)
769        target_schema_id: u16,
770        /// Byte size of left operand data
771        left_size: u16,
772        /// Byte size of right operand data
773        right_size: u16,
774    },
775    /// Typed column access on a RowView
776    /// Used with LoadColF64/I64/Bool/Str for direct Arrow buffer reads
777    ColumnAccess {
778        /// Column index in the Arrow schema
779        col_id: u32,
780    },
781    /// A named reference (e.g., trait name for BoxTraitObject)
782    Name(StringId),
783    /// A method call descriptor (name + arg count) for dynamic dispatch
784    MethodCall { name: StringId, arg_count: u16 },
785    /// Typed method call using compile-time resolved MethodId.
786    /// Replaces stack-based string dispatch for known methods.
787    /// For `MethodId::DYNAMIC`, the VM falls back to string lookup
788    /// using `string_id` from the string pool.
789    TypedMethodCall {
790        /// Compile-time resolved method identifier
791        method_id: u16,
792        /// Number of arguments (not counting receiver)
793        arg_count: u16,
794        /// String pool index for the method name (used for dynamic fallback
795        /// and error messages)
796        string_id: u16,
797    },
798    /// Foreign function index — indexes into program.foreign_functions
799    ForeignFunction(u16),
800    /// Matrix dimensions (rows, cols) for NewMatrix opcode
801    MatrixDims { rows: u16, cols: u16 },
802    /// Numeric width tag for compact typed opcodes (AddTyped, SubTyped, etc.)
803    Width(NumericWidth),
804    /// Local index + width for StoreLocalTyped
805    TypedLocal(u16, NumericWidth),
806}
807
808/// Built-in functions
809#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
810pub enum BuiltinFunction {
811    // Math functions
812    Abs,
813    Sqrt,
814    Ln,
815    Pow,
816    Exp,
817    Log,
818    Min,
819    Max,
820    Floor,
821    Ceil,
822    Round,
823    Sin,
824    Cos,
825    Tan,
826    Asin,
827    Acos,
828    Atan,
829
830    // Statistical functions
831    StdDev,
832
833    // Array functions
834    Range,
835    Slice,
836    Push,
837    Pop,
838    First,
839    Last,
840    Zip,
841    Filled,
842
843    // Array method-style functions
844    Map,
845    Filter,
846    Reduce,
847    ForEach,
848    Find,
849    FindIndex,
850    Some,
851    Every,
852
853    // Utility functions
854    Print,
855    Format,
856    Len,
857    // Throw removed: Shape uses Result types
858    Snapshot,
859    Exit,
860
861    // Object functions
862    ObjectRest,
863
864    // Control flow functions
865    ControlFold,
866
867    // Type functions
868    TypeOf,
869    IsNumber,
870    IsString,
871    IsBool,
872    IsArray,
873    IsObject,
874    IsDataRow,
875
876    // Conversion
877    ToString,
878    ToNumber,
879    ToBool,
880    IntoInt,
881    IntoNumber,
882    IntoDecimal,
883    IntoBool,
884    IntoString,
885    TryIntoInt,
886    TryIntoNumber,
887    TryIntoDecimal,
888    TryIntoBool,
889    TryIntoString,
890
891    // Native C/Arrow interop helpers
892    NativePtrSize,
893    NativePtrNewCell,
894    NativePtrFreeCell,
895    NativePtrReadPtr,
896    NativePtrWritePtr,
897    NativeTableFromArrowC,
898    NativeTableFromArrowCTyped,
899    NativeTableBindType,
900    /// Format a value respecting meta formatting for TypeAnnotatedValues.
901    /// Used by string interpolation to apply custom formatters.
902    FormatValueWithMeta,
903    /// Format a value using a typed interpolation format spec.
904    /// Used by string interpolation for spec-aware rendering (fixed/table).
905    FormatValueWithSpec,
906
907    // Math intrinsics (6 functions)
908    IntrinsicSum,
909    IntrinsicMean,
910    IntrinsicMin,
911    IntrinsicMax,
912    IntrinsicStd,
913    IntrinsicVariance,
914
915    // Random number generation intrinsics (5 functions)
916    IntrinsicRandom,
917    IntrinsicRandomInt,
918    IntrinsicRandomSeed,
919    IntrinsicRandomNormal,
920    IntrinsicRandomArray,
921
922    // Distribution intrinsics (5 functions)
923    IntrinsicDistUniform,
924    IntrinsicDistLognormal,
925    IntrinsicDistExponential,
926    IntrinsicDistPoisson,
927    IntrinsicDistSampleN,
928
929    // Stochastic process intrinsics (4 functions)
930    IntrinsicBrownianMotion,
931    IntrinsicGbm,
932    IntrinsicOuProcess,
933    IntrinsicRandomWalk,
934
935    // Rolling window intrinsics (6 functions)
936    IntrinsicRollingSum,
937    IntrinsicRollingMean,
938    IntrinsicRollingStd,
939    IntrinsicRollingMin,
940    IntrinsicRollingMax,
941    IntrinsicEma,
942    IntrinsicLinearRecurrence,
943
944    // Series transformation intrinsics (7 functions)
945    IntrinsicShift,
946    IntrinsicDiff,
947    IntrinsicPctChange,
948    IntrinsicFillna,
949    IntrinsicCumsum,
950    IntrinsicCumprod,
951    IntrinsicClip,
952
953    // Statistical intrinsics (4 functions)
954    IntrinsicCorrelation,
955    IntrinsicCovariance,
956    IntrinsicPercentile,
957    IntrinsicMedian,
958
959    // Character code intrinsics
960    IntrinsicCharCode,
961    IntrinsicFromCharCode,
962
963    // Series access (critical for backtesting!)
964    IntrinsicSeries,
965
966    // Vector intrinsics (10 functions)
967    IntrinsicVecAbs,
968    IntrinsicVecSqrt,
969    IntrinsicVecLn,
970    IntrinsicVecExp,
971    IntrinsicVecAdd,
972    IntrinsicVecSub,
973    IntrinsicVecMul,
974    IntrinsicVecDiv,
975    IntrinsicVecMax,
976    IntrinsicVecMin,
977    IntrinsicVecSelect,
978
979    // Matrix intrinsics (2 functions)
980    IntrinsicMatMulVec,
981    IntrinsicMatMulMat,
982
983    // Internal evaluation helpers
984    EvalTimeRef,
985    EvalDateTimeExpr,
986    EvalDataDateTimeRef,
987    EvalDataSet,
988    EvalDataRelative,
989    EvalDataRelativeRange,
990
991    // Option type constructors
992    SomeCtor,
993    OkCtor,
994    ErrCtor,
995
996    // Collection constructors
997    HashMapCtor,
998    SetCtor,
999    DequeCtor,
1000    PriorityQueueCtor,
1001
1002    // Json navigation helpers (used by std::core::json_value extend block)
1003    JsonObjectGet,
1004    JsonArrayAt,
1005    JsonObjectKeys,
1006    JsonArrayLen,
1007    JsonObjectLen,
1008
1009    // Window functions (SQL-style)
1010    WindowRowNumber,
1011    WindowRank,
1012    WindowDenseRank,
1013    WindowNtile,
1014    WindowLag,
1015    WindowLead,
1016    WindowFirstValue,
1017    WindowLastValue,
1018    WindowNthValue,
1019    WindowSum,
1020    WindowAvg,
1021    WindowMin,
1022    WindowMax,
1023    WindowCount,
1024
1025    // JOIN operations
1026    JoinExecute,
1027
1028    // Reflection
1029    Reflect,
1030
1031    // Content string builtins
1032    /// Wrap a string value as ContentNode::plain(text)
1033    MakeContentText,
1034    /// Collect N ContentNodes from the stack into a ContentNode::Fragment
1035    MakeContentFragment,
1036    /// Apply a ContentFormatSpec (encoded as ints/bools on stack) to a ContentNode
1037    ApplyContentStyle,
1038    /// Create a chart ContentNode from a table/array value using column specs
1039    MakeContentChartFromValue,
1040
1041    // Content namespace constructors
1042    /// Content.chart(type_str) — create a chart ContentNode
1043    ContentChart,
1044    /// Content.text(str) — create a plain text ContentNode
1045    ContentTextCtor,
1046    /// Content.table(headers, rows) — create a table ContentNode
1047    ContentTableCtor,
1048    /// Content.code(language, source) — create a code block ContentNode
1049    ContentCodeCtor,
1050    /// Content.kv(pairs) — create a key-value ContentNode
1051    ContentKvCtor,
1052    /// Content.fragment(parts) — create a fragment ContentNode
1053    ContentFragmentCtor,
1054
1055    // DateTime constructors
1056    /// DateTime.now() — current local time as DateTime<FixedOffset>
1057    DateTimeNow,
1058    /// DateTime.utc() — current UTC time as DateTime<FixedOffset> at +00:00
1059    DateTimeUtc,
1060    /// DateTime.parse(str) — parse from string (ISO 8601, RFC 2822, common formats)
1061    DateTimeParse,
1062    /// DateTime.from_epoch(ms) — from milliseconds since Unix epoch
1063    DateTimeFromEpoch,
1064
1065    // Concurrency primitive constructors
1066    /// Mutex(value) — create a new mutex wrapping the given value
1067    MutexCtor,
1068    /// Atomic(value) — create a new atomic integer with the given initial value
1069    AtomicCtor,
1070    /// Lazy(initializer) — create a lazy value with the given initializer closure
1071    LazyCtor,
1072    /// Channel() — create a new MPSC channel, returns [sender, receiver] array
1073    ChannelCtor,
1074
1075    // Additional math builtins
1076    /// sign(x) — returns -1, 0, or 1
1077    Sign,
1078    /// gcd(a, b) — greatest common divisor
1079    Gcd,
1080    /// lcm(a, b) — least common multiple
1081    Lcm,
1082    /// hypot(a, b) — hypotenuse sqrt(a^2 + b^2)
1083    Hypot,
1084    /// clamp(x, min, max) — clamp value between min and max
1085    Clamp,
1086    /// isNaN(x) — check if value is NaN
1087    IsNaN,
1088    /// isFinite(x) — check if value is finite
1089    IsFinite,
1090
1091    // Table construction (1)
1092    /// Build a TypedTable from inline row values: args = [schema_id, row_count, field_count, val1, val2, ...]
1093    MakeTableFromRows,
1094}
1095
1096impl BuiltinFunction {
1097    /// Convert a discriminant value back to a BuiltinFunction variant.
1098    ///
1099    /// Used by the JIT generic builtin trampoline: the translator encodes
1100    /// the builtin as `*builtin as u16` and the FFI function converts it
1101    /// back at runtime.
1102    pub fn from_discriminant(id: u16) -> Option<Self> {
1103        // Ordered to match the enum declaration order (discriminants 0, 1, 2, ...)
1104        const VARIANTS: &[BuiltinFunction] = &[
1105            // Math (18) — discriminants 0..17
1106            BuiltinFunction::Abs,
1107            BuiltinFunction::Sqrt,
1108            BuiltinFunction::Ln,
1109            BuiltinFunction::Pow,
1110            BuiltinFunction::Exp,
1111            BuiltinFunction::Log,
1112            BuiltinFunction::Min,
1113            BuiltinFunction::Max,
1114            BuiltinFunction::Floor,
1115            BuiltinFunction::Ceil,
1116            BuiltinFunction::Round,
1117            BuiltinFunction::Sin,
1118            BuiltinFunction::Cos,
1119            BuiltinFunction::Tan,
1120            BuiltinFunction::Asin,
1121            BuiltinFunction::Acos,
1122            BuiltinFunction::Atan,
1123            // Stats (1)
1124            BuiltinFunction::StdDev,
1125            // Array (8)
1126            BuiltinFunction::Range,
1127            BuiltinFunction::Slice,
1128            BuiltinFunction::Push,
1129            BuiltinFunction::Pop,
1130            BuiltinFunction::First,
1131            BuiltinFunction::Last,
1132            BuiltinFunction::Zip,
1133            BuiltinFunction::Filled,
1134            // HOF (8)
1135            BuiltinFunction::Map,
1136            BuiltinFunction::Filter,
1137            BuiltinFunction::Reduce,
1138            BuiltinFunction::ForEach,
1139            BuiltinFunction::Find,
1140            BuiltinFunction::FindIndex,
1141            BuiltinFunction::Some,
1142            BuiltinFunction::Every,
1143            // Utility (5)
1144            BuiltinFunction::Print,
1145            BuiltinFunction::Format,
1146            BuiltinFunction::Len,
1147            BuiltinFunction::Snapshot,
1148            BuiltinFunction::Exit,
1149            // Object (1)
1150            BuiltinFunction::ObjectRest,
1151            // Control (1)
1152            BuiltinFunction::ControlFold,
1153            // Type (7)
1154            BuiltinFunction::TypeOf,
1155            BuiltinFunction::IsNumber,
1156            BuiltinFunction::IsString,
1157            BuiltinFunction::IsBool,
1158            BuiltinFunction::IsArray,
1159            BuiltinFunction::IsObject,
1160            BuiltinFunction::IsDataRow,
1161            // Conversion (13)
1162            BuiltinFunction::ToString,
1163            BuiltinFunction::ToNumber,
1164            BuiltinFunction::ToBool,
1165            BuiltinFunction::IntoInt,
1166            BuiltinFunction::IntoNumber,
1167            BuiltinFunction::IntoDecimal,
1168            BuiltinFunction::IntoBool,
1169            BuiltinFunction::IntoString,
1170            BuiltinFunction::TryIntoInt,
1171            BuiltinFunction::TryIntoNumber,
1172            BuiltinFunction::TryIntoDecimal,
1173            BuiltinFunction::TryIntoBool,
1174            BuiltinFunction::TryIntoString,
1175            // Native ptr (8)
1176            BuiltinFunction::NativePtrSize,
1177            BuiltinFunction::NativePtrNewCell,
1178            BuiltinFunction::NativePtrFreeCell,
1179            BuiltinFunction::NativePtrReadPtr,
1180            BuiltinFunction::NativePtrWritePtr,
1181            BuiltinFunction::NativeTableFromArrowC,
1182            BuiltinFunction::NativeTableFromArrowCTyped,
1183            BuiltinFunction::NativeTableBindType,
1184            // Format (2)
1185            BuiltinFunction::FormatValueWithMeta,
1186            BuiltinFunction::FormatValueWithSpec,
1187            // Math intrinsics (6)
1188            BuiltinFunction::IntrinsicSum,
1189            BuiltinFunction::IntrinsicMean,
1190            BuiltinFunction::IntrinsicMin,
1191            BuiltinFunction::IntrinsicMax,
1192            BuiltinFunction::IntrinsicStd,
1193            BuiltinFunction::IntrinsicVariance,
1194            // Random (5)
1195            BuiltinFunction::IntrinsicRandom,
1196            BuiltinFunction::IntrinsicRandomInt,
1197            BuiltinFunction::IntrinsicRandomSeed,
1198            BuiltinFunction::IntrinsicRandomNormal,
1199            BuiltinFunction::IntrinsicRandomArray,
1200            // Distribution (5)
1201            BuiltinFunction::IntrinsicDistUniform,
1202            BuiltinFunction::IntrinsicDistLognormal,
1203            BuiltinFunction::IntrinsicDistExponential,
1204            BuiltinFunction::IntrinsicDistPoisson,
1205            BuiltinFunction::IntrinsicDistSampleN,
1206            // Stochastic (4)
1207            BuiltinFunction::IntrinsicBrownianMotion,
1208            BuiltinFunction::IntrinsicGbm,
1209            BuiltinFunction::IntrinsicOuProcess,
1210            BuiltinFunction::IntrinsicRandomWalk,
1211            // Rolling (7)
1212            BuiltinFunction::IntrinsicRollingSum,
1213            BuiltinFunction::IntrinsicRollingMean,
1214            BuiltinFunction::IntrinsicRollingStd,
1215            BuiltinFunction::IntrinsicRollingMin,
1216            BuiltinFunction::IntrinsicRollingMax,
1217            BuiltinFunction::IntrinsicEma,
1218            BuiltinFunction::IntrinsicLinearRecurrence,
1219            // Series transform (7)
1220            BuiltinFunction::IntrinsicShift,
1221            BuiltinFunction::IntrinsicDiff,
1222            BuiltinFunction::IntrinsicPctChange,
1223            BuiltinFunction::IntrinsicFillna,
1224            BuiltinFunction::IntrinsicCumsum,
1225            BuiltinFunction::IntrinsicCumprod,
1226            BuiltinFunction::IntrinsicClip,
1227            // Statistics (4)
1228            BuiltinFunction::IntrinsicCorrelation,
1229            BuiltinFunction::IntrinsicCovariance,
1230            BuiltinFunction::IntrinsicPercentile,
1231            BuiltinFunction::IntrinsicMedian,
1232            // Char codes (2)
1233            BuiltinFunction::IntrinsicCharCode,
1234            BuiltinFunction::IntrinsicFromCharCode,
1235            // Series (1)
1236            BuiltinFunction::IntrinsicSeries,
1237            // Vector (11)
1238            BuiltinFunction::IntrinsicVecAbs,
1239            BuiltinFunction::IntrinsicVecSqrt,
1240            BuiltinFunction::IntrinsicVecLn,
1241            BuiltinFunction::IntrinsicVecExp,
1242            BuiltinFunction::IntrinsicVecAdd,
1243            BuiltinFunction::IntrinsicVecSub,
1244            BuiltinFunction::IntrinsicVecMul,
1245            BuiltinFunction::IntrinsicVecDiv,
1246            BuiltinFunction::IntrinsicVecMax,
1247            BuiltinFunction::IntrinsicVecMin,
1248            BuiltinFunction::IntrinsicVecSelect,
1249            // Matrix (2)
1250            BuiltinFunction::IntrinsicMatMulVec,
1251            BuiltinFunction::IntrinsicMatMulMat,
1252            // Eval helpers (6)
1253            BuiltinFunction::EvalTimeRef,
1254            BuiltinFunction::EvalDateTimeExpr,
1255            BuiltinFunction::EvalDataDateTimeRef,
1256            BuiltinFunction::EvalDataSet,
1257            BuiltinFunction::EvalDataRelative,
1258            BuiltinFunction::EvalDataRelativeRange,
1259            // Ctors (7)
1260            BuiltinFunction::SomeCtor,
1261            BuiltinFunction::OkCtor,
1262            BuiltinFunction::ErrCtor,
1263            BuiltinFunction::HashMapCtor,
1264            BuiltinFunction::SetCtor,
1265            BuiltinFunction::DequeCtor,
1266            BuiltinFunction::PriorityQueueCtor,
1267            // JSON (5)
1268            BuiltinFunction::JsonObjectGet,
1269            BuiltinFunction::JsonArrayAt,
1270            BuiltinFunction::JsonObjectKeys,
1271            BuiltinFunction::JsonArrayLen,
1272            BuiltinFunction::JsonObjectLen,
1273            // Window (14)
1274            BuiltinFunction::WindowRowNumber,
1275            BuiltinFunction::WindowRank,
1276            BuiltinFunction::WindowDenseRank,
1277            BuiltinFunction::WindowNtile,
1278            BuiltinFunction::WindowLag,
1279            BuiltinFunction::WindowLead,
1280            BuiltinFunction::WindowFirstValue,
1281            BuiltinFunction::WindowLastValue,
1282            BuiltinFunction::WindowNthValue,
1283            BuiltinFunction::WindowSum,
1284            BuiltinFunction::WindowAvg,
1285            BuiltinFunction::WindowMin,
1286            BuiltinFunction::WindowMax,
1287            BuiltinFunction::WindowCount,
1288            // Join/Reflect (2)
1289            BuiltinFunction::JoinExecute,
1290            BuiltinFunction::Reflect,
1291            // Content (3 + 6 constructors)
1292            BuiltinFunction::MakeContentText,
1293            BuiltinFunction::MakeContentFragment,
1294            BuiltinFunction::ApplyContentStyle,
1295            BuiltinFunction::MakeContentChartFromValue,
1296            BuiltinFunction::ContentChart,
1297            BuiltinFunction::ContentTextCtor,
1298            BuiltinFunction::ContentTableCtor,
1299            BuiltinFunction::ContentCodeCtor,
1300            BuiltinFunction::ContentKvCtor,
1301            BuiltinFunction::ContentFragmentCtor,
1302            // DateTime (4)
1303            BuiltinFunction::DateTimeNow,
1304            BuiltinFunction::DateTimeUtc,
1305            BuiltinFunction::DateTimeParse,
1306            BuiltinFunction::DateTimeFromEpoch,
1307            // Concurrency (4)
1308            BuiltinFunction::MutexCtor,
1309            BuiltinFunction::AtomicCtor,
1310            BuiltinFunction::LazyCtor,
1311            BuiltinFunction::ChannelCtor,
1312            // Math extras (7)
1313            BuiltinFunction::Sign,
1314            BuiltinFunction::Gcd,
1315            BuiltinFunction::Lcm,
1316            BuiltinFunction::Hypot,
1317            BuiltinFunction::Clamp,
1318            BuiltinFunction::IsNaN,
1319            BuiltinFunction::IsFinite,
1320            // Table construction (1)
1321            BuiltinFunction::MakeTableFromRows,
1322        ];
1323        VARIANTS.get(id as usize).copied()
1324    }
1325}