To: vim_dev@googlegroups.com Subject: Patch 8.2.0683 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ 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 + 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 -- Bram@Moolenaar.net -- 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 ///