zubbers/vm/
disassembler.rs

1use super::*;
2use gc::trace::{ Trace, Tracer };
3use colored::Colorize;
4
5pub struct Disassembler<'c> {
6    offset: usize,
7    line: usize,
8    chunk: &'c Chunk,
9    heap: &'c Heap<Object>,
10}
11
12impl<'c> Disassembler<'c> {
13    pub fn new(chunk: &'c Chunk, heap: &'c Heap<Object>) -> Self {
14        Disassembler {
15            offset: 0,
16            line: 0,
17            chunk,
18            heap,
19        }
20    }
21
22    pub fn disassemble(mut self) {
23        let bytes = self.chunk.as_ref();
24
25        println!();
26        let name = format!("== {} ==", self.chunk.name());
27        eprint!("{}", name.cyan());
28
29        while self.offset < bytes.len() {
30            self.disassemble_instruction();
31        }
32
33        println!();
34    }
35
36    fn disassemble_instruction(&mut self) {
37        let line = self.chunk.line(self.offset);
38        if self.line == line {
39        } else {
40            self.line = line;
41        }
42        let inst = self.read_byte();
43        println!();
44        let off = format!("{:04} | ", self.offset);
45
46        eprint!("{}", off.blue());
47        decode_op!(inst, self);
48    }
49
50    fn constant(&mut self, idx: u8) {
51        let val = self.chunk.get_constant(idx);
52        eprint!("CONSTANT\t{}\t{:?}", idx, val);
53    }
54
55    fn ret(&self) { eprint!("RETURN"); }
56    fn print(&self) { eprint!("PRINT"); }
57    fn add(&self) { eprint!("ADD"); }
58    fn sub(&self) { eprint!("SUB"); }
59    fn mul(&self) { eprint!("MUL"); }
60    fn rem(&self) { eprint!("REM"); }
61    fn pow(&self) { eprint!("POW"); }
62    fn div(&self) { eprint!("DIV"); }
63    fn neg(&self) { eprint!("NEG"); }
64    fn not(&self) { eprint!("NOT"); }
65    fn eq(&self) { eprint!("EQ"); }
66    fn gt(&self) { eprint!("GT"); }
67    fn lt(&self) { eprint!("LT"); }
68    fn pop(&self) { eprint!("POP"); }
69
70    fn list(&mut self) {
71        eprint!("LIST");
72        self.read_byte();
73    }
74
75    fn index(&mut self) {}
76
77    fn dict(&mut self) {
78        eprint!("DICT");
79        self.read_byte();
80    }
81
82    fn set_element(&mut self) {
83        eprint!("SET_ELEMENT")
84    }
85
86
87    fn jmp(&mut self) {
88        let offset = self.offset - 1;
89        let ip = self.read_u16();
90        eprint!("JUMP\t{} -> {}", offset, ip);
91    }
92
93    fn jze(&mut self) {
94        let offset = self.offset - 1;
95        let ip = self.read_u16();
96        eprint!("JUMP_IF_FALSE\t{} -> {}", offset, ip);
97    }
98
99    fn op_loop(&mut self) {
100        let sub = self.read_u16() as usize;
101        eprint!("LOOP\t{} -> {}", self.offset, self.offset - sub);
102    }
103
104    fn get_global(&mut self) {
105        let val = self.read_constant();
106        eprint!("GET_GLOBAL\t{}", val.with_heap(self.heap));
107    }
108
109    fn set_global(&mut self) {
110        let val = self.read_constant();
111        eprint!("SET_GLOBAL\t{}", val.with_heap(self.heap));
112    }
113
114    fn define_global(&mut self) {
115        let name = self.read_constant();
116        eprint!("DEFINE_GLOBAL\t{}", name.with_heap(self.heap));
117    }
118
119    fn get_local(&mut self) {
120        let val = self.read_byte();
121        eprint!("GET_LOCAL\t{}", val);
122    }
123
124    fn set_local(&mut self) {
125        let val = self.read_byte();
126        eprint!("SET_LOCAL\t{}", val);
127    }
128
129    fn immediate(&mut self) {
130        self.offset += 8;
131        let b1 = self.chunk.get(self.offset - 8) as u64;
132        let b2 = self.chunk.get(self.offset - 7) as u64;
133        let b3 = self.chunk.get(self.offset - 6) as u64;
134        let b4 = self.chunk.get(self.offset - 5) as u64;
135        let b5 = self.chunk.get(self.offset - 4) as u64;
136        let b6 = self.chunk.get(self.offset - 3) as u64;
137        let b7 = self.chunk.get(self.offset - 2) as u64;
138        let b8 = self.chunk.get(self.offset - 1) as u64;
139        let raw = b1   +
140            (b2 << 8)  +
141            (b3 << 16) +
142            (b4 << 24) +
143            (b5 << 32) +
144            (b6 << 40) +
145            (b7 << 48) +
146            (b8 << 56);
147        let val = unsafe { Value::from_raw(raw) };
148        eprint!("FLOAT\t{}", val.with_heap(self.heap));
149    }
150
151    fn imm_nil(&self) {
152        eprint!("NIL");
153    }
154
155    fn imm_true(&self) {
156        eprint!("TRUE");
157    }
158
159    fn imm_false(&self) {
160        eprint!("FALSE");
161    }
162
163    fn call(&self, arity: u8) {
164        eprint!("CALL_{}", arity);
165    }
166
167    fn invoke(&mut self, arity: u8) {
168        let idx = self.read_byte();
169        let val = self.chunk.get_constant(idx).expect("invalid constant segment index");
170        eprint!("INVOKE_{} {}", arity, val.with_heap(&self.heap));
171    }
172
173    fn close_upvalue(&self) {
174        eprint!("CLOSE_UPVALUE");
175    }
176
177    fn get_upvalue(&mut self) {
178        let index = self.read_byte();
179        eprint!("GET_UPVALUE\t{}", index);
180    }
181
182    fn set_upvalue(&mut self) {
183        let index = self.read_byte();
184        eprint!("SET_UPVALE\t{}", index);
185    }
186
187    fn closure(&mut self) {
188        let val = self.read_constant();
189        let count = val
190            .as_object()
191            .and_then(|o| self.heap.get(o))
192            .and_then(|o| o.as_function())
193            .expect("closure argument to be a function")
194            .upvalue_count();
195
196        print!("CLOSURE\t{} ", val.with_heap(self.heap));
197        println!();
198
199        if let Variant::Obj(cl) = val.with_heap(self.heap).item.decode() {
200            unsafe {
201                let closure = cl.get_unchecked().as_function().unwrap();
202
203                let dis = Disassembler::new(closure.chunk(), &self.heap);
204                dis.disassemble()
205            }
206        }
207
208        for _ in 0..count {
209            let _is_local = self.read_byte() > 0;
210            let _index = self.read_byte();
211        }
212    }
213
214    fn class(&mut self, idx: u8) {
215        let val = self.chunk.get_constant(idx).expect("invalid constant segment index");
216        let methods = self.read_byte();
217        eprint!("CLASS\t{}\t{}\t({} method(s))", idx, val.with_heap(&self.heap), methods);
218    }
219
220    fn get_property(&mut self) {
221        let idx = self.read_byte();
222        let val = self.chunk.get_constant(idx).expect("invalid constant segment index");
223        eprint!("GET_PROPERTY\t{}\t{}", idx, val.with_heap(&self.heap));
224    }
225
226    fn set_property(&mut self) {
227        let idx = self.read_byte();
228        let val = self.chunk.get_constant(idx).expect("invalid constant segment index");
229        eprint!("SET_PROPERTY\t{}\t{}", idx, val.with_heap(&self.heap));
230    }
231
232    fn read_byte(&mut self) -> u8 {
233        self.offset += 1;
234        self.chunk.as_ref()[self.offset - 1]
235    }
236
237    fn read_u16(&mut self) -> u16 {
238        self.offset += 2;
239        let lo = self.chunk.get(self.offset - 2) as u16;
240        let hi = self.chunk.get(self.offset - 1) as u16;
241        lo + (hi << 8)
242    }
243
244    fn read_constant(&mut self) -> Value {
245        let idx = self.read_byte();
246        *self.chunk.get_constant(idx).expect("invalid constant segment index")
247    }
248}