diff --git a/ast.c b/ast.c index d3e217dafcca2a..4bd3784fbae9ae 100644 --- a/ast.c +++ b/ast.c @@ -97,7 +97,7 @@ rb_ast_parse_str(VALUE str, VALUE keep_script_lines, VALUE error_tolerant, VALUE StringValue(str); VALUE vparser = ast_parse_new(); - if (RTEST(keep_script_lines)) rb_parser_keep_script_lines(vparser); + if (RTEST(keep_script_lines)) rb_parser_set_script_lines(vparser, Qtrue); if (RTEST(error_tolerant)) rb_parser_error_tolerant(vparser); if (RTEST(keep_tokens)) rb_parser_keep_tokens(vparser); ast = rb_parser_compile_string_path(vparser, Qnil, str, 1); @@ -121,7 +121,7 @@ rb_ast_parse_file(VALUE path, VALUE keep_script_lines, VALUE error_tolerant, VAL f = rb_file_open_str(path, "r"); rb_funcall(f, rb_intern("set_encoding"), 2, rb_enc_from_encoding(enc), rb_str_new_cstr("-")); VALUE vparser = ast_parse_new(); - if (RTEST(keep_script_lines)) rb_parser_keep_script_lines(vparser); + if (RTEST(keep_script_lines)) rb_parser_set_script_lines(vparser, Qtrue); if (RTEST(error_tolerant)) rb_parser_error_tolerant(vparser); if (RTEST(keep_tokens)) rb_parser_keep_tokens(vparser); ast = rb_parser_compile_file_path(vparser, Qnil, f, 1); @@ -149,7 +149,7 @@ rb_ast_parse_array(VALUE array, VALUE keep_script_lines, VALUE error_tolerant, V array = rb_check_array_type(array); VALUE vparser = ast_parse_new(); - if (RTEST(keep_script_lines)) rb_parser_keep_script_lines(vparser); + if (RTEST(keep_script_lines)) rb_parser_set_script_lines(vparser, Qtrue); if (RTEST(error_tolerant)) rb_parser_error_tolerant(vparser); if (RTEST(keep_tokens)) rb_parser_keep_tokens(vparser); ast = rb_parser_compile_generic(vparser, lex_array, Qnil, array, 1); @@ -184,8 +184,8 @@ node_find(VALUE self, const int node_id) extern VALUE rb_e_script; -static VALUE -script_lines(VALUE path) +VALUE +rb_script_lines_for(VALUE path, bool add) { VALUE hash, lines; ID script_lines; @@ -193,10 +193,19 @@ script_lines(VALUE path) if (!rb_const_defined_at(rb_cObject, script_lines)) return Qnil; hash = rb_const_get_at(rb_cObject, script_lines); if (!RB_TYPE_P(hash, T_HASH)) return Qnil; - lines = rb_hash_lookup(hash, path); - if (!RB_TYPE_P(lines, T_ARRAY)) return Qnil; + if (add) { + rb_hash_aset(hash, path, lines = rb_ary_new()); + } + else if (!RB_TYPE_P((lines = rb_hash_lookup(hash, path)), T_ARRAY)) { + return Qnil; + } return lines; } +static VALUE +script_lines(VALUE path) +{ + return rb_script_lines_for(path, false); +} static VALUE node_id_for_backtrace_location(rb_execution_context_t *ec, VALUE module, VALUE location) diff --git a/ast.rb b/ast.rb index ec870d8c7a725a..fa9b69507c3f43 100644 --- a/ast.rb +++ b/ast.rb @@ -20,7 +20,7 @@ module RubyVM::AbstractSyntaxTree # call-seq: - # RubyVM::AbstractSyntaxTree.parse(string, keep_script_lines: false, error_tolerant: false, keep_tokens: false) -> RubyVM::AbstractSyntaxTree::Node + # RubyVM::AbstractSyntaxTree.parse(string, keep_script_lines: RubyVM.keep_script_lines, error_tolerant: false, keep_tokens: false) -> RubyVM::AbstractSyntaxTree::Node # # Parses the given _string_ into an abstract syntax tree, # returning the root node of that tree. @@ -55,12 +55,12 @@ module RubyVM::AbstractSyntaxTree # # Note that parsing continues even after the errored expression. # - def self.parse string, keep_script_lines: false, error_tolerant: false, keep_tokens: false + def self.parse string, keep_script_lines: RubyVM.keep_script_lines, error_tolerant: false, keep_tokens: false Primitive.ast_s_parse string, keep_script_lines, error_tolerant, keep_tokens end # call-seq: - # RubyVM::AbstractSyntaxTree.parse_file(pathname, keep_script_lines: false, error_tolerant: false, keep_tokens: false) -> RubyVM::AbstractSyntaxTree::Node + # RubyVM::AbstractSyntaxTree.parse_file(pathname, keep_script_lines: RubyVM.keep_script_lines, error_tolerant: false, keep_tokens: false) -> RubyVM::AbstractSyntaxTree::Node # # Reads the file from _pathname_, then parses it like ::parse, # returning the root node of the abstract syntax tree. @@ -72,13 +72,13 @@ def self.parse string, keep_script_lines: false, error_tolerant: false, keep_tok # # => # # # See ::parse for explanation of keyword argument meaning and usage. - def self.parse_file pathname, keep_script_lines: false, error_tolerant: false, keep_tokens: false + def self.parse_file pathname, keep_script_lines: RubyVM.keep_script_lines, error_tolerant: false, keep_tokens: false Primitive.ast_s_parse_file pathname, keep_script_lines, error_tolerant, keep_tokens end # call-seq: - # RubyVM::AbstractSyntaxTree.of(proc, keep_script_lines: false, error_tolerant: false, keep_tokens: false) -> RubyVM::AbstractSyntaxTree::Node - # RubyVM::AbstractSyntaxTree.of(method, keep_script_lines: false, error_tolerant: false, keep_tokens: false) -> RubyVM::AbstractSyntaxTree::Node + # RubyVM::AbstractSyntaxTree.of(proc, keep_script_lines: RubyVM.keep_script_lines, error_tolerant: false, keep_tokens: false) -> RubyVM::AbstractSyntaxTree::Node + # RubyVM::AbstractSyntaxTree.of(method, keep_script_lines: RubyVM.keep_script_lines, error_tolerant: false, keep_tokens: false) -> RubyVM::AbstractSyntaxTree::Node # # Returns AST nodes of the given _proc_ or _method_. # @@ -93,7 +93,7 @@ def self.parse_file pathname, keep_script_lines: false, error_tolerant: false, k # # => # # # See ::parse for explanation of keyword argument meaning and usage. - def self.of body, keep_script_lines: false, error_tolerant: false, keep_tokens: false + def self.of body, keep_script_lines: RubyVM.keep_script_lines, error_tolerant: false, keep_tokens: false Primitive.ast_s_of body, keep_script_lines, error_tolerant, keep_tokens end diff --git a/internal/parse.h b/internal/parse.h index c66c8df7b61684..ce99556ef95842 100644 --- a/internal/parse.h +++ b/internal/parse.h @@ -78,7 +78,7 @@ size_t rb_ruby_parser_memsize(const void *ptr); void rb_ruby_parser_set_options(rb_parser_t *p, int print, int loop, int chomp, int split); rb_parser_t *rb_ruby_parser_set_context(rb_parser_t *p, const struct rb_iseq_struct *base, int main); -void rb_ruby_parser_keep_script_lines(rb_parser_t *p); +void rb_ruby_parser_set_script_lines(rb_parser_t *p, VALUE lines_array); void rb_ruby_parser_error_tolerant(rb_parser_t *p); rb_ast_t* rb_ruby_parser_compile_file_path(rb_parser_t *p, VALUE fname, VALUE file, int start); void rb_ruby_parser_keep_tokens(rb_parser_t *p); diff --git a/internal/ruby_parser.h b/internal/ruby_parser.h index c6240cf9fa9e52..fc23177719ea93 100644 --- a/internal/ruby_parser.h +++ b/internal/ruby_parser.h @@ -19,7 +19,7 @@ VALUE rb_parser_encoding(VALUE); VALUE rb_parser_set_yydebug(VALUE, VALUE); void rb_parser_set_options(VALUE, int, int, int, int); void *rb_parser_load_file(VALUE parser, VALUE name); -void rb_parser_keep_script_lines(VALUE vparser); +void rb_parser_set_script_lines(VALUE vparser, VALUE lines_array); void rb_parser_error_tolerant(VALUE vparser); void rb_parser_keep_tokens(VALUE vparser); diff --git a/iseq.c b/iseq.c index 51d7ef78da60d1..80bd280a14b25e 100644 --- a/iseq.c +++ b/iseq.c @@ -1122,6 +1122,7 @@ rb_iseq_compile_with_option(VALUE src, VALUE file, VALUE realpath, VALUE line, V const rb_iseq_t *outer_scope = rb_iseq_new(NULL, name, name, Qnil, 0, ISEQ_TYPE_TOP); VALUE outer_scope_v = (VALUE)outer_scope; rb_parser_set_context(parser, outer_scope, FALSE); + rb_parser_set_script_lines(parser, RBOOL(ruby_vm_keep_script_lines)); RB_GC_GUARD(outer_scope_v); ast = (*parse)(parser, file, src, ln); } diff --git a/parse.y b/parse.y index e9252154e92785..847a8e0933775a 100644 --- a/parse.y +++ b/parse.y @@ -151,26 +151,6 @@ literal_hash(VALUE a) return rb_iseq_cdhash_hash(a); } -static ID -script_lines(void) -{ - ID script_lines; - CONST_ID(script_lines, "SCRIPT_LINES__"); - return script_lines; -} - -static int -script_lines_defined(void) -{ - return rb_const_defined_at(rb_cObject, script_lines()); -} - -static VALUE -script_lines_get(void) -{ - return rb_const_get_at(rb_cObject, script_lines()); -} - static VALUE syntax_error_new(void) { @@ -550,7 +530,6 @@ struct parser_params { unsigned int do_loop: 1; unsigned int do_chomp: 1; unsigned int do_split: 1; - unsigned int keep_script_lines: 1; unsigned int error_tolerant: 1; unsigned int keep_tokens: 1; @@ -6844,20 +6823,6 @@ static void parser_prepare(struct parser_params *p); #ifndef RIPPER static NODE *parser_append_options(struct parser_params *p, NODE *node); -static VALUE -debug_lines(struct parser_params *p, VALUE fname) -{ - if (script_lines_defined()) { - VALUE hash = script_lines_get(); - if (RB_TYPE_P(hash, T_HASH)) { - VALUE lines = rb_ary_new(); - rb_hash_aset(hash, fname, lines); - return lines; - } - } - return 0; -} - static int e_option_supplied(struct parser_params *p) { @@ -6873,7 +6838,6 @@ yycompile0(VALUE arg) int cov = FALSE; if (!compile_for_eval && !NIL_P(p->ruby_sourcefile_string)) { - p->debug_lines = debug_lines(p, p->ruby_sourcefile_string); if (p->debug_lines && p->ruby_sourceline > 0) { VALUE str = rb_default_rs; n = p->ruby_sourceline; @@ -6887,11 +6851,7 @@ yycompile0(VALUE arg) } } - if (p->keep_script_lines || ruby_vm_keep_script_lines) { - if (!p->debug_lines) { - p->debug_lines = rb_ary_new(); - } - + if (p->debug_lines) { RB_OBJ_WRITE(p->ast, &p->ast->body.script_lines, p->debug_lines); } @@ -13983,9 +13943,19 @@ rb_ruby_parser_set_context(rb_parser_t *p, const struct rb_iseq_struct *base, in } void -rb_ruby_parser_keep_script_lines(rb_parser_t *p) +rb_ruby_parser_set_script_lines(rb_parser_t *p, VALUE lines) { - p->keep_script_lines = 1; + if (!RTEST(lines)) { + lines = Qfalse; + } + else if (lines == Qtrue) { + lines = rb_ary_new(); + } + else { + Check_Type(lines, T_ARRAY); + rb_ary_modify(lines); + } + p->debug_lines = lines; } void @@ -14073,12 +14043,12 @@ rb_parser_error_tolerant(VALUE vparser) } void -rb_parser_keep_script_lines(VALUE vparser) +rb_parser_set_script_lines(VALUE vparser, VALUE lines) { struct parser_params *p; TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, p); - rb_ruby_parser_keep_script_lines(p); + rb_ruby_parser_set_script_lines(p, lines); } void diff --git a/ruby.c b/ruby.c index 243fbac5962b6c..2b4397c0011617 100644 --- a/ruby.c +++ b/ruby.c @@ -2397,6 +2397,8 @@ struct load_file_arg { VALUE f; }; +VALUE rb_script_lines_for(VALUE path, bool add); + static VALUE load_file_internal(VALUE argp_v) { @@ -2499,6 +2501,12 @@ load_file_internal(VALUE argp_v) } rb_parser_set_options(parser, opt->do_print, opt->do_loop, opt->do_line, opt->do_split); + + VALUE lines = rb_script_lines_for(orig_fname, true); + if (!NIL_P(lines)) { + rb_parser_set_script_lines(parser, lines); + } + if (NIL_P(f)) { f = rb_str_new(0, 0); rb_enc_associate(f, enc); diff --git a/ruby_parser.c b/ruby_parser.c index 9ab78be2a9689a..c059ac2d11af79 100644 --- a/ruby_parser.c +++ b/ruby_parser.c @@ -853,12 +853,12 @@ rb_parser_set_context(VALUE vparser, const struct rb_iseq_struct *base, int main } void -rb_parser_keep_script_lines(VALUE vparser) +rb_parser_set_script_lines(VALUE vparser, VALUE lines) { struct ruby_parser *parser; TypedData_Get_Struct(vparser, struct ruby_parser, &ruby_parser_data_type, parser); - rb_ruby_parser_keep_script_lines(parser->parser_params); + rb_ruby_parser_set_script_lines(parser->parser_params, lines); } void diff --git a/vm_eval.c b/vm_eval.c index fb24e2a9e9fbca..36c665509352d8 100644 --- a/vm_eval.c +++ b/vm_eval.c @@ -1681,6 +1681,7 @@ eval_make_iseq(VALUE src, VALUE fname, int line, const rb_binding_t *bind, } rb_parser_set_context(parser, parent, FALSE); + rb_parser_set_script_lines(parser, RBOOL(ruby_vm_keep_script_lines)); ast = rb_parser_compile_string_path(parser, fname, src, line); if (ast->body.root) { ast->body.coverage_enabled = coverage_enabled;