1use std::cell::RefCell;
2use std::collections::HashMap;
3use std::rc::Rc;
4
5use byteorder::{BigEndian, ByteOrder};
6use object::builtins::BuiltIns;
7
8use object::Object::ClosureObj;
9use object::{BoundMethodObject, BuiltinFunc, ClassObject, Closure, InstanceObject, Object};
10
11use crate::compiler::Bytecode;
12use crate::frame::Frame;
13use crate::op_code::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 name: String::new(),
38 instructions: vec![],
39 num_locals: 0,
40 num_parameters: 0,
41 }),
42 free: vec![],
43 },
44 0,
45 );
46
47 let main_fn = Rc::from(object::CompiledFunction {
48 name: String::new(),
49 instructions: bytecode.instructions.data,
50 num_locals: 0,
51 num_parameters: 0,
52 });
53 let main_closure = Closure {
54 func: main_fn,
55 free: vec![],
56 };
57 let main_frame = Frame::new(main_closure, 0);
58 let mut frames = vec![empty_frame; MAX_FRAMES];
59 frames[0] = main_frame;
60
61 let null = Rc::new(Object::Null);
62 return VM {
63 constants: bytecode.constants,
64 stack: vec![Rc::clone(&null); STACK_SIZE],
65 sp: 0,
66 globals: vec![null; GLOBAL_SIZE],
67 frames,
68 frame_index: 1,
69 };
70 }
71
72 pub fn new_with_global_store(bytecode: Bytecode, globals: Vec<Rc<Object>>) -> VM {
73 let mut vm = VM::new(bytecode);
74 vm.globals = globals;
75 return vm;
76 }
77
78 pub fn run(&mut self) {
79 let mut ip: usize;
80 let mut ins: Vec<u8>;
81 while self.current_frame().ip
82 < self.current_frame().instructions().data.clone().len() as i32 - 1
83 {
84 self.current_frame().ip += 1;
85 ip = self.current_frame().ip as usize;
86 ins = self.current_frame().instructions().data.clone();
87
88 let op: u8 = *ins.get(ip).unwrap();
89 let opcode = Opcode::from_repr(op).expect("unknown opcode in compiled bytecode");
90
91 match opcode {
92 Opcode::OpConst => {
93 let const_index = BigEndian::read_u16(&ins[ip + 1..ip + 3]) as usize;
94 self.current_frame().ip += 2;
95 self.push(Rc::clone(&self.constants[const_index]))
96 }
97 Opcode::OpAdd | Opcode::OpSub | Opcode::OpMul | Opcode::OpDiv => {
98 self.execute_binary_operation(opcode);
99 }
100 Opcode::OpPop => {
101 self.pop();
102 }
103 Opcode::OpTrue => {
104 self.push(Rc::new(Object::Boolean(true)));
105 }
106 Opcode::OpFalse => {
107 self.push(Rc::new(Object::Boolean(false)));
108 }
109 Opcode::OpEqual
110 | Opcode::OpNotEqual
111 | Opcode::OpGreaterThan
112 | Opcode::OpLessThan => {
113 self.execute_comparison(opcode);
114 }
115 Opcode::OpMinus => {
116 self.execute_minus_operation(opcode);
117 }
118 Opcode::OpBang => {
119 self.execute_bang_operation();
120 }
121 Opcode::OpJump => {
122 let pos = BigEndian::read_u16(&ins[ip + 1..ip + 3]) as usize;
123 self.current_frame().ip = pos as i32 - 1;
124 }
125 Opcode::OpJumpNotTruthy => {
126 let pos = BigEndian::read_u16(&ins[ip + 1..ip + 3]) as usize;
127 self.current_frame().ip += 2;
128 let condition = self.pop();
129 if !self.is_truthy(condition) {
130 self.current_frame().ip = pos as i32 - 1;
131 }
132 }
133 Opcode::OpNull => {
134 self.push(Rc::new(Object::Null));
135 }
136 Opcode::OpGetGlobal => {
137 let global_index = BigEndian::read_u16(&ins[ip + 1..ip + 3]) as usize;
138 self.current_frame().ip += 2;
139 self.push(Rc::clone(&self.globals[global_index]));
140 }
141 Opcode::OpSetGlobal => {
142 let global_index = BigEndian::read_u16(&ins[ip + 1..ip + 3]) as usize;
143 self.current_frame().ip += 2;
144 self.globals[global_index] = self.pop();
145 }
146 Opcode::OpArray => {
147 let count = BigEndian::read_u16(&ins[ip + 1..ip + 3]) as usize;
148 self.current_frame().ip += 2;
149 let elements = self.build_array(self.sp - count, self.sp);
150 self.sp -= count;
151 self.push(Rc::new(Object::Array(elements)));
152 }
153 Opcode::OpHash => {
154 let count = BigEndian::read_u16(&ins[ip + 1..ip + 3]) as usize;
155 self.current_frame().ip += 2;
156 #[allow(clippy::mutable_key_type)]
157 let elements = self.build_hash(self.sp - count, self.sp);
158 self.sp -= count;
159 self.push(Rc::new(Object::Hash(elements)));
160 }
161 Opcode::OpIndex => {
162 let index = self.pop();
163 let left = self.pop();
164 self.execute_index_operation(left, index);
165 }
166 Opcode::OpReturnValue => {
167 let return_value = self.pop();
168 if self.frame_index == 1 {
169 self.stack[0] = return_value;
172 self.sp = 0;
173 break;
174 }
175 let frame = self.pop_frame();
176 self.sp = frame.base_pointer - 1;
177 self.push(return_value);
178 }
179 Opcode::OpReturn => {
180 if self.frame_index == 1 {
181 self.stack[0] = Rc::new(object::Object::Null);
182 self.sp = 0;
183 break;
184 }
185 let frame = self.pop_frame();
186 self.sp = frame.base_pointer - 1;
187 self.push(Rc::new(object::Object::Null));
188 }
189 Opcode::OpCall => {
190 let num_args = ins[ip + 1] as usize;
191 self.current_frame().ip += 1;
192 self.execute_call(num_args);
193 }
194 Opcode::OpSetLocal => {
195 let local_index = ins[ip + 1] as usize;
196 self.current_frame().ip += 1;
197 let base = self.current_frame().base_pointer;
198 self.stack[base + local_index] = self.pop();
199 }
200 Opcode::OpGetLocal => {
201 let local_index = ins[ip + 1] as usize;
202 self.current_frame().ip += 1;
203 let base = self.current_frame().base_pointer;
204 self.push(Rc::clone(&self.stack[base + local_index]));
205 }
206 Opcode::OpGetBuiltin => {
207 let built_index = ins[ip + 1] as usize;
208 self.current_frame().ip += 1;
209 let definition = BuiltIns.get(built_index).unwrap().function;
210 self.push(Rc::new(Object::Builtin(definition)));
211 }
212 Opcode::OpClosure => {
213 let const_index = BigEndian::read_u16(&ins[ip + 1..ip + 3]) as usize;
214 let num_free = ins[ip + 3] as usize;
215 self.current_frame().ip += 3;
216 self.push_closure(const_index, num_free);
217 }
218 Opcode::OpGetFree => {
219 let free_index = ins[ip + 1] as usize;
220 self.current_frame().ip += 1;
221 let current_closure = self.current_frame().cl.clone();
222 self.push(current_closure.free[free_index].clone());
223 }
224 Opcode::OpCurrentClosure => {
225 let current_closure = self.current_frame().cl.clone();
226 self.push(Rc::new(Object::ClosureObj(current_closure)));
227 }
228 Opcode::OpClass => {
229 let name_index = BigEndian::read_u16(&ins[ip + 1..ip + 3]) as usize;
230 self.current_frame().ip += 2;
231 let name = self.constant_string(name_index);
232 self.push(Rc::new(Object::Class(Rc::new(RefCell::new(ClassObject {
233 name,
234 constructor: None,
235 methods: HashMap::new(),
236 })))));
237 }
238 Opcode::OpMethod => {
239 let name_index = BigEndian::read_u16(&ins[ip + 1..ip + 3]) as usize;
240 let kind = ins[ip + 3];
241 self.current_frame().ip += 3;
242 let name = self.constant_string(name_index);
243 let method = self.pop();
244 let class = match &*self.stack[self.sp - 1] {
245 Object::Class(class) => Rc::clone(class),
246 value => panic!("cannot install method on {}", value),
247 };
248 if kind == 1 {
249 class.borrow_mut().constructor = Some(method);
250 } else {
251 class.borrow_mut().methods.insert(name, method);
252 }
253 }
254 Opcode::OpGetProperty => {
255 let name_index = BigEndian::read_u16(&ins[ip + 1..ip + 3]) as usize;
256 self.current_frame().ip += 2;
257 let name = self.constant_string(name_index);
258 let receiver = self.pop();
259 let value = self.get_property(&receiver, &name);
260 self.push(value);
261 }
262 Opcode::OpSetProperty => {
263 let name_index = BigEndian::read_u16(&ins[ip + 1..ip + 3]) as usize;
264 self.current_frame().ip += 2;
265 let name = self.constant_string(name_index);
266 let value = self.pop();
267 let receiver = self.pop();
268 self.set_property(&receiver, name, value);
269 }
270 Opcode::OpNew => {
271 let num_args = ins[ip + 1] as usize;
272 self.current_frame().ip += 1;
273 self.execute_new(num_args);
274 }
275 }
276 }
277 }
278
279 fn execute_binary_operation(&mut self, opcode: Opcode) {
280 let right = self.pop();
281 let left = self.pop();
282 match (left.as_ref(), right.as_ref()) {
283 (Object::Integer(l), Object::Integer(r)) => {
284 let result = match opcode {
285 Opcode::OpAdd => l + r,
286 Opcode::OpSub => l - r,
287 Opcode::OpMul => l * r,
288 Opcode::OpDiv => l / r,
289 _ => panic!("Unknown opcode for int"),
290 };
291 self.push(Rc::from(Object::Integer(result)));
292 }
293 (Object::String(l), Object::String(r)) => {
294 let result = match opcode {
295 Opcode::OpAdd => l.to_string() + &r.to_string(),
296 _ => panic!("Unknown opcode for string"),
297 };
298 self.push(Rc::from(Object::String(result)));
299 }
300 _ => {
301 panic!("unsupported add for those types")
302 }
303 }
304 }
305
306 fn execute_comparison(&mut self, opcode: Opcode) {
307 let right = self.pop();
308 let left = self.pop();
309 if opcode == Opcode::OpEqual || opcode == Opcode::OpNotEqual {
310 let equal = left.as_ref() == right.as_ref();
311 self.push(Rc::new(Object::Boolean(if opcode == Opcode::OpEqual {
312 equal
313 } else {
314 !equal
315 })));
316 return;
317 }
318 match (left.as_ref(), right.as_ref()) {
319 (Object::Integer(l), Object::Integer(r)) => {
320 let result = match opcode {
321 Opcode::OpGreaterThan => l > r,
322 Opcode::OpLessThan => l < r,
323 _ => panic!("Unknown opcode for comparing int"),
324 };
325 self.push(Rc::from(Object::Boolean(result)));
326 }
327 _ => {
328 panic!("unsupported comparison for those types")
329 }
330 }
331 }
332
333 fn execute_minus_operation(&mut self, opcode: Opcode) {
334 let operand = self.pop();
335 match operand.as_ref() {
336 Object::Integer(l) => {
337 self.push(Rc::from(Object::Integer(-*l)));
338 }
339 _ => {
340 panic!("unsupported types for negation {:?}", opcode)
341 }
342 }
343 }
344 fn execute_bang_operation(&mut self) {
345 let operand = self.pop();
346 match operand.as_ref() {
347 Object::Boolean(l) => {
348 self.push(Rc::from(Object::Boolean(!*l)));
349 }
350 _ => {
351 self.push(Rc::from(Object::Boolean(false)));
352 }
353 }
354 }
355
356 pub fn last_popped_stack_elm(&self) -> Option<Rc<Object>> {
357 self.stack.get(self.sp).cloned()
358 }
359
360 fn pop(&mut self) -> Rc<Object> {
361 let o = Rc::clone(&self.stack[self.sp - 1]);
362 self.sp -= 1;
363 return o;
364 }
365
366 fn push(&mut self, o: Rc<Object>) {
367 if self.sp >= STACK_SIZE {
368 panic!("Stack overflow");
369 };
370 self.stack[self.sp] = o;
371 self.sp += 1;
372 }
373 fn is_truthy(&self, condition: Rc<Object>) -> bool {
374 match condition.as_ref() {
375 Object::Boolean(b) => *b,
376 Object::Null => false,
377 _ => true,
378 }
379 }
380 fn build_array(&self, start: usize, end: usize) -> Vec<Rc<Object>> {
381 let mut elements = Vec::with_capacity(end - start);
382 for i in start..end {
383 elements.push(Rc::clone(&self.stack[i]));
384 }
385 return elements;
386 }
387
388 #[allow(clippy::mutable_key_type)]
391 fn build_hash(&self, start: usize, end: usize) -> HashMap<Rc<Object>, Rc<Object>> {
392 let mut elements = HashMap::new();
393 for i in (start..end).step_by(2) {
394 let key = Rc::clone(&self.stack[i]);
395 let value = Rc::clone(&self.stack[i + 1]);
396 elements.insert(key, value);
397 }
398 return elements;
399 }
400
401 fn execute_index_operation(&mut self, left: Rc<Object>, index: Rc<Object>) {
402 match (left.as_ref(), index.as_ref()) {
403 (Object::Array(l), Object::Integer(i)) => {
404 self.execute_array_index(l, *i);
405 }
406 (Object::Hash(l), _) => {
407 self.execute_hash_index(l, index);
408 }
409 _ => {
410 panic!("unsupported index operation for those types")
411 }
412 }
413 }
414
415 fn execute_array_index(&mut self, array: &[Rc<Object>], index: i64) {
416 if index < array.len() as i64 && index >= 0 {
417 self.push(Rc::clone(&array[index as usize]));
418 } else {
419 self.push(Rc::new(Object::Null));
420 }
421 }
422
423 #[allow(clippy::mutable_key_type)]
424 fn execute_hash_index(&mut self, hash: &HashMap<Rc<Object>, Rc<Object>>, index: Rc<Object>) {
425 match &*index {
426 Object::Integer(_) | Object::Boolean(_) | Object::String(_) => match hash.get(&index) {
427 Some(el) => {
428 self.push(Rc::clone(el));
429 }
430 None => {
431 self.push(Rc::new(Object::Null));
432 }
433 },
434 _ => {
435 panic!("unsupported hash index operation for those types {}", index)
436 }
437 }
438 }
439
440 fn current_frame(&mut self) -> &mut Frame {
441 &mut self.frames[self.frame_index - 1]
442 }
443
444 fn push_frame(&mut self, frame: Frame) {
445 self.frames[self.frame_index] = frame;
446 self.frame_index += 1;
447 }
448
449 fn pop_frame(&mut self) -> Frame {
450 self.frame_index -= 1;
451 return self.frames[self.frame_index].clone();
452 }
453
454 fn execute_call(&mut self, num_args: usize) {
455 let callee = Rc::clone(&self.stack[self.sp - 1 - num_args]);
456 match &*callee {
457 Object::ClosureObj(cf) => {
458 self.call_closure(cf.clone(), num_args);
459 }
460 Object::Builtin(bt) => {
461 self.call_builtin(*bt, num_args);
462 }
463 Object::BoundMethod(bound) => {
464 self.call_bound_method(bound.clone(), num_args);
465 }
466 Object::Class(class) => {
467 panic!("class {} must be constructed with new", class.borrow().name)
468 }
469 _ => {
470 panic!("calling non-closure")
471 }
472 }
473 }
474 fn call_closure(&mut self, cl: Closure, num_args: usize) {
475 if cl.func.num_parameters != num_args {
476 panic!("wrong number of arguments: want={}, got={}", cl.func.num_parameters, num_args);
477 }
478
479 let frame = Frame::new(cl.clone(), self.sp - num_args);
480 self.sp = frame.base_pointer + cl.func.num_locals;
481 self.push_frame(frame);
482 }
483
484 fn call_builtin(&mut self, bt: BuiltinFunc, num_args: usize) {
485 let args = self.stack[self.sp - num_args..self.sp].to_vec();
486 let result = bt(args);
487 self.sp = self.sp - num_args - 1;
488 self.push(result);
489 }
490
491 fn push_closure(&mut self, const_index: usize, num_free: usize) {
492 match &*self.constants[const_index] {
493 Object::CompiledFunction(f) => {
494 let mut free = Vec::with_capacity(num_free);
495 for i in 0..num_free {
496 let f = self.stack[self.sp - num_free + i].clone();
497 free.push(f);
498 }
499 self.sp -= num_free;
500 let closure = ClosureObj(Closure {
501 func: f.clone(),
502 free,
503 });
504 self.push(Rc::new(closure));
505 }
506 o => {
507 panic!("not a function {}", o);
508 }
509 }
510 }
511
512 fn constant_string(&self, index: usize) -> String {
513 match &*self.constants[index] {
514 Object::String(value) => value.clone(),
515 value => panic!("expected string constant, got {}", value),
516 }
517 }
518
519 fn get_property(&self, receiver: &Rc<Object>, name: &str) -> Rc<Object> {
520 let Object::Instance(instance) = &**receiver else {
521 panic!("cannot read property '{}' of {}", name, receiver);
522 };
523 if let Some(value) = instance.borrow().fields.get(name).cloned() {
524 return value;
525 }
526 let (class_name, method) = {
527 let instance_object = instance.borrow();
528 let class = instance_object.class.borrow();
529 (class.name.clone(), class.methods.get(name).cloned())
530 };
531 match method {
532 Some(method) => Rc::new(Object::BoundMethod(Rc::new(BoundMethodObject {
533 receiver: Rc::clone(instance),
534 method,
535 name: name.to_string(),
536 }))),
537 None => panic!("property '{}' does not exist on {}", name, class_name),
538 }
539 }
540
541 fn set_property(&self, receiver: &Rc<Object>, name: String, value: Rc<Object>) {
542 let Object::Instance(instance) = &**receiver else {
543 panic!("cannot set property '{}' of {}", name, receiver);
544 };
545 instance.borrow_mut().fields.insert(name, value);
546 }
547
548 fn execute_new(&mut self, num_args: usize) {
549 let base = self.sp - num_args - 1;
550 let class = match &*self.stack[base] {
551 Object::Class(class) => Rc::clone(class),
552 value => panic!("cannot construct {}", value),
553 };
554 let instance = Rc::new(RefCell::new(InstanceObject {
555 class: Rc::clone(&class),
556 fields: HashMap::new(),
557 }));
558 let instance_value = Rc::new(Object::Instance(instance));
559 let constructor = class.borrow().constructor.clone();
560 let Some(constructor) = constructor else {
561 if num_args != 0 {
562 panic!(
563 "wrong number of arguments for {}.constructor: want=0, got={}",
564 class.borrow().name,
565 num_args
566 );
567 }
568 self.sp = base;
569 self.push(instance_value);
570 return;
571 };
572
573 let closure = match &*constructor {
574 Object::ClosureObj(closure) => closure.clone(),
575 value => panic!("constructor is not a closure: {}", value),
576 };
577 let expected = closure.func.num_parameters.saturating_sub(1);
578 if expected != num_args {
579 panic!(
580 "wrong number of arguments for {}.constructor: want={}, got={}",
581 class.borrow().name,
582 expected,
583 num_args
584 );
585 }
586 self.rewrite_receiver_call(constructor, instance_value, num_args);
587 self.call_closure(closure, num_args + 1);
588 }
589
590 fn call_bound_method(&mut self, bound: Rc<BoundMethodObject>, num_args: usize) {
591 let closure = match &*bound.method {
592 Object::ClosureObj(closure) => closure.clone(),
593 value => panic!("bound method is not a closure: {}", value),
594 };
595 let expected = closure.func.num_parameters.saturating_sub(1);
596 if expected != num_args {
597 let class_name = bound.receiver.borrow().class.borrow().name.clone();
598 panic!(
599 "wrong number of arguments for {}.{}: want={}, got={}",
600 class_name, bound.name, expected, num_args
601 );
602 }
603 let receiver = Rc::new(Object::Instance(Rc::clone(&bound.receiver)));
604 self.rewrite_receiver_call(Rc::clone(&bound.method), receiver, num_args);
605 self.call_closure(closure, num_args + 1);
606 }
607
608 fn rewrite_receiver_call(
609 &mut self,
610 callable: Rc<Object>,
611 receiver: Rc<Object>,
612 num_args: usize,
613 ) {
614 let base = self.sp - num_args - 1;
615 for index in (base + 1..self.sp).rev() {
616 self.stack[index + 1] = Rc::clone(&self.stack[index]);
617 }
618 self.stack[base] = callable;
619 self.stack[base + 1] = receiver;
620 self.sp += 1;
621 }
622}