Sha256: b79e03eeed568690ee356d1b27dfa28cdae39fccd47da7ad61ff56c5ff6ccc8e

Contents?: true

Size: 1.78 KB

Versions: 1

Compression:

Stored size: 1.78 KB

Contents

# frozen_string_literal: true

require 'koota/decode'

module Koota
  # Implements a Koota virtual machine.
  class VM
    module Opcodes
      HALT = 0x00
      JUMP = 0x01
      PUT  = 0x02
      PICK = 0x03
      CALL = 0x04
      RET  = 0x05
      JRND = 0x06
    end

    CALL_STACK_MAX = 256

    def initialize(random: Random.new)
      @random = random
    end

    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
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
koota-0.6.1 lib/koota/vm.rb