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