diff options
author | eileencodes <eileencodes@gmail.com> | 2023-12-04 11:45:42 -0500 |
---|---|---|
committer | Aaron Patterson <aaron.patterson@gmail.com> | 2023-12-04 12:03:22 -0800 |
commit | 569750f624dbb4e9d5836d4e9c46816224f4b681 (patch) | |
tree | c6a7d470bc270f41bbcd2112afa4e6313dba84df | |
parent | e3ca50b02fc4e3381f62a60bce0164d2132cf4ed (diff) | |
download | ruby-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.c | 21 | ||||
-rw-r--r-- | test/ruby/test_compile_prism.rb | 6 |
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") |