1use core::mem::size_of;
2
3
4pub type LocalIndex = u16;
5pub type UpvalueIndex = u16;
6
7
8const OP_NOP: u8 = 0x00;
18const OP_EXIT: u8 = 0x01; const OP_ERROR: u8 = 0x02; const OP_RETURN: u8 = 0x08; const OP_CALL: u8 = 0x09;
25const OP_IN_ARGS: u8 = 0x0A;
26
27const OP_POP: u8 = 0x10; const OP_DROP: u8 = 0x11; const OP_DROPN: u8 = 0x12; const OP_CLONE: u8 = 0x13; const OP_SWAP: u8 = 0x14; const OP_SHIFT: u8 = 0x15; const OP_TUPLE: u8 = 0x18; const OP_TUPLEN: u8 = 0x19; const OP_ITER_INIT: u8 = 0x1A; const OP_ITER_NEXT: u8 = 0x1B; const OP_ITER_UNPACK: u8 = 0x1C; const OP_LD_FUN: u8 = 0x40; const OP_LD_FUN_16: u8 = 0x41; const OP_LD_CONST: u8 = 0x42; const OP_LD_CONST_16: u8 = 0x43; const OP_IN_GLOBAL_IM: u8 = 0x48; const OP_IN_GLOBAL_MUT: u8 = 0x49; const OP_ST_GLOBAL: u8 = 0x4A; const OP_LD_GLOBAL: u8 = 0x4B; const OP_DP_GLOBAL: u8 = 0x4C; const OP_IN_LOCAL: u8 = 0x50; const OP_ST_LOCAL: u8 = 0x51; const OP_ST_LOCAL_16: u8 = 0x52; const OP_LD_LOCAL: u8 = 0x53; const OP_LD_LOCAL_16: u8 = 0x54; const OP_DP_LOCALS: u8 = 0x55; const OP_ST_UPVAL: u8 = 0x58; const OP_ST_UPVAL_16: u8 = 0x59; const OP_LD_UPVAL: u8 = 0x5A; const OP_LD_UPVAL_16: u8 = 0x5B; const OP_CLOSE_UPVAL: u8 = 0x5C; const OP_CLOSE_UPVAL_16: u8 = 0x5D; const OP_LD_NIL: u8 = 0x60; const OP_LD_FALSE: u8 = 0x61; const OP_LD_TRUE: u8 = 0x62; const OP_LD_EMPTY: u8 = 0x63; const OP_LD_U8: u8 = 0x64; const OP_LD_I8: u8 = 0x65; const OP_LD_I16: u8 = 0x66; const OP_NEG: u8 = 0x70; const OP_POS: u8 = 0x71;
91const OP_INV: u8 = 0x72;
92const OP_NOT: u8 = 0x73;
93
94const OP_AND: u8 = 0x78; const OP_XOR: u8 = 0x79;
98const OP_OR: u8 = 0x7A;
99const OP_SHL: u8 = 0x7B;
100const OP_SHR: u8 = 0x7C;
101
102const OP_ADD: u8 = 0x80;
103const OP_SUB: u8 = 0x81;
104const OP_MUL: u8 = 0x82;
105const OP_DIV: u8 = 0x83;
106const OP_MOD: u8 = 0x84;
107
108const OP_EQ: u8 = 0x88;
109const OP_NE: u8 = 0x89;
110const OP_LT: u8 = 0x8A;
111const OP_LE: u8 = 0x8B;
112const OP_GE: u8 = 0x8C;
113const OP_GT: u8 = 0x8D;
114
115const OP_JUMP: u8 = 0x90; const OP_JUMP_FALSE: u8 = 0x91; const OP_JUMP_TRUE: u8 = 0x92; const OP_PJMP_FALSE: u8 = 0x93; const OP_PJMP_TRUE: u8 = 0x94; const OP_LJUMP: u8 = 0x98; const OP_LJUMP_FALSE: u8 = 0x99; const OP_LJUMP_TRUE: u8 = 0x9A; const OP_PLJMP_FALSE: u8 = 0x9B; const OP_PLJMP_TRUE: u8 = 0x9C; const DBG_INSPECT: u8 = 0xF0;
132const DBG_ASSERT: u8 = 0xF1;
133const DBG_DUMP_STACK: u8 = 0xF2;
134const DBG_DUMP_GLOBALS: u8 = 0xF3;
135const DBG_DUMP_STRINGS: u8 = 0xF4;
136
137
138#[repr(u8)]
139#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
140pub enum OpCode {
141 Nop = OP_NOP,
142 Exit = OP_EXIT,
143 Error = OP_ERROR,
144
145 Return = OP_RETURN,
146 Call = OP_CALL,
147 InsertArgs = OP_IN_ARGS,
148
149 Pop = OP_POP,
150 Drop = OP_DROP,
151 DropN = OP_DROPN,
152 Clone = OP_CLONE,
153
154 Tuple = OP_TUPLE,
155 TupleN = OP_TUPLEN,
156
157 IterInit = OP_ITER_INIT,
158 IterNext = OP_ITER_NEXT,
159 IterUnpack = OP_ITER_UNPACK,
160
161 LoadFunction = OP_LD_FUN,
162 LoadFunction16 = OP_LD_FUN_16,
163
164 LoadConst = OP_LD_CONST,
165 LoadConst16 = OP_LD_CONST_16,
166
167 InsertGlobal = OP_IN_GLOBAL_IM,
168 InsertGlobalMut = OP_IN_GLOBAL_MUT,
169 StoreGlobal = OP_ST_GLOBAL,
170 LoadGlobal = OP_LD_GLOBAL,
171
172 InsertLocal = OP_IN_LOCAL,
173 StoreLocal = OP_ST_LOCAL,
174 StoreLocal16 = OP_ST_LOCAL_16,
175 LoadLocal = OP_LD_LOCAL,
176 LoadLocal16 = OP_LD_LOCAL_16,
177 DropLocals = OP_DP_LOCALS,
178
179 StoreUpvalue = OP_ST_UPVAL,
180 StoreUpvalue16 = OP_ST_UPVAL_16,
181 LoadUpvalue = OP_LD_UPVAL,
182 LoadUpvalue16 = OP_LD_UPVAL_16,
183
184 CloseUpvalue = OP_CLOSE_UPVAL,
185 CloseUpvalue16 = OP_CLOSE_UPVAL_16,
186
187 Nil = OP_LD_NIL,
188 True = OP_LD_TRUE,
189 False = OP_LD_FALSE,
190 Empty = OP_LD_EMPTY,
191
192 UInt8 = OP_LD_U8,
193 Int8 = OP_LD_I8,
194 Int16 = OP_LD_I16,
195
196 Neg = OP_NEG,
197 Pos = OP_POS,
198 Inv = OP_INV,
199 Not = OP_NOT,
200
201 And = OP_AND,
202 Xor = OP_XOR,
203 Or = OP_OR,
204 Shl = OP_SHL,
205 Shr = OP_SHR,
206 Add = OP_ADD,
207 Sub = OP_SUB,
208 Mul = OP_MUL,
209 Div = OP_DIV,
210 Mod = OP_MOD,
211 EQ = OP_EQ,
212 NE = OP_NE,
213 LT = OP_LT,
214 LE = OP_LE,
215 GE = OP_GE,
216 GT = OP_GT,
217
218 Jump = OP_JUMP,
219 JumpIfFalse = OP_JUMP_FALSE,
220 JumpIfTrue = OP_JUMP_TRUE,
221 PopJumpIfFalse = OP_PJMP_FALSE,
222 PopJumpIfTrue = OP_PJMP_TRUE,
223
224 LongJump = OP_LJUMP,
225 LongJumpIfFalse = OP_LJUMP_FALSE,
226 LongJumpIfTrue = OP_LJUMP_TRUE,
227 PopLongJumpIfFalse = OP_PLJMP_FALSE,
228 PopLongJumpIfTrue = OP_PLJMP_TRUE,
229
230 Inspect = DBG_INSPECT,
231 Assert = DBG_ASSERT,
232}
233
234impl OpCode {
235 #[inline]
236 pub fn from_byte(byte: u8) -> Option<OpCode> {
237 let opcode = match byte {
238 OP_NOP => Self::Nop,
239 OP_EXIT => Self::Exit,
240 OP_ERROR => Self::Error,
241
242 OP_RETURN => Self::Return,
243 OP_CALL => Self::Call,
244 OP_IN_ARGS => Self::InsertArgs,
245
246 OP_POP => Self::Pop,
247 OP_DROP => Self::Drop,
248 OP_DROPN => Self::DropN,
249 OP_CLONE => Self::Clone,
250
251 OP_TUPLE => Self::Tuple,
252 OP_TUPLEN => Self::TupleN,
253
254 OP_ITER_INIT => Self::IterInit,
255 OP_ITER_NEXT => Self::IterNext,
256 OP_ITER_UNPACK => Self::IterUnpack,
257
258 OP_LD_FUN => Self::LoadFunction,
259 OP_LD_FUN_16 => Self::LoadFunction16,
260
261 OP_LD_CONST => Self::LoadConst,
262 OP_LD_CONST_16 => Self::LoadConst16,
263
264 OP_IN_GLOBAL_IM => Self::InsertGlobal,
265 OP_IN_GLOBAL_MUT => Self::InsertGlobalMut,
266 OP_ST_GLOBAL => Self::StoreGlobal,
267 OP_LD_GLOBAL => Self::LoadGlobal,
268
269 OP_IN_LOCAL => Self::InsertLocal,
270 OP_ST_LOCAL => Self::StoreLocal,
271 OP_ST_LOCAL_16 => Self::StoreLocal16,
272 OP_LD_LOCAL => Self::LoadLocal,
273 OP_LD_LOCAL_16 => Self::LoadLocal16,
274 OP_DP_LOCALS => Self::DropLocals,
275
276 OP_ST_UPVAL => Self::StoreUpvalue,
277 OP_ST_UPVAL_16 => Self::StoreUpvalue16,
278 OP_LD_UPVAL => Self::LoadUpvalue,
279 OP_LD_UPVAL_16 => Self::LoadUpvalue16,
280
281 OP_CLOSE_UPVAL => Self::CloseUpvalue,
282 OP_CLOSE_UPVAL_16 => Self::CloseUpvalue16,
283
284 OP_LD_NIL => Self::Nil,
285 OP_LD_TRUE => Self::True,
286 OP_LD_FALSE => Self::False,
287 OP_LD_EMPTY => Self::Empty,
288 OP_LD_U8 => Self::UInt8,
289 OP_LD_I8 => Self::Int8,
290 OP_LD_I16 => Self::Int16,
291
292 OP_NEG => Self::Neg,
293 OP_POS => Self::Pos,
294 OP_INV => Self::Inv,
295 OP_NOT => Self::Not,
296
297 OP_AND => Self::And,
298 OP_XOR => Self::Xor,
299 OP_OR => Self::Or,
300 OP_SHL => Self::Shl,
301 OP_SHR => Self::Shr,
302 OP_ADD => Self::Add,
303 OP_SUB => Self::Sub,
304 OP_MUL => Self::Mul,
305 OP_DIV => Self::Div,
306 OP_MOD => Self::Mod,
307 OP_EQ => Self::EQ,
308 OP_NE => Self::NE,
309 OP_LT => Self::LT,
310 OP_LE => Self::LE,
311 OP_GE => Self::GE,
312 OP_GT => Self::GT,
313
314 OP_JUMP => Self::Jump,
315 OP_JUMP_FALSE => Self::JumpIfFalse,
316 OP_JUMP_TRUE => Self::JumpIfTrue,
317 OP_PJMP_FALSE => Self::PopJumpIfFalse,
318 OP_PJMP_TRUE => Self::PopJumpIfTrue,
319
320 OP_LJUMP => Self::LongJump,
321 OP_LJUMP_FALSE => Self::LongJumpIfFalse,
322 OP_LJUMP_TRUE => Self::LongJumpIfTrue,
323 OP_PLJMP_FALSE => Self::PopLongJumpIfFalse,
324 OP_PLJMP_TRUE => Self::PopLongJumpIfTrue,
325
326 DBG_INSPECT => Self::Inspect,
327 DBG_ASSERT => Self::Assert,
328
329 _ => return None,
330 };
331 Some(opcode)
332 }
333
334 #[inline]
335 pub const fn instr_len(&self) -> usize {
336 match self {
337 Self::Drop => 1 + size_of::<u8>(),
340
341 Self::LoadFunction => 1 + size_of::<u8>(),
342 Self::LoadFunction16 => 1 + size_of::<u16>(),
343
344 Self::LoadConst => 1 + size_of::<u8>(),
345 Self::LoadConst16 => 1 + size_of::<u16>(),
346
347 Self::StoreLocal => 1 + size_of::<u8>(),
348 Self::StoreLocal16 => 1 + size_of::<u16>(),
349 Self::LoadLocal => 1 + size_of::<u8>(),
350 Self::LoadLocal16 => 1 + size_of::<u16>(),
351 Self::DropLocals => 1 + size_of::<u8>(),
352
353 Self::StoreUpvalue => 1 + size_of::<u8>(),
354 Self::StoreUpvalue16 => 1 + size_of::<u16>(),
355 Self::LoadUpvalue => 1 + size_of::<u8>(),
356 Self::LoadUpvalue16 => 1 + size_of::<u16>(),
357
358 Self::CloseUpvalue => 1 + size_of::<u8>(),
359 Self::CloseUpvalue16 => 1 + size_of::<u16>(),
360
361 Self::Tuple => 1 + size_of::<u8>(),
362 Self::UInt8 => 1 + size_of::<u8>(),
363 Self::Int8 => 1 + size_of::<i8>(),
364 Self::Int16 => 1 + size_of::<i16>(),
365
366 Self::Jump => 1 + size_of::<i16>(),
367 Self::JumpIfFalse => 1 + size_of::<i16>(),
368 Self::JumpIfTrue => 1 + size_of::<i16>(),
369 Self::PopJumpIfFalse => 1 + size_of::<i16>(),
370 Self::PopJumpIfTrue => 1 + size_of::<i16>(),
371
372 _ => 1,
373 }
374 }
375}
376
377impl From<OpCode> for u8 {
378 fn from(opcode: OpCode) -> Self { opcode as u8 }
379}
380
381impl TryFrom<u8> for OpCode {
382 type Error = u8;
383 fn try_from(byte: u8) -> Result<Self, u8> {
384 if let Some(opcode) = OpCode::from_byte(byte) {
385 Ok(opcode)
386 } else {
387 Err(byte)
388 }
389 }
390}
391
392impl PartialEq<u8> for OpCode {
393 fn eq(&self, other: &u8) -> bool { *other == (*self).into() }
394}
395
396impl core::fmt::Display for OpCode {
398 fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
399 let mnemonic = match *self {
400 Self::Nop => "NOP",
401 Self::Exit => "EXIT",
402 Self::Error => "ERROR",
403
404 Self::Return => "RETURN",
405 Self::Call => "CALL",
406 Self::InsertArgs => "IN_ARGS",
407
408 Self::Pop => "POP",
409 Self::Drop => "DROP",
410 Self::DropN => "DROPN",
411 Self::Clone => "CLONE",
412
413 Self::Tuple => "TUPLE",
414 Self::TupleN => "TUPLEN",
415
416 Self::IterInit => "ITER_INIT",
417 Self::IterNext => "ITER_NEXT",
418 Self::IterUnpack => "ITER_UNPACK",
419
420 Self::LoadFunction => "LD_FUN",
421 Self::LoadFunction16 => "LD_FUN_16",
422
423 Self::LoadConst => "LD_CONST",
424 Self::LoadConst16 => "LD_CONST_16",
425
426 Self::InsertGlobal => "IN_GLOBAL_IM",
427 Self::InsertGlobalMut => "IN_GLOBAL_MUT",
428 Self::StoreGlobal => "ST_GLOBAL",
429 Self::LoadGlobal => "LD_GLOBAL",
430
431 Self::InsertLocal => "IN_LOCAL",
432 Self::StoreLocal => "ST_LOCAL",
433 Self::StoreLocal16 => "ST_LOCAL_16",
434 Self::LoadLocal => "LD_LOCAL",
435 Self::LoadLocal16 => "LD_LOCAL_16",
436 Self::DropLocals => "DP_LOCALS",
437
438 Self::StoreUpvalue => "ST_UPVAL",
439 Self::StoreUpvalue16 => "ST_UPVAL_16",
440 Self::LoadUpvalue => "LD_UPVAL",
441 Self::LoadUpvalue16 => "LD_UPVAL_16",
442
443 Self::CloseUpvalue => "CLOSE_UPVAL",
444 Self::CloseUpvalue16 => "CLOSE_UPVAL_16",
445
446 Self::Nil => "LD_NIL",
447 Self::True => "LD_TRUE",
448 Self::False => "LD_FALSE",
449 Self::Empty => "LD_EMPTY",
450 Self::UInt8 => "LD_U8",
451 Self::Int8 => "LD_I8",
452 Self::Int16 => "LD_I16",
453
454 Self::Neg => "NEG",
455 Self::Pos => "POS",
456 Self::Inv => "INV",
457 Self::Not => "NOT",
458
459 Self::And => "AND",
460 Self::Xor => "XOR",
461 Self::Or => "OR",
462 Self::Shl => "SHL",
463 Self::Shr => "SHR",
464 Self::Add => "ADD",
465 Self::Sub => "SUB",
466 Self::Mul => "MUL",
467 Self::Div => "DIV",
468 Self::Mod => "MOD",
469 Self::EQ => "CMP_EQ",
470 Self::NE => "CMP_NE",
471 Self::LT => "CMP_LT",
472 Self::LE => "CMP_LE",
473 Self::GE => "CMP_GE",
474 Self::GT => "CMP_GT",
475
476 Self::Jump => "JUMP",
477 Self::JumpIfFalse => "JUMP_FALSE",
478 Self::JumpIfTrue => "JUMP_TRUE",
479 Self::PopJumpIfFalse => "PJMP_FALSE",
480 Self::PopJumpIfTrue => "PJMP_TRUE",
481
482 Self::LongJump => "LJUMP",
483 Self::LongJumpIfFalse => "LJUMP_FALSE",
484 Self::LongJumpIfTrue => "LJUMP_TRUE",
485 Self::PopLongJumpIfFalse => "PLJMP_FALSE",
486 Self::PopLongJumpIfTrue => "PLJMP_TRUE",
487
488 Self::Inspect => "DBG_INSPECT",
489 Self::Assert => "DBG_ASSERT",
490 };
491
492 if let Some(width) = fmt.width() {
493 write!(fmt, "{:1$}", mnemonic, width)
494 } else {
495 fmt.write_str(mnemonic)
496 }
497 }
498}