1use serde::{Deserialize, Serialize};
2
3macro_rules! declare_opcodes {
4
5 ( { $($variant:tt);* } { $( [ $super:tt => $(($k:path, $v:expr),)* ] );* } ) => {
6 #[repr(u8)]
7 #[derive(Copy, Clone, Debug, Hash, PartialEq, Serialize, Deserialize, Eq, PartialOrd, Ord)]
8 pub enum OpCode {
9 $($variant),*
10
11 ,
12
13 $($super),*
14 }
15
16 pub const fn op_code_to_super_instruction_pattern(op_code: OpCode) -> Option<&'static [(OpCode, usize)]> {
19 match op_code {
20 $(OpCode::$super => Some( &[ $(($k, $v)),* ]) ),* ,
21 _ => None
22 }
23 }
24
25 pub const fn sequence_to_opcode(pattern: &[(OpCode, usize)]) -> Option<OpCode> {
26 match pattern {
27 $(&[ $(($k, _)),* ] => Some(OpCode::$super) ),* ,
28 _ => None
29 }
30 }
31
32 pub static PATTERNS: &'static [&'static [(OpCode, usize)]] = &[
33 $( &[ $(($k, $v)),* ] ),* ,
34 ];
35 }
36
37}
38
39declare_opcodes! {
40 {
41 VOID;
42 PUSH;
43 IF;
44 JMP;
45 FUNC;
46 SCLOSURE;
47 ECLOSURE;
48 BIND;
49 SDEF;
50 EDEF;
51 POPPURE;
52 POPN;
53 POPSINGLE;
54 PASS;
55 PUSHCONST;
56 NDEFS;
57 PANIC;
58 TAILCALL;
59 SET;
60 READLOCAL;
61 READLOCAL0;
62 READLOCAL1;
63 READLOCAL2;
64 READLOCAL3;
65 SETLOCAL;
66 COPYCAPTURESTACK;
67 COPYCAPTURECLOSURE;
68 COPYHEAPCAPTURECLOSURE;
69 FIRSTCOPYHEAPCAPTURECLOSURE;
70 TCOJMP;
71 CALLGLOBAL;
72 CALLGLOBALTAIL;
73 LOADINT0; LOADINT1;
75 LOADINT2;
76 CGLOCALCONST;
77 MOVEREADLOCAL;
78 MOVEREADLOCAL0;
79 MOVEREADLOCAL1;
80 MOVEREADLOCAL2;
81 MOVEREADLOCAL3;
82 READCAPTURED;
83 BEGINSCOPE;
84 LETENDSCOPE;
85 PUREFUNC;
86 ADD;
87 SUB;
88 MUL;
89 DIV;
90 EQUAL;
91 NUMEQUAL;
92 NULL;
93 LTE;
94 CONS; LIST;
96 CAR;
97 CDR;
98 NEWBOX;
99 SETBOX;
100 UNBOX;
101 NEWSCLOSURE;
102 ADDREGISTER;
103 SUBREGISTER;
104 LTEREGISTER;
105 SUBREGISTER1;
106 ALLOC;
107 READALLOC;
108 SETALLOC;
109 DynSuperInstruction;
110 Arity;
111 LetVar;
112 ADDIMMEDIATE;
113 SUBIMMEDIATE;
114 LTEIMMEDIATE;
115 BINOPADD;
116 BINOPSUB;
117 LTEIMMEDIATEIF;
118 NOT;
119 VEC;
120 Apply;
121 POPJMP;
122 CALLGLOBALTAILPOP;
123 BINOPADDTAIL;
124 LOADINT0POP; LOADINT1POP;
126 LOADINT2POP
127 }
128
129 {
131
132
133 [
134 CaseLambdaDispatch =>
135 (OpCode::BEGINSCOPE, 0),
136 (OpCode::READLOCAL0, 0),
137 (OpCode::CALLGLOBAL, 75),
138 (OpCode::FUNC, 1),
139 (OpCode::READLOCAL1, 1),
140 (OpCode::PUSHCONST, 565),
141 (OpCode::CALLGLOBAL, 75),
142 (OpCode::FUNC, 1),
143 (OpCode::NUMEQUAL, 2),
144 (OpCode::PASS, 2),
145 (OpCode::IF, 22),
146 ]
147
148 }
194}
195
196impl OpCode {
205 pub fn is_super_instruction(&self) -> bool {
207 *self as u32 > Self::LTEIMMEDIATEIF as u32
209 }
210
211 pub fn super_instructions(&self) -> &'static [&'static [(OpCode, usize)]] {
214 todo!()
215 }
216
217 pub fn is_ephemeral_opcode(&self) -> bool {
218 use OpCode::*;
219
220 matches!(
221 self,
222 ECLOSURE
223 | PASS
224 | Arity
225 | NDEFS
226 | COPYCAPTURECLOSURE
227 | COPYCAPTURESTACK
228 | COPYHEAPCAPTURECLOSURE,
229 )
230 }
231
232 pub fn from(s: &str) -> Self {
234 use OpCode::*;
235 match s {
236 "VOID" => VOID,
237 "PUSH" => PUSH,
238 "IF" => IF,
239 "JMP" => JMP,
240 "FUNC" => FUNC,
241 "SCLOSURE" => SCLOSURE,
242 "ECLOSURE" => ECLOSURE,
243 "BIND" => BIND,
245 "SDEF" => SDEF,
246 "EDEF" => EDEF,
247 "PASS" => PASS,
248 "PUSHCONST" => PUSHCONST,
249 "NDEFS" => NDEFS,
250 "PANIC" => PANIC,
251 "TAILCALL" => TAILCALL,
252 "SET" => SET,
253 "READLOCAL" => READLOCAL,
254 "SETLOCAL" => SETLOCAL,
255 "TCOJMP" => TCOJMP,
256 "CALLGLOBAL" => CALLGLOBAL,
257 "CALLGLOBALTAIL" => CALLGLOBALTAIL,
258 "LOADINT0" => LOADINT0, "LOADINT1" => LOADINT1,
260 "LOADINT2" => LOADINT2,
261 "CGLOCALCONST" => CGLOCALCONST,
262 "MOVEREADLOCAL" => MOVEREADLOCAL,
263 "BEGINSCOPE" => BEGINSCOPE,
264 "ADD" => ADD,
265 "SUB" => SUB,
266 "MUL" => MUL,
267 "DIV" => DIV,
268 "EQUAL" => EQUAL,
269 "LTE" => LTE,
270 "LETENDSCOPE" => LETENDSCOPE,
271 "PUREFUNC" => PUREFUNC,
272 "POP_PURE" => POPPURE,
273 "READCAPTURED" => READCAPTURED,
274 "COPYCAPTURESTACK" => COPYCAPTURESTACK,
275 "COPYCAPTURECLOSURE" => COPYCAPTURECLOSURE,
276 "COPYHEAPCAPTURECLOSURE" => COPYHEAPCAPTURECLOSURE,
277 "NEWSCLOSURE" => NEWSCLOSURE,
278 "ADDREGISTER" => ADDREGISTER,
279 "SUBREGISTER" => SUBREGISTER,
280 "LTEREGISTER" => LTEREGISTER,
281 "SUBREGISTER1" => SUBREGISTER1,
282 "ALLOC" => ALLOC,
283 "READALLOC" => READALLOC,
284 "SETALLOC" => SETALLOC,
285 _ => panic!("Unable to map string to opcode"),
286 }
287 }
288
289 pub fn width(&self) -> usize {
290 match self {
291 OpCode::VOID => todo!(),
292 OpCode::PUSH => todo!(),
293 OpCode::IF => todo!(),
294 OpCode::JMP => todo!(),
295 OpCode::FUNC => todo!(),
296 OpCode::SCLOSURE => todo!(),
297 OpCode::ECLOSURE => todo!(),
298 OpCode::BIND => todo!(),
300 OpCode::SDEF => todo!(),
301 OpCode::EDEF => todo!(),
302 OpCode::POPPURE => todo!(),
303 OpCode::PASS => todo!(),
304 OpCode::PUSHCONST => todo!(),
305 OpCode::NDEFS => todo!(),
306 OpCode::PANIC => todo!(),
307 OpCode::TAILCALL => todo!(),
308 OpCode::SET => todo!(),
309 OpCode::READLOCAL => todo!(),
310 OpCode::SETLOCAL => todo!(),
311 OpCode::COPYCAPTURESTACK => todo!(),
312 OpCode::COPYCAPTURECLOSURE => todo!(),
313 OpCode::TCOJMP => todo!(),
314 OpCode::CALLGLOBAL => 2,
315 OpCode::CALLGLOBALTAIL => todo!(),
316 OpCode::LOADINT0 => todo!(),
317 OpCode::LOADINT1 => todo!(),
318 OpCode::LOADINT2 => todo!(),
319 OpCode::CGLOCALCONST => todo!(),
320 OpCode::MOVEREADLOCAL => todo!(),
321 OpCode::READCAPTURED => todo!(),
322 OpCode::BEGINSCOPE => todo!(),
323 OpCode::LETENDSCOPE => todo!(),
324 OpCode::PUREFUNC => todo!(),
325 OpCode::ADD => 2,
326 OpCode::SUB => todo!(),
327 OpCode::MUL => todo!(),
328 OpCode::DIV => todo!(),
329 OpCode::EQUAL => todo!(),
330 OpCode::LTE => todo!(),
331 OpCode::NEWSCLOSURE => todo!(),
332 OpCode::ADDREGISTER => 2,
333 OpCode::SUBREGISTER => 2,
334 OpCode::LTEREGISTER => 2,
335 OpCode::SUBREGISTER1 => todo!(),
336 OpCode::ALLOC => todo!(),
337 _ => todo!(),
338 }
339 }
340}