Class: Koota::VM
- Inherits:
-
Object
- Object
- Koota::VM
- Defined in:
- lib/koota/vm.rb
Overview
Implements a Koota virtual machine.
Defined Under Namespace
Modules: Opcodes
Constant Summary collapse
- CALL_STACK_MAX =
256
Instance Method Summary collapse
- #call(memory) ⇒ Object
-
#initialize(random: Random.new) ⇒ VM
constructor
A new instance of VM.
Constructor Details
#initialize(random: Random.new) ⇒ VM
Returns a new instance of VM.
20 21 22 |
# File 'lib/koota/vm.rb', line 20 def initialize(random: Random.new) @random = random end |
Instance Method Details
#call(memory) ⇒ Object
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/koota/vm.rb', line 24 def call(memory) output = ''.dup call_stack = [] offset = 0 while offset < memory.length op = memory[offset] offset += 1 case op when Opcodes::HALT then break when Opcodes::JUMP offset = Decode.short(memory, offset) when Opcodes::PUT decoded, advance = Decode.utf8(memory, offset) output << decoded offset += advance when Opcodes::PICK list_pointer = Decode.short(memory, offset) list_length = Decode.short(memory, list_pointer) # Jump to the chosen offset. # Multiply the rand by two because each offset has two bytes, and the # list length represents the length of each two-byte block. # Also, the offset starts at 1 to skip the list length. offset = Decode.short(memory, list_pointer + 2 * @random.rand(1..list_length)) when Opcodes::CALL break if call_stack.length >= CALL_STACK_MAX routine_pointer = Decode.short(memory, offset) call_stack.push(offset + 2) # opcode after the routine pointer offset = routine_pointer when Opcodes::RET offset = call_stack.pop break if offset.nil? when Opcodes::JRND offset = @random.rand(2) == 1 ? Decode.short(memory, offset) : offset + 2 else break end end output end |