This commit is contained in:
Peter Zhu 2024-01-23 14:43:53 -05:00
Родитель 333f4b4930
Коммит cecf42601a
2 изменённых файлов: 25 добавлений и 15 удалений

Просмотреть файл

@ -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) {
pm_insert_local_index(name, local_index, index_lookup_table, local_table_for_iseq, scope_node);
local_index++;
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++;
}
}

Просмотреть файл

@ -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