To: vim_dev@googlegroups.com Subject: Patch 8.2.1300 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.1300 Problem: Vim9: optional argument type not parsed properly. Solution: Skip over the "?". (issue #6507) Files: src/vim9compile.c, src/proto/vim9compile.pro, src/evalvars.c, src/userfunc.c, src/testdir/test_vim9_func.vim *** ../vim-8.2.1299/src/vim9compile.c 2020-07-25 19:30:55.111813216 +0200 --- src/vim9compile.c 2020-07-26 17:51:05.253603723 +0200 *************** *** 534,541 **** if (name != NULL) // TODO: how about a builtin function? ufunc = find_func(name, FALSE, NULL); ! if (ufunc != NULL && ufunc->uf_func_type != NULL) ! return ufunc->uf_func_type; } actual = alloc_type(type_gap); --- 534,549 ---- if (name != NULL) // TODO: how about a builtin function? ufunc = find_func(name, FALSE, NULL); ! if (ufunc != NULL) ! { ! // May need to get the argument types from default values by ! // compiling the function. ! if (ufunc->uf_def_status == UF_TO_BE_COMPILED ! && compile_def_function(ufunc, TRUE, NULL) == FAIL) ! return NULL; ! if (ufunc->uf_func_type != NULL) ! return ufunc->uf_func_type; ! } } actual = alloc_type(type_gap); *************** *** 1916,1927 **** /* * Skip over a type definition and return a pointer to just after it. */ char_u * ! skip_type(char_u *start) { char_u *p = start; while (ASCII_ISALNUM(*p) || *p == '_') ++p; --- 1924,1938 ---- /* * Skip over a type definition and return a pointer to just after it. + * When "optional" is TRUE then a leading "?" is accepted. */ char_u * ! skip_type(char_u *start, int optional) { char_u *p = start; + if (optional && *p == '?') + ++p; while (ASCII_ISALNUM(*p) || *p == '_') ++p; *************** *** 1929,1935 **** if (*skipwhite(p) == '<') { p = skipwhite(p); ! p = skip_type(skipwhite(p + 1)); p = skipwhite(p); if (*p == '>') ++p; --- 1940,1946 ---- if (*skipwhite(p) == '<') { p = skipwhite(p); ! p = skip_type(skipwhite(p + 1), FALSE); p = skipwhite(p); if (*p == '>') ++p; *************** *** 1945,1951 **** { char_u *sp = p; ! p = skip_type(p); if (p == sp) return p; // syntax error if (*p == ',') --- 1956,1962 ---- { char_u *sp = p; ! p = skip_type(p, TRUE); if (p == sp) return p; // syntax error if (*p == ',') *************** *** 1954,1960 **** if (*p == ')') { if (p[1] == ':') ! p = skip_type(skipwhite(p + 2)); else ++p; } --- 1965,1971 ---- if (*p == ')') { if (p[1] == ':') ! p = skip_type(skipwhite(p + 2), FALSE); else ++p; } *************** *** 1962,1968 **** else { // handle func: return_type ! p = skip_type(skipwhite(p + 1)); } } --- 1973,1979 ---- else { // handle func: return_type ! p = skip_type(skipwhite(p + 1), FALSE); } } *** ../vim-8.2.1299/src/proto/vim9compile.pro 2020-07-22 21:45:10.529629648 +0200 --- src/proto/vim9compile.pro 2020-07-26 17:19:28.745369328 +0200 *************** *** 6,12 **** int check_typval_type(type_T *expected, typval_T *actual_tv); int check_type(type_T *expected, type_T *actual, int give_msg); int check_compare_types(exptype_T type, typval_T *tv1, typval_T *tv2); ! char_u *skip_type(char_u *start); type_T *parse_type(char_u **arg, garray_T *type_gap); char *vartype_name(vartype_T type); char *type_name(type_T *type, char **tofree); --- 6,12 ---- int check_typval_type(type_T *expected, typval_T *actual_tv); int check_type(type_T *expected, type_T *actual, int give_msg); int check_compare_types(exptype_T type, typval_T *tv1, typval_T *tv2); ! char_u *skip_type(char_u *start, int optional); type_T *parse_type(char_u **arg, garray_T *type_gap); char *vartype_name(vartype_T type); char *type_name(type_T *type, char **tofree); *** ../vim-8.2.1299/src/evalvars.c 2020-07-23 17:16:15.046100627 +0200 --- src/evalvars.c 2020-07-26 17:18:18.397667886 +0200 *************** *** 1013,1019 **** if (end == arg + 2 && end[-1] == ':') --end; if (*end == ':') ! end = skip_type(skipwhite(end + 1)); } return end; } --- 1013,1019 ---- if (end == arg + 2 && end[-1] == ':') --end; if (*end == ':') ! end = skip_type(skipwhite(end + 1), FALSE); } return end; } *** ../vim-8.2.1299/src/userfunc.c 2020-07-25 15:41:04.408638663 +0200 --- src/userfunc.c 2020-07-26 17:19:18.109414478 +0200 *************** *** 123,129 **** return arg; } type = skipwhite(p); ! p = skip_type(type); type = vim_strnsave(type, p - type); } else if (*skipwhite(p) != '=') --- 123,129 ---- return arg; } type = skipwhite(p); ! p = skip_type(type, TRUE); type = vim_strnsave(type, p - type); } else if (*skipwhite(p) != '=') *************** *** 2778,2784 **** if (*p == ':') { ret_type = skipwhite(p + 1); ! p = skip_type(ret_type); if (p > ret_type) { ret_type = vim_strnsave(ret_type, p - ret_type); --- 2778,2784 ---- if (*p == ':') { ret_type = skipwhite(p + 1); ! p = skip_type(ret_type, FALSE); if (p > ret_type) { ret_type = vim_strnsave(ret_type, p - ret_type); *** ../vim-8.2.1299/src/testdir/test_vim9_func.vim 2020-07-25 16:32:58.679704392 +0200 --- src/testdir/test_vim9_func.vim 2020-07-26 17:54:41.016747500 +0200 *************** *** 350,355 **** --- 350,368 ---- let Funcref: func(string) = function('UseNumber') END CheckScriptFailure(lines, 'E1013: type mismatch, expected func(string) but got func(number)') + + lines =<< trim END + vim9script + def EchoNr(nr = 34) + g:echo = nr + enddef + let Funcref: func(?number) = function('EchoNr') + Funcref() + assert_equal(34, g:echo) + Funcref(123) + assert_equal(123, g:echo) + END + CheckScriptSuccess(lines) enddef let SomeFunc = function('len') *** ../vim-8.2.1299/src/version.c 2020-07-26 15:55:21.614845244 +0200 --- src/version.c 2020-07-26 17:13:48.178811251 +0200 *************** *** 756,757 **** --- 756,759 ---- { /* Add new patch number below this line */ + /**/ + 1300, /**/ -- From "know your smileys": :-)-O Smiling doctor with stethoscope /// 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 ///