summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--iseq.c51
-rw-r--r--prism_compile.c2
-rw-r--r--test/ruby/test_compile_prism.rb5
3 files changed, 53 insertions, 5 deletions
diff --git a/iseq.c b/iseq.c
index 3d18fb597a..a60228c8e5 100644
--- a/iseq.c
+++ b/iseq.c
@@ -1571,6 +1571,48 @@ iseqw_s_compile(int argc, VALUE *argv, VALUE self)
/*
* 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:
* InstructionSequence.compile_prism(source[, file[, path[, line[, options]]]]) -> iseq
*
* Takes +source+, which can be a string of Ruby code, or an open +File+ object.
@@ -1589,19 +1631,19 @@ iseqw_s_compile(int argc, VALUE *argv, VALUE self)
*
* 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>>
*
* 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>
*
* file = File.open("test.rb")
- * RubyVM::InstructionSequence.compile(file)
+ * RubyVM::InstructionSequence.compile_prism(file)
* #=> <RubyVM::InstructionSequence:<compiled>@<compiled>:1>
*
* 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>
*
*/
@@ -4283,6 +4325,7 @@ Init_ISeq(void)
(void)iseq_s_load;
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_file_prism", iseqw_s_compile_file_prism, -1);
rb_define_singleton_method(rb_cISeq, "new", iseqw_s_compile, -1);
diff --git a/prism_compile.c b/prism_compile.c
index a9c8aea4b4..5f5e0aa6fe 100644
--- a/prism_compile.c
+++ b/prism_compile.c
@@ -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.
for (; tmp_array_size; tmp_array_size--)
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);
// Emit the optimized code.
diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb
index afe39f9aef..92c1304e9b 100644
--- a/test/ruby/test_compile_prism.rb
+++ b/test/ruby/test_compile_prism.rb
@@ -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("[[*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
assert_prism_eval("[**{x: 'hello'}]")
@@ -2628,7 +2631,7 @@ end
def compare_eval(source, raw:, location:)
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
if ruby_eval.is_a? Proc