diff --git a/prism_compile.c b/prism_compile.c index ae7274f9a3..2370b28982 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -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: { diff --git a/prism_compile.h b/prism_compile.h index d307807b84..2d64811e69 100644 --- a/prism_compile.h +++ b/prism_compile.h @@ -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); diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 63b06bc9bd..1f0bce2037 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -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