]> granicus.if.org Git - vim/commitdiff
patch 8.2.2617: Vim9: script variable in block not found by function v8.2.2617
authorBram Moolenaar <Bram@vim.org>
Wed, 17 Mar 2021 17:42:08 +0000 (18:42 +0100)
committerBram Moolenaar <Bram@vim.org>
Wed, 17 Mar 2021 17:42:08 +0000 (18:42 +0100)
Problem:    Vim9: script variable in a block scope not found by a nested
            function.
Solution:   Copy the block scope IDs before compiling the function.

src/testdir/test_vim9_disassemble.vim
src/testdir/test_vim9_func.vim
src/version.c
src/vim9compile.c

index 9d05bbfd221f7f1f64d74bfb99b9c5bdae67cb7e..7470ac3ce7b4f44cca548efd261401df56ea2c1c 100644 (file)
@@ -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*' ..
index 6258b7d5d4687e34bc88d9abb7a14abdd410aa2c..73d8e37aa77ae410fa511f15ed5873416f52e2eb 100644 (file)
@@ -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()
index a92db82f344060c28f02d4eb458a46a3594799ee..3bb4eceb749147dd71439b5b3128c6cd07c2566e 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2617,
 /**/
     2616,
 /**/
index 3fef9bd6b0bea3c2db2312075bc973521ca01fd0..93ded085777c7e2a3a6a08ad5906d231d7b2ecbb 100644 (file)
@@ -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?