mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-28 12:14:43 +00:00
306 lines
8.8 KiB
Rust
306 lines
8.8 KiB
Rust
//! defines `Opcode` (represents Python bytecode opcodes).
|
|
//!
|
|
//! Opcode(Pythonバイトコードオペコードを表す)を定義する
|
|
|
|
#![allow(dead_code)]
|
|
#![allow(non_camel_case_types)]
|
|
|
|
use crate::impl_display_from_debug;
|
|
|
|
/// Based on Python opcodes.
|
|
/// This is represented by u8.
|
|
///
|
|
/// TODO: implement all opcodes
|
|
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Ord, Eq)]
|
|
#[repr(u8)]
|
|
pub enum Opcode {
|
|
POP_TOP = 1,
|
|
ROT_TWO = 2,
|
|
ROT_THREE = 3,
|
|
DUP_TOP = 4,
|
|
DUP_TOP2 = 5,
|
|
ROT_FOUR = 6,
|
|
NOP = 9,
|
|
UNARY_POSITIVE = 10,
|
|
UNARY_NEGATIVE = 11,
|
|
UNARY_NOT = 12,
|
|
UNARY_INVERT = 15,
|
|
BINARY_MATRIX_MULTIPLY = 16,
|
|
INPLACE_MATRIX_MULTIPLY = 17,
|
|
BINARY_POWER = 19,
|
|
BINARY_MULTIPLY = 20,
|
|
BINARY_MODULO = 22,
|
|
BINARY_ADD = 23,
|
|
BINARY_SUBTRACT = 24,
|
|
BINARY_SUBSCR = 25,
|
|
BINARY_TRUE_DIVIDE = 27,
|
|
INPLACE_FLOOR_DIVIDE = 28,
|
|
INPLACE_TRUE_DIVIDE = 29,
|
|
GET_LEN = 30,
|
|
MATCH_MAPPING = 31,
|
|
MATCH_SEQUENCE = 32,
|
|
MATCH_KEYS = 33,
|
|
PUSH_EXC_INFO = 35,
|
|
CHECK_EXC_MATCH = 36,
|
|
CHECK_EG_MATCH = 37,
|
|
WITH_EXCEPT_START = 49,
|
|
GET_AITER = 50,
|
|
GET_ANEXT = 51,
|
|
BEFORE_ASYNC_WITH = 52,
|
|
BEFORE_WITH = 53,
|
|
END_ASYNC_FOR = 54,
|
|
// TODO:
|
|
INPLACE_ADD = 55,
|
|
INPLACE_SUBTRACT = 56,
|
|
INPLACE_MULTIPLY = 57,
|
|
INPLACE_MODULO = 59,
|
|
STORE_SUBSCR = 60,
|
|
BINARY_AND = 64,
|
|
BINARY_XOR = 65,
|
|
BINARY_OR = 66,
|
|
GET_ITER = 68,
|
|
GET_YIELD_FROM_ITER = 69,
|
|
PRINT_EXPR = 70,
|
|
LOAD_BUILD_CLASS = 71,
|
|
LOAD_ASSERTION_ERROR = 74,
|
|
LIST_TO_TUPLE = 82,
|
|
RETURN_VALUE = 83,
|
|
/* ↓ These opcodes take an arg */
|
|
STORE_NAME = 90,
|
|
DELETE_NAME = 91,
|
|
UNPACK_SEQUENCE = 92,
|
|
FOR_ITER = 93,
|
|
UNPACK_EX = 94,
|
|
STORE_ATTR = 95,
|
|
STORE_GLOBAL = 97,
|
|
LOAD_CONST = 100,
|
|
LOAD_NAME = 101,
|
|
BUILD_TUPLE = 102,
|
|
BUILD_LIST = 103,
|
|
BUILD_SET = 104,
|
|
BUILD_MAP = 105, // build a Dict object
|
|
LOAD_ATTR = 106,
|
|
COMPARE_OP = 107,
|
|
IMPORT_NAME = 108,
|
|
IMPORT_FROM = 109,
|
|
JUMP_FORWARD = 110,
|
|
JUMP_IF_FALSE_OR_POP = 111,
|
|
JUMP_IF_TRUE_OR_POP = 112,
|
|
JUMP_ABSOLUTE = 113,
|
|
POP_JUMP_IF_FALSE = 114,
|
|
POP_JUMP_IF_TRUE = 115,
|
|
LOAD_GLOBAL = 116,
|
|
IS_OP = 117,
|
|
CONTAINS_OP = 118,
|
|
LOAD_FAST = 124,
|
|
STORE_FAST = 125,
|
|
DELETE_FAST = 126,
|
|
RAISE_VARARGS = 130,
|
|
CALL_FUNCTION = 131,
|
|
MAKE_FUNCTION = 132,
|
|
LOAD_CLOSURE = 135,
|
|
LOAD_DEREF = 136,
|
|
STORE_DEREF = 137,
|
|
CALL_FUNCTION_KW = 141,
|
|
CALL_FUNCTION_EX = 142,
|
|
LOAD_METHOD = 160,
|
|
CALL_METHOD = 161,
|
|
LIST_EXTEND = 162,
|
|
// Erg-specific opcodes (must have a unary `ERG_`)
|
|
// Define in descending order from 219, 255
|
|
ERG_POP_NTH = 196,
|
|
ERG_PEEK_NTH = 197, // get ref to the arg-th element from TOS
|
|
ERG_INC = 198, // name += 1; arg: typecode
|
|
ERG_DEC = 199, // name -= 1
|
|
ERG_LOAD_FAST_IMMUT = 200,
|
|
ERG_STORE_FAST_IMMUT = 201,
|
|
ERG_MOVE_FAST = 202,
|
|
ERG_CLONE_FAST = 203,
|
|
ERG_COPY_FAST = 204,
|
|
ERG_REF_FAST = 205,
|
|
ERG_REF_MUT_FAST = 206,
|
|
ERG_MOVE_OUTER = 207,
|
|
ERG_CLONE_OUTER = 208,
|
|
ERG_COPY_OUTER = 209,
|
|
ERG_REF_OUTER = 210,
|
|
ERG_REF_MUT_OUTER = 211,
|
|
ERG_LESS_THAN = 212,
|
|
ERG_LESS_EQUAL = 213,
|
|
ERG_EQUAL = 214,
|
|
ERG_NOT_EQUAL = 215,
|
|
ERG_MAKE_SLOT = 216,
|
|
ERG_MAKE_TYPE = 217,
|
|
ERG_MAKE_PURE_FUNCTION = 218,
|
|
ERG_CALL_PURE_FUNCTION = 219,
|
|
/* ↑ These opcodes take an arg ↑ */
|
|
/* ↓ These opcodes take no arg ↓ */
|
|
// ... = 220,
|
|
ERG_LOAD_EMPTY_SLOT = 242,
|
|
ERG_LOAD_EMPTY_STR = 243,
|
|
ERG_LOAD_1_NAT = 244,
|
|
ERG_LOAD_1_INT = 245,
|
|
ERG_LOAD_1_REAL = 246,
|
|
ERG_LOAD_NONE = 247,
|
|
ERG_MUTATE = 248, // !x
|
|
/// `[] =` (it doesn't cause any exceptions)
|
|
ERG_STORE_SUBSCR = 249,
|
|
// ... = 250,
|
|
/// `= []` (it doesn't cause any exceptions)
|
|
ERG_BINARY_SUBSCR = 251,
|
|
ERG_BINARY_RANGE = 252,
|
|
/// `/?` (rhs may be 0, it may cause a runtime panic)
|
|
ERG_TRY_BINARY_DIVIDE = 253,
|
|
/// `/` (rhs could not be 0, it doesn't cause any exceptions)
|
|
ERG_BINARY_TRUE_DIVIDE = 254,
|
|
NOT_IMPLEMENTED = 255,
|
|
}
|
|
|
|
use Opcode::*;
|
|
|
|
impl_display_from_debug!(Opcode);
|
|
|
|
impl From<u8> for Opcode {
|
|
fn from(byte: u8) -> Self {
|
|
match byte {
|
|
1 => POP_TOP,
|
|
2 => ROT_TWO,
|
|
3 => ROT_THREE,
|
|
4 => DUP_TOP,
|
|
5 => DUP_TOP2,
|
|
6 => ROT_FOUR,
|
|
9 => NOP,
|
|
10 => UNARY_POSITIVE,
|
|
11 => UNARY_NEGATIVE,
|
|
12 => UNARY_NOT,
|
|
15 => UNARY_INVERT,
|
|
19 => BINARY_POWER,
|
|
20 => BINARY_MULTIPLY,
|
|
22 => BINARY_MODULO,
|
|
23 => BINARY_ADD,
|
|
24 => BINARY_SUBTRACT,
|
|
25 => BINARY_SUBSCR,
|
|
27 => BINARY_TRUE_DIVIDE,
|
|
28 => INPLACE_FLOOR_DIVIDE,
|
|
29 => INPLACE_TRUE_DIVIDE,
|
|
30 => GET_LEN,
|
|
31 => MATCH_MAPPING,
|
|
32 => MATCH_SEQUENCE,
|
|
33 => MATCH_KEYS,
|
|
35 => PUSH_EXC_INFO,
|
|
36 => CHECK_EXC_MATCH,
|
|
37 => CHECK_EG_MATCH,
|
|
49 => WITH_EXCEPT_START,
|
|
50 => GET_AITER,
|
|
51 => GET_ANEXT,
|
|
52 => BEFORE_ASYNC_WITH,
|
|
53 => BEFORE_WITH,
|
|
54 => END_ASYNC_FOR,
|
|
55 => INPLACE_ADD,
|
|
56 => INPLACE_SUBTRACT,
|
|
57 => INPLACE_MULTIPLY,
|
|
59 => INPLACE_MODULO,
|
|
60 => STORE_SUBSCR,
|
|
64 => BINARY_AND,
|
|
65 => BINARY_XOR,
|
|
66 => BINARY_OR,
|
|
68 => GET_ITER,
|
|
69 => GET_YIELD_FROM_ITER,
|
|
70 => PRINT_EXPR,
|
|
71 => LOAD_BUILD_CLASS,
|
|
74 => LOAD_ASSERTION_ERROR,
|
|
82 => LIST_TO_TUPLE,
|
|
83 => RETURN_VALUE,
|
|
/* ↓ These opcodes take an arg */
|
|
90 => STORE_NAME,
|
|
91 => DELETE_NAME,
|
|
92 => UNPACK_SEQUENCE,
|
|
93 => FOR_ITER,
|
|
94 => UNPACK_EX,
|
|
95 => STORE_ATTR,
|
|
97 => STORE_GLOBAL,
|
|
100 => LOAD_CONST,
|
|
101 => LOAD_NAME,
|
|
102 => BUILD_TUPLE,
|
|
103 => BUILD_LIST,
|
|
104 => BUILD_SET,
|
|
105 => BUILD_MAP,
|
|
106 => LOAD_ATTR,
|
|
107 => COMPARE_OP,
|
|
108 => IMPORT_NAME,
|
|
109 => IMPORT_FROM,
|
|
110 => JUMP_FORWARD,
|
|
111 => JUMP_IF_FALSE_OR_POP,
|
|
112 => JUMP_IF_TRUE_OR_POP,
|
|
113 => JUMP_ABSOLUTE,
|
|
114 => POP_JUMP_IF_FALSE,
|
|
115 => POP_JUMP_IF_TRUE,
|
|
116 => LOAD_GLOBAL,
|
|
117 => IS_OP,
|
|
118 => CONTAINS_OP,
|
|
124 => LOAD_FAST,
|
|
125 => STORE_FAST,
|
|
126 => DELETE_FAST,
|
|
130 => RAISE_VARARGS,
|
|
131 => CALL_FUNCTION,
|
|
132 => MAKE_FUNCTION,
|
|
135 => LOAD_CLOSURE,
|
|
136 => LOAD_DEREF,
|
|
137 => STORE_DEREF,
|
|
141 => CALL_FUNCTION_KW,
|
|
142 => CALL_FUNCTION_EX,
|
|
160 => LOAD_METHOD,
|
|
161 => CALL_METHOD,
|
|
162 => LIST_EXTEND,
|
|
// Erg-specific opcodes
|
|
196 => ERG_POP_NTH,
|
|
197 => ERG_PEEK_NTH,
|
|
198 => ERG_INC,
|
|
199 => ERG_DEC,
|
|
200 => ERG_LOAD_FAST_IMMUT,
|
|
201 => ERG_STORE_FAST_IMMUT,
|
|
202 => ERG_MOVE_FAST,
|
|
203 => ERG_CLONE_FAST,
|
|
204 => ERG_COPY_FAST,
|
|
205 => ERG_REF_FAST,
|
|
206 => ERG_REF_MUT_FAST,
|
|
207 => ERG_MOVE_OUTER,
|
|
208 => ERG_CLONE_OUTER,
|
|
209 => ERG_COPY_OUTER,
|
|
210 => ERG_REF_OUTER,
|
|
211 => ERG_REF_MUT_OUTER,
|
|
212 => ERG_LESS_THAN,
|
|
213 => ERG_LESS_EQUAL,
|
|
214 => ERG_EQUAL,
|
|
215 => ERG_NOT_EQUAL,
|
|
// ERG_GREATER_THAN is not necessary (can be done by inverting the argument of LESS_THAN)
|
|
216 => ERG_MAKE_SLOT,
|
|
217 => ERG_MAKE_TYPE,
|
|
218 => ERG_MAKE_PURE_FUNCTION,
|
|
219 => ERG_CALL_PURE_FUNCTION,
|
|
/* ↑ These opcodes take an arg ↑ */
|
|
/* ↓ These opcodes take no arg ↓ */
|
|
// ... = 220,
|
|
242 => ERG_LOAD_EMPTY_SLOT,
|
|
243 => ERG_LOAD_EMPTY_STR,
|
|
244 => ERG_LOAD_1_NAT,
|
|
245 => ERG_LOAD_1_INT,
|
|
246 => ERG_LOAD_1_REAL,
|
|
247 => ERG_LOAD_NONE,
|
|
248 => ERG_MUTATE,
|
|
249 => ERG_STORE_SUBSCR,
|
|
// 250 =>
|
|
251 => ERG_BINARY_SUBSCR,
|
|
252 => ERG_BINARY_RANGE,
|
|
253 => ERG_TRY_BINARY_DIVIDE,
|
|
254 => ERG_BINARY_TRUE_DIVIDE,
|
|
255 => NOT_IMPLEMENTED,
|
|
other => panic!("not implemented opcode: {other}"),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Opcode {
|
|
pub const fn take_arg(&self) -> bool {
|
|
90 <= (*self as u8) && (*self as u8) < 220
|
|
}
|
|
}
|