diff options
-rw-r--r-- | iseq.c | 11 | ||||
-rw-r--r-- | load.c | 2 | ||||
-rw-r--r-- | prism_compile.c | 37 | ||||
-rw-r--r-- | prism_compile.h | 16 | ||||
-rw-r--r-- | ruby.c | 4 | ||||
-rw-r--r-- | template/prelude.c.tmpl | 2 | ||||
-rw-r--r-- | vm_eval.c | 2 |
7 files changed, 51 insertions, 23 deletions
@@ -1050,7 +1050,7 @@ pm_iseq_new_with_opt(pm_scope_node_t *node, VALUE name, VALUE path, VALUE realpa }; prepare_iseq_build(iseq, name, path, realpath, first_lineno, &code_location, -1, - parent, isolated_depth, type, Qnil, option); + parent, isolated_depth, type, node->script_lines == NULL ? Qnil : *node->script_lines, option); pm_iseq_compile_node(iseq, node); finish_iseq_build(iseq); @@ -1296,15 +1296,17 @@ pm_iseq_compile_with_option(VALUE src, VALUE file, VALUE realpath, VALUE line, V break; } + VALUE script_lines; VALUE error; + if (RB_TYPE_P(src, T_FILE)) { VALUE filepath = rb_io_path(src); - error = pm_load_parse_file(&result, filepath); + error = pm_load_parse_file(&result, filepath, ruby_vm_keep_script_lines ? &script_lines : NULL); RB_GC_GUARD(filepath); } else { src = StringValue(src); - error = pm_parse_string(&result, src, file); + error = pm_parse_string(&result, src, file, ruby_vm_keep_script_lines ? &script_lines : NULL); } if (error == Qnil) { @@ -1718,7 +1720,8 @@ iseqw_s_compile_file_prism(int argc, VALUE *argv, VALUE self) result.options.line = 1; result.node.coverage_enabled = 1; - VALUE error = pm_load_parse_file(&result, file); + VALUE script_lines; + VALUE error = pm_load_parse_file(&result, file, ruby_vm_keep_script_lines ? &script_lines : NULL); if (error == Qnil) { make_compile_option(&option, opt); @@ -748,7 +748,7 @@ load_iseq_eval(rb_execution_context_t *ec, VALUE fname) result.options.line = 1; result.node.coverage_enabled = 1; - VALUE error = pm_load_parse_file(&result, fname); + VALUE error = pm_load_parse_file(&result, fname, NULL); if (error == Qnil) { iseq = pm_iseq_new_top(&result.node, rb_fstring_lit("<top (required)>"), fname, realpath_internal_cached(realpath_map, fname), NULL); diff --git a/prism_compile.c b/prism_compile.c index dd2e30865a..5bd02ed04f 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -3107,6 +3107,7 @@ pm_scope_node_init(const pm_node_t *node, pm_scope_node_t *scope, pm_scope_node_ scope->filepath_encoding = previous->filepath_encoding; scope->constants = previous->constants; scope->coverage_enabled = previous->coverage_enabled; + scope->script_lines = previous->script_lines; } switch (PM_NODE_TYPE(node)) { @@ -10379,7 +10380,7 @@ pm_parse_process_error(const pm_parse_result_t *result) * result object is zeroed out. */ static VALUE -pm_parse_process(pm_parse_result_t *result, pm_node_t *node) +pm_parse_process(pm_parse_result_t *result, pm_node_t *node, VALUE *script_lines) { pm_parser_t *parser = &result->parser; @@ -10397,6 +10398,20 @@ pm_parse_process(pm_parse_result_t *result, pm_node_t *node) scope_node->coverage_enabled = coverage_enabled; + // If RubyVM.keep_script_lines is set to true, then we need to create that + // array of script lines here. + if (script_lines != NULL) { + *script_lines = rb_ary_new_capa(parser->newline_list.size); + + for (size_t index = 0; index < parser->newline_list.size; index++) { + size_t offset = parser->newline_list.offsets[index]; + size_t length = index == parser->newline_list.size - 1 ? (parser->end - (parser->start + offset)) : (parser->newline_list.offsets[index + 1] - offset); + rb_ary_push(*script_lines, rb_enc_str_new((const char *) parser->start + offset, length, scope_node->encoding)); + } + + scope_node->script_lines = script_lines; + } + // Emit all of the various warnings from the parse. const pm_diagnostic_t *warning; const char *warning_filepath = (const char *) pm_string_source(&parser->filepath); @@ -10663,7 +10678,7 @@ pm_load_file(pm_parse_result_t *result, VALUE filepath, bool load_error) * is zeroed out. */ VALUE -pm_parse_file(pm_parse_result_t *result, VALUE filepath) +pm_parse_file(pm_parse_result_t *result, VALUE filepath, VALUE *script_lines) { result->node.filepath_encoding = rb_enc_get(filepath); pm_options_filepath_set(&result->options, RSTRING_PTR(filepath)); @@ -10672,7 +10687,7 @@ pm_parse_file(pm_parse_result_t *result, VALUE filepath) pm_parser_init(&result->parser, pm_string_source(&result->input), pm_string_length(&result->input), &result->options); pm_node_t *node = pm_parse(&result->parser); - VALUE error = pm_parse_process(result, node); + VALUE error = pm_parse_process(result, node, script_lines); // If we're parsing a filepath, then we need to potentially support the // SCRIPT_LINES__ constant, which can be a hash that has an array of lines @@ -10680,10 +10695,10 @@ pm_parse_file(pm_parse_result_t *result, VALUE filepath) ID id_script_lines = rb_intern("SCRIPT_LINES__"); if (rb_const_defined_at(rb_cObject, id_script_lines)) { - VALUE script_lines = rb_const_get_at(rb_cObject, id_script_lines); + VALUE constant_script_lines = rb_const_get_at(rb_cObject, id_script_lines); - if (RB_TYPE_P(script_lines, T_HASH)) { - rb_hash_aset(script_lines, filepath, pm_parse_file_script_lines(&result->node, &result->parser)); + if (RB_TYPE_P(constant_script_lines, T_HASH)) { + rb_hash_aset(constant_script_lines, filepath, pm_parse_file_script_lines(&result->node, &result->parser)); } } @@ -10695,11 +10710,11 @@ pm_parse_file(pm_parse_result_t *result, VALUE filepath) * cannot be read or if it cannot be parsed properly. */ VALUE -pm_load_parse_file(pm_parse_result_t *result, VALUE filepath) +pm_load_parse_file(pm_parse_result_t *result, VALUE filepath, VALUE *script_lines) { VALUE error = pm_load_file(result, filepath, false); if (NIL_P(error)) { - error = pm_parse_file(result, filepath); + error = pm_parse_file(result, filepath, script_lines); } return error; @@ -10712,7 +10727,7 @@ pm_load_parse_file(pm_parse_result_t *result, VALUE filepath) * error is returned. */ VALUE -pm_parse_string(pm_parse_result_t *result, VALUE source, VALUE filepath) +pm_parse_string(pm_parse_result_t *result, VALUE source, VALUE filepath, VALUE *script_lines) { rb_encoding *encoding = rb_enc_get(source); if (!rb_enc_asciicompat(encoding)) { @@ -10730,7 +10745,7 @@ pm_parse_string(pm_parse_result_t *result, VALUE source, VALUE filepath) pm_parser_init(&result->parser, pm_string_source(&result->input), pm_string_length(&result->input), &result->options); pm_node_t *node = pm_parse(&result->parser); - return pm_parse_process(result, node); + return pm_parse_process(result, node, script_lines); } /** @@ -10780,7 +10795,7 @@ pm_parse_stdin(pm_parse_result_t *result) // we went through an IO object to be visible to the user. rb_reset_argf_lineno(0); - return pm_parse_process(result, node); + return pm_parse_process(result, node, NULL); } #undef NEW_ISEQ diff --git a/prism_compile.h b/prism_compile.h index 8df82c5c7c..28f32cfbe9 100644 --- a/prism_compile.h +++ b/prism_compile.h @@ -30,6 +30,16 @@ typedef struct pm_scope_node { rb_encoding *encoding; /** + * This is a pointer to the list of script lines for the ISEQs that will be + * associated with this scope node. It is only set if + * RubyVM.keep_script_lines is true. If it is set, it will be set to a + * pointer to an array that is always stack allocated (so no GC marking is + * needed by this struct). If it is not set, it will be NULL. It is + * inherited by all child scopes. + */ + VALUE *script_lines; + + /** * This is the encoding of the actual filepath object that will be used when * a __FILE__ node is compiled or when the path has to be set on a syntax * error. @@ -75,9 +85,9 @@ typedef struct { } pm_parse_result_t; VALUE pm_load_file(pm_parse_result_t *result, VALUE filepath, bool load_error); -VALUE pm_parse_file(pm_parse_result_t *result, VALUE filepath); -VALUE pm_load_parse_file(pm_parse_result_t *result, VALUE filepath); -VALUE pm_parse_string(pm_parse_result_t *result, VALUE source, VALUE filepath); +VALUE pm_parse_file(pm_parse_result_t *result, VALUE filepath, VALUE *script_lines); +VALUE pm_load_parse_file(pm_parse_result_t *result, VALUE filepath, VALUE *script_lines); +VALUE pm_parse_string(pm_parse_result_t *result, VALUE source, VALUE filepath, VALUE *script_lines); VALUE pm_parse_stdin(pm_parse_result_t *result); void pm_parse_result_free(pm_parse_result_t *result); @@ -2188,7 +2188,7 @@ prism_script(ruby_cmdline_options_t *opt, pm_parse_result_t *result) ruby_opt_init(opt); result->node.coverage_enabled = 0; - error = pm_parse_string(result, opt->e_script, rb_str_new2("-e")); + error = pm_parse_string(result, opt->e_script, rb_str_new2("-e"), NULL); } else { pm_options_command_line_set(options, command_line); @@ -2201,7 +2201,7 @@ prism_script(ruby_cmdline_options_t *opt, pm_parse_result_t *result) // to load, it doesn't require files required by -r. if (NIL_P(error)) { ruby_opt_init(opt); - error = pm_parse_file(result, opt->script_name); + error = pm_parse_file(result, opt->script_name, NULL); } // Check if (after requiring all of the files through -r flags) we have diff --git a/template/prelude.c.tmpl b/template/prelude.c.tmpl index af493dfaca..125a293423 100644 --- a/template/prelude.c.tmpl +++ b/template/prelude.c.tmpl @@ -158,7 +158,7 @@ static void pm_prelude_load(pm_parse_result_t *result, VALUE name, VALUE code, int line) { pm_options_line_set(&result->options, line); - VALUE error = pm_parse_string(result, code, name); + VALUE error = pm_parse_string(result, code, name, NULL); if (!NIL_P(error)) { pm_parse_result_free(result); @@ -1719,7 +1719,7 @@ pm_eval_make_iseq(VALUE src, VALUE fname, int line, // Add our empty local scope at the very end of the array for our eval // scope's locals. pm_options_scope_init(&result.options.scopes[scopes_count], 0); - VALUE error = pm_parse_string(&result, src, fname); + VALUE error = pm_parse_string(&result, src, fname, NULL); // If the parse failed, clean up and raise. if (error != Qnil) { |