To: vim_dev@googlegroups.com Subject: Patch 8.2.4115 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.4115 Problem: Cannot use a method with a complex expression. Solution: Evaluate the expression after "->" and use the result. Files: src/eval.c, src/errors.h, src/testdir/test_vim9_expr.vim *** ../vim-8.2.4114/src/eval.c 2022-01-16 14:51:26.434049441 +0000 --- src/eval.c 2022-01-16 19:30:15.990218003 +0000 *************** *** 3948,3953 **** --- 3948,3954 ---- char_u *name; long len; char_u *alias; + char_u *tofree = NULL; typval_T base = *rettv; int ret = OK; int evaluate = evalarg != NULL *************** *** 3968,4034 **** } else { ! if (**arg == '.') { ! int len2; ! char_u *fname; ! int idx; ! imported_T *import = find_imported(name, len, TRUE, ! evalarg == NULL ? NULL : evalarg->eval_cctx); ! type_T *type; ! ! // value->import.func() ! if (import != NULL) ! { ! name = NULL; ! ++*arg; ! fname = *arg; ! len2 = get_name_len(arg, &alias, evaluate, TRUE); ! if (len2 <= 0) { ! if (verbose) ! emsg(_(e_missing_name_after_dot)); ret = FAIL; } ! else if (evaluate) { ! int cc = fname[len2]; ! ufunc_T *ufunc; ! ! fname[len2] = NUL; ! idx = find_exported(import->imp_sid, fname, &ufunc, &type, ! evalarg->eval_cctx, verbose); ! fname[len2] = cc; ! ! if (idx >= 0) ! { ! scriptitem_T *si = SCRIPT_ITEM(import->imp_sid); ! svar_T *sv = ! ((svar_T *)si->sn_var_vals.ga_data) + idx; ! ! if (sv->sv_tv->v_type == VAR_FUNC ! && sv->sv_tv->vval.v_string != NULL) ! { ! name = sv->sv_tv->vval.v_string; ! len = STRLEN(name); ! } ! else ! { ! // TODO: how about a partial? ! if (verbose) ! semsg(_(e_not_callable_type_str), fname); ! ret = FAIL; ! } ! } ! else if (ufunc != NULL) { ! name = ufunc->uf_name; ! len = STRLEN(name); } else ! ret = FAIL; } } } if (ret == OK) --- 3969,4036 ---- } else { ! char_u *paren; ! ! // If there is no "(" immediately following, but there is further on, ! // it can be "import.Func()", "dict.Func()", "list[nr]", etc. ! // Does not handle anything where "(" is part of the expression. ! *arg = skipwhite(*arg); ! ! if (**arg != '(' && alias == NULL ! && (paren = vim_strchr(*arg, '(')) != NULL) { ! typval_T ref; ! ! *arg = name; ! *paren = NUL; ! ref.v_type = VAR_UNKNOWN; ! if (eval7(arg, &ref, evalarg, FALSE) == FAIL) ! { ! *arg = name + len; ! ret = FAIL; ! } ! else if (*skipwhite(*arg) != NUL) ! { ! if (verbose) ! semsg(_(e_trailing_characters_str), *arg); ! ret = FAIL; ! } ! else if (ref.v_type == VAR_FUNC && ref.vval.v_string != NULL) ! { ! name = ref.vval.v_string; ! ref.vval.v_string = NULL; ! tofree = name; ! len = STRLEN(name); ! } ! else if (ref.v_type == VAR_PARTIAL && ref.vval.v_partial != NULL) ! { ! if (ref.vval.v_partial->pt_argc > 0 ! || ref.vval.v_partial->pt_dict != NULL) { ! emsg(_(e_cannot_use_partial_here)); ret = FAIL; } ! else { ! name = vim_strsave(partial_name(ref.vval.v_partial)); ! tofree = name; ! if (name == NULL) { ! ret = FAIL; ! name = *arg; } else ! len = STRLEN(name); } } + else + { + if (verbose) + semsg(_(e_not_callable_type_str), name); + ret = FAIL; + } + clear_tv(&ref); + *paren = '('; } if (ret == OK) *************** *** 4057,4062 **** --- 4059,4065 ---- // evaluating the arguments is possible (see test55). if (evaluate) clear_tv(&base); + vim_free(tofree); return ret; } *** ../vim-8.2.4114/src/errors.h 2022-01-16 11:25:20.897661683 +0000 --- src/errors.h 2022-01-16 19:16:30.640672054 +0000 *************** *** 3212,3215 **** --- 3212,3217 ---- INIT(= N_("E1263: Using autoload in a script not under an autoload directory")); EXTERN char e_autoload_import_cannot_use_absolute_or_relative_path[] INIT(= N_("E1264: Autoload import cannot use absolute or relative path: %s")); + EXTERN char e_cannot_use_partial_here[] + INIT(= N_("E1265: Cannot use a partial here")); #endif *** ../vim-8.2.4114/src/testdir/test_vim9_expr.vim 2022-01-16 18:06:17.723808427 +0000 --- src/testdir/test_vim9_expr.vim 2022-01-16 19:35:24.146209984 +0000 *************** *** 3136,3151 **** var sorted = [3, 1, 2] -> sort() assert_equal([1, 2, 3], sorted) def SetNumber(n: number) g:number = n enddef const Setit = SetNumber len('text')->Setit() assert_equal(4, g:number) unlet g:number END ! CheckDefAndScriptSuccess(lines) lines =<< trim END def RetVoid() --- 3136,3172 ---- var sorted = [3, 1, 2] -> sort() assert_equal([1, 2, 3], sorted) + END + CheckDefAndScriptSuccess(lines) + lines =<< trim END + vim9script def SetNumber(n: number) g:number = n enddef const Setit = SetNumber len('text')->Setit() assert_equal(4, g:number) + + const SetFuncref = funcref(SetNumber) + len('longer')->SetFuncref() + assert_equal(6, g:number) + + const SetList = [SetNumber, SetFuncref] + len('xx')->SetList[0]() + assert_equal(2, g:number) + len('xxx')->SetList[1]() + assert_equal(3, g:number) + + const SetDict = {key: SetNumber} + len('xxxx')->SetDict['key']() + assert_equal(4, g:number) + len('xxxxx')->SetDict.key() + assert_equal(5, g:number) + unlet g:number END ! CheckScriptSuccess(lines) # TODO: CheckDefAndScriptSuccess() lines =<< trim END def RetVoid() *** ../vim-8.2.4114/src/version.c 2022-01-16 18:06:17.727808421 +0000 --- src/version.c 2022-01-16 19:37:37.198167497 +0000 *************** *** 752,753 **** --- 752,755 ---- { /* Add new patch number below this line */ + /**/ + 4115, /**/ -- CUSTOMER: You're not fooling anyone y'know. Look, isn't there something you can do? DEAD PERSON: I feel happy... I feel happy. [whop] CUSTOMER: Ah, thanks very much. MORTICIAN: Not at all. See you on Thursday. CUSTOMER: Right. The Quest for the Holy Grail (Monty Python) /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///