class Kaguya::VM

Public Class Methods

new(iseq) click to toggle source

@param [Array] iseq

# File lib/kaguya/vm.rb, line 8
def initialize(iseq)
  @iseq = iseq
  @pc = 0
  @left_stack = [0]
  @right_stack = []
end

Public Instance Methods

run() click to toggle source
# File lib/kaguya/vm.rb, line 15
def run
  loop do
    instruction = fetch(@pc)
    execute(instruction)
  end
end

Private Instance Methods

execute(instruction) click to toggle source

@param [Array] instruction

# File lib/kaguya/vm.rb, line 31
def execute(instruction)
  case instruction[0]
  when :forward
    if @right_stack.size < 1
      @left_stack.push(0)
    else
      @left_stack.push(@right_stack.pop)
    end
    @pc += 1
  when :backward
    @right_stack.push(@left_stack.pop)
    @pc += 1
  when :increment
    @left_stack.push(@left_stack.pop + 1)
    @pc += 1
  when :decrement
    @left_stack.push(@left_stack.pop - 1)
    @pc += 1
  when :output
    value = @left_stack.pop
    STDOUT.print(value.chr)
    @left_stack.push(value)
    @pc += 1
  when :input
    @left_stack.pop
    @left_stack.push(STDIN.getc.ord)
    @pc += 1
  when :branch_ifzero
    value = @left_stack.pop
    @left_stack.push(value)
    if value.zero?
      @pc += instruction[1]
    else
      @pc += 1
    end
  when :branch_unlesszero
    value = @left_stack.pop
    @left_stack.push(value)
    if !value.zero?
      @pc += instruction[1]
    else
      @pc += 1
    end
  when :leave
    exit 0
  else
    raise "Unknown instruction #{instruction[0]}"
  end
rescue => e
  pp @left_stack
  pp @right_stack
  raise(e)
end
fetch(pc) click to toggle source

@param [Integer] pc @return [Integer]

# File lib/kaguya/vm.rb, line 26
def fetch(pc)
  @iseq[pc]
end