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}