compiler/
vm.rs

1use std::borrow::Borrow;
2use std::collections::HashMap;
3use std::rc::Rc;
4
5use byteorder::{BigEndian, ByteOrder};
6use object::builtins::BuiltIns;
7
8use object::{BuiltinFunc, Closure, CompiledFunction, Object};
9use object::Object::ClosureObj;
10
11use crate::compiler::Bytecode;
12use crate::frame::Frame;
13use crate::op_code::{cast_u8_to_opcode, Opcode};
14
15const STACK_SIZE: usize = 2048;
16pub const GLOBAL_SIZE: usize = 65536;
17const MAX_FRAMES: usize = 1024;
18
19pub struct VM {
20    constants: Vec<Rc<Object>>,
21
22    stack: Vec<Rc<Object>>,
23    sp: usize, // stack pointer. Always point to the next value. Top of the stack is stack[sp -1]
24
25    pub globals: Vec<Rc<Object>>,
26
27    frames: Vec<Frame>,
28    frame_index: usize,
29}
30
31impl VM {
32    pub fn new(bytecode: Bytecode) -> VM {
33        // it's rust, it's verbose. You can't just grow your vector size.
34        let empty_frame = Frame::new(
35            Closure {
36                func: Rc::from(object::CompiledFunction { instructions: vec![], num_locals: 0, num_parameters: 0 }),
37                free: vec![]
38            },
39            0,
40        );
41
42        let main_fn = Rc::from(object::CompiledFunction {
43            instructions: bytecode.instructions.data,
44            num_locals: 0,
45            num_parameters: 0,
46        });
47        let main_closure = Closure {func: main_fn, free: vec![] };
48        let main_frame = Frame::new(main_closure, 0);
49        let mut frames = vec![empty_frame; MAX_FRAMES];
50        frames[0] = main_frame;
51
52        return VM {
53            constants: bytecode.constants,
54            stack: vec![Rc::new(Object::Null); STACK_SIZE],
55            sp: 0,
56            globals: vec![Rc::new(Object::Null); GLOBAL_SIZE],
57            frames,
58            frame_index: 1,
59        };
60    }
61
62    pub fn new_with_global_store(bytecode: Bytecode, globals: Vec<Rc<Object>>) -> VM {
63        let mut vm = VM::new(bytecode);
64        vm.globals = globals;
65        return vm;
66    }
67
68    pub fn run(&mut self) {
69        let mut ip = 0;
70        let mut ins: Vec<u8>;
71        while self.current_frame().ip
72            < self.current_frame().instructions().data.clone().len() as i32 - 1
73        {
74            self.current_frame().ip += 1;
75            ip = self.current_frame().ip as usize;
76            ins = self.current_frame().instructions().data.clone();
77
78            let op: u8 = *ins.get(ip).unwrap();
79            let opcode = cast_u8_to_opcode(op);
80
81            match opcode {
82                Opcode::OpConst => {
83                    let const_index = BigEndian::read_u16(&ins[ip + 1..ip + 3]) as usize;
84                    self.current_frame().ip += 2;
85                    self.push(Rc::clone(&self.constants[const_index]))
86                }
87                Opcode::OpAdd | Opcode::OpSub | Opcode::OpMul | Opcode::OpDiv => {
88                    self.execute_binary_operation(opcode);
89                }
90                Opcode::OpPop => {
91                    self.pop();
92                }
93                Opcode::OpTrue => {
94                    self.push(Rc::new(Object::Boolean(true)));
95                }
96                Opcode::OpFalse => {
97                    self.push(Rc::new(Object::Boolean(false)));
98                }
99                Opcode::OpEqual | Opcode::OpNotEqual | Opcode::OpGreaterThan => {
100                    self.execute_comparison(opcode);
101                }
102                Opcode::OpMinus => {
103                    self.execute_minus_operation(opcode);
104                }
105                Opcode::OpBang => {
106                    self.execute_bang_operation();
107                }
108                Opcode::OpJump => {
109                    let pos = BigEndian::read_u16(&ins[ip + 1..ip + 3]) as usize;
110                    self.current_frame().ip = pos as i32 - 1;
111                }
112                Opcode::OpJumpNotTruthy => {
113                    let pos = BigEndian::read_u16(&ins[ip + 1..ip + 3]) as usize;
114                    self.current_frame().ip += 2;
115                    let condition = self.pop();
116                    if !self.is_truthy(condition) {
117                        self.current_frame().ip = pos as i32 - 1;
118                    }
119                }
120                Opcode::OpNull => {
121                    self.push(Rc::new(Object::Null));
122                }
123                Opcode::OpGetGlobal => {
124                    let global_index = BigEndian::read_u16(&ins[ip + 1..ip + 3]) as usize;
125                    self.current_frame().ip += 2;
126                    self.push(Rc::clone(&self.globals[global_index]));
127                }
128                Opcode::OpSetGlobal => {
129                    let global_index = BigEndian::read_u16(&ins[ip + 1..ip + 3]) as usize;
130                    self.current_frame().ip += 2;
131                    self.globals[global_index] = self.pop();
132                }
133                Opcode::OpArray => {
134                    let count = BigEndian::read_u16(&ins[ip + 1..ip + 3]) as usize;
135                    self.current_frame().ip += 2;
136                    let elements = self.build_array(self.sp - count, self.sp);
137                    self.sp = self.sp - count;
138                    self.push(Rc::new(Object::Array(elements)));
139                }
140                Opcode::OpHash => {
141                    let count = BigEndian::read_u16(&ins[ip + 1..ip + 3]) as usize;
142                    self.current_frame().ip += 2;
143                    let elements = self.build_hash(self.sp - count, self.sp);
144                    self.sp = self.sp - count;
145                    self.push(Rc::new(Object::Hash(elements)));
146                }
147                Opcode::OpIndex => {
148                    let index = self.pop();
149                    let left = self.pop();
150                    self.execute_index_operation(left, index);
151                }
152                Opcode::OpReturnValue => {
153                    let return_value = self.pop();
154                    let frame = self.pop_frame();
155                    self.sp = frame.base_pointer - 1;
156                    self.push(return_value);
157                }
158                Opcode::OpReturn => {
159                    let frame = self.pop_frame();
160                    self.sp = frame.base_pointer - 1;
161                    self.push(Rc::new(object::Object::Null));
162                }
163                Opcode::OpCall => {
164                    let num_args = ins[ip + 1] as usize;
165                    self.current_frame().ip += 1;
166                    self.execute_call(num_args);
167                }
168                Opcode::OpSetLocal => {
169                    let local_index = ins[ip + 1] as usize;
170                    self.current_frame().ip += 1;
171                    let base = self.current_frame().base_pointer;
172                    self.stack[base + local_index] = self.pop();
173                }
174                Opcode::OpGetLocal => {
175                    let local_index = ins[ip + 1] as usize;
176                    self.current_frame().ip += 1;
177                    let base = self.current_frame().base_pointer;
178                    self.push(Rc::clone(&self.stack[base + local_index]));
179                }
180                Opcode::OpGetBuiltin => {
181                    let built_index = ins[ip + 1] as usize;
182                    self.current_frame().ip += 1;
183                    let definition = BuiltIns.get(built_index).unwrap().1;
184                    self.push(Rc::new(Object::Builtin(definition)));
185                }
186                Opcode::OpClosure => {
187                    let const_index = BigEndian::read_u16(&ins[ip + 1..ip + 3]) as usize;
188                    let num_free = ins[ip + 3] as usize;
189                    self.current_frame().ip += 3;
190                    self.push_closure(const_index, num_free);
191                }
192                Opcode::OpGetFree => {
193                    let free_index = ins[ip + 1] as usize;
194                    self.current_frame().ip += 1;
195                    let current_closure = self.current_frame().cl.clone();
196                    self.push(current_closure.free[free_index].clone());
197                }
198                Opcode::OpCurrentClosure => {
199                    let current_closure = self.current_frame().cl.clone();
200                    self.push(Rc::new(Object::ClosureObj(current_closure)));
201                }
202            }
203        }
204    }
205
206    fn execute_binary_operation(&mut self, opcode: Opcode) {
207        let right = self.pop();
208        let left = self.pop();
209        match (left.borrow(), right.borrow()) {
210            (Object::Integer(l), Object::Integer(r)) => {
211                let result = match opcode {
212                    Opcode::OpAdd => l + r,
213                    Opcode::OpSub => l - r,
214                    Opcode::OpMul => l * r,
215                    Opcode::OpDiv => l / r,
216                    _ => panic!("Unknown opcode for int"),
217                };
218                self.push(Rc::from(Object::Integer(result)));
219            }
220            (Object::String(l), Object::String(r)) => {
221                let result = match opcode {
222                    Opcode::OpAdd => l.to_string() + &r.to_string(),
223                    _ => panic!("Unknown opcode for string"),
224                };
225                self.push(Rc::from(Object::String(result)));
226            }
227            _ => {
228                panic!("unsupported add for those types")
229            }
230        }
231    }
232
233    fn execute_comparison(&mut self, opcode: Opcode) {
234        let right = self.pop();
235        let left = self.pop();
236        match (left.borrow(), right.borrow()) {
237            (Object::Integer(l), Object::Integer(r)) => {
238                let result = match opcode {
239                    Opcode::OpEqual => l == r,
240                    Opcode::OpNotEqual => l != r,
241                    Opcode::OpGreaterThan => l > r,
242                    _ => panic!("Unknown opcode for comparing int"),
243                };
244                self.push(Rc::from(Object::Boolean(result)));
245            }
246            (Object::Boolean(l), Object::Boolean(r)) => {
247                let result = match opcode {
248                    Opcode::OpEqual => l == r,
249                    Opcode::OpNotEqual => l != r,
250                    _ => panic!("Unknown opcode for comparing boolean"),
251                };
252                self.push(Rc::from(Object::Boolean(result)));
253            }
254            _ => {
255                panic!("unsupported comparison for those types")
256            }
257        }
258    }
259
260    fn execute_minus_operation(&mut self, opcode: Opcode) {
261        let operand = self.pop();
262        match operand.borrow() {
263            Object::Integer(l) => {
264                self.push(Rc::from(Object::Integer(-*l)));
265            }
266            _ => {
267                panic!("unsupported types for negation {:?}", opcode)
268            }
269        }
270    }
271    fn execute_bang_operation(&mut self) {
272        let operand = self.pop();
273        match operand.borrow() {
274            Object::Boolean(l) => {
275                self.push(Rc::from(Object::Boolean(!*l)));
276            }
277            _ => {
278                self.push(Rc::from(Object::Boolean(false)));
279            }
280        }
281    }
282
283    pub fn last_popped_stack_elm(&self) -> Option<Rc<Object>> {
284        self.stack.get(self.sp).cloned()
285    }
286
287    fn pop(&mut self) -> Rc<Object> {
288        let o = Rc::clone(&self.stack[self.sp - 1]);
289        self.sp -= 1;
290        return o;
291    }
292
293    fn push(&mut self, o: Rc<Object>) {
294        if self.sp >= STACK_SIZE {
295            panic!("Stack overflow");
296        };
297        self.stack[self.sp] = o;
298        self.sp += 1;
299    }
300    fn is_truthy(&self, condition: Rc<Object>) -> bool {
301        match condition.borrow() {
302            Object::Boolean(b) => *b,
303            Object::Null => false,
304            _ => true,
305        }
306    }
307    fn build_array(&self, start: usize, end: usize) -> Vec<Rc<Object>> {
308        let mut elements = Vec::with_capacity(end - start);
309        for i in start..end {
310            elements.push(Rc::clone(&self.stack[i]));
311        }
312        return elements;
313    }
314
315    fn build_hash(&self, start: usize, end: usize) -> HashMap<Rc<Object>, Rc<Object>> {
316        let mut elements = HashMap::new();
317        for i in (start..end).step_by(2) {
318            let key = Rc::clone(&self.stack[i]);
319            let value = Rc::clone(&self.stack[i + 1]);
320            elements.insert(key, value);
321        }
322        return elements;
323    }
324
325    fn execute_index_operation(&mut self, left: Rc<Object>, index: Rc<Object>) {
326        match (left.borrow(), index.borrow()) {
327            (Object::Array(l), Object::Integer(i)) => {
328                self.execute_array_index(l, *i);
329            }
330            (Object::Hash(l), _) => {
331                self.execute_hash_index(l, index);
332            }
333            _ => {
334                panic!("unsupported index operation for those types")
335            }
336        }
337    }
338
339    fn execute_array_index(&mut self, array: &Vec<Rc<Object>>, index: i64) {
340        if index < array.len() as i64 && index >= 0 {
341            self.push(Rc::clone(&array[index as usize]));
342        } else {
343            self.push(Rc::new(Object::Null));
344        }
345    }
346
347    fn execute_hash_index(&mut self, hash: &HashMap<Rc<Object>, Rc<Object>>, index: Rc<Object>) {
348        match &*index {
349            Object::Integer(_) | Object::Boolean(_) | Object::String(_) => match hash.get(&index) {
350                Some(el) => {
351                    self.push(Rc::clone(el));
352                }
353                None => {
354                    self.push(Rc::new(Object::Null));
355                }
356            },
357            _ => {
358                panic!("unsupported hash index operation for those types {}", index)
359            }
360        }
361    }
362
363    fn current_frame(&mut self) -> &mut Frame {
364        &mut self.frames[self.frame_index - 1]
365    }
366
367    fn push_frame(&mut self, frame: Frame) {
368        self.frames[self.frame_index] = frame;
369        self.frame_index += 1;
370    }
371
372    fn pop_frame(&mut self) -> Frame {
373        self.frame_index -= 1;
374        return self.frames[self.frame_index].clone();
375    }
376
377    fn execute_call(&mut self, num_args: usize) {
378        let callee = &*self.stack[self.sp - 1 - num_args];
379        match callee {
380            Object::ClosureObj(cf) => {
381                self.call_closure(cf.clone(), num_args);
382            }
383            Object::Builtin(bt) => {
384                self.call_builtin(bt.clone(), num_args);
385            }
386            _ => {
387                panic!("calling non-closure")
388            }
389        }
390    }
391    fn call_closure(&mut self, cl: Closure, num_args: usize) {
392        if cl.func.num_parameters != num_args {
393            panic!("wrong number of arguments: want={}, got={}", cl.func.num_parameters, num_args);
394        }
395
396        let frame = Frame::new(cl.clone(), self.sp - num_args);
397        self.sp = frame.base_pointer + cl.func.num_locals;
398        self.push_frame(frame);
399    }
400
401    fn call_builtin(&mut self, bt: BuiltinFunc, num_args: usize) {
402        let args = self.stack[self.sp - num_args..self.sp].to_vec();
403        let result = bt(args);
404        self.sp = self.sp - num_args - 1;
405        self.push(result);
406    }
407
408    fn push_closure(&mut self, const_index: usize, num_free: usize) {
409        match &*self.constants[const_index] {
410            Object::CompiledFunction(f) => {
411                let mut free = Vec::with_capacity(num_free);
412                for i in 0..num_free {
413                    let f = self.stack[self.sp - num_free + i].clone();
414                    free[i] = f;
415                }
416                self.sp = self.sp - num_free;
417                let closure = ClosureObj (Closure {
418                    func: f.clone(),
419                    free,
420                });
421                self.push(Rc::new(closure));
422            }
423            o => {
424                panic!("not a function {}", o);
425            }
426        }
427
428    }
429}