     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})"
+    b.add_stmt "rs.push(#{params.join ','})"
+    b.add_stmt "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.add_stmt new Move "#{temp} = rs.pop2()"
         b.push2 temp
       else
-        b.add_line "#{temp} = rs.pop()"
+        b.add_stmt "#{temp} = rs.pop()"
         b.push temp
 
 compile_obj_handlers = {

  dconst_0: { compile: (b) -> b.push2 new Primitive "0"; }
  dconst_1: { compile: (b) -> b.push2 new Primitive "1"; }
  # the *astore commands don't work yet...
  iastore: {compile: (b) -> b.add_line "b.check_null($2).array[$1]=$0",b.pop(),b.pop(),b.pop()}
  lastore: {compile: (b) -> b.add_line "b.check_null($2).array[$1]=$0",b.pop(),b.pop(),b.pop2()}
  fastore: {compile: (b) -> b.add_line "b.check_null($2).array[$1]=$0",b.pop(),b.pop(),b.pop()}
  dastore: {compile: (b) -> b.add_line "b.check_null($2).array[$1]=$0",b.pop(),b.pop(),b.pop2()}
  aastore: {compile: (b) -> b.add_line "b.check_null($2).array[$1]=$0",b.pop(),b.pop(),b.pop()}
  bastore: {compile: (b) -> b.add_line "b.check_null($2).array[$1]=$0",b.pop(),b.pop(),b.pop()}
  castore: {compile: (b) -> b.add_line "b.check_null($2).array[$1]=$0",b.pop(),b.pop(),b.pop()}
  sastore: {compile: (b) -> b.add_line "b.check_null($2).array[$1]=$0",b.pop(),b.pop(),b.pop()}
  pop: {compile: (b) -> b.pop()}
  pop2: {compile: (b) -> b.pop2()}
  # TODO: avoid duplicating non-primitive expressions so as to save on computation

  i2c: { compile: (b) -> b.push "#{b.pop()}&0xFFFF" }
  i2s: { compile: (b) -> b.push "util.truncate(#{b.pop()}, 16)" }

  ireturn: { compile: (b) -> b.add_stmt "return #{b.pop()}" }
  lreturn: { compile: (b) -> b.add_stmt "return #{b.pop2()}" }
  freturn: { compile: (b) -> b.add_stmt "return #{b.pop()}" }
  dreturn: { compile: (b) -> b.add_stmt "return #{b.pop2()}" }
  areturn: { compile: (b) -> b.add_stmt "return #{b.pop()}" }
  'return': { compile: (b) -> b.add_stmt "return" }

  arraylength: { compile: (b) ->
    t = b.new_temp()
    b.add_stmt "#{t} = rs.check_null(#{b.pop()}).array.length"
    b.push t
  }

  getstatic: { compile: (b) ->
    temp = b.new_temp()
    b.add_stmt "#{temp} = rs.static_get(#{JSON.stringify @field_spec})"
    if @field_spec.type in ['J','D'] then b.push2 temp else b.push temp }

  'new': { compile: (b) ->
    temp = b.new_temp()
    b.add_stmt "#{temp} = rs.init_object(#{JSON.stringify @class})"
    b.push temp }

  goto: { compile: (b, idx) ->
    b.next = [@offset + idx]
    b.add_stmt -> b.compile_epilogue()
    b.add_stmt "label = #{@offset + idx}; continue"
  }

  goto_w: { compile: (b, idx) ->
    b.next = [@offset + idx]
    b.add_stmt -> b.compile_epilogue()
    b.add_stmt "label = #{@offset + idx}; continue"
  }
}

