Store depth offset inside the scope node.

Instead of incrementing the depth using call by reference as we're
recursing up the stack we could instead store an offset for each known
scope where we know the depth is going to represented differently in the
Prism ast.
This commit is contained in:
Matt Valentine-House 2023-11-30 11:05:26 +00:00
Родитель a1647c460f
Коммит 57782d3d47
3 изменённых файлов: 38 добавлений и 24 удалений

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

@ -689,7 +689,7 @@ pm_interpolated_node_compile(pm_node_list_t *parts, rb_iseq_t *iseq, NODE dummy_
// It also takes a pointer to depth, and increments depth appropriately
// according to the depth of the local
static int
pm_lookup_local_index_any_scope(rb_iseq_t *iseq, pm_scope_node_t *scope_node, pm_constant_id_t constant_id, int *depth)
pm_lookup_local_index_any_scope(rb_iseq_t *iseq, pm_scope_node_t *scope_node, pm_constant_id_t constant_id)
{
if (!scope_node) {
// We have recursed up all scope nodes
@ -701,8 +701,7 @@ pm_lookup_local_index_any_scope(rb_iseq_t *iseq, pm_scope_node_t *scope_node, pm
if (!st_lookup(scope_node->index_lookup_table, constant_id, &local_index)) {
// Local does not exist at this level, continue recursing up
(*depth)++;
return pm_lookup_local_index_any_scope(iseq, scope_node->previous, constant_id, depth);
return pm_lookup_local_index_any_scope(iseq, scope_node->previous, constant_id);
}
return (int)scope_node->index_lookup_table->num_entries - (int)local_index;
@ -723,14 +722,14 @@ pm_lookup_local_index(rb_iseq_t *iseq, pm_scope_node_t *scope_node, pm_constant_
}
static int
pm_lookup_local_index_with_depth(rb_iseq_t *iseq, pm_scope_node_t *scope_node, pm_constant_id_t constant_id, int *depth)
pm_lookup_local_index_with_depth(rb_iseq_t *iseq, pm_scope_node_t *scope_node, pm_constant_id_t constant_id, uint32_t depth)
{
for(int i = 0; i < *depth; i++) {
for(uint32_t i = 0; i < depth; i++) {
scope_node = scope_node->previous;
iseq = (rb_iseq_t *)ISEQ_BODY(iseq)->parent_iseq;
}
return pm_lookup_local_index_any_scope(iseq, scope_node, constant_id, depth);
return pm_lookup_local_index_any_scope(iseq, scope_node, constant_id);
}
// This returns the CRuby ID which maps to the pm_constant_id_t
@ -1337,8 +1336,10 @@ pm_scope_node_init(const pm_node_t *node, pm_scope_node_t *scope, pm_scope_node_
scope->parameters = NULL;
scope->body = NULL;
scope->constants = NULL;
scope->local_depth_offset = 0;
if (previous) {
scope->constants = previous->constants;
scope->local_depth_offset = previous->local_depth_offset;
}
scope->index_lookup_table = NULL;
@ -1368,6 +1369,7 @@ pm_scope_node_init(const pm_node_t *node, pm_scope_node_t *scope, pm_scope_node_
case PM_ENSURE_NODE: {
pm_ensure_node_t *cast = (pm_ensure_node_t *)node;
scope->body = (pm_node_t *)cast->statements;
scope->local_depth_offset += 1;
break;
}
case PM_FOR_NODE: {
@ -3049,9 +3051,9 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
LABEL *end_label = NEW_LABEL(lineno);
pm_constant_id_t constant_id = local_variable_and_write_node->name;
int *depth = (int *)&local_variable_and_write_node->depth;
int depth = local_variable_and_write_node->depth + scope_node->local_depth_offset;
int local_index = pm_lookup_local_index_with_depth(iseq, scope_node, constant_id, depth);
ADD_GETLOCAL(ret, &dummy_line_node, local_index, *depth);
ADD_GETLOCAL(ret, &dummy_line_node, local_index, depth);
PM_DUP_UNLESS_POPPED;
@ -3063,7 +3065,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
PM_DUP_UNLESS_POPPED;
ADD_SETLOCAL(ret, &dummy_line_node, local_index, *depth);
ADD_SETLOCAL(ret, &dummy_line_node, local_index, depth);
ADD_LABEL(ret, end_label);
return;
@ -3073,9 +3075,9 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
pm_constant_id_t constant_id = local_variable_operator_write_node->name;
int *depth = (int *)&local_variable_operator_write_node->depth;
int depth = local_variable_operator_write_node->depth + scope_node->local_depth_offset;
int local_index = pm_lookup_local_index_with_depth(iseq, scope_node, constant_id, depth);
ADD_GETLOCAL(ret, &dummy_line_node, local_index, *depth);
ADD_GETLOCAL(ret, &dummy_line_node, local_index, depth);
PM_COMPILE_NOT_POPPED(local_variable_operator_write_node->value);
ID method_id = pm_constant_id_lookup(scope_node, local_variable_operator_write_node->operator);
@ -3085,7 +3087,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
PM_DUP_UNLESS_POPPED;
ADD_SETLOCAL(ret, &dummy_line_node, local_index, *depth);
ADD_SETLOCAL(ret, &dummy_line_node, local_index, depth);
return;
}
@ -3099,9 +3101,9 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
ADD_INSNL(ret, &dummy_line_node, branchunless, set_label);
pm_constant_id_t constant_id = local_variable_or_write_node->name;
int *depth = (int *)&local_variable_or_write_node->depth;
int depth = local_variable_or_write_node->depth + scope_node->local_depth_offset;
int local_index = pm_lookup_local_index_with_depth(iseq, scope_node, constant_id, depth);
ADD_GETLOCAL(ret, &dummy_line_node, local_index, *depth);
ADD_GETLOCAL(ret, &dummy_line_node, local_index, depth);
PM_DUP_UNLESS_POPPED;
@ -3114,7 +3116,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
PM_DUP_UNLESS_POPPED;
ADD_SETLOCAL(ret, &dummy_line_node, local_index, *depth);
ADD_SETLOCAL(ret, &dummy_line_node, local_index, depth);
ADD_LABEL(ret, end_label);
return;
@ -3123,9 +3125,8 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
pm_local_variable_read_node_t *local_read_node = (pm_local_variable_read_node_t *) node;
if (!popped) {
int *depth = (int *)&local_read_node->depth;
int index = pm_lookup_local_index_with_depth(iseq, scope_node, local_read_node->name, depth);
ADD_GETLOCAL(ret, &dummy_line_node, index, *depth);
int index = pm_lookup_local_index_with_depth(iseq, scope_node, local_read_node->name, local_read_node->depth);
ADD_GETLOCAL(ret, &dummy_line_node, index, local_read_node->depth + scope_node->local_depth_offset);
}
return;
}
@ -3133,10 +3134,9 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
pm_local_variable_target_node_t *local_write_node = (pm_local_variable_target_node_t *) node;
pm_constant_id_t constant_id = local_write_node->name;
int depth = 0;
int index = pm_lookup_local_index_any_scope(iseq, scope_node, constant_id, &depth);
int index = pm_lookup_local_index_any_scope(iseq, scope_node, constant_id);
ADD_SETLOCAL(ret, &dummy_line_node, index, depth);
ADD_SETLOCAL(ret, &dummy_line_node, index, local_write_node->depth + scope_node->local_depth_offset);
return;
}
case PM_LOCAL_VARIABLE_WRITE_NODE: {
@ -3147,10 +3147,9 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
pm_constant_id_t constant_id = local_write_node->name;
int depth = 0;
int index = pm_lookup_local_index_any_scope(iseq, scope_node, constant_id, &depth);
int index = pm_lookup_local_index_any_scope(iseq, scope_node, constant_id);
ADD_SETLOCAL(ret, &dummy_line_node, index, depth);
ADD_SETLOCAL(ret, &dummy_line_node, index, local_write_node->depth + scope_node->local_depth_offset);
return;
}
case PM_MATCH_LAST_LINE_NODE: {

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

@ -13,6 +13,11 @@ typedef struct pm_scope_node {
ID *constants;
st_table *index_lookup_table;
// Some locals are defined at higher scopes than they are used. We can use
// this offset to control which parent scopes local table we should be
// referencing from the current scope.
unsigned int local_depth_offset;
} pm_scope_node_t;
void pm_scope_node_init(const pm_node_t *node, pm_scope_node_t *scope, pm_scope_node_t *previous, pm_parser_t *parser);

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

@ -737,6 +737,16 @@ module Prism
end
a + b + c
CODE
assert_prism_eval(<<~CODE)
foo = 1
begin
ensure
begin
ensure
foo.nil?
end
end
CODE
end
def test_NextNode