To: vim_dev@googlegroups.com Subject: Patch 8.2.0527 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.0527 Problem: Vim9: function types insufficiently tested. Solution: Add more tests. Fix white space check. Add "test_vim9" target. Files: src/vim9compile.c, src/testdir/test_vim9_func.vim, src/Makefile, src/testdir/Makefile, src/testdir/Make_all.mak *** ../vim-8.2.0526/src/vim9compile.c 2020-04-06 22:12:57.145652827 +0200 --- src/vim9compile.c 2020-04-07 20:33:18.943457072 +0200 *************** *** 314,319 **** --- 314,324 ---- // recognize commonly used types if (argcount <= 0) { + if (ret_type == &t_unknown) + { + // (argcount == 0) is not possible + return &t_func_unknown; + } if (ret_type == &t_void) { if (argcount == 0) *************** *** 350,355 **** --- 355,361 ---- return &t_any; type->tt_type = VAR_FUNC; type->tt_member = ret_type; + type->tt_argcount = argcount; type->tt_args = NULL; return type; } *************** *** 1589,1595 **** if (len == 4 && STRNCMP(*arg, "func", len) == 0) { type_T *type; ! type_T *ret_type = &t_any; int argcount = -1; int flags = 0; int first_optional = -1; --- 1595,1601 ---- if (len == 4 && STRNCMP(*arg, "func", len) == 0) { type_T *type; ! type_T *ret_type = &t_unknown; int argcount = -1; int flags = 0; int first_optional = -1; *************** *** 1657,1663 **** { // parse return type ++*arg; ! if (!VIM_ISWHITE(*p)) semsg(_(e_white_after), ":"); *arg = skipwhite(*arg); ret_type = parse_type(arg, type_gap); --- 1663,1669 ---- { // parse return type ++*arg; ! if (!VIM_ISWHITE(**arg)) semsg(_(e_white_after), ":"); *arg = skipwhite(*arg); ret_type = parse_type(arg, type_gap); *************** *** 2405,2411 **** { int ret = OK; ! if (expected->tt_type != VAR_UNKNOWN && expected->tt_type != VAR_ANY) { if (expected->tt_type != actual->tt_type) { --- 2411,2420 ---- { int ret = OK; ! // When expected is "unknown" we accept any actual type. ! // When expected is "any" we accept any actual type except "void". ! if (expected->tt_type != VAR_UNKNOWN ! && (expected->tt_type != VAR_ANY || actual->tt_type == VAR_VOID)) { if (expected->tt_type != actual->tt_type) { *************** *** 2421,2428 **** } else if (expected->tt_type == VAR_FUNC) { ! if (expected->tt_member != &t_any ! && expected->tt_member != &t_unknown) ret = check_type(expected->tt_member, actual->tt_member, FALSE); if (ret == OK && expected->tt_argcount != -1 && (actual->tt_argcount < expected->tt_min_argcount --- 2430,2436 ---- } else if (expected->tt_type == VAR_FUNC) { ! if (expected->tt_member != &t_unknown) ret = check_type(expected->tt_member, actual->tt_member, FALSE); if (ret == OK && expected->tt_argcount != -1 && (actual->tt_argcount < expected->tt_min_argcount *************** *** 4044,4079 **** if (r == FAIL) goto theend; ! stack = &cctx->ctx_type_stack; ! stacktype = stack->ga_len == 0 ? &t_void ! : ((type_T **)stack->ga_data)[stack->ga_len - 1]; ! if (idx >= 0 && (is_decl || !has_type)) { ! lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx; ! if (new_local && !has_type) { ! if (stacktype->tt_type == VAR_VOID) ! { ! emsg(_("E1031: Cannot use void value")); ! goto theend; ! } ! else { ! // An empty list or dict has a &t_void member, for a ! // variable that implies &t_any. ! if (stacktype == &t_list_empty) ! lvar->lv_type = &t_list_any; ! else if (stacktype == &t_dict_empty) ! lvar->lv_type = &t_dict_any; else ! lvar->lv_type = stacktype; } } ! else if (need_type(stacktype, lvar->lv_type, -1, cctx) == FAIL) goto theend; } - else if (*p != '=' && check_type(type, stacktype, TRUE) == FAIL) - goto theend; } else if (cmdidx == CMD_const) { --- 4052,4090 ---- if (r == FAIL) goto theend; ! if (cctx->ctx_skip != TRUE) { ! stack = &cctx->ctx_type_stack; ! stacktype = stack->ga_len == 0 ? &t_void ! : ((type_T **)stack->ga_data)[stack->ga_len - 1]; ! if (idx >= 0 && (is_decl || !has_type)) { ! lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx; ! if (new_local && !has_type) { ! if (stacktype->tt_type == VAR_VOID) ! { ! emsg(_("E1031: Cannot use void value")); ! goto theend; ! } else ! { ! // An empty list or dict has a &t_void member, for a ! // variable that implies &t_any. ! if (stacktype == &t_list_empty) ! lvar->lv_type = &t_list_any; ! else if (stacktype == &t_dict_empty) ! lvar->lv_type = &t_dict_any; ! else ! lvar->lv_type = stacktype; ! } } + else if (need_type(stacktype, lvar->lv_type, -1, cctx) == FAIL) + goto theend; } ! else if (*p != '=' && check_type(type, stacktype, TRUE) == FAIL) goto theend; } } else if (cmdidx == CMD_const) { *** ../vim-8.2.0526/src/testdir/test_vim9_func.vim 2020-04-06 21:35:02.464237765 +0200 --- src/testdir/test_vim9_func.vim 2020-04-06 23:44:45.188546833 +0200 *************** *** 373,378 **** --- 373,383 ---- return 1234 enddef + def FuncNoArgRetString(): string + funcResult = 45 + return 'text' + enddef + def FuncOneArgNoRet(arg: number) funcResult = arg enddef *************** *** 382,387 **** --- 387,396 ---- return arg enddef + def FuncOneArgRetString(arg: string): string + return arg + enddef + def FuncOneArgRetAny(arg: any): any return arg enddef *************** *** 415,420 **** --- 424,455 ---- assert_equal(13, funcResult) enddef + def Test_func_type_part() + let RefVoid: func: void + RefVoid = FuncNoArgNoRet + RefVoid = FuncOneArgNoRet + CheckDefFailure(['let RefVoid: func: void', 'RefVoid = FuncNoArgRetNumber'], 'E1013: type mismatch, expected func() but got func(): number') + CheckDefFailure(['let RefVoid: func: void', 'RefVoid = FuncNoArgRetString'], 'E1013: type mismatch, expected func() but got func(): string') + + let RefAny: func(): any + RefAny = FuncNoArgRetNumber + RefAny = FuncNoArgRetString + CheckDefFailure(['let RefAny: func(): any', 'RefAny = FuncNoArgNoRet'], 'E1013: type mismatch, expected func(): any but got func()') + CheckDefFailure(['let RefAny: func(): any', 'RefAny = FuncOneArgNoRet'], 'E1013: type mismatch, expected func(): any but got func(number)') + + let RefNr: func: number + RefNr = FuncNoArgRetNumber + RefNr = FuncOneArgRetNumber + CheckDefFailure(['let RefNr: func: number', 'RefNr = FuncNoArgNoRet'], 'E1013: type mismatch, expected func(): number but got func()') + CheckDefFailure(['let RefNr: func: number', 'RefNr = FuncNoArgRetString'], 'E1013: type mismatch, expected func(): number but got func(): string') + + let RefStr: func: string + RefStr = FuncNoArgRetString + RefStr = FuncOneArgRetString + CheckDefFailure(['let RefStr: func: string', 'RefStr = FuncNoArgNoRet'], 'E1013: type mismatch, expected func(): string but got func()') + CheckDefFailure(['let RefStr: func: string', 'RefStr = FuncNoArgRetNumber'], 'E1013: type mismatch, expected func(): string but got func(): number') + enddef + def Test_func_type_fails() CheckDefFailure(['let ref1: func()'], 'E704:') *** ../vim-8.2.0526/src/Makefile 2020-04-05 20:20:40.100596581 +0200 --- src/Makefile 2020-04-07 20:40:46.881763609 +0200 *************** *** 2301,2307 **** # export TEST_FILTER=Test_terminal_wipe_buffer # A partial match also works: # export TEST_FILTER=wipe_buffer ! $(NEW_TESTS): cd testdir; $(MAKE) $@ VIMPROG=../$(VIMTESTTARGET) $(GUI_TESTARG) SCRIPTSOURCE=../$(SCRIPTSOURCE) newtests: --- 2301,2307 ---- # export TEST_FILTER=Test_terminal_wipe_buffer # A partial match also works: # export TEST_FILTER=wipe_buffer ! $(NEW_TESTS) test_vim9: cd testdir; $(MAKE) $@ VIMPROG=../$(VIMTESTTARGET) $(GUI_TESTARG) SCRIPTSOURCE=../$(SCRIPTSOURCE) newtests: *** ../vim-8.2.0526/src/testdir/Makefile 2020-02-20 22:34:59.264986542 +0100 --- src/testdir/Makefile 2020-04-07 20:49:29.091821932 +0200 *************** *** 78,83 **** --- 78,93 ---- @if test -f test.log; then \ exit 1; \ fi + + # Run only tests specific for Vim9 script + test_vim9: + rm -f test_vim9_*.res test.log messages + @MAKEFLAGS=--no-print-directory $(MAKE) -f Makefile $(TEST_VIM9_RES) VIMPROG=$(VIMPROG) XXDPROG=$(XXDPROG) SCRIPTSOURCE=$(SCRIPTSOURCE) + @cat messages + @MAKEFLAGS=--no-print-directory $(MAKE) -f Makefile report VIMPROG=$(VIMPROG) XXDPROG=$(XXDPROG) SCRIPTSOURCE=$(SCRIPTSOURCE) + @if test -f test.log; then \ + exit 1; \ + fi RM_ON_RUN = test.out X* viminfo RM_ON_START = tiny.vim small.vim mbyte.vim mzscheme.vim test.ok benchmark.out *** ../vim-8.2.0526/src/testdir/Make_all.mak 2020-04-05 23:04:53.664241873 +0200 --- src/testdir/Make_all.mak 2020-04-07 20:39:22.066081532 +0200 *************** *** 43,48 **** --- 43,61 ---- # Tests for the GUI. SCRIPTS_GUI = + # Tests for Vim9 script. + TEST_VIM9 = \ + test_vim9_disassemble \ + test_vim9_expr \ + test_vim9_func \ + test_vim9_script + + TEST_VIM9_RES = \ + test_vim9_disassemble.res \ + test_vim9_expr.res \ + test_vim9_func.res \ + test_vim9_script.res + # Individual tests, including the ones part of test_alot. # Please keep sorted up to test_alot. NEW_TESTS = \ *************** *** 272,281 **** test_utf8 \ test_utf8_comparisons \ test_vartabs \ ! test_vim9_disassemble \ ! test_vim9_expr \ ! test_vim9_func \ ! test_vim9_script \ test_viminfo \ test_vimscript \ test_virtualedit \ --- 285,291 ---- test_utf8 \ test_utf8_comparisons \ test_vartabs \ ! $(TEST_VIM9) \ test_viminfo \ test_vimscript \ test_virtualedit \ *************** *** 482,491 **** test_user_func.res \ test_usercommands.res \ test_vartabs.res \ ! test_vim9_disassemble.res \ ! test_vim9_expr.res \ ! test_vim9_func.res \ ! test_vim9_script.res \ test_viminfo.res \ test_vimscript.res \ test_virtualedit.res \ --- 492,498 ---- test_user_func.res \ test_usercommands.res \ test_vartabs.res \ ! $(TEST_VIM9_RES) \ test_viminfo.res \ test_vimscript.res \ test_virtualedit.res \ *** ../vim-8.2.0526/src/version.c 2020-04-07 19:57:26.043208340 +0200 --- src/version.c 2020-04-07 20:50:30.695593979 +0200 *************** *** 740,741 **** --- 740,743 ---- { /* Add new patch number below this line */ + /**/ + 527, /**/ -- Zen Microsystems: we're the om in .commmmmmmmm /// 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 ///