/* call-seq:
 *   iseq.each(&block) => nil
 *
 * Yields each instruction in the sequence.
 */
static VALUE iseq_each(VALUE self)
{
  rb_iseq_t *iseqdat = iseq_check(self);
  VALUE * seq;

  for(seq = iseqdat->iseq; seq < iseqdat->iseq + iseqdat->iseq_size; )
  {
    VALUE insn = *seq++;
    int op_type_idx;
    int len = insn_len(insn);
    VALUE args = rb_ary_new();

    for(op_type_idx = 0; op_type_idx < len-1; ++op_type_idx, ++seq)
    {
      switch(insn_op_type(insn, op_type_idx))
      {
        case TS_VALUE:
          rb_ary_push(args, *seq);
          break;

        case TS_LINDEX:
        case TS_DINDEX:
        case TS_NUM:
          rb_ary_push(args, INT2FIX(*seq));
          break;

        case TS_ISEQ:
        {
          rb_iseq_t * iseq = (rb_iseq_t *)*seq;
          if(iseq)
          {
            rb_ary_push(args, iseq->self);
          }
          else
          {
            rb_ary_push(args, Qnil);
          }
          break;
        }

        case TS_GENTRY:
        {
          struct global_entry *entry = (struct global_entry *)*seq;
          rb_ary_push(args, ID2SYM(rb_intern(rb_id2name(entry->id))));
          break;
        }

        case TS_OFFSET:
          rb_ary_push(args, Qnil);
          /* TODO */
          break;

        case TS_VARIABLE:
          rb_ary_push(args, Qnil);
          /* TODO */
          break;

        case TS_CDHASH:
          rb_ary_push(args, Qnil);
          /* TODO */
          break;

        case TS_IC:
        {
          NODE * ic = (NODE *)*seq;
          rb_ary_push(args, wrap_node_as(ic, rb_cInlineCache));
          break;
        }

        case TS_ID:
          rb_ary_push(args, ID2SYM(*seq));
          break;
      }
    }

    rb_yield(rb_class_new_instance(
            RARRAY(args)->len,
            RARRAY(args)->ptr,
            instruction_class[insn]));
  }

  return Qnil;
}