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(&sect).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(&sect).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}