lust/bytecode/
instruction.rs

1use core::fmt;
2pub type Register = u8;
3pub type ConstIndex = u16;
4pub type JumpOffset = i16;
5#[derive(Debug, Clone, Copy, PartialEq)]
6pub enum Instruction {
7    LoadNil(Register),
8    LoadBool(Register, bool),
9    LoadConst(Register, ConstIndex),
10    LoadGlobal(Register, ConstIndex),
11    StoreGlobal(ConstIndex, Register),
12    Move(Register, Register),
13    Add(Register, Register, Register),
14    Sub(Register, Register, Register),
15    Mul(Register, Register, Register),
16    Div(Register, Register, Register),
17    Mod(Register, Register, Register),
18    Neg(Register, Register),
19    Eq(Register, Register, Register),
20    Ne(Register, Register, Register),
21    Lt(Register, Register, Register),
22    Le(Register, Register, Register),
23    Gt(Register, Register, Register),
24    Ge(Register, Register, Register),
25    And(Register, Register, Register),
26    Or(Register, Register, Register),
27    Not(Register, Register),
28    Jump(JumpOffset),
29    JumpIf(Register, JumpOffset),
30    JumpIfNot(Register, JumpOffset),
31    Call(Register, Register, u8, Register),
32    Return(Register),
33    NewArray(Register, Register, u8),
34    NewMap(Register),
35    NewTable(Register),
36    NewStruct(Register, ConstIndex, ConstIndex, Register, u8),
37    NewEnumUnit(Register, ConstIndex, ConstIndex),
38    NewEnumVariant(Register, ConstIndex, ConstIndex, Register, u8),
39    TupleNew(Register, Register, u8),
40    TupleGet(Register, Register, u8),
41    IsEnumVariant(Register, Register, ConstIndex, ConstIndex),
42    GetEnumValue(Register, Register, u8),
43    GetField(Register, Register, ConstIndex),
44    SetField(Register, ConstIndex, Register),
45    GetIndex(Register, Register, Register),
46    ArrayLen(Register, Register),
47    SetIndex(Register, Register, Register),
48    Concat(Register, Register, Register),
49    CallMethod(Register, ConstIndex, Register, u8, Register),
50    TypeIs(Register, Register, ConstIndex),
51    LoadUpvalue(Register, u8),
52    StoreUpvalue(u8, Register),
53    Closure(Register, ConstIndex, Register, u8),
54}
55
56#[derive(Debug, Clone, Copy, PartialEq, Eq)]
57pub enum OpCode {
58    LoadNil,
59    LoadBool,
60    LoadConst,
61    LoadGlobal,
62    StoreGlobal,
63    Move,
64    Add,
65    Sub,
66    Mul,
67    Div,
68    Mod,
69    Neg,
70    Eq,
71    Ne,
72    Lt,
73    Le,
74    Gt,
75    Ge,
76    And,
77    Or,
78    Not,
79    Jump,
80    JumpIf,
81    JumpIfNot,
82    Call,
83    Return,
84    NewArray,
85    NewMap,
86    NewTable,
87    NewStruct,
88    NewEnumUnit,
89    NewEnumVariant,
90    TupleNew,
91    TupleGet,
92    IsEnumVariant,
93    GetEnumValue,
94    GetField,
95    SetField,
96    GetIndex,
97    ArrayLen,
98    SetIndex,
99    Concat,
100    CallMethod,
101    TypeIs,
102    LoadUpvalue,
103    StoreUpvalue,
104    Closure,
105}
106
107impl Instruction {
108    pub fn opcode(&self) -> OpCode {
109        match self {
110            Instruction::LoadNil(_) => OpCode::LoadNil,
111            Instruction::LoadBool(_, _) => OpCode::LoadBool,
112            Instruction::LoadConst(_, _) => OpCode::LoadConst,
113            Instruction::LoadGlobal(_, _) => OpCode::LoadGlobal,
114            Instruction::StoreGlobal(_, _) => OpCode::StoreGlobal,
115            Instruction::Move(_, _) => OpCode::Move,
116            Instruction::Add(_, _, _) => OpCode::Add,
117            Instruction::Sub(_, _, _) => OpCode::Sub,
118            Instruction::Mul(_, _, _) => OpCode::Mul,
119            Instruction::Div(_, _, _) => OpCode::Div,
120            Instruction::Mod(_, _, _) => OpCode::Mod,
121            Instruction::Neg(_, _) => OpCode::Neg,
122            Instruction::Eq(_, _, _) => OpCode::Eq,
123            Instruction::Ne(_, _, _) => OpCode::Ne,
124            Instruction::Lt(_, _, _) => OpCode::Lt,
125            Instruction::Le(_, _, _) => OpCode::Le,
126            Instruction::Gt(_, _, _) => OpCode::Gt,
127            Instruction::Ge(_, _, _) => OpCode::Ge,
128            Instruction::And(_, _, _) => OpCode::And,
129            Instruction::Or(_, _, _) => OpCode::Or,
130            Instruction::Not(_, _) => OpCode::Not,
131            Instruction::Jump(_) => OpCode::Jump,
132            Instruction::JumpIf(_, _) => OpCode::JumpIf,
133            Instruction::JumpIfNot(_, _) => OpCode::JumpIfNot,
134            Instruction::Call(_, _, _, _) => OpCode::Call,
135            Instruction::Return(_) => OpCode::Return,
136            Instruction::NewArray(_, _, _) => OpCode::NewArray,
137            Instruction::NewMap(_) => OpCode::NewMap,
138            Instruction::NewTable(_) => OpCode::NewTable,
139            Instruction::NewStruct(_, _, _, _, _) => OpCode::NewStruct,
140            Instruction::NewEnumUnit(_, _, _) => OpCode::NewEnumUnit,
141            Instruction::NewEnumVariant(_, _, _, _, _) => OpCode::NewEnumVariant,
142            Instruction::TupleNew(_, _, _) => OpCode::TupleNew,
143            Instruction::TupleGet(_, _, _) => OpCode::TupleGet,
144            Instruction::IsEnumVariant(_, _, _, _) => OpCode::IsEnumVariant,
145            Instruction::GetEnumValue(_, _, _) => OpCode::GetEnumValue,
146            Instruction::GetField(_, _, _) => OpCode::GetField,
147            Instruction::SetField(_, _, _) => OpCode::SetField,
148            Instruction::GetIndex(_, _, _) => OpCode::GetIndex,
149            Instruction::ArrayLen(_, _) => OpCode::ArrayLen,
150            Instruction::SetIndex(_, _, _) => OpCode::SetIndex,
151            Instruction::Concat(_, _, _) => OpCode::Concat,
152            Instruction::CallMethod(_, _, _, _, _) => OpCode::CallMethod,
153            Instruction::TypeIs(_, _, _) => OpCode::TypeIs,
154            Instruction::LoadUpvalue(_, _) => OpCode::LoadUpvalue,
155            Instruction::StoreUpvalue(_, _) => OpCode::StoreUpvalue,
156            Instruction::Closure(_, _, _, _) => OpCode::Closure,
157        }
158    }
159}
160
161impl fmt::Display for Instruction {
162    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
163        match self {
164            Instruction::LoadNil(r) => write!(f, "LoadNil R{}", r),
165            Instruction::LoadBool(r, b) => write!(f, "LoadBool R{}, {}", r, b),
166            Instruction::LoadConst(r, c) => write!(f, "LoadConst R{}, K{}", r, c),
167            Instruction::LoadGlobal(r, c) => write!(f, "LoadGlobal R{}, K{}", r, c),
168            Instruction::StoreGlobal(c, r) => write!(f, "StoreGlobal K{}, R{}", c, r),
169            Instruction::Move(d, s) => write!(f, "Move R{}, R{}", d, s),
170            Instruction::Add(d, l, r) => write!(f, "Add R{}, R{}, R{}", d, l, r),
171            Instruction::Sub(d, l, r) => write!(f, "Sub R{}, R{}, R{}", d, l, r),
172            Instruction::Mul(d, l, r) => write!(f, "Mul R{}, R{}, R{}", d, l, r),
173            Instruction::Div(d, l, r) => write!(f, "Div R{}, R{}, R{}", d, l, r),
174            Instruction::Mod(d, l, r) => write!(f, "Mod R{}, R{}, R{}", d, l, r),
175            Instruction::Neg(d, s) => write!(f, "Neg R{}, R{}", d, s),
176            Instruction::Eq(d, l, r) => write!(f, "Eq R{}, R{}, R{}", d, l, r),
177            Instruction::Ne(d, l, r) => write!(f, "Ne R{}, R{}, R{}", d, l, r),
178            Instruction::Lt(d, l, r) => write!(f, "Lt R{}, R{}, R{}", d, l, r),
179            Instruction::Le(d, l, r) => write!(f, "Le R{}, R{}, R{}", d, l, r),
180            Instruction::Gt(d, l, r) => write!(f, "Gt R{}, R{}, R{}", d, l, r),
181            Instruction::Ge(d, l, r) => write!(f, "Ge R{}, R{}, R{}", d, l, r),
182            Instruction::And(d, l, r) => write!(f, "And R{}, R{}, R{}", d, l, r),
183            Instruction::Or(d, l, r) => write!(f, "Or R{}, R{}, R{}", d, l, r),
184            Instruction::Not(d, s) => write!(f, "Not R{}, R{}", d, s),
185            Instruction::Jump(offset) => write!(f, "Jump {}", offset),
186            Instruction::JumpIf(r, offset) => write!(f, "JumpIf R{}, {}", r, offset),
187            Instruction::JumpIfNot(r, offset) => write!(f, "JumpIfNot R{}, {}", r, offset),
188            Instruction::Call(func, args, cnt, dest) => {
189                if *cnt == 0 {
190                    write!(f, "Call R{}, <no args>, R{}", func, dest)
191                } else {
192                    write!(
193                        f,
194                        "Call R{}, R{}..R{}, R{}",
195                        func,
196                        args,
197                        args + cnt - 1,
198                        dest
199                    )
200                }
201            }
202
203            Instruction::Return(r) => write!(f, "Return R{}", r),
204            Instruction::NewArray(d, elems, cnt) => {
205                if *cnt == 0 {
206                    write!(f, "NewArray R{}, <no elements>", d)
207                } else {
208                    let end = (*elems as usize) + (*cnt as usize) - 1;
209                    write!(f, "NewArray R{}, R{}..R{}", d, elems, end)
210                }
211            }
212
213            Instruction::NewMap(r) => write!(f, "NewMap R{}", r),
214            Instruction::NewTable(r) => write!(f, "NewTable R{}", r),
215            Instruction::NewStruct(d, name, field_names, fields, cnt) => {
216                write!(
217                    f,
218                    "NewStruct R{}, K{}, K{}..K{}, R{}..R{}",
219                    d,
220                    name,
221                    field_names,
222                    field_names + (*cnt as u16) - 1,
223                    fields,
224                    fields + cnt - 1
225                )
226            }
227
228            Instruction::NewEnumUnit(d, enum_name, variant) => {
229                write!(f, "NewEnumUnit R{}, K{}, K{}", d, enum_name, variant)
230            }
231
232            Instruction::NewEnumVariant(d, enum_name, variant, values, cnt) => {
233                write!(
234                    f,
235                    "NewEnumVariant R{}, K{}, K{}, R{}..R{}",
236                    d,
237                    enum_name,
238                    variant,
239                    values,
240                    values + cnt - 1
241                )
242            }
243
244            Instruction::TupleNew(d, first, cnt) => {
245                write!(f, "TupleNew R{}, R{}..R{}", d, first, first + cnt - 1)
246            }
247
248            Instruction::TupleGet(d, tuple, idx) => {
249                write!(f, "TupleGet R{}, R{}, {}", d, tuple, idx)
250            }
251
252            Instruction::IsEnumVariant(d, val, enum_name, variant) => {
253                write!(
254                    f,
255                    "IsEnumVariant R{}, R{}, K{}, K{}",
256                    d, val, enum_name, variant
257                )
258            }
259
260            Instruction::GetEnumValue(d, enum_reg, idx) => {
261                write!(f, "GetEnumValue R{}, R{}, {}", d, enum_reg, idx)
262            }
263
264            Instruction::GetField(d, obj, field) => {
265                write!(f, "GetField R{}, R{}, K{}", d, obj, field)
266            }
267
268            Instruction::SetField(obj, field, val) => {
269                write!(f, "SetField R{}, K{}, R{}", obj, field, val)
270            }
271
272            Instruction::GetIndex(d, arr, idx) => write!(f, "GetIndex R{}, R{}, R{}", d, arr, idx),
273            Instruction::ArrayLen(d, arr) => write!(f, "ArrayLen R{}, R{}", d, arr),
274            Instruction::SetIndex(arr, idx, val) => {
275                write!(f, "SetIndex R{}, R{}, R{}", arr, idx, val)
276            }
277
278            Instruction::Concat(d, l, r) => write!(f, "Concat R{}, R{}, R{}", d, l, r),
279            Instruction::CallMethod(obj, method, args, cnt, dest) => {
280                write!(
281                    f,
282                    "CallMethod R{}, K{}, R{}..R{}, R{}",
283                    obj,
284                    method,
285                    args,
286                    args + cnt - 1,
287                    dest
288                )
289            }
290
291            Instruction::TypeIs(d, val, type_name) => {
292                write!(f, "TypeIs R{}, R{}, K{}", d, val, type_name)
293            }
294
295            Instruction::LoadUpvalue(d, idx) => write!(f, "LoadUpvalue R{}, U{}", d, idx),
296            Instruction::StoreUpvalue(idx, s) => write!(f, "StoreUpvalue U{}, R{}", idx, s),
297            Instruction::Closure(d, func, upvals, cnt) => {
298                write!(
299                    f,
300                    "Closure R{}, F{}, R{}..R{}",
301                    d,
302                    func,
303                    upvals,
304                    upvals + cnt - 1
305                )
306            }
307        }
308    }
309}