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, 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 { 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}