зеркало из https://github.com/github/ruby.git
error.c: name_err_local_variables
* error.c (name_err_local_variables): new method NameError#local_variables for internal use only. [Feature #11777] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52942 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
cb3b463a50
Коммит
506b25aabf
|
@ -1,3 +1,9 @@
|
|||
Tue Dec 8 14:27:07 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||
|
||||
* error.c (name_err_local_variables): new method
|
||||
NameError#local_variables for internal use only.
|
||||
[Feature #11777]
|
||||
|
||||
Tue Dec 8 14:20:38 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||
|
||||
* marshal.c (w_objivar): skip internal instance variables in
|
||||
|
|
40
error.c
40
error.c
|
@ -35,6 +35,9 @@
|
|||
#define WEXITSTATUS(status) (status)
|
||||
#endif
|
||||
|
||||
VALUE rb_iseqw_local_variables(VALUE iseqval);
|
||||
VALUE rb_iseqw_new(const rb_iseq_t *);
|
||||
|
||||
VALUE rb_eEAGAIN;
|
||||
VALUE rb_eEWOULDBLOCK;
|
||||
VALUE rb_eEINPROGRESS;
|
||||
|
@ -660,7 +663,7 @@ static VALUE rb_eNOERROR;
|
|||
|
||||
static ID id_new, id_cause, id_message, id_backtrace;
|
||||
static ID id_name, id_args, id_Errno, id_errno, id_i_path;
|
||||
static ID id_receiver;
|
||||
static ID id_receiver, id_iseq, id_local_variables;
|
||||
extern ID ruby_static_id_status;
|
||||
#define id_bt idBt
|
||||
#define id_bt_locations idBt_locations
|
||||
|
@ -1102,10 +1105,18 @@ static VALUE
|
|||
name_err_initialize(int argc, VALUE *argv, VALUE self)
|
||||
{
|
||||
VALUE name;
|
||||
VALUE iseqw = Qnil;
|
||||
|
||||
name = (argc > 1) ? argv[--argc] : Qnil;
|
||||
rb_call_super(argc, argv);
|
||||
rb_ivar_set(self, id_name, name);
|
||||
{
|
||||
rb_thread_t *th = GET_THREAD();
|
||||
rb_control_frame_t *cfp =
|
||||
rb_vm_get_ruby_level_next_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp));
|
||||
if (cfp) iseqw = rb_iseqw_new(cfp->iseq);
|
||||
}
|
||||
rb_ivar_set(self, id_iseq, iseqw);
|
||||
return self;
|
||||
}
|
||||
|
||||
|
@ -1122,6 +1133,30 @@ name_err_name(VALUE self)
|
|||
return rb_attr_get(self, id_name);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* name_error.local_variables -> array
|
||||
*
|
||||
* Return a list of the local variable names defined where this
|
||||
* NameError exception was raised.
|
||||
*
|
||||
* Internal use only.
|
||||
*/
|
||||
|
||||
static VALUE
|
||||
name_err_local_variables(VALUE self)
|
||||
{
|
||||
VALUE vars = rb_attr_get(self, id_local_variables);
|
||||
|
||||
if (NIL_P(vars)) {
|
||||
VALUE iseqw = rb_attr_get(self, id_iseq);
|
||||
if (!NIL_P(iseqw)) vars = rb_iseqw_local_variables(iseqw);
|
||||
if (NIL_P(vars)) vars = rb_ary_new();
|
||||
rb_ivar_set(self, id_local_variables, vars);
|
||||
}
|
||||
return vars;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* NoMethodError.new(msg, name [, args]) -> no_method_error
|
||||
|
@ -1942,6 +1977,7 @@ Init_Exception(void)
|
|||
rb_define_method(rb_eNameError, "initialize", name_err_initialize, -1);
|
||||
rb_define_method(rb_eNameError, "name", name_err_name, 0);
|
||||
rb_define_method(rb_eNameError, "receiver", name_err_receiver, 0);
|
||||
rb_define_method(rb_eNameError, "local_variables", name_err_local_variables, 0);
|
||||
rb_cNameErrorMesg = rb_define_class_under(rb_eNameError, "message", rb_cData);
|
||||
rb_define_method(rb_cNameErrorMesg, "==", name_err_mesg_equal, 1);
|
||||
rb_define_method(rb_cNameErrorMesg, "to_str", name_err_mesg_to_str, 0);
|
||||
|
@ -1974,9 +2010,11 @@ Init_Exception(void)
|
|||
id_name = rb_intern_const("name");
|
||||
id_args = rb_intern_const("args");
|
||||
id_receiver = rb_intern_const("receiver");
|
||||
id_local_variables = rb_intern_const("local_variables");
|
||||
id_Errno = rb_intern_const("Errno");
|
||||
id_errno = rb_intern_const("errno");
|
||||
id_i_path = rb_intern_const("@path");
|
||||
id_iseq = rb_make_internal_id();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
6
iseq.c
6
iseq.c
|
@ -2319,6 +2319,12 @@ rb_iseqw_line_trace_specify(VALUE iseqval, VALUE pos, VALUE set)
|
|||
return data.prev == 1 ? Qtrue : Qfalse;
|
||||
}
|
||||
|
||||
VALUE
|
||||
rb_iseqw_local_variables(VALUE iseqval)
|
||||
{
|
||||
return rb_iseq_local_variables(iseqw_check(iseqval));
|
||||
}
|
||||
|
||||
/*
|
||||
* Document-class: RubyVM::InstructionSequence
|
||||
*
|
||||
|
|
3
iseq.h
3
iseq.h
|
@ -214,6 +214,9 @@ enum defined_type {
|
|||
VALUE rb_iseq_defined_string(enum defined_type type);
|
||||
void rb_iseq_make_compile_option(struct rb_compile_option_struct *option, VALUE opt);
|
||||
|
||||
/* vm.c */
|
||||
VALUE rb_iseq_local_variables(const rb_iseq_t *iseq);
|
||||
|
||||
RUBY_SYMBOL_EXPORT_END
|
||||
|
||||
#endif /* RUBY_ISEQ_H */
|
||||
|
|
|
@ -688,6 +688,16 @@ end.join
|
|||
assert_equal(:foo, e.name)
|
||||
assert_equal([1, 2], e.args)
|
||||
assert_same(obj, e.receiver)
|
||||
def obj.test(a, b=nil, *c, &d)
|
||||
e = a
|
||||
1.times {|f| g = foo}
|
||||
end
|
||||
e = assert_raise(NameError) {
|
||||
obj.test(3)
|
||||
}
|
||||
assert_equal(:foo, e.name)
|
||||
assert_same(obj, e.receiver)
|
||||
assert_equal(%i[a b c d e f g], e.local_variables.sort)
|
||||
end
|
||||
|
||||
def test_output_string_encoding
|
||||
|
|
11
vm.c
11
vm.c
|
@ -755,6 +755,17 @@ rb_vm_env_local_variables(const rb_env_t *env)
|
|||
return local_var_list_finish(&vars);
|
||||
}
|
||||
|
||||
VALUE
|
||||
rb_iseq_local_variables(const rb_iseq_t *iseq)
|
||||
{
|
||||
struct local_var_list vars;
|
||||
local_var_list_init(&vars);
|
||||
while (collect_local_variables_in_iseq(iseq, &vars)) {
|
||||
iseq = iseq->body->parent_iseq;
|
||||
}
|
||||
return local_var_list_finish(&vars);
|
||||
}
|
||||
|
||||
/* Proc */
|
||||
|
||||
static inline VALUE
|
||||
|
|
Загрузка…
Ссылка в новой задаче