зеркало из https://github.com/github/ruby.git
Fix intermediate array off-by-one error
Co-authored-by: Adam Hess <HParker@github.com>
This commit is contained in:
Родитель
f77517f473
Коммит
30038656aa
51
iseq.c
51
iseq.c
|
@ -1569,6 +1569,48 @@ iseqw_s_compile(int argc, VALUE *argv, VALUE self)
|
||||||
return iseqw_s_compile_parser(argc, argv, self, rb_ruby_prism_p());
|
return iseqw_s_compile_parser(argc, argv, self, rb_ruby_prism_p());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* call-seq:
|
||||||
|
* InstructionSequence.compile_parsey(source[, file[, path[, line[, options]]]]) -> iseq
|
||||||
|
*
|
||||||
|
* Takes +source+, which can be a string of Ruby code, or an open +File+ object.
|
||||||
|
* that contains Ruby source code. It parses and compiles using parse.y.
|
||||||
|
*
|
||||||
|
* Optionally takes +file+, +path+, and +line+ which describe the file path,
|
||||||
|
* real path and first line number of the ruby code in +source+ which are
|
||||||
|
* metadata attached to the returned +iseq+.
|
||||||
|
*
|
||||||
|
* +file+ is used for `__FILE__` and exception backtrace. +path+ is used for
|
||||||
|
* +require_relative+ base. It is recommended these should be the same full
|
||||||
|
* path.
|
||||||
|
*
|
||||||
|
* +options+, which can be +true+, +false+ or a +Hash+, is used to
|
||||||
|
* modify the default behavior of the Ruby iseq compiler.
|
||||||
|
*
|
||||||
|
* For details regarding valid compile options see ::compile_option=.
|
||||||
|
*
|
||||||
|
* RubyVM::InstructionSequence.compile_parsey("a = 1 + 2")
|
||||||
|
* #=> <RubyVM::InstructionSequence:<compiled>@<compiled>>
|
||||||
|
*
|
||||||
|
* path = "test.rb"
|
||||||
|
* RubyVM::InstructionSequence.compile_parsey(File.read(path), path, File.expand_path(path))
|
||||||
|
* #=> <RubyVM::InstructionSequence:<compiled>@test.rb:1>
|
||||||
|
*
|
||||||
|
* file = File.open("test.rb")
|
||||||
|
* RubyVM::InstructionSequence.compile_parsey(file)
|
||||||
|
* #=> <RubyVM::InstructionSequence:<compiled>@<compiled>:1>
|
||||||
|
*
|
||||||
|
* path = File.expand_path("test.rb")
|
||||||
|
* RubyVM::InstructionSequence.compile_parsey(File.read(path), path, path)
|
||||||
|
* #=> <RubyVM::InstructionSequence:<compiled>@/absolute/path/to/test.rb:1>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static VALUE
|
||||||
|
iseqw_s_compile_parsey(int argc, VALUE *argv, VALUE self)
|
||||||
|
{
|
||||||
|
return iseqw_s_compile_parser(argc, argv, self, false);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* call-seq:
|
* call-seq:
|
||||||
* InstructionSequence.compile_prism(source[, file[, path[, line[, options]]]]) -> iseq
|
* InstructionSequence.compile_prism(source[, file[, path[, line[, options]]]]) -> iseq
|
||||||
|
@ -1589,19 +1631,19 @@ iseqw_s_compile(int argc, VALUE *argv, VALUE self)
|
||||||
*
|
*
|
||||||
* For details regarding valid compile options see ::compile_option=.
|
* For details regarding valid compile options see ::compile_option=.
|
||||||
*
|
*
|
||||||
* RubyVM::InstructionSequence.compile("a = 1 + 2")
|
* RubyVM::InstructionSequence.compile_prism("a = 1 + 2")
|
||||||
* #=> <RubyVM::InstructionSequence:<compiled>@<compiled>>
|
* #=> <RubyVM::InstructionSequence:<compiled>@<compiled>>
|
||||||
*
|
*
|
||||||
* path = "test.rb"
|
* path = "test.rb"
|
||||||
* RubyVM::InstructionSequence.compile(File.read(path), path, File.expand_path(path))
|
* RubyVM::InstructionSequence.compile_prism(File.read(path), path, File.expand_path(path))
|
||||||
* #=> <RubyVM::InstructionSequence:<compiled>@test.rb:1>
|
* #=> <RubyVM::InstructionSequence:<compiled>@test.rb:1>
|
||||||
*
|
*
|
||||||
* file = File.open("test.rb")
|
* file = File.open("test.rb")
|
||||||
* RubyVM::InstructionSequence.compile(file)
|
* RubyVM::InstructionSequence.compile_prism(file)
|
||||||
* #=> <RubyVM::InstructionSequence:<compiled>@<compiled>:1>
|
* #=> <RubyVM::InstructionSequence:<compiled>@<compiled>:1>
|
||||||
*
|
*
|
||||||
* path = File.expand_path("test.rb")
|
* path = File.expand_path("test.rb")
|
||||||
* RubyVM::InstructionSequence.compile(File.read(path), path, path)
|
* RubyVM::InstructionSequence.compile_prism(File.read(path), path, path)
|
||||||
* #=> <RubyVM::InstructionSequence:<compiled>@/absolute/path/to/test.rb:1>
|
* #=> <RubyVM::InstructionSequence:<compiled>@/absolute/path/to/test.rb:1>
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@ -4283,6 +4325,7 @@ Init_ISeq(void)
|
||||||
(void)iseq_s_load;
|
(void)iseq_s_load;
|
||||||
|
|
||||||
rb_define_singleton_method(rb_cISeq, "compile", iseqw_s_compile, -1);
|
rb_define_singleton_method(rb_cISeq, "compile", iseqw_s_compile, -1);
|
||||||
|
rb_define_singleton_method(rb_cISeq, "compile_parsey", iseqw_s_compile_parsey, -1);
|
||||||
rb_define_singleton_method(rb_cISeq, "compile_prism", iseqw_s_compile_prism, -1);
|
rb_define_singleton_method(rb_cISeq, "compile_prism", iseqw_s_compile_prism, -1);
|
||||||
rb_define_singleton_method(rb_cISeq, "compile_file_prism", iseqw_s_compile_file_prism, -1);
|
rb_define_singleton_method(rb_cISeq, "compile_file_prism", iseqw_s_compile_file_prism, -1);
|
||||||
rb_define_singleton_method(rb_cISeq, "new", iseqw_s_compile, -1);
|
rb_define_singleton_method(rb_cISeq, "new", iseqw_s_compile, -1);
|
||||||
|
|
|
@ -6797,6 +6797,8 @@ pm_compile_array_node(rb_iseq_t *iseq, const pm_node_t *node, const pm_node_list
|
||||||
// Create the temporary array.
|
// Create the temporary array.
|
||||||
for (; tmp_array_size; tmp_array_size--)
|
for (; tmp_array_size; tmp_array_size--)
|
||||||
rb_ary_push(tmp_array, pm_static_literal_value(iseq, elements->nodes[index++], scope_node));
|
rb_ary_push(tmp_array, pm_static_literal_value(iseq, elements->nodes[index++], scope_node));
|
||||||
|
|
||||||
|
index--; // about to be incremented by for loop
|
||||||
OBJ_FREEZE(tmp_array);
|
OBJ_FREEZE(tmp_array);
|
||||||
|
|
||||||
// Emit the optimized code.
|
// Emit the optimized code.
|
||||||
|
|
|
@ -768,6 +768,9 @@ module Prism
|
||||||
assert_prism_eval("a = [1,2]; [0, *a, 3, 4, *5..6, 7, 8, *9..11]")
|
assert_prism_eval("a = [1,2]; [0, *a, 3, 4, *5..6, 7, 8, *9..11]")
|
||||||
assert_prism_eval("[[*1..2], 3, *4..5]")
|
assert_prism_eval("[[*1..2], 3, *4..5]")
|
||||||
|
|
||||||
|
elements = Array.new(64) { ":foo" }
|
||||||
|
assert_prism_eval("[#{elements.join(", ")}, bar: 1, baz: 2]")
|
||||||
|
|
||||||
# Test keyword splat inside of array
|
# Test keyword splat inside of array
|
||||||
assert_prism_eval("[**{x: 'hello'}]")
|
assert_prism_eval("[**{x: 'hello'}]")
|
||||||
|
|
||||||
|
@ -2628,7 +2631,7 @@ end
|
||||||
def compare_eval(source, raw:, location:)
|
def compare_eval(source, raw:, location:)
|
||||||
source = raw ? source : "class Prism::TestCompilePrism\n#{source}\nend"
|
source = raw ? source : "class Prism::TestCompilePrism\n#{source}\nend"
|
||||||
|
|
||||||
ruby_eval = RubyVM::InstructionSequence.compile(source).eval
|
ruby_eval = RubyVM::InstructionSequence.compile_parsey(source).eval
|
||||||
prism_eval = RubyVM::InstructionSequence.compile_prism(source).eval
|
prism_eval = RubyVM::InstructionSequence.compile_prism(source).eval
|
||||||
|
|
||||||
if ruby_eval.is_a? Proc
|
if ruby_eval.is_a? Proc
|
||||||
|
|
Загрузка…
Ссылка в новой задаче