tower_vm/interpreter/
machine.rs

1use crate::{
2    Instruction,
3    TypeFlag,
4    Value,
5};
6
7const STACK_SIZE: usize = 1024;
8
9macro_rules! binop_helper {
10    ($fn_name:ident, $op:tt) => {
11        fn $fn_name(&mut self) {
12            let lhs = self.value_pop();
13            let rhs = self.value_pop();
14            self.value_push(lhs $op rhs);
15        }
16    };
17}
18
19macro_rules! comp_helper {
20    ($fn_name:ident, $op:tt) => {
21        fn $fn_name(&mut self) {
22            let lhs = self.value_pop();
23            let rhs = self.value_pop();
24            let curr_ty = self.ty_flag;
25            self.ty_flag = TypeFlag::Bool;
26            self.value_push((lhs $op rhs).into());
27            self.ty_flag = curr_ty;
28        }
29    };
30}
31
32
33macro_rules! bytecode {
34    ( $( $item:expr ),* ) => {
35        {
36            let mut tmp_vec: Vec<u8> = vec![];
37
38            $(
39                tmp_vec.push($item as u8);
40            )*
41
42            tmp_vec
43        }
44    }
45}
46
47#[derive(Clone)]
48pub struct Machine {
49    stack: [u64; STACK_SIZE],
50    sp: usize,
51    code: Vec<u8>,
52    ip: usize,
53    heap: Vec<u8>,
54    ty_flag: TypeFlag, // 0 = i8, 1 = i16, 2 = i32, 3 = i64, 4 = f32, 5 = f64, 6 = bool, 7 = char, 8 = u8, 9 = u16, 10 = u32, 11 = u64
55    stream: String,
56    read_wait: bool,// if true pauses execution waiting for an external push to string and then pushes string to stack
57    halt: bool,
58}
59
60impl Machine {
61    pub fn new() -> Self {
62        Self {
63            stack: [0; STACK_SIZE],
64            sp: 0,
65            code: Vec::new(),
66            ip: 0,
67            heap: Vec::new(),
68            ty_flag: 11.into(), // default to u64
69            stream: String::new(),
70            read_wait: false,
71            halt: false,
72        }
73    }
74
75    fn push_stream(&mut self) {
76        let mut stream = self.stream.clone();
77
78        loop {
79            match stream.pop() {
80                Some(ch) => self.value_push(ch.into()),
81                None => break,
82            }
83        }
84    }
85
86    pub fn set_stream(&mut self, input: &str) {
87        self.stream = input.to_string();
88        
89        if self.read_wait {
90            self.push_stream();
91            self.read_wait = false;
92        }
93    }
94
95    pub fn get_stream(&self) -> Option<String> {
96        if self.stream.len() > 0 {
97            return Some(self.stream.clone());
98        }else{
99            return None;
100        }
101    }
102
103    pub fn clear_stream(&mut self) {
104        self.stream = String::new();
105    }
106
107    fn zero(&mut self) {
108        self.stack.fill(0);
109        self.sp = 0;
110        self.code = vec![];
111        self.ip = 0;
112        self.heap = vec![];
113        self.ty_flag = 11.into();
114        self.clear_stream();
115        self.read_wait = false;
116        self.halt = false;
117    }
118
119    pub fn push_code(&mut self, code: &[u8]) {
120        self.code.extend_from_slice(code)
121    }
122
123    fn stack_push(&mut self, raw: u64) {
124        // push a raw value to the stack and increment the stack pointer
125        self.stack[self.sp] = raw;
126        self.sp += 1;
127    }
128
129    fn stack_pop(&mut self) -> u64 {
130        // get the raw value from the stack and decrement the stack pointer
131        match self.sp.checked_sub(1) {
132            Some(n) => self.sp = n,
133            None => panic!("Error: Stack underflow has occured."),
134        };
135        self.stack[self.sp]
136    }
137
138    fn value_pop(&mut self) -> Value {
139        // pop a value from the stack and convert it to the current type flag
140        Value::from_stack(self.ty_flag, self.stack_pop())
141    }
142
143    fn value_push(&mut self, value: Value) {
144        // push a value to the stack
145        self.stack_push(value.to_stack());
146    }
147
148    fn halt(&mut self) {
149        self.halt = true;
150    }
151
152    fn set_ty_flag(&mut self) {
153        // ip currently points to the SET_TYPE instruction
154        // increment ip to point to the next byte which is the type flag
155        self.ty_flag = self.code[self.ip].into();
156        self.ip += 1;
157    }
158
159    fn get_ty_flag(&mut self) {
160        self.stack_push(self.ty_flag.into());
161    }
162
163    binop_helper!(add, +);
164
165    binop_helper!(sub, -);
166
167    binop_helper!(mul, *);
168
169    binop_helper!(div, /);
170
171    binop_helper!(rem, %);
172
173    fn neg(&mut self) {
174        self.stack[self.sp - 1] =
175            (-(Value::from_stack(self.ty_flag, self.stack[self.sp - 1]))).to_stack();
176    }
177
178    fn incr(&mut self) {
179        let value = Value::from_stack(self.ty_flag, self.stack[self.sp - 1]);
180        self.stack[self.sp - 1] = (value + Value::from_stack(self.ty_flag, 1)).to_stack();
181    }
182
183    fn decr(&mut self) {
184        let value = Value::from_stack(self.ty_flag, self.stack[self.sp - 1]);
185        self.stack[self.sp - 1] = (value - Value::from_stack(self.ty_flag, 1)).to_stack();
186    }
187
188    comp_helper!(eq, ==);
189    comp_helper!(neq, !=);
190    comp_helper!(lt, <);
191    comp_helper!(gt, >);
192    comp_helper!(lte, <=);
193    comp_helper!(gte, >=);
194
195    binop_helper!(and, &);
196    binop_helper!(or, |);
197    binop_helper!(xor, ^);
198    binop_helper!(shl, <<);
199    binop_helper!(shr, >>);
200
201    fn not(&mut self) {
202        self.stack[self.sp - 1] =
203            (!Value::from_stack(self.ty_flag, self.stack[self.sp - 1])).to_stack();
204    }
205
206    fn jmp(&mut self) {
207        let addr = self.stack_pop() as usize;
208        self.ip = addr;
209    }
210
211    fn jmp_if(&mut self) {
212        let cond = self.value_pop();
213        let addr = self.stack_pop() as usize;
214
215        if cond.to_stack() != 0 {
216            self.ip = addr;
217        }
218    }
219
220    fn jmp_if_not(&mut self) {
221        let cond = self.value_pop();
222        let addr = self.stack_pop() as usize;
223
224        if cond.to_stack() == 0 {
225            self.ip = addr;
226        }
227    }
228
229    fn call(&mut self) {
230        let addr = self.stack_pop() as usize;
231        self.stack_push(self.ip as u64);
232        self.ip = addr;
233    }
234
235    fn ret(&mut self) {
236        self.ip = self.stack_pop() as usize;
237    }
238
239    fn push(&mut self) {
240        let value = Value::from_code(
241            self.ty_flag,
242            &self.code[self.ip..self.ip + self.ty_flag.size()],
243        );
244        self.value_push(value);
245        self.ip += self.ty_flag.size();
246    }
247
248    fn dup(&mut self) {
249        self.stack[self.sp] = self.stack[self.sp - 1];
250        self.sp += 1;
251    }
252
253    fn drop(&mut self) {
254        self.sp -= 1;
255    }
256
257    fn swap(&mut self) {
258        let tmp = self.stack[self.sp - 1];
259        self.stack[self.sp - 1] = self.stack[self.sp - 2];
260        self.stack[self.sp - 2] = tmp;
261    }
262
263    fn load(&mut self) {
264        let addr = self.stack_pop() as usize;
265        let value = Value::from_code(self.ty_flag, &self.heap[addr..addr + self.ty_flag.size()]);
266        self.value_push(value);
267    }
268
269    fn store(&mut self) {
270        let addr = self.stack_pop() as usize;
271        let value = self.value_pop();
272        let raw = value.to_code();
273        for i in 0..self.ty_flag.size() {
274            self.heap[addr + i] = raw[i];
275        }
276    }
277
278    fn alloc(&mut self) {
279        let size = self.stack_pop() as usize;
280        let addr = self.heap.len();
281        self.heap.resize(addr + size, 0);
282        self.stack_push(addr as u64);
283    }
284
285    fn free(&mut self) {
286        let addr = self.stack_pop() as usize;
287        let size = self.stack_pop() as usize;
288        self.heap.resize(addr + size, 0);
289    }
290
291    fn heap_size(&mut self) {
292        self.stack_push(self.heap.len() as u64);
293    }
294
295    fn stack_size(&mut self) {
296        self.stack_push(self.sp as u64);
297    }
298
299    fn load_code(&mut self) {
300        let addr = self.stack_pop() as usize;
301        let size = self.stack_pop() as usize;
302        let new_code_start = self.code.len();
303        self.code.extend_from_slice(&self.heap[addr..addr + size]);
304        self.stack_push(new_code_start as u64);
305    }
306
307    fn save_code(&mut self) {
308        let addr = self.stack_pop() as usize;
309        let size = self.stack_pop() as usize;
310        let code_seg = &self.code[addr..addr + size];
311        let heap_len = self.heap.len();
312        self.heap.extend_from_slice(code_seg);
313        self.stack_push(heap_len as u64);
314    }
315
316    fn write(&mut self) {
317        let value = self.value_pop().to_string();
318        self.stream += &value;
319    }
320
321    fn read(&mut self) {
322        self.read_wait = true;
323    }
324    
325    fn print(&mut self) {
326        println!("{}", self.stream)
327    }
328
329    fn fetch_instr(&mut self) -> Instruction {
330        if self.ip >= self.code.len() {
331            panic!("Error: Instruction pointer has gone out of bounds")
332        }else{
333            self.ip += 1;
334            return self.code[self.ip - 1].into()
335        }
336    }
337
338    fn dispatch(&mut self) {
339        use Instruction::*;
340
341        let instr = self.fetch_instr();
342
343        match instr {
344            Halt => self.halt(),
345            SetType => self.set_ty_flag(),
346            GetType => self.get_ty_flag(),
347            Add => self.add(),
348            Sub => self.sub(),
349            Mul => self.mul(),
350            Div => self.div(),
351            Rem => self.rem(),
352            Neg => self.neg(),
353            Incr => self.incr(),
354            Decr => self.decr(),
355            Eq => self.eq(),
356            Neq => self.neq(),
357            Lt => self.lt(),
358            Gt => self.gt(),
359            Lte => self.lte(),
360            Gte => self.gte(),
361            And => self.and(),
362            Or => self.or(),
363            Xor => self.xor(),
364            Shl => self.shl(),
365            Shr => self.shr(),
366            Not => self.not(),
367            Jmp => self.jmp(),
368            JmpIf => self.jmp_if(),
369            JmpIfNot => self.jmp_if_not(),
370            Call => self.call(),
371            Ret => self.ret(),
372            Push => self.push(),//
373            Dup => self.dup(),
374            Drop => self.drop(),
375            Swap => self.swap(),
376            Load => self.load(),
377            Store => self.store(),
378            Alloc => self.alloc(),
379            Free => self.free(),
380            HeapSize => self.heap_size(),
381            StackSize => self.stack_size(),
382            LoadCode => self.load_code(),
383            SaveCode => self.save_code(),
384            Read => self.read(),
385            Write => self.write(),
386            Print => self.print(),
387            Clear => self.clear_stream(),
388        }
389    }
390
391    fn run(&mut self) {
392        while self.ip <= self.code.len()  && !self.halt {
393            if !self.read_wait {
394                self.dispatch()
395            }
396        }
397    }
398
399    pub fn execute(&mut self) {
400        self.run()
401    }
402
403    pub fn execute_code(&mut self, code: Vec<u8>) {
404        self.code = code;
405        self.run();
406    }
407}
408
409#[cfg(test)]
410mod tests {
411    use std::vec;
412
413    use super::*;
414
415    #[test]
416    fn test_internal_stack_ops() {
417        let mut machine = Machine::new();
418
419        machine.stack_push(10);
420        assert_eq!(machine.sp, 1);
421
422        let pop = machine.stack_pop();
423        assert_eq!(pop, 10u64);
424        assert_eq!(machine.sp, 0);
425    }
426
427    #[test]
428    fn test_push_instr() {
429        use Instruction::*;
430        use TypeFlag::*;
431        let mut machine = Machine::new();
432
433        let value: Value = 11i8.into();
434        
435        machine.code = bytecode!(SetType, I8, Push);
436        machine.code.extend_from_slice(&value.to_code());
437        machine.push_code(&bytecode!(Halt));
438        machine.run();
439        assert_eq!(machine.stack[machine.sp - 1], 11);
440    }
441
442    #[test]
443    fn test_arith_instrs() {
444        use Instruction::*;
445        use TypeFlag::*;
446
447        let mut machine = Machine::new();
448
449        let lhs: Value = 1000i64.into();
450        let rhs: Value = 500i64.into();
451        let mut start = vec![];
452        start = bytecode!(SetType, I64, Push);
453        start.extend_from_slice(&rhs.to_code());
454        start.extend_from_slice(&bytecode![Push]);
455        start.extend_from_slice(&lhs.to_code());
456        
457        let mut add_test = start.clone();
458        add_test.extend_from_slice(&bytecode!(Add, Halt));
459        machine.code = add_test;
460        machine.run();
461        assert_eq!(Value::from(1500i64), machine.value_pop());
462        machine.zero();
463
464        let mut sub_test = start.clone();
465        sub_test.extend_from_slice(&bytecode!(Sub, Halt));
466        machine.code = sub_test;
467        machine.run();
468        assert_eq!(Value::from(500i64), machine.value_pop());
469        machine.zero();
470
471        let mut mul_test = start.clone();
472        mul_test.extend_from_slice(&bytecode!(Mul, Halt));
473        machine.code = mul_test;
474        machine.run();
475        assert_eq!(Value::from(500000i64), machine.value_pop());
476        machine.zero();
477
478        let mut div_test = start.clone();
479        div_test.extend_from_slice(&bytecode!(Div, Halt));
480        machine.code = div_test;
481        machine.run();
482        assert_eq!(Value::from(2i64), machine.value_pop());
483        machine.zero();
484
485        let mut rem_test = start;
486        rem_test.extend_from_slice(&bytecode!(Rem, Halt));
487        machine.code = rem_test;
488        machine.run();
489        assert_eq!(Value::from(0i64), machine.value_pop());
490    }
491
492    #[test]
493    fn test_write() {
494        let mut machine = Machine::new();
495        machine.code = vec![Instruction::SetType as u8, TypeFlag::Char as u8, Instruction::Push as u8];
496        machine.code.extend_from_slice(&Value::from('c').to_code());
497        machine.code.extend_from_slice(&vec![Instruction::Write as u8, Instruction::Halt as u8]);
498        machine.execute();
499        let out = machine.get_stream().unwrap();
500        assert_eq!(out, 'c'.to_string());
501    }
502}