Module: BindingOfCaller

Included in:
Binding
Defined in:
lib/binding_of_caller/mri2.rb,
lib/binding_of_caller/version.rb,
lib/binding_of_caller/rubinius.rb,
lib/binding_of_caller/jruby_interpreted.rb,
ext/binding_of_caller/binding_of_caller.c

Defined Under Namespace

Modules: BindingExtensions Classes: JRubyBindingHolder

Constant Summary collapse

VERSION =
"0.8.0"

Instance Method Summary collapse

Instance Method Details

#callersObject



202
203
204
205
206
207
208
209
210
211
# File 'ext/binding_of_caller/binding_of_caller.c', line 202

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_countObject



174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
# File 'ext/binding_of_caller/binding_of_caller.c', line 174

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_descriptionObject



168
169
170
171
172
# File 'ext/binding_of_caller/binding_of_caller.c', line 168

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

#frame_typeObject



162
163
164
165
166
# File 'ext/binding_of_caller/binding_of_caller.c', line 162

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

#of_caller(rb_level) ⇒ Object



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'ext/binding_of_caller/binding_of_caller.c', line 123

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;
}