summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2021-03-17 18:42:08 +0100
committerBram Moolenaar <Bram@vim.org>2021-03-17 18:42:08 +0100
commit8863bda25df821fc79bebf9dc73c79776ae5f675 (patch)
tree0c71db682e0c9ea275dfd06123586a94ccf82e23
parent3e1916947d5b29f67af554ce3b874b03a84c9093 (diff)
downloadvim-git-8863bda25df821fc79bebf9dc73c79776ae5f675.tar.gz
patch 8.2.2617: Vim9: script variable in block not found by functionv8.2.2617
Problem: Vim9: script variable in a block scope not found by a nested function. Solution: Copy the block scope IDs before compiling the function.
-rw-r--r--src/testdir/test_vim9_disassemble.vim4
-rw-r--r--src/testdir/test_vim9_func.vim20
-rw-r--r--src/version.c2
-rw-r--r--src/vim9compile.c28
4 files changed, 38 insertions, 16 deletions
diff --git a/src/testdir/test_vim9_disassemble.vim b/src/testdir/test_vim9_disassemble.vim
index 9d05bbfd2..7470ac3ce 100644
--- 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
index 6258b7d5d..73d8e37aa 100644
--- 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
index a92db82f3..3bb4eceb7 100644
--- 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
index 3fef9bd6b..93ded0857 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -5183,6 +5183,21 @@ compile_nested_function(exarg_T *eap, cctx_T *cctx)
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, cctx_T *cctx)
// 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?