erg_common/
opcode.rs

1//! defines `Opcode` (represents Python bytecode opcodes).
2//!
3//! Opcode(Pythonバイトコードオペコードを表す)を定義する
4
5#![allow(dead_code)]
6#![allow(non_camel_case_types)]
7
8use crate::{impl_display_from_debug, impl_u8_enum};
9
10/// Based on Python opcodes.
11/// This is represented by u8.
12#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Ord, Eq)]
13#[repr(u8)]
14pub enum CommonOpcode {
15    POP_TOP = 1,
16    // ROT_TWO = 2,
17    // ROT_THREE = 3,
18    // DUP_TOP = 4,
19    // DUP_TOP2 = 5,
20    // ROT_FOUR = 6,
21    NOP = 9,
22    UNARY_POSITIVE = 10,
23    UNARY_NEGATIVE = 11,
24    UNARY_NOT = 12,
25    UNARY_INVERT = 15,
26    BINARY_MATRIX_MULTIPLY = 16,
27    INPLACE_MATRIX_MULTIPLY = 17,
28    STORE_SUBSCR = 60,
29    GET_ITER = 68,
30    GET_YIELD_FROM_ITER = 69,
31    PRINT_EXPR = 70,
32    LOAD_BUILD_CLASS = 71,
33    RETURN_VALUE = 83,
34    IMPORT_STAR = 84,
35    YIELD_VALUE = 86,
36    POP_BLOCK = 87,
37    POP_EXCEPT = 89,
38    /* ↓ These opcodes take an arg */
39    STORE_NAME = 90,
40    DELETE_NAME = 91,
41    FOR_ITER = 93,
42    UNPACK_EX = 94,
43    STORE_ATTR = 95,
44    STORE_GLOBAL = 97,
45    LOAD_CONST = 100,
46    LOAD_NAME = 101,
47    BUILD_TUPLE = 102,
48    BUILD_LIST = 103,
49    BUILD_SET = 104,
50    BUILD_MAP = 105, // build a Dict object
51    LOAD_ATTR = 106,
52    COMPARE_OP = 107,
53    IMPORT_NAME = 108,
54    IMPORT_FROM = 109,
55    // JUMP_FORWARD = 110,
56    JUMP_IF_FALSE_OR_POP = 111,
57    JUMP_IF_TRUE_OR_POP = 112,
58    // JUMP_ABSOLUTE = 113,
59    // POP_JUMP_IF_FALSE = 114,
60    // POP_JUMP_IF_TRUE = 115,
61    LOAD_GLOBAL = 116,
62    CONTAINS_OP = 118,
63    LOAD_FAST = 124,
64    STORE_FAST = 125,
65    DELETE_FAST = 126,
66    RAISE_VARARGS = 130,
67    MAKE_FUNCTION = 132,
68    CALL_FUNCTION_EX = 142,
69    EXTENDED_ARG = 144,
70    BUILD_CONST_KEY_MAP = 156,
71    BUILD_STRING = 157,
72    LOAD_METHOD = 160,
73    NOT_IMPLEMENTED = 255,
74}
75
76use CommonOpcode::*;
77
78impl_display_from_debug!(CommonOpcode);
79
80impl TryFrom<u8> for CommonOpcode {
81    type Error = ();
82    fn try_from(byte: u8) -> Result<Self, ()> {
83        Ok(match byte {
84            1 => POP_TOP,
85            // 2 => ROT_TWO,
86            // 3 => ROT_THREE,
87            // 4 => DUP_TOP,
88            // 5 => DUP_TOP2,
89            // 6 => ROT_FOUR,
90            9 => NOP,
91            10 => UNARY_POSITIVE,
92            11 => UNARY_NEGATIVE,
93            12 => UNARY_NOT,
94            15 => UNARY_INVERT,
95            60 => STORE_SUBSCR,
96            68 => GET_ITER,
97            69 => GET_YIELD_FROM_ITER,
98            70 => PRINT_EXPR,
99            71 => LOAD_BUILD_CLASS,
100            83 => RETURN_VALUE,
101            84 => IMPORT_STAR,
102            86 => YIELD_VALUE,
103            87 => POP_BLOCK,
104            89 => POP_EXCEPT,
105            /* ↓ These opcodes take an arg */
106            90 => STORE_NAME,
107            91 => DELETE_NAME,
108            93 => FOR_ITER,
109            94 => UNPACK_EX,
110            95 => STORE_ATTR,
111            97 => STORE_GLOBAL,
112            100 => LOAD_CONST,
113            101 => LOAD_NAME,
114            102 => BUILD_TUPLE,
115            103 => BUILD_LIST,
116            104 => BUILD_SET,
117            105 => BUILD_MAP,
118            106 => LOAD_ATTR,
119            107 => COMPARE_OP,
120            108 => IMPORT_NAME,
121            109 => IMPORT_FROM,
122            // 110 => JUMP_FORWARD,
123            111 => JUMP_IF_FALSE_OR_POP,
124            112 => JUMP_IF_TRUE_OR_POP,
125            // 113 => JUMP_ABSOLUTE,
126            // 114 => POP_JUMP_IF_FALSE,
127            // 115 => POP_JUMP_IF_TRUE,
128            116 => LOAD_GLOBAL,
129            118 => CONTAINS_OP,
130            124 => LOAD_FAST,
131            125 => STORE_FAST,
132            126 => DELETE_FAST,
133            130 => RAISE_VARARGS,
134            132 => MAKE_FUNCTION,
135            142 => CALL_FUNCTION_EX,
136            144 => EXTENDED_ARG,
137            156 => BUILD_CONST_KEY_MAP,
138            157 => BUILD_STRING,
139            160 => LOAD_METHOD,
140            255 => NOT_IMPLEMENTED,
141            _other => return Err(()),
142        })
143    }
144}
145
146impl From<CommonOpcode> for u8 {
147    fn from(op: CommonOpcode) -> u8 {
148        op as u8
149    }
150}
151
152impl CommonOpcode {
153    pub const fn take_arg(&self) -> bool {
154        90 <= (*self as u8) && (*self as u8) < 220
155    }
156
157    pub fn is_jump_op(op: u8) -> bool {
158        [93, 110, 111, 112, 113, 114, 115, 140, 143, 175, 176].contains(&op)
159    }
160}
161
162impl_u8_enum! {CompareOp;
163    LT = 0,
164    LE = 1,
165    EQ = 2,
166    NE = 3,
167    GT = 4,
168    GE = 5,
169}
170
171impl CompareOp {
172    fn show_op(&self) -> &str {
173        match self {
174            CompareOp::LT => "<",
175            CompareOp::LE => "<=",
176            CompareOp::EQ => "==",
177            CompareOp::NE => "!=",
178            CompareOp::GT => ">",
179            CompareOp::GE => ">=",
180        }
181    }
182}