зеркало из https://github.com/github/ruby.git
[PRISM] Handle RubyVM.keep_script_lines
This commit is contained in:
Родитель
554098303d
Коммит
371432b2d7
11
iseq.c
11
iseq.c
|
@ -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);
|
||||
|
|
2
load.c
2
load.c
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -29,6 +29,16 @@ typedef struct pm_scope_node {
|
|||
const pm_parser_t *parser;
|
||||
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
|
||||
|
@ -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);
|
||||
|
||||
|
|
4
ruby.c
4
ruby.c
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче