Patch 8.2.0683
Problem: Vim9: parsing type does not always work.
Solution: Handle func type without return value. Test more closures.
Fix type check offset. Fix garbage collection.
Files: src/vim9compile.c, src/vim9execute.c, src/proto/vim9execute.pro,
src/userfunc.c, src/testdir/test_vim9_func.vim
*** ../vim-8.2.0682/src/vim9compile.c 2020-05-02 19:04:55.497402088 +0200
--- src/vim9compile.c 2020-05-02 20:33:31.411900168 +0200
***************
*** 824,830 ****
isn->isn_arg.type.ct_off = offset;
// type becomes vartype
! ((type_T **)stack->ga_data)[stack->ga_len - 1] = vartype;
return OK;
}
--- 824,830 ----
isn->isn_arg.type.ct_off = offset;
// type becomes vartype
! ((type_T **)stack->ga_data)[stack->ga_len + offset] = vartype;
return OK;
}
***************
*** 1671,1678 ****
if (*p == ',')
p = skipwhite(p + 1);
}
! if (*p == ')' && p[1] == ':')
! p = skip_type(skipwhite(p + 2));
}
return p;
--- 1671,1683 ----
if (*p == ',')
p = skipwhite(p + 1);
}
! if (*p == ')')
! {
! if (p[1] == ':')
! p = skip_type(skipwhite(p + 2));
! else
! p = skipwhite(p + 1);
! }
}
return p;
*** ../vim-8.2.0682/src/vim9execute.c 2020-05-02 17:52:38.404147677 +0200
--- src/vim9execute.c 2020-05-02 22:55:07.649657849 +0200
***************
*** 2437,2447 ****
break;
case ISN_FUNCREF:
{
dfunc_T *df = ((dfunc_T *)def_functions.ga_data)
! + iptr->isn_arg.funcref.fr_func;
smsg("%4d FUNCREF %s $%d", current, df->df_ufunc->uf_name,
! iptr->isn_arg.funcref.fr_var_idx + df->df_varcount);
}
break;
--- 2437,2448 ----
break;
case ISN_FUNCREF:
{
+ funcref_T *funcref = &iptr->isn_arg.funcref;
dfunc_T *df = ((dfunc_T *)def_functions.ga_data)
! + funcref->fr_func;
smsg("%4d FUNCREF %s $%d", current, df->df_ufunc->uf_name,
! funcref->fr_var_idx + dfunc->df_varcount);
}
break;
***************
*** 2675,2679 ****
--- 2676,2700 ----
return OK;
}
+ /*
+ * Mark items in a def function as used.
+ */
+ int
+ set_ref_in_dfunc(ufunc_T *ufunc, int copyID)
+ {
+ dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx;
+ int abort = FALSE;
+
+ if (dfunc->df_funcstack != NULL)
+ {
+ typval_T *stack = dfunc->df_funcstack->fs_ga.ga_data;
+ int idx;
+
+ for (idx = 0; idx < dfunc->df_funcstack->fs_ga.ga_len; ++idx)
+ abort = abort || set_ref_in_item(stack + idx, copyID, NULL, NULL);
+ }
+ return abort;
+ }
+
#endif // FEAT_EVAL
*** ../vim-8.2.0682/src/proto/vim9execute.pro 2020-01-26 15:52:33.023833239
+0100
--- src/proto/vim9execute.pro 2020-05-02 22:50:30.310558993 +0200
***************
*** 1,6 ****
/* vim9execute.c */
! int call_def_function(ufunc_T *ufunc, int argc, typval_T *argv, typval_T
*rettv);
void ex_disassemble(exarg_T *eap);
int tv2bool(typval_T *tv);
int check_not_string(typval_T *tv);
/* vim: set ft=c : */
--- 1,7 ----
/* vim9execute.c */
! int call_def_function(ufunc_T *ufunc, int argc_arg, typval_T *argv, typval_T
*rettv);
void ex_disassemble(exarg_T *eap);
int tv2bool(typval_T *tv);
int check_not_string(typval_T *tv);
+ int set_ref_in_dfunc(ufunc_T *ufunc, int copyID);
/* vim: set ft=c : */
*** ../vim-8.2.0682/src/userfunc.c 2020-05-01 19:29:05.006157706 +0200
--- src/userfunc.c 2020-05-02 23:00:23.236805855 +0200
***************
*** 4392,4397 ****
--- 4392,4399 ----
fp = HI2UF(hi);
if (!func_name_refcount(fp->uf_name))
abort = abort || set_ref_in_func(NULL, fp, copyID);
+ else if (fp->uf_dfunc_idx >= 0)
+ abort = abort || set_ref_in_dfunc(fp, copyID);
}
}
return abort;
***************
*** 4439,4445 ****
--- 4441,4450 ----
{
for (fc = fp->uf_scoped; fc != NULL; fc = fc->func->uf_scoped)
abort = abort || set_ref_in_funccal(fc, copyID);
+ if (fp->uf_dfunc_idx >= 0)
+ abort = abort || set_ref_in_dfunc(fp, copyID);
}
+
vim_free(tofree);
return abort;
}
*** ../vim-8.2.0682/src/testdir/test_vim9_func.vim 2020-05-02
19:04:55.497402088 +0200
--- src/testdir/test_vim9_func.vim 2020-05-02 23:08:10.047352870 +0200
***************
*** 662,666 ****
--- 662,710 ----
unlet g:Ref
enddef
+ def MakeTwoRefs()
+ let local = ['some']
+ g:Extend = {s -> local->add(s)}
+ g:Read = {-> local}
+ enddef
+
+ def Test_closure_two_refs()
+ MakeTwoRefs()
+ assert_equal('some', join(g:Read(), ' '))
+ g:Extend('more')
+ assert_equal('some more', join(g:Read(), ' '))
+ g:Extend('even')
+ assert_equal('some more even', join(g:Read(), ' '))
+
+ unlet g:Extend
+ unlet g:Read
+ enddef
+
+ " TODO: fix memory leak when using same function again.
+ def MakeTwoRefs_2()
+ let local = ['some']
+ g:Extend = {s -> local->add(s)}
+ g:Read = {-> local}
+ enddef
+
+ def ReadRef(Ref: func(): list<string>): string
+ return join(Ref(), ' ')
+ enddef
+
+ def ExtendRef(Ref: func(string), add: string)
+ Ref(add)
+ enddef
+
+ def Test_closure_two_indirect_refs()
+ MakeTwoRefs_2()
+ assert_equal('some', ReadRef(g:Read))
+ ExtendRef(g:Extend, 'more')
+ assert_equal('some more', ReadRef(g:Read))
+ ExtendRef(g:Extend, 'even')
+ assert_equal('some more even', ReadRef(g:Read))
+
+ unlet g:Extend
+ unlet g:Read
+ enddef
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
*** ../vim-8.2.0682/src/version.c 2020-05-02 19:04:55.497402088 +0200
--- src/version.c 2020-05-02 19:12:36.067894408 +0200
***************
*** 748,749 ****
--- 748,751 ----
{ /* Add new patch number below this line */
+ /**/
+ 683,
/**/
--
Nothing is fool-proof to a sufficiently talented fool.
/// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/vim_dev/202005022113.042LDaDK004432%40masaka.moolenaar.net.