# HG changeset patch # User Bram Moolenaar # Date 1616003103 -3600 # Node ID c308076e225ecea503c32d289cd9a2d213cd5282 # Parent 6eae6237cc7dd6a7946392b8239c4ec466a7a629 patch 8.2.2617: Vim9: script variable in block not found by function Commit: https://github.com/vim/vim/commit/8863bda25df821fc79bebf9dc73c79776ae5f675 Author: Bram Moolenaar Date: Wed Mar 17 18:42:08 2021 +0100 patch 8.2.2617: Vim9: script variable in block not found by function Problem: Vim9: script variable in a block scope not found by a nested function. Solution: Copy the block scope IDs before compiling the function. diff --git a/src/testdir/test_vim9_disassemble.vim b/src/testdir/test_vim9_disassemble.vim --- a/src/testdir/test_vim9_disassemble.vim +++ b/src/testdir/test_vim9_disassemble.vim @@ -947,7 +947,7 @@ def NestedOuter() enddef enddef -def Test_nested_func() +def Test_disassemble_nested_func() var instr = execute('disassemble NestedOuter') assert_match('NestedOuter\_s*' .. 'def g:Inner()\_s*' .. @@ -965,7 +965,7 @@ def NestedDefList() def /Info/ enddef -def Test_nested_def_list() +def Test_disassemble_nested_def_list() var instr = execute('disassemble NestedDefList') assert_match('NestedDefList\_s*' .. 'def\_s*' .. diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim --- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -393,7 +393,6 @@ def Test_nested_function() CheckDefFailure(lines, 'E1117:') # nested function inside conditional - # TODO: should it work when "thecount" is inside the "if"? lines =<< trim END vim9script var thecount = 0 @@ -411,6 +410,25 @@ def Test_nested_function() assert_equal(2, Test()) END CheckScriptSuccess(lines) + + # also works when "thecount" is inside the "if" block + lines =<< trim END + vim9script + if true + var thecount = 0 + def Test(): number + def TheFunc(): number + thecount += 1 + return thecount + enddef + return TheFunc() + enddef + endif + defcompile + assert_equal(1, Test()) + assert_equal(2, Test()) + END + CheckScriptSuccess(lines) enddef def Test_not_nested_function() diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -751,6 +751,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 2617, +/**/ 2616, /**/ 2615, diff --git a/src/vim9compile.c b/src/vim9compile.c --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -5183,6 +5183,21 @@ compile_nested_function(exarg_T *eap, cc r = eap->skip ? OK : FAIL; goto theend; } + + // copy over the block scope IDs before compiling + if (!is_global && cctx->ctx_ufunc->uf_block_depth > 0) + { + int block_depth = cctx->ctx_ufunc->uf_block_depth; + + ufunc->uf_block_ids = ALLOC_MULT(int, block_depth); + if (ufunc->uf_block_ids != NULL) + { + mch_memmove(ufunc->uf_block_ids, cctx->ctx_ufunc->uf_block_ids, + sizeof(int) * block_depth); + ufunc->uf_block_depth = block_depth; + } + } + if (func_needs_compiling(ufunc, PROFILING(ufunc)) && compile_def_function(ufunc, TRUE, PROFILING(ufunc), cctx) == FAIL) @@ -5209,25 +5224,12 @@ compile_nested_function(exarg_T *eap, cc // Define a local variable for the function reference. lvar_T *lvar = reserve_local(cctx, name_start, name_end - name_start, TRUE, ufunc->uf_func_type); - int block_depth = cctx->ctx_ufunc->uf_block_depth; if (lvar == NULL) goto theend; if (generate_FUNCREF(cctx, ufunc) == FAIL) goto theend; r = generate_STORE(cctx, ISN_STORE, lvar->lv_idx, NULL); - - // copy over the block scope IDs - if (block_depth > 0) - { - ufunc->uf_block_ids = ALLOC_MULT(int, block_depth); - if (ufunc->uf_block_ids != NULL) - { - mch_memmove(ufunc->uf_block_ids, cctx->ctx_ufunc->uf_block_ids, - sizeof(int) * block_depth); - ufunc->uf_block_depth = block_depth; - } - } } // TODO: warning for trailing text?