glyph_runtime/
instruction.rs

1//! VM instruction set for Glyph runtime
2
3use glyph_types::Value;
4use serde::{Deserialize, Serialize};
5
6/// Bytecode instructions for the Glyph VM
7#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
8pub enum Instruction {
9    // Stack operations
10    Push(Value),
11    Pop,
12    Dup,
13    Swap,
14    Rot3, // Rotate top 3 stack items
15
16    // Arithmetic (all immutable operations)
17    Add,
18    Sub,
19    Mul,
20    Div,
21    Mod,
22    Neg,
23    Pow,
24
25    // Comparison
26    Eq,
27    Ne,
28    Lt,
29    Le,
30    Gt,
31    Ge,
32
33    // Logical
34    And,
35    Or,
36    Not,
37
38    // Control flow
39    Jump(usize),
40    JumpIf(usize),
41    JumpIfNot(usize),
42    Call(usize),        // function index
43    CallNative(String), // native function name
44    Return,
45
46    // Immutable bindings (no mutation allowed)
47    BindLocal(String),  // Create new immutable binding
48    LoadLocal(String),  // Load from local binding
49    LoadGlobal(String), // Load from global binding
50
51    // Collections (all operations create new collections)
52    MakeList(usize),                 // number of elements
53    MakeDict(usize),                 // number of key-value pairs
54    MakeTuple(usize),                // immutable tuple
55    GetIndex,                        // Push collection[index]
56    GetAttr(String),                 // Push object.attr
57    Slice(Option<i64>, Option<i64>), // collection[start:end]
58
59    // Collection builders (create new collections)
60    ListAppend, // [list, item] -> new_list
61    ListConcat, // [list1, list2] -> new_list
62    DictInsert, // [dict, key, value] -> new_dict
63    DictMerge,  // [dict1, dict2] -> new_dict
64
65    // Pattern matching support
66    MatchValue,         // Compare with pattern
67    MatchType(String),  // Check type
68    Destructure(usize), // Destructure tuple/list
69
70    // Promise/async operations
71    MakePromise,
72    AwaitPromise,
73    ResolvePromise,
74    RejectPromise,
75
76    // Result operations
77    MakeOk,
78    MakeErr,
79    UnwrapResult,
80    MapResult,
81
82    // Capability checks
83    RequireCapability(String),
84    CheckCapability(String),
85
86    // Intrinsics with capability requirements
87    CallIntrinsic {
88        name: String,
89        capability: Option<String>,
90    },
91
92    // Debug/telemetry
93    TraceValue(String),      // Debug trace with label
94    RecordTelemetry(String), // Record telemetry event
95
96    // Other
97    Nop,
98    Halt,
99}
100
101impl Instruction {
102    /// Returns the size of this instruction in bytes (for jump calculations)
103    pub fn size(&self) -> usize {
104        use std::mem;
105        // Real size calculation based on instruction type
106        match self {
107            // Fixed size instructions
108            Instruction::Add
109            | Instruction::Sub
110            | Instruction::Mul
111            | Instruction::Div
112            | Instruction::Mod
113            | Instruction::Neg
114            | Instruction::Pow
115            | Instruction::Eq
116            | Instruction::Ne
117            | Instruction::Lt
118            | Instruction::Le
119            | Instruction::Gt
120            | Instruction::Ge
121            | Instruction::And
122            | Instruction::Or
123            | Instruction::Not
124            | Instruction::Pop
125            | Instruction::Dup
126            | Instruction::Swap
127            | Instruction::Rot3
128            | Instruction::GetIndex
129            | Instruction::ListAppend
130            | Instruction::ListConcat
131            | Instruction::DictInsert
132            | Instruction::DictMerge
133            | Instruction::MatchValue
134            | Instruction::MakePromise
135            | Instruction::AwaitPromise
136            | Instruction::ResolvePromise
137            | Instruction::RejectPromise
138            | Instruction::MakeOk
139            | Instruction::MakeErr
140            | Instruction::UnwrapResult
141            | Instruction::MapResult
142            | Instruction::Return
143            | Instruction::Nop
144            | Instruction::Halt => 1,
145
146            // Variable size instructions
147            Instruction::Push(value) => 1 + mem::size_of_val(value),
148            Instruction::Jump(_)
149            | Instruction::JumpIf(_)
150            | Instruction::JumpIfNot(_)
151            | Instruction::Call(_) => 1 + mem::size_of::<usize>(),
152            Instruction::MakeList(n)
153            | Instruction::MakeDict(n)
154            | Instruction::MakeTuple(n)
155            | Instruction::Destructure(n) => 1 + mem::size_of_val(n),
156            Instruction::BindLocal(s)
157            | Instruction::LoadLocal(s)
158            | Instruction::LoadGlobal(s)
159            | Instruction::CallNative(s)
160            | Instruction::GetAttr(s)
161            | Instruction::MatchType(s)
162            | Instruction::RequireCapability(s)
163            | Instruction::CheckCapability(s)
164            | Instruction::TraceValue(s)
165            | Instruction::RecordTelemetry(s) => 1 + s.len(),
166            Instruction::CallIntrinsic { name, capability } => {
167                1 + name.len() + capability.as_ref().map_or(0, |c| c.len())
168            }
169            Instruction::Slice(start, end) => 1 + mem::size_of_val(start) + mem::size_of_val(end),
170        }
171    }
172
173    /// Check if this instruction requires a specific capability
174    pub fn required_capability(&self) -> Option<&str> {
175        match self {
176            Instruction::RequireCapability(cap) => Some(cap),
177            Instruction::CallIntrinsic {
178                capability: Some(cap),
179                ..
180            } => Some(cap),
181            _ => None,
182        }
183    }
184
185    /// Check if this instruction modifies state (all should be immutable)
186    pub fn is_pure(&self) -> bool {
187        match self {
188            // Only intrinsics and I/O operations are impure
189            Instruction::CallIntrinsic { .. }
190            | Instruction::TraceValue(_)
191            | Instruction::RecordTelemetry(_) => false,
192            _ => true,
193        }
194    }
195}