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:
parent
cb3b463a50
commit
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>
|
Tue Dec 8 14:20:38 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
* marshal.c (w_objivar): skip internal instance variables in
|
* marshal.c (w_objivar): skip internal instance variables in
|
||||||
|
40
error.c
40
error.c
@ -35,6 +35,9 @@
|
|||||||
#define WEXITSTATUS(status) (status)
|
#define WEXITSTATUS(status) (status)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
VALUE rb_iseqw_local_variables(VALUE iseqval);
|
||||||
|
VALUE rb_iseqw_new(const rb_iseq_t *);
|
||||||
|
|
||||||
VALUE rb_eEAGAIN;
|
VALUE rb_eEAGAIN;
|
||||||
VALUE rb_eEWOULDBLOCK;
|
VALUE rb_eEWOULDBLOCK;
|
||||||
VALUE rb_eEINPROGRESS;
|
VALUE rb_eEINPROGRESS;
|
||||||
@ -660,7 +663,7 @@ static VALUE rb_eNOERROR;
|
|||||||
|
|
||||||
static ID id_new, id_cause, id_message, id_backtrace;
|
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_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;
|
extern ID ruby_static_id_status;
|
||||||
#define id_bt idBt
|
#define id_bt idBt
|
||||||
#define id_bt_locations idBt_locations
|
#define id_bt_locations idBt_locations
|
||||||
@ -1102,10 +1105,18 @@ static VALUE
|
|||||||
name_err_initialize(int argc, VALUE *argv, VALUE self)
|
name_err_initialize(int argc, VALUE *argv, VALUE self)
|
||||||
{
|
{
|
||||||
VALUE name;
|
VALUE name;
|
||||||
|
VALUE iseqw = Qnil;
|
||||||
|
|
||||||
name = (argc > 1) ? argv[--argc] : Qnil;
|
name = (argc > 1) ? argv[--argc] : Qnil;
|
||||||
rb_call_super(argc, argv);
|
rb_call_super(argc, argv);
|
||||||
rb_ivar_set(self, id_name, name);
|
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;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1122,6 +1133,30 @@ name_err_name(VALUE self)
|
|||||||
return rb_attr_get(self, id_name);
|
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:
|
* call-seq:
|
||||||
* NoMethodError.new(msg, name [, args]) -> no_method_error
|
* 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, "initialize", name_err_initialize, -1);
|
||||||
rb_define_method(rb_eNameError, "name", name_err_name, 0);
|
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, "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_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, "==", name_err_mesg_equal, 1);
|
||||||
rb_define_method(rb_cNameErrorMesg, "to_str", name_err_mesg_to_str, 0);
|
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_name = rb_intern_const("name");
|
||||||
id_args = rb_intern_const("args");
|
id_args = rb_intern_const("args");
|
||||||
id_receiver = rb_intern_const("receiver");
|
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_errno = rb_intern_const("errno");
|
id_errno = rb_intern_const("errno");
|
||||||
id_i_path = rb_intern_const("@path");
|
id_i_path = rb_intern_const("@path");
|
||||||
|
id_iseq = rb_make_internal_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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;
|
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
|
* 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);
|
VALUE rb_iseq_defined_string(enum defined_type type);
|
||||||
void rb_iseq_make_compile_option(struct rb_compile_option_struct *option, VALUE opt);
|
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
|
RUBY_SYMBOL_EXPORT_END
|
||||||
|
|
||||||
#endif /* RUBY_ISEQ_H */
|
#endif /* RUBY_ISEQ_H */
|
||||||
|
@ -688,6 +688,16 @@ end.join
|
|||||||
assert_equal(:foo, e.name)
|
assert_equal(:foo, e.name)
|
||||||
assert_equal([1, 2], e.args)
|
assert_equal([1, 2], e.args)
|
||||||
assert_same(obj, e.receiver)
|
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
|
end
|
||||||
|
|
||||||
def test_output_string_encoding
|
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);
|
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 */
|
/* Proc */
|
||||||
|
|
||||||
static inline VALUE
|
static inline VALUE
|
||||||
|
Loading…
x
Reference in New Issue
Block a user