aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoreileencodes <eileencodes@gmail.com>2023-12-04 11:45:42 -0500
committerAaron Patterson <aaron.patterson@gmail.com>2023-12-04 12:03:22 -0800
commit569750f624dbb4e9d5836d4e9c46816224f4b681 (patch)
treec6a7d470bc270f41bbcd2112afa4e6313dba84df
parente3ca50b02fc4e3381f62a60bce0164d2132cf4ed (diff)
downloadruby-569750f624dbb4e9d5836d4e9c46816224f4b681.tar.gz
[Prism] Implement backref and numbered reference for `defined?`
This PR implements `PM_BACK_REFERENCE_READ_NODE` and `PM_NUMBERED_REFERENCE_READ_NODE` for `defined?`. The following now works: * `PM_NUMBERED_REFERENCE_READ_NODE` ``` defined? $1 defined? $2 ``` Instructions: ``` "********* RUBY *************" == disasm: #<ISeq:<compiled>@<compiled>:0 (0,0)-(0,12)> 0000 putnil 0001 defined ref, :$1, "global-variable" 0005 leave "********* PRISM *************" == disasm: #<ISeq:<compiled>@<compiled>:0 (0,0)-(0,12)> 0000 putnil 0001 defined ref, :$1, "global-variable" 0005 leave ``` * `PM_BACK_REFERENCE_READ_NODE` ``` defined? $' defined? $` defined? $& ``` Instructions: ``` "********* RUBY *************" == disasm: #<ISeq:<compiled>@<compiled>:0 (0,0)-(0,12)> 0000 putnil 0001 defined ref, :$`, "global-variable" 0005 leave "********* PRISM *************" == disasm: #<ISeq:<compiled>@<compiled>:0 (0,0)-(0,12)> 0000 putnil 0001 defined ref, :$`, "global-variable" 0005 leave ```
-rw-r--r--prism_compile.c21
-rw-r--r--test/ruby/test_compile_prism.rb6
2 files changed, 27 insertions, 0 deletions
diff --git a/prism_compile.c b/prism_compile.c
index 2c7b4f265f..e29e57721a 100644
--- a/prism_compile.c
+++ b/prism_compile.c
@@ -1488,6 +1488,27 @@ pm_compile_defined_expr0(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *co
ID2SYM(id), get_ivar_ic_value(iseq, id), PUSH_VAL(DEFINED_IVAR));
return;
}
+ case PM_BACK_REFERENCE_READ_NODE: {
+ char *char_ptr = (char *)(node->location.start) + 1;
+ ID backref_val = INT2FIX(rb_intern2(char_ptr, 1)) << 1 | 1;
+
+ PM_PUTNIL;
+ ADD_INSN3(ret, &dummy_line_node, defined, INT2FIX(DEFINED_REF),
+ backref_val,
+ PUSH_VAL(DEFINED_GVAR));
+
+ return;
+ }
+ case PM_NUMBERED_REFERENCE_READ_NODE: {
+ uint32_t reference_number = ((pm_numbered_reference_read_node_t *)node)->number;
+
+ PM_PUTNIL;
+ ADD_INSN3(ret, &dummy_line_node, defined, INT2FIX(DEFINED_REF),
+ INT2FIX(reference_number << 1),
+ PUSH_VAL(DEFINED_GVAR));
+
+ return;
+ }
case PM_GLOBAL_VARIABLE_READ_NODE: {
pm_global_variable_read_node_t *glabal_variable_read_node = (pm_global_variable_read_node_t *)node;
PM_PUTNIL;
diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb
index e51ca190d5..922640982e 100644
--- a/test/ruby/test_compile_prism.rb
+++ b/test/ruby/test_compile_prism.rb
@@ -125,6 +125,12 @@ module Prism
assert_prism_eval("defined? X &= 1")
assert_prism_eval("defined? X ||= 1")
+ assert_prism_eval("defined? $1")
+ assert_prism_eval("defined? $2")
+ assert_prism_eval("defined? $`")
+ assert_prism_eval("defined? $'")
+ assert_prism_eval("defined? $+")
+
assert_prism_eval("defined? $X = 1")
assert_prism_eval("defined? $X *= 1")
assert_prism_eval("defined? $X /= 1")