vermilion_vm/lib.rs
1//! The top level `lib.rs` for the Vermilion virtual machine.
2
3pub mod instruction;
4pub mod object;
5
6use instruction::Opcode;
7pub use object::VermilionObject;
8use std::collections::HashMap;
9
10/// A function used for external symbols.
11pub type ExternalFunction = fn(&VirtualMachine);
12
13/// A vermilion 2021 R2 compliant symbol.
14#[derive(Clone)]
15pub enum VermilionSymbol {
16
17 /// An internal symbol; with a name and a pointer to an address
18 /// in memory.
19 Internal(String, i64),
20
21 /// An external symbol that has not yet been specified a function.
22 UndefinedExternal(String),
23
24 /// An external symbol defined by the pointer.
25 External(String, ExternalFunction),
26
27}
28
29// A Vermilion 2021 R2 compilant memory section.
30#[derive(Clone)]
31pub struct VermilionSection(pub usize, pub usize);
32
33/// A Vermilion 2021 R2 compliant virtual machine.
34pub struct VirtualMachine {
35
36 /// The memory accessible to the virtual machine. Due to restrictions
37 /// in the Vermilion 2021 R2 specification, there is a maximum of 4 GB
38 /// of memory available.
39 pub heap: Vec<u8>,
40
41 /// The stack, as specified in the Vermilion 2021 R2 specification.
42 pub stack: Vec<VermilionObject>,
43
44 /// A call stack, used for resolving where a return instruction should
45 /// jump to.
46 pub call_stack: Vec<i64>,
47
48 /// The list of symbols accessible to the virtual machine.
49 pub symbols: HashMap<i64, VermilionSymbol>,
50
51 /// List of allocated memory sections
52 pub sections: HashMap<i64, VermilionSection>,
53
54 /// The program counter, the current position in memory that the virtual
55 /// machine is reading bytecode from.
56 pub pc: usize,
57
58 /// The exit code of the virtual machine.
59 pub exit_code: Option<i64>,
60
61}
62
63/// An implementation of the Vermilion 2021 R2 specification.
64impl VirtualMachine {
65
66 /// Creates a new empty virtual machine.
67 pub fn new() -> Self {
68 Self {
69 heap: vec![],
70 stack: vec![],
71 call_stack: vec![],
72 symbols: HashMap::new(),
73 sections: HashMap::new(),
74 pc: 0,
75 exit_code: None,
76 }
77 }
78
79 /// Calls a function based on its symbol ID.
80 pub fn call_function_id(&mut self, id: i64) {
81 // Search through the symbol table to find a function
82 // with a machine name.
83
84 let symbols = self.symbols.clone();
85
86 for symbol in symbols {
87 // Resolve the function and call it if it was found.
88
89 match symbol.1 {
90 VermilionSymbol::Internal(_, addr) => {
91 if id == symbol.0 {
92 self.call_stack.push(self.pc as i64);
93 self.pc = addr.clone() as usize;
94 self.run();
95 }
96 },
97 VermilionSymbol::External(_, f) => {
98 if id == symbol.0 {
99 f(self);
100 }
101 },
102 VermilionSymbol::UndefinedExternal(_) => {
103 if id == symbol.0 {
104 panic!("Call of undefined external function.");
105 }
106 }
107 }
108 }
109 }
110
111 /// Calls an internal function.
112 pub fn call_function(&mut self, name: String) {
113 // Search through the symbol table to find a function
114 // with a machine name.
115
116 let mut symbols = self.symbols.clone();
117 let values = symbols.values_mut();
118
119 for symbol in values {
120 // Resolve the function and call it if it was found.
121
122 match symbol {
123 VermilionSymbol::Internal(n, addr) => {
124 if n == &name {
125 self.call_stack.push(self.pc as i64);
126 self.pc = addr.clone() as usize;
127 self.run();
128 //self.pc = self.call_stack.pop().unwrap() as usize;
129 }
130 },
131 VermilionSymbol::External(n, f) => {
132 if n == &name {
133 f(self);
134 }
135 },
136 VermilionSymbol::UndefinedExternal(n) => {
137 if n == &name {
138 panic!("Call of undefined external function.");
139 }
140 }
141 }
142 }
143 }
144
145 /// Returns the opcode of the current byte at the program counter.
146 fn get_opcode(&mut self) -> Opcode {
147 // Resolve the current byte in the heap
148 let opcode = match self.heap[self.pc] {
149 0x01 => Opcode::Boolean,
150 0x02 => Opcode::Byte,
151 0x03 => Opcode::Integer,
152 0x04 => Opcode::Float,
153 0x05 => Opcode::Pop,
154 0x06 => Opcode::Clone,
155 0x07 => Opcode::Clear,
156 0x0a => Opcode::Trap,
157 0x0e => Opcode::BooleanAdd,
158 0x0f => Opcode::BooleanSubtract,
159 0x10 => Opcode::ByteAdd,
160 0x11 => Opcode::ByteSubtract,
161 0x12 => Opcode::ByteMultiply,
162 0x13 => Opcode::ByteDivide,
163 0x14 => Opcode::ByteRemainder,
164 0x15 => Opcode::IntegerAdd,
165 0x16 => Opcode::IntegerSubtract,
166 0x17 => Opcode::IntegerMultiply,
167 0x18 => Opcode::IntegerDivide,
168 0x19 => Opcode::IntegerRemainder,
169 0x1a => Opcode::FloatAdd,
170 0x1b => Opcode::FloatSubtract,
171 0x1c => Opcode::FloatMultiply,
172 0x1d => Opcode::FloatDivide,
173 0x1e => Opcode::FloatRemainder,
174 0x1f => Opcode::CastBoolean,
175 0x20 => Opcode::CastByte,
176 0x21 => Opcode::CastInteger,
177 0x22 => Opcode::CastFloat,
178 0x23 => Opcode::NegateBoolean,
179 0x24 => Opcode::NegateInteger,
180 0x25 => Opcode::NegateFloat,
181 0x26 => Opcode::Load,
182 0x27 => Opcode::Store,
183 0x28 => Opcode::Realloc,
184 0x29 => Opcode::HeapSize,
185 0x2a => Opcode::Alloc,
186 0x2b => Opcode::ReallocSection,
187 0x2c => Opcode::SectionAddr,
188 0x2d => Opcode::SectionShiftLeft,
189 0x2e => Opcode::SectionShiftRight,
190 0x2f => Opcode::Free,
191 0x30 => Opcode::FreeAndShift,
192 0x31 => Opcode::Branch,
193 0x32 => Opcode::BranchIfZero,
194 0x33 => Opcode::BranchIfNotZero,
195 0x34 => Opcode::Equal,
196 0x35 => Opcode::GreaterThan,
197 0x36 => Opcode::LessThan,
198 0x37 => Opcode::GreaterThanOrEqual,
199 0x38 => Opcode::LessThanOrEqual,
200 0x39 => Opcode::Call,
201 0x3a => Opcode::Return,
202 _ => Opcode::Illegal,
203 };
204
205 // Move on to the next byte
206 self.pc += 1;
207
208 opcode
209 }
210
211 /// Returns the next byte as an unsigned 8-bit integer.
212 fn next_byte(&mut self) -> u8 {
213 // get the next byte
214 let val = self.heap[self.pc];
215
216 // move on to the next byte
217 self.pc += 1;
218
219 val
220 }
221
222 /// Returns the next 8 bytes as a 64 bit integer.
223 fn next_64bit_int(&mut self) -> i64 {
224 let val = i64::from_le_bytes([
225 self.heap[self.pc],
226 self.heap[self.pc + 1],
227 self.heap[self.pc + 2],
228 self.heap[self.pc + 3],
229 self.heap[self.pc + 4],
230 self.heap[self.pc + 5],
231 self.heap[self.pc + 6],
232 self.heap[self.pc + 7],
233 ]);
234
235 self.pc += 8;
236
237 val
238 }
239
240 /// Returns the next 8 bytes as a 64 bit float.
241 fn next_64bit_float(&mut self) -> f64 {
242 let val = f64::from_le_bytes([
243 self.heap[self.pc],
244 self.heap[self.pc + 1],
245 self.heap[self.pc + 2],
246 self.heap[self.pc + 3],
247 self.heap[self.pc + 4],
248 self.heap[self.pc + 5],
249 self.heap[self.pc + 6],
250 self.heap[self.pc + 7],
251 ]);
252
253 self.pc += 8;
254
255 val
256 }
257
258 /// Returns the highest section
259 fn get_highest_section(&mut self) -> usize {
260 let mut highest = 0;
261
262 let keys = self.sections.keys();
263
264 for key in keys {
265 if key > &highest {
266 highest = *key;
267 }
268 }
269
270 highest as usize
271 }
272
273 /// Shifts a section to the left.
274 fn shift_left(&mut self, sect: i64, amount: i64) {
275 let s = &mut self.sections.get_mut(§).unwrap();
276 let old_end_position = s.0.clone();
277 let size = s.1 - s.0;
278
279 let h = self.heap.clone();
280
281 self.heap.drain(old_end_position..old_end_position + amount as usize);
282
283 s.0 = s.0 - amount as usize;
284 s.1 = s.0 + size;
285
286 let mut i = 0;
287 while i < amount {
288 self.heap.insert((s.1 + 1) + i as usize, *h.get(i as usize).unwrap());
289 i += 1;
290 }
291 }
292
293 /// Shifts a section to the right.
294 fn shift_right(&mut self, sect: i64, amount: i64) {
295 let s = &mut self.sections.get_mut(§).unwrap();
296 let old_start_position = s.0.clone();
297 let size = s.1 - s.0;
298
299 let h = self.heap.clone();
300
301 self.heap.drain(old_start_position - amount as usize..old_start_position);
302
303 s.0 = s.0 + amount as usize;
304 s.1 = s.0 + size;
305
306 let mut i = 0;
307 while i < amount {
308 self.heap.insert(s.0 - 1, *h.get(i as usize).unwrap());
309 i += 1;
310 }
311 }
312
313 /// Runs a single instruction in memory, from the program counter. Returns
314 /// true if the virtual machine should exit.
315 fn run_instruction(&mut self) -> bool {
316 // Interpret the current instruction
317
318 if self.pc >= self.heap.len() {
319 return true;
320 }
321
322
323 let opcode = self.get_opcode();
324
325 match opcode {
326 Opcode::Boolean => {
327 // Push a boolean to the stack
328 let obj = VermilionObject::Boolean(self.next_byte() != 0);
329 self.stack.push(obj);
330 },
331 Opcode::Byte => {
332 // Push a byte to the stack
333 let obj = VermilionObject::Byte(self.next_byte());
334 self.stack.push(obj);
335 },
336 Opcode::Integer => {
337 // Push an integer to the stack
338 let obj = VermilionObject::Integer(self.next_64bit_int());
339 self.stack.push(obj);
340 },
341 Opcode::Float => {
342 // Push a float to the stack
343 let obj = VermilionObject::Float(self.next_64bit_float());
344 self.stack.push(obj);
345 },
346 Opcode::Pop => {
347 // remove the topmost item from the stack
348 self.stack.pop();
349 },
350 Opcode::Clone => {
351 // clone the topmost item and push the cloned item back onto
352 // the stack
353 let v = &self.stack[self.stack.len() - 1];
354 let v2 = v.clone();
355 self.stack.push(v2);
356 },
357 Opcode::Clear => {
358 // clear the stack
359 self.stack.clear();
360 },
361 Opcode::Trap => {
362 // exit the application
363 let exit_code = self.stack.pop().unwrap();
364
365 match exit_code {
366 VermilionObject::Integer(i) => {
367 self.exit_code = Some(i);
368 return true;
369 },
370 _ => {
371 // Invalid arguments
372 self.exit_code = Some(255);
373 return true;
374 }
375 }
376 },
377 Opcode::BooleanAdd => {
378 // add boolean
379 let right = self.stack.pop().unwrap();
380 let left = self.stack.pop().unwrap();
381
382 match right {
383 VermilionObject::Boolean(r) => {
384 match left {
385 VermilionObject::Boolean(l) => {
386 self.stack.push(VermilionObject::Boolean(l || r));
387 },
388 _ => {
389 // Invalid arguments
390 self.exit_code = Some(255);
391 return true;
392 }
393 }
394 },
395 _ => {
396 // Invalid arguments
397 self.exit_code = Some(255);
398 return true;
399 }
400 }
401 },
402 Opcode::BooleanSubtract => {
403 // subtract boolean
404 let right = self.stack.pop().unwrap();
405 let left = self.stack.pop().unwrap();
406
407 match right {
408 VermilionObject::Boolean(r) => {
409 match left {
410 VermilionObject::Boolean(l) => {
411 if l {
412 if !r {
413 self.stack.push(VermilionObject::Boolean(true));
414 } else {
415 self.stack.push(VermilionObject::Boolean(false));
416 }
417 } else {
418 self.stack.push(VermilionObject::Boolean(false));
419 }
420 //self.stack.push(VermilionObject::Boolean(l && r));
421 },
422 _ => {
423 // Invalid arguments
424 self.exit_code = Some(255);
425 return true;
426 }
427 }
428 },
429 _ => {
430 // Invalid arguments
431 self.exit_code = Some(255);
432 return true;
433 }
434 }
435 },
436 Opcode::ByteAdd => {
437 // add byte
438 let right = self.stack.pop().unwrap();
439 let left = self.stack.pop().unwrap();
440
441 match right {
442 VermilionObject::Byte(r) => {
443 match left {
444 VermilionObject::Byte(l) => {
445 self.stack.push(VermilionObject::Byte(l + r));
446 },
447 _ => {
448 // Invalid arguments
449 self.exit_code = Some(255);
450 return true;
451 }
452 }
453 },
454 _ => {
455 // Invalid arguments
456 self.exit_code = Some(255);
457 return true;
458 }
459 }
460 },
461 Opcode::ByteSubtract => {
462 // subtract byte
463 let right = self.stack.pop().unwrap();
464 let left = self.stack.pop().unwrap();
465
466 match right {
467 VermilionObject::Byte(r) => {
468 match left {
469 VermilionObject::Byte(l) => {
470 self.stack.push(VermilionObject::Byte(l - r));
471 },
472 _ => {
473 // Invalid arguments
474 self.exit_code = Some(255);
475 return true;
476 }
477 }
478 },
479 _ => {
480 // Invalid arguments
481 self.exit_code = Some(255);
482 return true;
483 }
484 }
485 },
486 Opcode::ByteMultiply => {
487 // multiply byte
488 let right = self.stack.pop().unwrap();
489 let left = self.stack.pop().unwrap();
490
491 match right {
492 VermilionObject::Byte(r) => {
493 match left {
494 VermilionObject::Byte(l) => {
495 self.stack.push(VermilionObject::Byte(l * r));
496 },
497 _ => {
498 // Invalid arguments
499 self.exit_code = Some(255);
500 return true;
501 }
502 }
503 },
504 _ => {
505 // Invalid arguments
506 self.exit_code = Some(255);
507 return true;
508 }
509 }
510 },
511 Opcode::ByteDivide => {
512 // divide byte
513 let right = self.stack.pop().unwrap();
514 let left = self.stack.pop().unwrap();
515
516 match right {
517 VermilionObject::Byte(r) => {
518 match left {
519 VermilionObject::Byte(l) => {
520 self.stack.push(VermilionObject::Byte(l / r));
521 },
522 _ => {
523 // Invalid arguments
524 self.exit_code = Some(255);
525 return true;
526 }
527 }
528 },
529 _ => {
530 // Invalid arguments
531 self.exit_code = Some(255);
532 return true;
533 }
534 }
535 },
536 Opcode::ByteRemainder => {
537 // get remainder of byte
538 let right = self.stack.pop().unwrap();
539 let left = self.stack.pop().unwrap();
540
541 match right {
542 VermilionObject::Byte(r) => {
543 match left {
544 VermilionObject::Byte(l) => {
545 self.stack.push(VermilionObject::Byte(l % r));
546 },
547 _ => {
548 // Invalid arguments
549 self.exit_code = Some(255);
550 return true;
551 }
552 }
553 },
554 _ => {
555 // Invalid arguments
556 self.exit_code = Some(255);
557 return true;
558 }
559 }
560 },
561 Opcode::IntegerAdd => {
562 // add integer
563 let right = self.stack.pop().unwrap();
564 let left = self.stack.pop().unwrap();
565
566 match right {
567 VermilionObject::Integer(r) => {
568 match left {
569 VermilionObject::Integer(l) => {
570 self.stack.push(VermilionObject::Integer(l + r));
571 },
572 _ => {
573 // Invalid arguments
574 self.exit_code = Some(255);
575 return true;
576 }
577 }
578 },
579 _ => {
580 // Invalid arguments
581 self.exit_code = Some(255);
582 return true;
583 }
584 }
585 },
586 Opcode::IntegerSubtract => {
587 // subtract integer
588 let right = self.stack.pop().unwrap();
589 let left = self.stack.pop().unwrap();
590
591 match right {
592 VermilionObject::Integer(r) => {
593 match left {
594 VermilionObject::Integer(l) => {
595 self.stack.push(VermilionObject::Integer(l - r));
596 },
597 _ => {
598 // Invalid arguments
599 self.exit_code = Some(255);
600 return true;
601 }
602 }
603 },
604 _ => {
605 // Invalid arguments
606 self.exit_code = Some(255);
607 return true;
608 }
609 }
610 },
611 Opcode::IntegerMultiply => {
612 // multiply integer
613 let right = self.stack.pop().unwrap();
614 let left = self.stack.pop().unwrap();
615
616 match right {
617 VermilionObject::Integer(r) => {
618 match left {
619 VermilionObject::Integer(l) => {
620 self.stack.push(VermilionObject::Integer(l * r));
621 },
622 _ => {
623 // Invalid arguments
624 self.exit_code = Some(255);
625 return true;
626 }
627 }
628 },
629 _ => {
630 // Invalid arguments
631 self.exit_code = Some(255);
632 return true;
633 }
634 }
635 },
636 Opcode::IntegerDivide => {
637 // divide integer
638 let right = self.stack.pop().unwrap();
639 let left = self.stack.pop().unwrap();
640
641 match right {
642 VermilionObject::Integer(r) => {
643 match left {
644 VermilionObject::Integer(l) => {
645 self.stack.push(VermilionObject::Integer(l / r));
646 },
647 _ => {
648 // Invalid arguments
649 self.exit_code = Some(255);
650 return true;
651 }
652 }
653 },
654 _ => {
655 // Invalid arguments
656 self.exit_code = Some(255);
657 return true;
658 }
659 }
660 },
661 Opcode::IntegerRemainder => {
662 // get remainder of integer
663 let right = self.stack.pop().unwrap();
664 let left = self.stack.pop().unwrap();
665
666 match right {
667 VermilionObject::Integer(r) => {
668 match left {
669 VermilionObject::Integer(l) => {
670 self.stack.push(VermilionObject::Integer(l % r));
671 },
672 _ => {
673 // Invalid arguments
674 self.exit_code = Some(255);
675 return true;
676 }
677 }
678 },
679 _ => {
680 // Invalid arguments
681 self.exit_code = Some(255);
682 return true;
683 }
684 }
685 },
686 Opcode::FloatAdd => {
687 // add float
688 let right = self.stack.pop().unwrap();
689 let left = self.stack.pop().unwrap();
690
691 match right {
692 VermilionObject::Float(r) => {
693 match left {
694 VermilionObject::Float(l) => {
695 self.stack.push(VermilionObject::Float(l + r));
696 },
697 _ => {
698 // Invalid arguments
699 self.exit_code = Some(255);
700 return true;
701 }
702 }
703 },
704 _ => {
705 // Invalid arguments
706 self.exit_code = Some(255);
707 return true;
708 }
709 }
710 },
711 Opcode::FloatSubtract => {
712 // subtract float
713 let right = self.stack.pop().unwrap();
714 let left = self.stack.pop().unwrap();
715
716 match right {
717 VermilionObject::Float(r) => {
718 match left {
719 VermilionObject::Float(l) => {
720 self.stack.push(VermilionObject::Float(l - r));
721 },
722 _ => {
723 // Invalid arguments
724 self.exit_code = Some(255);
725 return true;
726 }
727 }
728 },
729 _ => {
730 // Invalid arguments
731 self.exit_code = Some(255);
732 return true;
733 }
734 }
735 },
736 Opcode::FloatMultiply => {
737 // multiply float
738 let right = self.stack.pop().unwrap();
739 let left = self.stack.pop().unwrap();
740
741 match right {
742 VermilionObject::Float(r) => {
743 match left {
744 VermilionObject::Float(l) => {
745 self.stack.push(VermilionObject::Float(l * r));
746 },
747 _ => {
748 // Invalid arguments
749 self.exit_code = Some(255);
750 return true;
751 }
752 }
753 },
754 _ => {
755 // Invalid arguments
756 self.exit_code = Some(255);
757 return true;
758 }
759 }
760 },
761 Opcode::FloatDivide => {
762 // divide float
763 let right = self.stack.pop().unwrap();
764 let left = self.stack.pop().unwrap();
765
766 match right {
767 VermilionObject::Float(r) => {
768 match left {
769 VermilionObject::Float(l) => {
770 self.stack.push(VermilionObject::Float(l / r));
771 },
772 _ => {
773 // Invalid arguments
774 self.exit_code = Some(255);
775 return true;
776 }
777 }
778 },
779 _ => {
780 // Invalid arguments
781 self.exit_code = Some(255);
782 return true;
783 }
784 }
785 },
786 Opcode::FloatRemainder => {
787 // get remainder of float
788 let right = self.stack.pop().unwrap();
789 let left = self.stack.pop().unwrap();
790
791 match right {
792 VermilionObject::Float(r) => {
793 match left {
794 VermilionObject::Float(l) => {
795 self.stack.push(VermilionObject::Float(l % r));
796 },
797 _ => {
798 // Invalid arguments
799 self.exit_code = Some(255);
800 return true;
801 }
802 }
803 },
804 _ => {
805 // Invalid arguments
806 self.exit_code = Some(255);
807 return true;
808 }
809 }
810 },
811 Opcode::CastBoolean => {
812 // cast anything to a boolean
813 let to_cast = self.stack.pop().unwrap();
814
815 match to_cast {
816 VermilionObject::Boolean(r) => {
817 self.stack.push(VermilionObject::Boolean(r));
818 },
819 VermilionObject::Byte(r) => {
820 self.stack.push(VermilionObject::Boolean(r != 0));
821 },
822 VermilionObject::Integer(r) => {
823 self.stack.push(VermilionObject::Boolean(r != 0));
824 },
825 VermilionObject::Float(r) => {
826 self.stack.push(VermilionObject::Boolean(r != 0f64));
827 },
828 }
829 },
830 Opcode::CastByte => {
831 // cast anything to a byte
832 let to_cast = self.stack.pop().unwrap();
833
834 match to_cast {
835 VermilionObject::Boolean(r) => {
836 self.stack.push(VermilionObject::Byte(r as u8));
837 },
838 VermilionObject::Byte(r) => {
839 self.stack.push(VermilionObject::Byte(r));
840 },
841 VermilionObject::Integer(r) => {
842 self.stack.push(VermilionObject::Byte(r as u8));
843 },
844 VermilionObject::Float(r) => {
845 self.stack.push(VermilionObject::Byte(r as u8));
846 },
847 }
848 },
849 Opcode::CastInteger => {
850 // cast anything to an integer
851 let to_cast = self.stack.pop().unwrap();
852
853 match to_cast {
854 VermilionObject::Boolean(r) => {
855 self.stack.push(VermilionObject::Integer(r as i64));
856 },
857 VermilionObject::Byte(r) => {
858 self.stack.push(VermilionObject::Integer(r as i64));
859 },
860 VermilionObject::Integer(r) => {
861 self.stack.push(VermilionObject::Integer(r));
862 },
863 VermilionObject::Float(r) => {
864 self.stack.push(VermilionObject::Integer(r as i64));
865 },
866 }
867 },
868 Opcode::CastFloat => {
869 // cast anything to a float
870 let to_cast = self.stack.pop().unwrap();
871
872 match to_cast {
873 VermilionObject::Boolean(r) => {
874 self.stack.push(VermilionObject::Float((r as i64) as f64));
875 },
876 VermilionObject::Byte(r) => {
877 self.stack.push(VermilionObject::Float(r as f64));
878 },
879 VermilionObject::Integer(r) => {
880 self.stack.push(VermilionObject::Float(r as f64));
881 },
882 VermilionObject::Float(r) => {
883 self.stack.push(VermilionObject::Float(r));
884 },
885 }
886 },
887 Opcode::NegateBoolean => {
888 // negate boolean
889 let right = self.stack.pop().unwrap();
890
891 match right {
892 VermilionObject::Boolean(r) => {
893 self.stack.push(VermilionObject::Boolean(!r));
894 },
895 _ => {
896 // Invalid arguments
897 self.exit_code = Some(255);
898 return true;
899 }
900 }
901 },
902 Opcode::NegateByte => {
903 // negate byte
904 let right = self.stack.pop().unwrap();
905
906 match right {
907 VermilionObject::Byte(r) => {
908 self.stack.push(VermilionObject::Byte(!r));
909 },
910 _ => {
911 // Invalid arguments
912 self.exit_code = Some(255);
913 return true;
914 }
915 }
916 },
917 Opcode::NegateInteger => {
918 // negate integer
919 let right = self.stack.pop().unwrap();
920
921 match right {
922 VermilionObject::Integer(r) => {
923 self.stack.push(VermilionObject::Integer(-r));
924 },
925 _ => {
926 // Invalid arguments
927 self.exit_code = Some(255);
928 return true;
929 }
930 }
931 },
932 Opcode::NegateFloat => {
933 // negate float
934 let right = self.stack.pop().unwrap();
935
936 match right {
937 VermilionObject::Float(r) => {
938 self.stack.push(VermilionObject::Float(-r));
939 },
940 _ => {
941 // Invalid arguments
942 self.exit_code = Some(255);
943 return true;
944 }
945 }
946 },
947 Opcode::Load => {
948 // load byte from the heap
949 let right = self.stack.pop().unwrap();
950
951 match right {
952 VermilionObject::Integer(r) => {
953 let val = self.heap[r as usize];
954 self.stack.push(VermilionObject::Byte(val));
955 },
956 _ => {
957 // Invalid arguments
958 self.exit_code = Some(255);
959 return true;
960 }
961 }
962 },
963 Opcode::Store => {
964 // store a byte in the heap
965 let right = self.stack.pop().unwrap();
966 let left = self.stack.pop().unwrap();
967
968 match right {
969 VermilionObject::Integer(r) => {
970 match left {
971 VermilionObject::Integer(l) => {
972 self.heap[l as usize] = r as u8
973 },
974 _ => {
975 // Invalid arguments
976 self.exit_code = Some(255);
977 return true;
978 }
979 }
980 },
981 _ => {
982 // Invalid arguments
983 self.exit_code = Some(255);
984 return true;
985 }
986 }
987 },
988 Opcode::Realloc => {
989 // reallocate the heap
990 let right = self.stack.pop().unwrap();
991
992 match right {
993 VermilionObject::Integer(r) => {
994 self.heap.resize(r as usize, 0);
995 },
996 _ => {
997 // Invalid arguments
998 self.exit_code = Some(255);
999 return true;
1000 }
1001 }
1002 },
1003 Opcode::HeapSize => {
1004 // push heap size to stack
1005 self.stack.push(VermilionObject::Integer(self.heap.len() as i64));
1006 },
1007 Opcode::Alloc => {
1008 // allocate a section
1009 let right = self.stack.pop().unwrap();
1010
1011 match right {
1012 VermilionObject::Integer(r) => {
1013 let sectid = self.get_highest_section();
1014 let sect = &self.sections[&(sectid as i64)];
1015
1016 let sect2 = VermilionSection(sect.1 + 1, sect.1 + 1);
1017 self.sections.insert(r, sect2);
1018 },
1019 _ => {
1020 // Invalid arguments
1021 self.exit_code = Some(255);
1022 return true;
1023 }
1024 }
1025 },
1026 Opcode::ReallocSection => {
1027 // reallocate a section
1028 let right = self.stack.pop().unwrap();
1029 let left = self.stack.pop().unwrap();
1030
1031 match right {
1032 VermilionObject::Integer(r) => {
1033 match left {
1034 VermilionObject::Integer(l) => {
1035 let s = self.sections.get_mut(&l).unwrap();
1036 let size = s.1 - s.0;
1037 let difference = r - size as i64;
1038
1039 if difference >= 0 {
1040 // allocate new memory
1041 let mut i = 0;
1042
1043 while i < difference {
1044 self.heap.insert(s.1 + 1, 0);
1045 i += 1;
1046 }
1047 s.1 = s.0 + r as usize;
1048
1049
1050 // shift other sections
1051 for section in self.sections.iter_mut() {
1052 if section.0 > &l {
1053 section.1.0 += difference as usize;
1054 section.1.1 += difference as usize;
1055 }
1056 }
1057 } else {
1058 // free used memory
1059 // allocate new memory
1060
1061 self.heap.drain(difference as usize..s.1);
1062 s.1 = s.0 + r as usize;
1063
1064
1065 // shift other sections
1066 for section in self.sections.iter_mut() {
1067 if section.0 > &l {
1068 section.1.0 -= difference as usize;
1069 section.1.1 -= difference as usize;
1070 }
1071 }
1072 }
1073 },
1074 _ => {
1075 // Invalid arguments
1076 self.exit_code = Some(255);
1077 return true;
1078 }
1079 }
1080 },
1081 _ => {
1082 // Invalid arguments
1083 self.exit_code = Some(255);
1084 return true;
1085 }
1086 }
1087 },
1088 Opcode::SectionAddr => {
1089 // returns a section's start address
1090 let right = self.stack.pop().unwrap();
1091
1092 match right {
1093 VermilionObject::Integer(r) => {
1094 let item = &self.sections[&r];
1095 self.stack.push(VermilionObject::Integer(item.0 as i64))
1096 },
1097 _ => {
1098 // Invalid arguments
1099 self.exit_code = Some(255);
1100 return true;
1101 }
1102 }
1103 },
1104 Opcode::SectionShiftLeft => {
1105 // shift a section to the left
1106 let right = self.stack.pop().unwrap();
1107 let left = self.stack.pop().unwrap();
1108
1109 match right {
1110 VermilionObject::Integer(r) => {
1111 match left {
1112 VermilionObject::Integer(l) => {
1113 self.shift_left(l, r)
1114 },
1115 _ => {
1116 // Invalid arguments
1117 self.exit_code = Some(255);
1118 return true;
1119 }
1120 }
1121 },
1122 _ => {
1123 // Invalid arguments
1124 self.exit_code = Some(255);
1125 return true;
1126 }
1127 }
1128 },
1129 Opcode::SectionShiftRight => {
1130 // shift a section to the right
1131 let right = self.stack.pop().unwrap();
1132 let left = self.stack.pop().unwrap();
1133
1134 match right {
1135 VermilionObject::Integer(r) => {
1136 match left {
1137 VermilionObject::Integer(l) => {
1138 self.shift_right(l, r)
1139 },
1140 _ => {
1141 // Invalid arguments
1142 self.exit_code = Some(255);
1143 return true;
1144 }
1145 }
1146 },
1147 _ => {
1148 // Invalid arguments
1149 self.exit_code = Some(255);
1150 return true;
1151 }
1152 }
1153 },
1154 Opcode::Free => {
1155 // frees a section
1156 let right = self.stack.pop().unwrap();
1157
1158 match right {
1159 VermilionObject::Integer(r) => {
1160 let item = &self.sections[&r];
1161 self.heap.drain(item.0..item.1);
1162
1163 let mut i = 0;
1164 let size = item.1 - item.0;
1165 while i < size {
1166 self.heap.insert(item.0 + i, 0);
1167 i += 1;
1168 }
1169 //self.stack.push(VermilionObject::Integer(item.0 as i64))
1170 },
1171 _ => {
1172 // Invalid arguments
1173 self.exit_code = Some(255);
1174 return true;
1175 }
1176 }
1177 },
1178 Opcode::FreeAndShift => {
1179 // frees a section and shifts following sections to fill it in
1180 let right = self.stack.pop().unwrap();
1181
1182 match right {
1183 VermilionObject::Integer(r) => {
1184 let item = &self.sections[&r];
1185 self.heap.drain(item.0..item.1);
1186
1187 let mut i = 0;
1188 let size = item.1 - item.0;
1189 while i < size {
1190 self.heap.insert(item.0 + i, 0);
1191 i += 1;
1192 }
1193
1194 let iter = self.sections.clone();
1195 for item in iter {
1196 if item.0 > r {
1197 self.shift_left(item.0, size as i64);
1198 }
1199 }
1200 },
1201 _ => {
1202 // Invalid arguments
1203 self.exit_code = Some(255);
1204 return true;
1205 }
1206 }
1207 },
1208 Opcode::Branch => {
1209 // branch
1210 let right = self.stack.pop().unwrap();
1211
1212 match right {
1213 VermilionObject::Integer(r) => {
1214 self.pc = r as usize;
1215 },
1216 _ => {
1217 // Invalid arguments
1218 self.exit_code = Some(255);
1219 return true;
1220 }
1221 }
1222 },
1223 Opcode::BranchIfZero => {
1224 // branch if zero
1225 let right = self.stack.pop().unwrap();
1226 let left = self.stack.pop().unwrap();
1227
1228 match right {
1229 VermilionObject::Boolean(r) => {
1230 match left {
1231 VermilionObject::Integer(l) => {
1232 if !r {
1233 self.pc = l as usize;
1234 }
1235 },
1236 _ => {
1237 // Invalid arguments
1238 self.exit_code = Some(255);
1239 return true;
1240 }
1241 }
1242 },
1243 _ => {
1244 // Invalid arguments
1245 self.exit_code = Some(255);
1246 return true;
1247 }
1248 }
1249 },
1250 Opcode::BranchIfNotZero => {
1251 // branch if not zero
1252 let right = self.stack.pop().unwrap();
1253 let left = self.stack.pop().unwrap();
1254
1255 match right {
1256 VermilionObject::Boolean(r) => {
1257 match left {
1258 VermilionObject::Integer(l) => {
1259 if r {
1260 self.pc = l as usize;
1261 }
1262 },
1263 _ => {
1264 // Invalid arguments
1265 self.exit_code = Some(255);
1266 return true;
1267 }
1268 }
1269 },
1270 _ => {
1271 // Invalid arguments
1272 self.exit_code = Some(255);
1273 return true;
1274 }
1275 }
1276 },
1277 Opcode::Equal => {
1278 // equal
1279 let right = self.stack.pop().unwrap();
1280 let left = self.stack.pop().unwrap();
1281
1282 match right {
1283 VermilionObject::Boolean(r) => {
1284 match left {
1285 VermilionObject::Boolean(l) => {
1286 self.stack.push(VermilionObject::Boolean(l == r));
1287 },
1288 VermilionObject::Byte(l) => {
1289 self.stack.push(VermilionObject::Boolean(l == r as u8));
1290 },
1291 VermilionObject::Integer(l) => {
1292 self.stack.push(VermilionObject::Boolean(l == r as i64));
1293 },
1294 VermilionObject::Float(l) => {
1295 self.stack.push(VermilionObject::Boolean(l == (r as i64) as f64));
1296 },
1297 }
1298 },
1299 VermilionObject::Byte(r) => {
1300 match left {
1301 VermilionObject::Boolean(l) => {
1302 self.stack.push(VermilionObject::Boolean(l == (r != 0)));
1303 },
1304 VermilionObject::Byte(l) => {
1305 self.stack.push(VermilionObject::Boolean(l == r as u8));
1306 },
1307 VermilionObject::Integer(l) => {
1308 self.stack.push(VermilionObject::Boolean(l == r as i64));
1309 },
1310 VermilionObject::Float(l) => {
1311 self.stack.push(VermilionObject::Boolean(l == (r as i64) as f64));
1312 },
1313 }
1314 },
1315 VermilionObject::Integer(r) => {
1316 match left {
1317 VermilionObject::Boolean(l) => {
1318 self.stack.push(VermilionObject::Boolean(l == (r != 0)));
1319 },
1320 VermilionObject::Byte(l) => {
1321 self.stack.push(VermilionObject::Boolean(l == r as u8));
1322 },
1323 VermilionObject::Integer(l) => {
1324 self.stack.push(VermilionObject::Boolean(l == r as i64));
1325 },
1326 VermilionObject::Float(l) => {
1327 self.stack.push(VermilionObject::Boolean(l == (r as i64) as f64));
1328 },
1329 }
1330 },
1331 VermilionObject::Float(r) => {
1332 match left {
1333 VermilionObject::Boolean(l) => {
1334 self.stack.push(VermilionObject::Boolean(l == (r != 0f64)));
1335 },
1336 VermilionObject::Byte(l) => {
1337 self.stack.push(VermilionObject::Boolean(l == r as u8));
1338 },
1339 VermilionObject::Integer(l) => {
1340 self.stack.push(VermilionObject::Boolean(l == r as i64));
1341 },
1342 VermilionObject::Float(l) => {
1343 self.stack.push(VermilionObject::Boolean(l == (r as i64) as f64));
1344 },
1345 }
1346 },
1347 }
1348 },
1349 Opcode::GreaterThan => {
1350 // greater than
1351 let right = self.stack.pop().unwrap();
1352 let left = self.stack.pop().unwrap();
1353
1354 match right {
1355 VermilionObject::Boolean(r) => {
1356 match left {
1357 VermilionObject::Boolean(l) => {
1358 self.stack.push(VermilionObject::Boolean(l as u8 > r as u8));
1359 },
1360 VermilionObject::Byte(l) => {
1361 self.stack.push(VermilionObject::Boolean(l > r as u8));
1362 },
1363 VermilionObject::Integer(l) => {
1364 self.stack.push(VermilionObject::Boolean(l > r as i64));
1365 },
1366 VermilionObject::Float(l) => {
1367 self.stack.push(VermilionObject::Boolean(l > (r as i64) as f64));
1368 },
1369 }
1370 },
1371 VermilionObject::Byte(r) => {
1372 match left {
1373 VermilionObject::Boolean(l) => {
1374 self.stack.push(VermilionObject::Boolean(l > (r != 0)));
1375 },
1376 VermilionObject::Byte(l) => {
1377 self.stack.push(VermilionObject::Boolean(l > r as u8));
1378 },
1379 VermilionObject::Integer(l) => {
1380 self.stack.push(VermilionObject::Boolean(l > r as i64));
1381 },
1382 VermilionObject::Float(l) => {
1383 self.stack.push(VermilionObject::Boolean(l > (r as i64) as f64));
1384 },
1385 }
1386 },
1387 VermilionObject::Integer(r) => {
1388 match left {
1389 VermilionObject::Boolean(l) => {
1390 self.stack.push(VermilionObject::Boolean(l > (r != 0)));
1391 },
1392 VermilionObject::Byte(l) => {
1393 self.stack.push(VermilionObject::Boolean(l > r as u8));
1394 },
1395 VermilionObject::Integer(l) => {
1396 self.stack.push(VermilionObject::Boolean(l > r as i64));
1397 },
1398 VermilionObject::Float(l) => {
1399 self.stack.push(VermilionObject::Boolean(l > (r as i64) as f64));
1400 },
1401 }
1402 },
1403 VermilionObject::Float(r) => {
1404 match left {
1405 VermilionObject::Boolean(l) => {
1406 self.stack.push(VermilionObject::Boolean(l > (r != 0f64)));
1407 },
1408 VermilionObject::Byte(l) => {
1409 self.stack.push(VermilionObject::Boolean(l > r as u8));
1410 },
1411 VermilionObject::Integer(l) => {
1412 self.stack.push(VermilionObject::Boolean(l > r as i64));
1413 },
1414 VermilionObject::Float(l) => {
1415 self.stack.push(VermilionObject::Boolean(l > (r as i64) as f64));
1416 },
1417 }
1418 },
1419 }
1420 },
1421 Opcode::LessThan => {
1422 // less than
1423 let right = self.stack.pop().unwrap();
1424 let left = self.stack.pop().unwrap();
1425
1426 match right {
1427 VermilionObject::Boolean(r) => {
1428 match left {
1429 VermilionObject::Boolean(l) => {
1430 self.stack.push(VermilionObject::Boolean((l as u8) < r as u8));
1431 },
1432 VermilionObject::Byte(l) => {
1433 self.stack.push(VermilionObject::Boolean(l < r as u8));
1434 },
1435 VermilionObject::Integer(l) => {
1436 self.stack.push(VermilionObject::Boolean(l < r as i64));
1437 },
1438 VermilionObject::Float(l) => {
1439 self.stack.push(VermilionObject::Boolean(l < (r as i64) as f64));
1440 },
1441 }
1442 },
1443 VermilionObject::Byte(r) => {
1444 match left {
1445 VermilionObject::Boolean(l) => {
1446 self.stack.push(VermilionObject::Boolean(l < (r != 0)));
1447 },
1448 VermilionObject::Byte(l) => {
1449 self.stack.push(VermilionObject::Boolean(l < r as u8));
1450 },
1451 VermilionObject::Integer(l) => {
1452 self.stack.push(VermilionObject::Boolean(l < r as i64));
1453 },
1454 VermilionObject::Float(l) => {
1455 self.stack.push(VermilionObject::Boolean(l < (r as i64) as f64));
1456 },
1457 }
1458 },
1459 VermilionObject::Integer(r) => {
1460 match left {
1461 VermilionObject::Boolean(l) => {
1462 self.stack.push(VermilionObject::Boolean(l < (r != 0)));
1463 },
1464 VermilionObject::Byte(l) => {
1465 self.stack.push(VermilionObject::Boolean(l < r as u8));
1466 },
1467 VermilionObject::Integer(l) => {
1468 self.stack.push(VermilionObject::Boolean(l < r as i64));
1469 },
1470 VermilionObject::Float(l) => {
1471 self.stack.push(VermilionObject::Boolean(l < (r as i64) as f64));
1472 },
1473 }
1474 },
1475 VermilionObject::Float(r) => {
1476 match left {
1477 VermilionObject::Boolean(l) => {
1478 self.stack.push(VermilionObject::Boolean(l < (r != 0f64)));
1479 },
1480 VermilionObject::Byte(l) => {
1481 self.stack.push(VermilionObject::Boolean(l < r as u8));
1482 },
1483 VermilionObject::Integer(l) => {
1484 self.stack.push(VermilionObject::Boolean(l < r as i64));
1485 },
1486 VermilionObject::Float(l) => {
1487 self.stack.push(VermilionObject::Boolean(l < (r as i64) as f64));
1488 },
1489 }
1490 },
1491 }
1492 },
1493 Opcode::GreaterThanOrEqual => {
1494 // greater than or equal to
1495 let right = self.stack.pop().unwrap();
1496 let left = self.stack.pop().unwrap();
1497
1498 match right {
1499 VermilionObject::Boolean(r) => {
1500 match left {
1501 VermilionObject::Boolean(l) => {
1502 self.stack.push(VermilionObject::Boolean(l as u8 >= r as u8));
1503 },
1504 VermilionObject::Byte(l) => {
1505 self.stack.push(VermilionObject::Boolean(l >= r as u8));
1506 },
1507 VermilionObject::Integer(l) => {
1508 self.stack.push(VermilionObject::Boolean(l >= r as i64));
1509 },
1510 VermilionObject::Float(l) => {
1511 self.stack.push(VermilionObject::Boolean(l >= (r as i64) as f64));
1512 },
1513 }
1514 },
1515 VermilionObject::Byte(r) => {
1516 match left {
1517 VermilionObject::Boolean(l) => {
1518 self.stack.push(VermilionObject::Boolean(l >= (r != 0)));
1519 },
1520 VermilionObject::Byte(l) => {
1521 self.stack.push(VermilionObject::Boolean(l >= r as u8));
1522 },
1523 VermilionObject::Integer(l) => {
1524 self.stack.push(VermilionObject::Boolean(l >= r as i64));
1525 },
1526 VermilionObject::Float(l) => {
1527 self.stack.push(VermilionObject::Boolean(l >= (r as i64) as f64));
1528 },
1529 }
1530 },
1531 VermilionObject::Integer(r) => {
1532 match left {
1533 VermilionObject::Boolean(l) => {
1534 self.stack.push(VermilionObject::Boolean(l >= (r != 0)));
1535 },
1536 VermilionObject::Byte(l) => {
1537 self.stack.push(VermilionObject::Boolean(l >= r as u8));
1538 },
1539 VermilionObject::Integer(l) => {
1540 self.stack.push(VermilionObject::Boolean(l >= r as i64));
1541 },
1542 VermilionObject::Float(l) => {
1543 self.stack.push(VermilionObject::Boolean(l >= (r as i64) as f64));
1544 },
1545 }
1546 },
1547 VermilionObject::Float(r) => {
1548 match left {
1549 VermilionObject::Boolean(l) => {
1550 self.stack.push(VermilionObject::Boolean(l >= (r != 0f64)));
1551 },
1552 VermilionObject::Byte(l) => {
1553 self.stack.push(VermilionObject::Boolean(l >= r as u8));
1554 },
1555 VermilionObject::Integer(l) => {
1556 self.stack.push(VermilionObject::Boolean(l >= r as i64));
1557 },
1558 VermilionObject::Float(l) => {
1559 self.stack.push(VermilionObject::Boolean(l >= (r as i64) as f64));
1560 },
1561 }
1562 },
1563 }
1564 },
1565 Opcode::LessThanOrEqual => {
1566 // less than or equal to
1567 let right = self.stack.pop().unwrap();
1568 let left = self.stack.pop().unwrap();
1569
1570 match right {
1571 VermilionObject::Boolean(r) => {
1572 match left {
1573 VermilionObject::Boolean(l) => {
1574 self.stack.push(VermilionObject::Boolean((l as u8) <= r as u8));
1575 },
1576 VermilionObject::Byte(l) => {
1577 self.stack.push(VermilionObject::Boolean(l <= r as u8));
1578 },
1579 VermilionObject::Integer(l) => {
1580 self.stack.push(VermilionObject::Boolean(l <= r as i64));
1581 },
1582 VermilionObject::Float(l) => {
1583 self.stack.push(VermilionObject::Boolean(l <= (r as i64) as f64));
1584 },
1585 }
1586 },
1587 VermilionObject::Byte(r) => {
1588 match left {
1589 VermilionObject::Boolean(l) => {
1590 self.stack.push(VermilionObject::Boolean(l <= (r != 0)));
1591 },
1592 VermilionObject::Byte(l) => {
1593 self.stack.push(VermilionObject::Boolean(l <= r as u8));
1594 },
1595 VermilionObject::Integer(l) => {
1596 self.stack.push(VermilionObject::Boolean(l <= r as i64));
1597 },
1598 VermilionObject::Float(l) => {
1599 self.stack.push(VermilionObject::Boolean(l <= (r as i64) as f64));
1600 },
1601 }
1602 },
1603 VermilionObject::Integer(r) => {
1604 match left {
1605 VermilionObject::Boolean(l) => {
1606 self.stack.push(VermilionObject::Boolean(l <= (r != 0)));
1607 },
1608 VermilionObject::Byte(l) => {
1609 self.stack.push(VermilionObject::Boolean(l <= r as u8));
1610 },
1611 VermilionObject::Integer(l) => {
1612 self.stack.push(VermilionObject::Boolean(l <= r as i64));
1613 },
1614 VermilionObject::Float(l) => {
1615 self.stack.push(VermilionObject::Boolean(l <= (r as i64) as f64));
1616 },
1617 }
1618 },
1619 VermilionObject::Float(r) => {
1620 match left {
1621 VermilionObject::Boolean(l) => {
1622 self.stack.push(VermilionObject::Boolean(l <= (r != 0f64)));
1623 },
1624 VermilionObject::Byte(l) => {
1625 self.stack.push(VermilionObject::Boolean(l <= r as u8));
1626 },
1627 VermilionObject::Integer(l) => {
1628 self.stack.push(VermilionObject::Boolean(l <= r as i64));
1629 },
1630 VermilionObject::Float(l) => {
1631 self.stack.push(VermilionObject::Boolean(l <= (r as i64) as f64));
1632 },
1633 }
1634 },
1635 }
1636 },
1637 Opcode::Call => {
1638 // call function
1639 let right = self.stack.pop().unwrap();
1640
1641 match right {
1642 VermilionObject::Integer(r) => {
1643 self.call_function_id(r);
1644 },
1645 _ => {
1646 // Invalid arguments
1647 self.exit_code = Some(255);
1648 return true;
1649 }
1650 }
1651 },
1652 Opcode::Return => {
1653 // return from function call
1654 self.pc = self.call_stack.pop().expect("unable to get call stack item") as usize;
1655 return true;
1656 },
1657 Opcode::Illegal => {
1658 self.exit_code = Some(255);
1659 return true;
1660 },
1661 };
1662
1663 false
1664 }
1665
1666 /// Runs the instructions in memory, starting at the program counter.
1667 pub fn run(&mut self) {
1668 let mut should_exit = false;
1669
1670 while !should_exit {
1671 should_exit = self.run_instruction();
1672 }
1673 }
1674
1675}