summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Newton <kddnewton@gmail.com>2024-04-04 14:51:49 -0400
committerKevin Newton <kddnewton@gmail.com>2024-04-04 15:27:51 -0400
commit0aa1d61ab95befe0d8e68ebe86e238a09a8c11c5 (patch)
treebeaec843895f6f4d8cacf5e5cfc0a0dfaabe5675
parent48c2ffe98040f591b3cc27b9c600a61c2dcb8594 (diff)
[PRISM] Ensure unfrozen when interpolation is present in string literal
-rw-r--r--prism_compile.c64
-rw-r--r--test/.excludes-prism/TestISeq.rb1
2 files changed, 37 insertions, 28 deletions
diff --git a/prism_compile.c b/prism_compile.c
index 4ed37be840..a26962cb94 100644
--- a/prism_compile.c
+++ b/prism_compile.c
@@ -322,6 +322,7 @@ pm_interpolated_node_compile(rb_iseq_t *iseq, const pm_node_list_t *parts, const
{
int stack_size = 0;
size_t parts_size = parts->size;
+ bool interpolated = false;
if (parts_size > 0) {
VALUE current_string = Qnil;
@@ -340,41 +341,51 @@ pm_interpolated_node_compile(rb_iseq_t *iseq, const pm_node_list_t *parts, const
current_string = string_value;
}
}
- else if (
- PM_NODE_TYPE_P(part, PM_EMBEDDED_STATEMENTS_NODE) &&
- ((const pm_embedded_statements_node_t *) part)->statements != NULL &&
- ((const pm_embedded_statements_node_t *) part)->statements->body.size == 1 &&
- PM_NODE_TYPE_P(((const pm_embedded_statements_node_t *) part)->statements->body.nodes[0], PM_STRING_NODE)
- ) {
- const pm_string_node_t *string_node = (const pm_string_node_t *) ((const pm_embedded_statements_node_t *) part)->statements->body.nodes[0];
- VALUE string_value = parse_string_encoded(scope_node, (const pm_node_t *) string_node, &string_node->unescaped);
-
- if (RTEST(current_string)) {
- current_string = rb_str_concat(current_string, string_value);
- }
- else {
- current_string = string_value;
- }
- }
else {
- if (!RTEST(current_string)) {
- current_string = rb_enc_str_new(NULL, 0, scope_node->encoding);
+ interpolated = true;
+
+ if (
+ PM_NODE_TYPE_P(part, PM_EMBEDDED_STATEMENTS_NODE) &&
+ ((const pm_embedded_statements_node_t *) part)->statements != NULL &&
+ ((const pm_embedded_statements_node_t *) part)->statements->body.size == 1 &&
+ PM_NODE_TYPE_P(((const pm_embedded_statements_node_t *) part)->statements->body.nodes[0], PM_STRING_NODE)
+ ) {
+ const pm_string_node_t *string_node = (const pm_string_node_t *) ((const pm_embedded_statements_node_t *) part)->statements->body.nodes[0];
+ VALUE string_value = parse_string_encoded(scope_node, (const pm_node_t *) string_node, &string_node->unescaped);
+
+ if (RTEST(current_string)) {
+ current_string = rb_str_concat(current_string, string_value);
+ }
+ else {
+ current_string = string_value;
+ }
}
+ else {
+ if (!RTEST(current_string)) {
+ current_string = rb_enc_str_new(NULL, 0, scope_node->encoding);
+ }
- PUSH_INSN1(ret, *node_location, putobject, rb_fstring(current_string));
- PM_COMPILE_NOT_POPPED(part);
- PUSH_INSN(ret, *node_location, dup);
- PUSH_INSN1(ret, *node_location, objtostring, new_callinfo(iseq, idTo_s, 0, VM_CALL_FCALL | VM_CALL_ARGS_SIMPLE , NULL, FALSE));
- PUSH_INSN(ret, *node_location, anytostring);
+ PUSH_INSN1(ret, *node_location, putobject, rb_fstring(current_string));
+ PM_COMPILE_NOT_POPPED(part);
+ PUSH_INSN(ret, *node_location, dup);
+ PUSH_INSN1(ret, *node_location, objtostring, new_callinfo(iseq, idTo_s, 0, VM_CALL_FCALL | VM_CALL_ARGS_SIMPLE , NULL, FALSE));
+ PUSH_INSN(ret, *node_location, anytostring);
- current_string = Qnil;
- stack_size += 2;
+ current_string = Qnil;
+ stack_size += 2;
+ }
}
}
if (RTEST(current_string)) {
current_string = rb_fstring(current_string);
- PUSH_INSN1(ret, *node_location, putobject, current_string);
+
+ if (stack_size == 0 && interpolated) {
+ PUSH_INSN1(ret, *node_location, putstring, current_string);
+ }
+ else {
+ PUSH_INSN1(ret, *node_location, putobject, current_string);
+ }
current_string = Qnil;
stack_size++;
@@ -6231,7 +6242,6 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
else {
const pm_interpolated_string_node_t *cast = (const pm_interpolated_string_node_t *) node;
int length = pm_interpolated_node_compile(iseq, &cast->parts, &location, ret, popped, scope_node);
-
if (length > 1) PUSH_INSN1(ret, location, concatstrings, INT2FIX(length));
if (popped) PUSH_INSN(ret, location, pop);
}
diff --git a/test/.excludes-prism/TestISeq.rb b/test/.excludes-prism/TestISeq.rb
index b46047bc9e..3768d8fc05 100644
--- a/test/.excludes-prism/TestISeq.rb
+++ b/test/.excludes-prism/TestISeq.rb
@@ -1,4 +1,3 @@
exclude(:test_each_child, "https://github.com/ruby/prism/issues/2660")
-exclude(:test_frozen_string_literal_compile_option, "https://github.com/ruby/prism/issues/2661")
exclude(:test_syntax_error_message, "Assertion checks against specific error format")
exclude(:test_trace_points, "https://github.com/ruby/prism/issues/2660")