   iconst_3: { execute: (rs) -> rs.push new Primitive 3 }
   iconst_4: { execute: (rs) -> rs.push new Primitive 4 }
   iconst_5: { execute: (rs) -> rs.push new Primitive 5 }
-  lconst_0: { execute: (rs) -> rs.push new Primitive(gLong.ZERO), null }
+  lconst_0: { execute: (rs) -> rs.push new Primitive("gLong.ZERO"), null }
   istore_0: { execute: (rs) -> rs.put_cl 0, rs.pop() }
   istore_1: { execute: (rs) -> rs.put_cl 1, rs.pop() }
   istore_2: { execute: (rs) -> rs.put_cl 2, rs.pop() }

          else m.name
        rs = new RuntimeState
        m.code.each_opcode (idx, oc) ->
          opcodes[oc.name]?.execute rs, oc
        "#{name}: function {\n#{rs.compile()}\n},"
  "var #{class_name} = {\n#{methods.join "\n"}\n};\n"

# TODO: move to a separate file

class RuntimeState
  constructor: ->
    @_cs = []
    @locals = []
    @blocks = []
    @block_start_idxs = []
    @new_block 0

  push: (sf) -> @_cs.push sf
  pop: -> @_cs.pop()
  cl: (idx) -> @locals[idx]
  put_cl: (idx, val) -> @locals[idx] = val
  put_cl2: (idx,val) -> @put_cl(idx,val); @put_cl(idx+1,null)

  add_cond: (condFn, expr, dest1, dest2) ->
    @current_block().cond = { condFn: condFn, expr: expr, dest1: dest1, dest2: dest2 }
    @new_block dest1

  new_block: (start_idx) ->
    @blocks.push new BasicBlock
    @block_start_idxs.push(start_idx)

  current_block: -> _.last @blocks

  instr_idx2block: (idx) ->
    for blockStartIdx, i in @block_start_idxs
      return i - 1 if idx < blockStartIdx
    return @blocks.length - 1

  compile: ->
    for block, idx in @blocks
      if block.cond?
        d1 = @instr_idx2block block.cond.dest1
        d2 = @instr_idx2block block.cond.dest2
        block.out.push d1, d2
        @blocks[d1].in.push idx
        @blocks[d2].in.push idx

    @compile_block(@blocks[0])

  compile_block: (block) ->
    if block.in.length <= 1 && block.out.length == 2
      "if (#{block.cond.condFn block.cond.expr}) {\n#{
        @compile_block @blocks[block.out[1]]
      }\n} else {\n#{
        @compile_block @blocks[block.out[0]]
      }\n}"
    else
      "#{block}"

class BasicBlock
  constructor: ->
    @in = []
    @out = []
    @lines = []
    @cond = null

  add_line: (line) -> @lines.push line

  toString: -> @lines.join "\n"

class Expr

