diff options
-rw-r--r-- | prism_compile.c | 29 | ||||
-rw-r--r-- | test/ruby/test_compile_prism.rb | 9 |
2 files changed, 24 insertions, 14 deletions
diff --git a/prism_compile.c b/prism_compile.c index 9ddd502117..4ebfca9c1e 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -57,18 +57,8 @@ #define PM_NOP \ ADD_INSN(ret, &dummy_line_node, nop) -/** - * We're using the top most bit of a pm_constant_id_t as a tag to represent an - * anonymous local. When a child iseq is created and needs access to a value - * that has yet to be defined, or is defined by the parent node's iseq. This can - * be added to it's local table and then handled accordingly when compiling the - * scope node associated with the child iseq. - * - * See the compilation process for PM_FOR_NODE: as an example, where the - * variable referenced inside the StatementsNode is defined as part of the top - * level ForLoop node. -*/ -#define TEMP_CONSTANT_IDENTIFIER ((pm_constant_id_t)(1 << 31)) +#define PM_SPECIAL_CONSTANT_FLAG ((pm_constant_id_t)(1 << 31)) +#define PM_CONSTANT_AND ((pm_constant_id_t)(idAnd | PM_SPECIAL_CONSTANT_FLAG)) rb_iseq_t * pm_iseq_new_with_opt(pm_scope_node_t *scope_node, pm_parser_t *parser, VALUE name, VALUE path, VALUE realpath, @@ -2790,6 +2780,8 @@ pm_add_ensure_iseq(LINK_ANCHOR *const ret, rb_iseq_t *iseq, int is_return, const static void pm_insert_local_index(pm_constant_id_t constant_id, int local_index, st_table *index_lookup_table, rb_ast_id_table_t *local_table_for_iseq, pm_scope_node_t *scope_node) { + RUBY_ASSERT((constant_id & PM_SPECIAL_CONSTANT_FLAG) == 0); + ID local = pm_constant_id_lookup(scope_node, constant_id); local_table_for_iseq->ids[local_index] = local; st_insert(index_lookup_table, constant_id, local_index); @@ -3738,6 +3730,10 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, if (block_argument_node->expression) { PM_COMPILE(block_argument_node->expression); } + else { + pm_local_index_t index = pm_lookup_local_index(iseq, scope_node, PM_CONSTANT_AND, 0); + ADD_GETLOCAL(ret, &dummy_line_node, index.index, index.level); + } return; } case PM_BREAK_NODE: { @@ -6632,10 +6628,15 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, body->param.flags.has_block = true; pm_constant_id_t name = ((pm_block_parameter_node_t *)parameters_node->block)->name; - if (name != 0) { + if (name == 0) { + local_table_for_iseq->ids[local_index] = PM_CONSTANT_AND; + st_insert(index_lookup_table, PM_CONSTANT_AND, local_index); + } + else { pm_insert_local_index(name, local_index, index_lookup_table, local_table_for_iseq, scope_node); - local_index++; } + + local_index++; } } diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 66fbefd27b..8357914ce2 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -1690,6 +1690,15 @@ end def test_BlockArgumentNode assert_prism_eval("1.then(&:to_s)") + + # Test forwarding with no name + assert_prism_eval(<<~RUBY) + o = Object.new + def o.foo(&) = yield + def o.bar(&) = foo(&) + + o.bar { :ok } + RUBY end def test_BlockLocalVariableNode |