           "#{cmpMap[cmpCode]} 0"
     b.next.push @offset + idx
     v = b.pop()
-    b.compile_epilogue()
-    b.add_line "if (#{v} #{cond}) { label = #{@offset + idx}; continue }"
+    b.add_stmt -> b.compile_epilogue()
+    b.add_stmt "if (#{v} #{cond}) { label = #{@offset + idx}; continue }"
   BinaryBranchOpcode: (b, idx) ->
     cmpCode = @name[7..]
     b.next.push @offset + idx
     v2 = b.pop()
     v1 = b.pop()
-    b.compile_epilogue()
-    b.add_line "if (#{v1} #{cmpMap[cmpCode]} #{v2}) { label = #{@offset + idx}; continue }"
+    b.add_stmt -> b.compile_epilogue()
+    b.add_stmt "if (#{v1} #{cmpMap[cmpCode]} #{v2}) { label = #{@offset + idx}; continue }"
   InvokeOpcode: (b, idx) ->
     method = new Method # kludge
     method.access_flags = { static: @name == 'invokestatic' }

    b.stack.length -= method.param_bytes

    virtual = @name in ['invokevirtual', 'invokeinterface']
    b.add_line "rs.push(#{params.join ','})"
    b.add_line "rs.method_lookup(#{JSON.stringify @method_spec}).run(rs, #{virtual})"

    unless method.return_type.toString() is 'V'
      temp = b.new_temp()

      if method.return_type.toString() in ['D', 'J']
        b.add_line "#{temp} = rs.pop2()"
        b.push2 temp
      else
        b.add_line "#{temp} = rs.pop()"
        b.push temp

compile_obj_handlers = {

    # branching instructions will print the epilogue before they branch; return
    # instructions obviate the need for one
    unless op.offset? or (op.name.indexOf 'return') != -1
      @add_stmt => @compile_epilogue()

    for idx in @next
      next_block = @block_chain.get_block_from_instr idx
      # java bytecode verification ensures that the stack height and stack /
      # local table types match up across blocks
      next_block.compile @stack, @locals

    linearized_stmts = ""
    linearize = (arr) ->
      for s in arr
        if _.isFunction s
          linearize s()
        else
          linearized_stmts += s + ";\n"
    linearize @stmts

    @compiled_str =
      """
      case #{@start_idx}:
      // #{op.name for op in @opcodes}
      #{linearized_stmts}
      """

class Expr

  constructor: (str, subexps...) ->
    @fragments = str.split /(\$\d+)/
    for frag, i in @fragments
      if /\$\d+/.test frag
        @fragments[i] = subexps[parseInt frag[1..], 10]

  eval: (b) ->
    temp = b.new_temp()
    b.add_stmt "$0 = #{@}", temp
    new Primitive b

  toString: -> @fragments.join ''
