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