class A0A0
  OPS = Hash[*%w[S + D - M * L <=>]]

  def initialize source
    @program = *source.lines
    @line = @program.index { |p| p['>'] } || 0
    @program.map! { |p| p.scan /\w-?\d+/ }
  end

  def debug
    @program.each_with_index do |p, i|
      puts "%c%d\t%s" % ['* '[i <=> @line], i, (p || []) * ' ']
    end
    puts '-' * 20
  end

  def line
    @program[@line]
  end

  def operand modify
      v = line.index { |l| l['V'] }
      line[v] = line[v].sub(/-?\d+/) { |o| modify[o.to_i] } rescue nil
  end

  def run
    until line.empty?
      debug if $DEBUG
      insn = line.shift or exit
      arg = insn[1..-1].to_i

      case insn
      when /A/ then (@program[@line + arg] ||= []).concat line
      when /C/ then @program[@line + arg] = []
      when /G/ then @line += arg
      when /V/ then line[0].sub! /-?\d+/, arg.to_s
      when /O/ then print arg
      when /P/ then print (arg % 256).chr
      when /I/ then operand -> _ { STDIN.getc.send %w[to_i ord][arg] }
      when /([SDML])/ then operand -> o { o.send OPS[$1], arg }
      end

      @line += 1 unless insn['G']
      break unless line
    end
  end
end

cat = "A0 A0
A0 C3 G1 G1 A0
A0 I1 V0 P0 A0
A0 A1 G-3 G-3 A0
G-3"
A0A0.new(cat).run