diff options
author | Koichi Sasada <[email protected]> | 2021-09-30 16:58:46 +0900 |
---|---|---|
committer | Koichi Sasada <[email protected]> | 2021-10-21 16:17:39 +0900 |
commit | c7550537f11dcf6450a9d3df3af3fa1f4fe05b15 (patch) | |
tree | 9b73c5b1be4e42f0aaf92e64b9c6041777666251 /iseq.c | |
parent | 3b16d07e457264d7c171f8d1fcfaddb0dad90f57 (diff) |
`RubyVM.keep_script_lines`
`RubyVM.keep_script_lines` enables to keep script lines
for each ISeq and AST. This feature is for debugger/REPL
support.
```ruby
RubyVM.keep_script_lines = true
RubyVM::keep_script_lines = true
eval("def foo = nil\ndef bar = nil")
pp RubyVM::InstructionSequence.of(method(:foo)).script_lines
```
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/4913
Diffstat (limited to 'iseq.c')
-rw-r--r-- | iseq.c | 44 |
1 files changed, 40 insertions, 4 deletions
@@ -595,7 +595,8 @@ new_arena(void) static VALUE prepare_iseq_build(rb_iseq_t *iseq, VALUE name, VALUE path, VALUE realpath, VALUE first_lineno, const rb_code_location_t *code_location, const int node_id, - const rb_iseq_t *parent, int isolated_depth, enum iseq_type type, const rb_compile_option_t *option) + const rb_iseq_t *parent, int isolated_depth, enum iseq_type type, + VALUE script_lines, const rb_compile_option_t *option) { VALUE coverage = Qfalse; VALUE err_info = Qnil; @@ -616,6 +617,8 @@ prepare_iseq_build(rb_iseq_t *iseq, ISEQ_ORIGINAL_ISEQ_CLEAR(iseq); body->variable.flip_count = 0; + RB_OBJ_WRITE(iseq, &body->variable.script_lines, script_lines); + ISEQ_COMPILE_DATA_ALLOC(iseq); RB_OBJ_WRITE(iseq, &ISEQ_COMPILE_DATA(iseq)->err_info, err_info); RB_OBJ_WRITE(iseq, &ISEQ_COMPILE_DATA(iseq)->catch_table_ary, Qnil); @@ -894,7 +897,17 @@ rb_iseq_new_with_opt(const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE rea } if (ast && ast->compile_option) rb_iseq_make_compile_option(&new_opt, ast->compile_option); - prepare_iseq_build(iseq, name, path, realpath, first_lineno, node ? &node->nd_loc : NULL, node ? nd_node_id(node) : -1, parent, isolated_depth, type, &new_opt); + VALUE script_lines = Qnil; + + if (ast && !FIXNUM_P(ast->script_lines) && ast->script_lines) { + script_lines = ast->script_lines; + } + else if (parent) { + script_lines = parent->body->variable.script_lines; + } + + prepare_iseq_build(iseq, name, path, realpath, first_lineno, node ? &node->nd_loc : NULL, node ? nd_node_id(node) : -1, + parent, isolated_depth, type, script_lines, &new_opt); rb_iseq_compile_node(iseq, node); finish_iseq_build(iseq); @@ -913,7 +926,7 @@ rb_iseq_new_with_callback( rb_iseq_t *iseq = iseq_alloc(); if (!option) option = &COMPILE_OPTION_DEFAULT; - prepare_iseq_build(iseq, name, path, realpath, first_lineno, NULL, -1, parent, 0, type, option); + prepare_iseq_build(iseq, name, path, realpath, first_lineno, NULL, -1, parent, 0, type, Qnil, option); rb_iseq_compile_callback(iseq, ifunc); finish_iseq_build(iseq); @@ -1026,7 +1039,7 @@ iseq_load(VALUE data, const rb_iseq_t *parent, VALUE opt) make_compile_option(&option, opt); option.peephole_optimization = FALSE; /* because peephole optimization can modify original iseq */ prepare_iseq_build(iseq, name, path, realpath, first_lineno, &tmp_loc, NUM2INT(node_id), - parent, 0, (enum iseq_type)iseq_type, &option); + parent, 0, (enum iseq_type)iseq_type, Qnil, &option); rb_iseq_build_from_ary(iseq, misc, locals, params, exception, body); @@ -3680,6 +3693,26 @@ succ_index_lookup(const struct succ_index_table *sd, int x) } #endif + +/* + * call-seq: + * iseq.script_lines -> array or nil + * + * It returns recorded script lines if it is availalble. + * The script lines are not limited to the iseq range, but + * are entire lines of the source file. + * + * Note that this is an API for ruby internal use, debugging, + * and research. Do not use this for any other purpose. + * The compatibility is not guaranteed. + */ +static VALUE +iseqw_script_lines(VALUE self) +{ + const rb_iseq_t *iseq = iseqw_check(self); + return iseq->body->variable.script_lines; +} + /* * Document-class: RubyVM::InstructionSequence * @@ -3747,6 +3780,9 @@ Init_ISeq(void) rb_define_singleton_method(rb_cISeq, "disassemble", iseqw_s_disasm, 1); rb_define_singleton_method(rb_cISeq, "of", iseqw_s_of, 1); + // script lines + rb_define_method(rb_cISeq, "script_lines", iseqw_script_lines, 0); + rb_undef_method(CLASS_OF(rb_cISeq), "translate"); rb_undef_method(CLASS_OF(rb_cISeq), "load_iseq"); } |