To: vim_dev@googlegroups.com Subject: Patch 8.2.5026 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.5026 Problem: Vim9: a few lines not covered by tests. Solution: Delete dead code. Add a few test cases. make "12->func()" work. Files: src/vim9type.c, src/ex_docmd.c, src/proto/ex_docmd.pro, src/vim9compile.c, src/testdir/test_vim9_assign.vim, src/testdir/test_vim9_func.vim *** ../vim-8.2.5025/src/vim9type.c 2022-05-22 13:45:47.749779044 +0100 --- src/vim9type.c 2022-05-26 22:21:46.262567229 +0100 *************** *** 244,291 **** /* * Get a function type, based on the return type "ret_type". ! * If "argcount" is -1 or 0 a predefined type can be used. ! * If "argcount" > 0 always create a new type, so that arguments can be added. */ type_T * get_func_type(type_T *ret_type, int argcount, garray_T *type_gap) { // recognize commonly used types ! if (argcount <= 0) { ! if (ret_type == &t_unknown || ret_type == NULL) ! { ! // (argcount == 0) is not possible ! return &t_func_unknown; ! } ! if (ret_type == &t_void) ! { ! if (argcount == 0) ! return &t_func_0_void; ! else ! return &t_func_void; ! } ! if (ret_type == &t_any) ! { ! if (argcount == 0) ! return &t_func_0_any; ! else ! return &t_func_any; ! } ! if (ret_type == &t_number) ! { ! if (argcount == 0) ! return &t_func_0_number; ! else ! return &t_func_number; ! } ! if (ret_type == &t_string) ! { ! if (argcount == 0) ! return &t_func_0_string; ! else ! return &t_func_string; ! } } return alloc_func_type(ret_type, argcount, type_gap); --- 244,287 ---- /* * Get a function type, based on the return type "ret_type". ! * "argcount" must be -1 or 0, a predefined type can be used. */ type_T * get_func_type(type_T *ret_type, int argcount, garray_T *type_gap) { // recognize commonly used types ! if (ret_type == &t_unknown || ret_type == NULL) { ! // (argcount == 0) is not possible ! return &t_func_unknown; ! } ! if (ret_type == &t_void) ! { ! if (argcount == 0) ! return &t_func_0_void; ! else ! return &t_func_void; ! } ! if (ret_type == &t_any) ! { ! if (argcount == 0) ! return &t_func_0_any; ! else ! return &t_func_any; ! } ! if (ret_type == &t_number) ! { ! if (argcount == 0) ! return &t_func_0_number; ! else ! return &t_func_number; ! } ! if (ret_type == &t_string) ! { ! if (argcount == 0) ! return &t_func_0_string; ! else ! return &t_func_string; } return alloc_func_type(ret_type, argcount, type_gap); *************** *** 541,547 **** { if (tv->v_type == VAR_LIST) // e.g. for v:oldfiles return &t_list_string; ! if (tv->v_type == VAR_DICT) // e.g. for v:completed_item return &t_dict_any; return typval2type(tv, get_copyID(), type_gap, TVTT_DO_MEMBER); } --- 537,543 ---- { if (tv->v_type == VAR_LIST) // e.g. for v:oldfiles return &t_list_string; ! if (tv->v_type == VAR_DICT) // e.g. for v:event return &t_dict_any; return typval2type(tv, get_copyID(), type_gap, TVTT_DO_MEMBER); } *************** *** 1441,1446 **** --- 1437,1443 ---- type_name(type_T *type, char **tofree) { char *name; + char *arg_free = NULL; *tofree = NULL; if (type == NULL) *************** *** 1469,1481 **** ga_init2(&ga, 1, 100); if (ga_grow(&ga, 20) == FAIL) ! return "[unknown]"; STRCPY(ga.ga_data, "func("); ga.ga_len += 5; for (i = 0; i < type->tt_argcount; ++i) { - char *arg_free = NULL; char *arg_type; int len; --- 1466,1477 ---- ga_init2(&ga, 1, 100); if (ga_grow(&ga, 20) == FAIL) ! goto failed; STRCPY(ga.ga_data, "func("); ga.ga_len += 5; for (i = 0; i < type->tt_argcount; ++i) { char *arg_type; int len; *************** *** 1490,1506 **** } len = (int)STRLEN(arg_type); if (ga_grow(&ga, len + 8) == FAIL) ! { ! vim_free(arg_free); ! ga_clear(&ga); ! return "[unknown]"; ! } if (varargs && i == type->tt_argcount - 1) ga_concat(&ga, (char_u *)"..."); else if (i >= type->tt_min_argcount) *((char *)ga.ga_data + ga.ga_len++) = '?'; ga_concat(&ga, (char_u *)arg_type); ! vim_free(arg_free); } if (type->tt_argcount < 0) // any number of arguments --- 1486,1498 ---- } len = (int)STRLEN(arg_type); if (ga_grow(&ga, len + 8) == FAIL) ! goto failed; if (varargs && i == type->tt_argcount - 1) ga_concat(&ga, (char_u *)"..."); else if (i >= type->tt_min_argcount) *((char *)ga.ga_data + ga.ga_len++) = '?'; ga_concat(&ga, (char_u *)arg_type); ! VIM_CLEAR(arg_free); } if (type->tt_argcount < 0) // any number of arguments *************** *** 1516,1532 **** len = (int)STRLEN(ret_name) + 4; if (ga_grow(&ga, len) == FAIL) ! { ! vim_free(ret_free); ! ga_clear(&ga); ! return "[unknown]"; ! } STRCPY((char *)ga.ga_data + ga.ga_len, "): "); STRCPY((char *)ga.ga_data + ga.ga_len + 3, ret_name); vim_free(ret_free); } *tofree = ga.ga_data; return ga.ga_data; } return name; --- 1508,1525 ---- len = (int)STRLEN(ret_name) + 4; if (ga_grow(&ga, len) == FAIL) ! goto failed; STRCPY((char *)ga.ga_data + ga.ga_len, "): "); STRCPY((char *)ga.ga_data + ga.ga_len + 3, ret_name); vim_free(ret_free); } *tofree = ga.ga_data; return ga.ga_data; + + failed: + vim_free(arg_free); + ga_clear(&ga); + return "[unknown]"; } return name; *** ../vim-8.2.5025/src/ex_docmd.c 2022-05-17 13:14:19.800706270 +0100 --- src/ex_docmd.c 2022-05-26 21:38:23.839998845 +0100 *************** *** 3507,3512 **** --- 3507,3524 ---- } /* + * Return TRUE if "cmd" starts with "123->", a number followed by a method + * call. + */ + int + number_method(char_u *cmd) + { + char_u *p = skipdigits(cmd); + + return p > cmd && (p = skipwhite(p))[0] == '-' && p[1] == '>'; + } + + /* * Find an Ex command by its name, either built-in or user. * Start of the name can be found at eap->cmd. * Sets eap->cmdidx and returns a pointer to char after the command name. *************** *** 3716,3721 **** --- 3728,3740 ---- } } + // 1234->func() is a method call + if (number_method(eap->cmd)) + { + eap->cmdidx = CMD_eval; + return eap->cmd; + } + // "g:", "s:" and "l:" are always assumed to be a variable, thus start // an expression. A global/substitute/list command needs to use a // longer name. *** ../vim-8.2.5025/src/proto/ex_docmd.pro 2022-04-28 17:52:19.532130311 +0100 --- src/proto/ex_docmd.pro 2022-05-26 21:38:28.171998368 +0100 *************** *** 17,22 **** --- 17,23 ---- void undo_cmdmod(cmdmod_T *cmod); int parse_cmd_address(exarg_T *eap, char **errormsg, int silent); char_u *skip_option_env_lead(char_u *start); + int number_method(char_u *cmd); char_u *find_ex_command(exarg_T *eap, int *full, int (*lookup)(char_u *, size_t, int cmd, cctx_T *), cctx_T *cctx); int modifier_len(char_u *cmd); int cmd_exists(char_u *name); *** ../vim-8.2.5025/src/vim9compile.c 2022-05-25 19:15:06.382288150 +0100 --- src/vim9compile.c 2022-05-26 21:38:51.303995575 +0100 *************** *** 3001,3006 **** --- 3001,3007 ---- * 0z1234->func() should not be confused with a zero line number * "++nr" and "--nr" are eval commands * in "$ENV->func()" the "$" is not a range + * "123->func()" is a method call */ cmd = ea.cmd; if ((*cmd != '$' || starts_with_colon) *************** *** 3008,3014 **** || !(*cmd == '\'' || (cmd[0] == '0' && cmd[1] == 'z') || (cmd[0] != NUL && cmd[0] == cmd[1] ! && (*cmd == '+' || *cmd == '-'))))) { ea.cmd = skip_range(ea.cmd, TRUE, NULL); if (ea.cmd > cmd) --- 3009,3016 ---- || !(*cmd == '\'' || (cmd[0] == '0' && cmd[1] == 'z') || (cmd[0] != NUL && cmd[0] == cmd[1] ! && (*cmd == '+' || *cmd == '-')) ! || number_method(cmd)))) { ea.cmd = skip_range(ea.cmd, TRUE, NULL); if (ea.cmd > cmd) *** ../vim-8.2.5025/src/testdir/test_vim9_assign.vim 2022-05-26 19:54:02.187958880 +0100 --- src/testdir/test_vim9_assign.vim 2022-05-26 22:17:30.766753420 +0100 *************** *** 1121,1126 **** --- 1121,1129 ---- var dict4: dict = {one: 1, two: '2'} var dict5: dict = {one: 0z01, two: 0z02} + # check the type is OK + var events: dict = v:event + # overwrite dict3['key'] = 'another' assert_equal(dict3, {key: 'another'}) *************** *** 2105,2110 **** --- 2108,2139 ---- va foo = 123 END v9.CheckDefAndScriptFailure(lines, 'E1065:', 1) + + lines =<< trim END + var foo: func(number + END + v9.CheckDefAndScriptFailure(lines, 'E110:', 1) + + lines =<< trim END + var foo: func(number): func( + END + v9.CheckDefAndScriptFailure(lines, 'E110:', 1) + + for type in ['num_ber', + 'anys', 'ani', + 'bools', 'boel', + 'blobs', 'blub', + 'channels', 'channol', + 'dicts', 'duct', + 'floats', 'floot', + 'funcs', 'funk', + 'jobs', 'jop', + 'lists', 'last' + 'numbers', 'numbar', + 'strings', 'strung', + 'voids', 'viod'] + v9.CheckDefAndScriptFailure([$'var foo: {type}'], 'E1010:', 1) + endfor enddef def Test_var_declaration_inferred() *************** *** 2118,2123 **** --- 2147,2180 ---- echo GetList()->extend(['x']) END v9.CheckScriptFailure(lines, 'E1013:', 6) + + lines =<< trim END + vim9script + def GetNr(): number + return 5 + enddef + def TestOne() + var some = [function('len'), GetNr] + g:res = typename(some) + enddef + TestOne() + assert_equal('list', g:res) + + def TestTwo() + var some = [function('len'), GetNr] + g:res = typename(some) + enddef + TestTwo() + assert_equal('list', g:res) + unlet g:res + + # FIXME: why is the type different? + var first = [function('len'), GetNr] + assert_equal('list', typename(first)) + var second = [GetNr, function('len')] + assert_equal('list', typename(second)) + END + v9.CheckScriptSuccess(lines) enddef def Test_script_local_in_legacy() *** ../vim-8.2.5025/src/testdir/test_vim9_func.vim 2022-05-22 13:45:47.749779044 +0100 --- src/testdir/test_vim9_func.vim 2022-05-26 21:27:44.140391584 +0100 *************** *** 4051,4056 **** --- 4051,4113 ---- echo [0, 1, 2]->map((_) => 123) END v9.CheckDefAndScriptFailure(lines, ['E176', 'E1106: One argument too many'], 1) + + lines =<< trim END + vim9script + def OneArgument(arg: string) + echo arg + enddef + var Ref = OneArgument + Ref('a', 'b') + END + v9.CheckScriptFailure(lines, 'E118:') + enddef + + def Test_funcref_with_base() + var lines =<< trim END + vim9script + def TwoArguments(str: string, nr: number) + echo str nr + enddef + var Ref = TwoArguments + Ref('a', 12) + 'b'->Ref(34) + END + v9.CheckScriptSuccess(lines) + + lines =<< trim END + vim9script + def TwoArguments(str: string, nr: number) + echo str nr + enddef + var Ref = TwoArguments + 'a'->Ref('b') + END + v9.CheckScriptFailure(lines, 'E1013: Argument 2: type mismatch, expected number but got string', 6) + + lines =<< trim END + vim9script + def TwoArguments(str: string, nr: number) + echo str nr + enddef + var Ref = TwoArguments + 123->Ref(456) + END + v9.CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected string but got number') + + lines =<< trim END + vim9script + def TwoArguments(nr: number, str: string) + echo str nr + enddef + var Ref = TwoArguments + 123->Ref('b') + def AndNowCompiled() + 456->Ref('x') + enddef + AndNowCompiled() + END + v9.CheckScriptSuccess(lines) enddef def Test_closing_brace_at_start_of_line() *** ../vim-8.2.5025/src/version.c 2022-05-26 19:54:02.187958880 +0100 --- src/version.c 2022-05-26 20:41:11.850465465 +0100 *************** *** 736,737 **** --- 736,739 ---- { /* Add new patch number below this line */ + /**/ + 5026, /**/ -- Luxury. We used to have to get out of the lake at three o'clock in the morning, clean the lake, eat a handful of hot gravel, go to work at the mill every day for tuppence a month, come home, and Dad would beat us around the head and neck with a broken bottle, if we were LUCKY! /// 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 ///