1use serde::{Deserialize, Serialize};
2
3macro_rules! declare_opcodes {
4
5 ( { $($variant:tt);* } ) => {
6 #[derive(Copy, Clone, Debug, Hash, PartialEq, Serialize, Deserialize, Eq, PartialOrd, Ord)]
8 pub enum OpCode {
9 $($variant),*
10 }
11
12 pub const MAX_OPCODE_SIZE: usize = OpCode::CALLPRIMITIVETAIL as usize + 1;
13
14 pub const OPCODES_ARRAY: [OpCode; MAX_OPCODE_SIZE] = [
15 $(OpCode::$variant),*
16 ];
17 }
18
19}
20
21declare_opcodes! {
22 {
23 VOID;
24 PUSH;
25 IF;
26 JMP;
27 FUNC;
28 SCLOSURE;
29 ECLOSURE;
30 BIND;
31 SDEF;
32 EDEF;
33 POPPURE;
34 POPN;
35 POPSINGLE;
36 PASS;
37 PUSHCONST;
38 NDEFS;
39 PANIC;
40 TAILCALL;
41 SET;
42 READLOCAL;
43 READLOCAL0;
44 READLOCAL1;
45 READLOCAL2;
46 READLOCAL3;
47 SETLOCAL;
48 COPYCAPTURESTACK;
49 COPYCAPTURECLOSURE;
50 COPYHEAPCAPTURECLOSURE;
51 FIRSTCOPYHEAPCAPTURECLOSURE;
52 TCOJMP;
53 CALLGLOBAL;
54 CALLGLOBALTAIL;
55 LOADINT0; LOADINT1;
57 LOADINT2;
58 CGLOCALCONST;
59 MOVEREADLOCAL;
60 MOVEREADLOCAL0;
61 MOVEREADLOCAL1;
62 MOVEREADLOCAL2;
63 MOVEREADLOCAL3;
64 READCAPTURED;
65 BEGINSCOPE;
66 LETENDSCOPE;
67 PUREFUNC;
68 ADD;
69 SUB;
70 MUL;
71 DIV;
72 EQUAL;
73 NUMEQUAL;
74 NULL;
75 LTE;
76 GTE;
77 GT;
78 LT;
79 CONS; LIST;
81 CAR;
82 CDR;
83 NEWBOX;
84 SETBOX;
85 UNBOX;
86 NEWSCLOSURE;
87 ADDREGISTER;
88 SUBREGISTER;
89 LTEREGISTER;
90 SUBREGISTER1;
91 ALLOC;
92 READALLOC;
93 SETALLOC;
94 DynSuperInstruction;
95 Arity;
96 LetVar;
97 ADDIMMEDIATE;
98 SUBIMMEDIATE;
99 LTEIMMEDIATE;
100 BINOPADD;
101 BINOPSUB;
102 LTEIMMEDIATEIF;
103 NOT;
104 VEC;
105 Apply;
106 POPJMP;
107 BINOPADDTAIL;
108 LOADINT0POP; LOADINT1POP;
110 LOADINT2POP;
111 READLOCAL0CALLGLOBAL;
112 READLOCAL1CALLGLOBAL;
113 LISTREF;
114 VECTORREF;
115 TRUE;
116 FALSE;
117 NULLIF;
118 UNBOXCALL;
119 UNBOXTAIL;
120 EQUALCONST;
121 EQUAL2;
122 CALLGLOBALNOARITY;
126 CALLGLOBALTAILNOARITY;
127 FUNCNOARITY;
128 TAILCALLNOARITY;
129 SELFTAILCALLNOARITY;
130 CALLPRIMITIVE;
131 CALLPRIMITIVETAIL
132 }
133
134 }
200
201impl OpCode {
210 pub fn is_super_instruction(&self) -> bool {
212 *self as u32 > Self::LTEIMMEDIATEIF as u32
214 }
215
216 pub fn super_instructions(&self) -> &'static [&'static [(OpCode, usize)]] {
219 todo!()
220 }
221
222 pub fn is_ephemeral_opcode(&self) -> bool {
223 use OpCode::*;
224
225 matches!(
226 self,
227 ECLOSURE
228 | PASS
229 | Arity
230 | NDEFS
231 | COPYCAPTURECLOSURE
232 | COPYCAPTURESTACK
233 | COPYHEAPCAPTURECLOSURE,
234 )
235 }
236
237 pub fn from(s: &str) -> Self {
239 use OpCode::*;
240 match s {
241 "VOID" => VOID,
242 "PUSH" => PUSH,
243 "IF" => IF,
244 "JMP" => JMP,
245 "FUNC" => FUNC,
246 "SCLOSURE" => SCLOSURE,
247 "ECLOSURE" => ECLOSURE,
248 "BIND" => BIND,
250 "SDEF" => SDEF,
251 "EDEF" => EDEF,
252 "PASS" => PASS,
253 "PUSHCONST" => PUSHCONST,
254 "NDEFS" => NDEFS,
255 "PANIC" => PANIC,
256 "TAILCALL" => TAILCALL,
257 "SET" => SET,
258 "READLOCAL" => READLOCAL,
259 "SETLOCAL" => SETLOCAL,
260 "TCOJMP" => TCOJMP,
261 "CALLGLOBAL" => CALLGLOBAL,
262 "CALLGLOBALTAIL" => CALLGLOBALTAIL,
263 "LOADINT0" => LOADINT0, "LOADINT1" => LOADINT1,
265 "LOADINT2" => LOADINT2,
266 "CGLOCALCONST" => CGLOCALCONST,
267 "MOVEREADLOCAL" => MOVEREADLOCAL,
268 "BEGINSCOPE" => BEGINSCOPE,
269 "ADD" => ADD,
270 "SUB" => SUB,
271 "MUL" => MUL,
272 "DIV" => DIV,
273 "EQUAL" => EQUAL,
274 "LTE" => LTE,
275 "LETENDSCOPE" => LETENDSCOPE,
276 "PUREFUNC" => PUREFUNC,
277 "POP_PURE" => POPPURE,
278 "READCAPTURED" => READCAPTURED,
279 "COPYCAPTURESTACK" => COPYCAPTURESTACK,
280 "COPYCAPTURECLOSURE" => COPYCAPTURECLOSURE,
281 "COPYHEAPCAPTURECLOSURE" => COPYHEAPCAPTURECLOSURE,
282 "NEWSCLOSURE" => NEWSCLOSURE,
283 "ADDREGISTER" => ADDREGISTER,
284 "SUBREGISTER" => SUBREGISTER,
285 "LTEREGISTER" => LTEREGISTER,
286 "SUBREGISTER1" => SUBREGISTER1,
287 "ALLOC" => ALLOC,
288 "READALLOC" => READALLOC,
289 "SETALLOC" => SETALLOC,
290 _ => panic!("Unable to map string to opcode"),
291 }
292 }
293
294 pub fn width(&self) -> Option<usize> {
295 match self {
296 OpCode::VOID => Some(1),
297 OpCode::PUSH => Some(1),
298 OpCode::IF => None,
299 OpCode::JMP => None,
300 OpCode::FUNC => Some(1),
301 OpCode::SCLOSURE => None,
302 OpCode::ECLOSURE => Some(1),
303 OpCode::BIND => Some(1),
304 OpCode::SDEF => Some(1),
305 OpCode::EDEF => Some(1),
306 OpCode::POPPURE => Some(1),
307 OpCode::POPN => Some(1),
308 OpCode::POPSINGLE => Some(1),
309 OpCode::PASS => Some(1),
310 OpCode::PUSHCONST => Some(1),
311 OpCode::NDEFS => todo!(),
312 OpCode::PANIC => todo!(),
313 OpCode::TAILCALL => Some(1),
314 OpCode::SET => Some(1),
315 OpCode::READLOCAL => Some(1),
316 OpCode::READLOCAL0 => Some(1),
317 OpCode::READLOCAL1 => Some(1),
318 OpCode::READLOCAL2 => Some(1),
319 OpCode::READLOCAL3 => Some(1),
320 OpCode::SETLOCAL => todo!(),
321 OpCode::COPYCAPTURESTACK => todo!(),
322 OpCode::COPYCAPTURECLOSURE => todo!(),
323 OpCode::COPYHEAPCAPTURECLOSURE => todo!(),
324 OpCode::FIRSTCOPYHEAPCAPTURECLOSURE => todo!(),
325 OpCode::TCOJMP => None,
326 OpCode::CALLGLOBAL => Some(2),
327 OpCode::CALLGLOBALTAIL => None,
328 OpCode::LOADINT0 => Some(1),
329 OpCode::LOADINT1 => Some(1),
330 OpCode::LOADINT2 => Some(1),
331 OpCode::MOVEREADLOCAL => Some(1),
332 OpCode::MOVEREADLOCAL0 => Some(1),
333 OpCode::MOVEREADLOCAL1 => Some(1),
334 OpCode::MOVEREADLOCAL2 => Some(1),
335 OpCode::MOVEREADLOCAL3 => Some(1),
336 OpCode::READCAPTURED => Some(1),
337 OpCode::BEGINSCOPE => Some(1),
338 OpCode::LETENDSCOPE => Some(1),
339 OpCode::PUREFUNC => None,
340 OpCode::ADD => Some(2),
341 OpCode::SUB => Some(2),
342 OpCode::MUL => Some(2),
343 OpCode::DIV => Some(2),
344 OpCode::EQUAL => Some(2),
345 OpCode::NUMEQUAL => Some(2),
346 OpCode::NULL => Some(2),
347 OpCode::LTE => Some(2),
348 OpCode::GTE => Some(2),
349 OpCode::GT => Some(2),
350 OpCode::LT => Some(2),
351 OpCode::CONS => Some(2),
352 OpCode::LIST => Some(2),
353 OpCode::CAR => Some(2),
354 OpCode::CDR => Some(2),
355 OpCode::NEWBOX => Some(2),
356 OpCode::SETBOX => Some(2),
357 OpCode::UNBOX => Some(2),
358 OpCode::NEWSCLOSURE => None,
359 OpCode::ADDREGISTER => Some(2),
360 OpCode::SUBREGISTER => Some(2),
361 OpCode::LTEREGISTER => Some(2),
362 OpCode::SUBREGISTER1 => Some(2),
363 OpCode::ALLOC => todo!(),
364 OpCode::READALLOC => todo!(),
365 OpCode::SETALLOC => todo!(),
366 OpCode::DynSuperInstruction => todo!(),
367 OpCode::Arity => todo!(),
368 OpCode::LetVar => todo!(),
369 OpCode::ADDIMMEDIATE => Some(2),
370 OpCode::SUBIMMEDIATE => Some(2),
371 OpCode::LTEIMMEDIATE => Some(2),
372 OpCode::BINOPADD => Some(2),
373 OpCode::BINOPSUB => Some(2),
374 OpCode::LTEIMMEDIATEIF => None,
375 OpCode::NOT => Some(2),
376 OpCode::VEC => todo!(),
377 OpCode::Apply => todo!(),
378 OpCode::POPJMP => todo!(),
379 OpCode::BINOPADDTAIL => todo!(),
380 OpCode::LOADINT0POP => todo!(),
381 OpCode::LOADINT1POP => todo!(),
382 OpCode::LOADINT2POP => todo!(),
383 _ => todo!(),
384 }
385 }
386}