# module BindingOfCaller

### Constants

VERSION

### Public Instance Methods

callers() click to toggle source

    static VALUE
    callers(VALUE self)
    {
      VALUE ary = rb_ary_new();

      for (int i = 0; i < FIX2INT(frame_count(self)); i++)
        rb_ary_push(ary, binding_of_caller(self, INT2FIX(i)));

      return ary;
    }

frame_count() click to toggle source

    static VALUE frame_count(VALUE self)
    {
      rb_thread_t *th;
      GetThreadPtr(rb_thread_current(), th);

      rb_control_frame_t *cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
      rb_control_frame_t *limit_cfp = (void *)(th->stack + th->stack_size);

      int i = 1;
      while (cfp < limit_cfp) {
        cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);

        if (cfp >= limit_cfp)
          return INT2FIX(i);

        // skip invalid frames
        if (!valid_frame_p(cfp, limit_cfp))
          cfp = find_valid_frame(cfp, limit_cfp);

        if (!cfp)
          break;

        i++;
      }

      return INT2FIX(i);
    }

frame_description() click to toggle source

    static VALUE
    frame_description(VALUE self)
    {
      return rb_iv_get(self, "@frame_description");
    }

frame_type() click to toggle source

    static VALUE
    frame_type(VALUE self)
    {
      return rb_iv_get(self, "@frame_type");
    }

of_caller(p1) click to toggle source

    static VALUE binding_of_caller(VALUE self, VALUE rb_level)
    {
      rb_thread_t *th;
      GetThreadPtr(rb_thread_current(), th);

      rb_control_frame_t *cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
      rb_control_frame_t *limit_cfp = (void *)(th->stack + th->stack_size);
      int level = FIX2INT(rb_level);

      // attempt to locate the nth parent control frame
      for (int i = 0; i < level; i++) {
        cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);

        if (cfp >= limit_cfp)
          rb_raise(rb_eRuntimeError, "Invalid frame, gone beyond end of stack!");

        // skip invalid frames
        if (!valid_frame_p(cfp, limit_cfp))
          cfp = find_valid_frame(cfp, limit_cfp);
      }

      VALUE bindval = binding_alloc(rb_cBinding);
      rb_binding_t *bind;

      if (cfp == 0)
        rb_raise(rb_eRuntimeError, "Can't create Binding Object on top of Fiber.");

      GetBindingPtr(bindval, bind);

      bind->env = rb_vm_make_env_object(th, cfp);
      bind->filename = cfp->iseq->filename;
      bind->line_no = rb_vm_get_sourceline(cfp);

      rb_iv_set(bindval, "@frame_type", frametype_name(cfp->flag));
      rb_iv_set(bindval, "@frame_description", cfp->iseq->name);

      return bindval;
    }