To: vim_dev@googlegroups.com Subject: Patch 8.2.0517 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.0517 Problem: Vim9: cannot separate "func" and "func(): void". Solution: Use VAR_ANY for "any" and VAR_UNKNOWN for "no type". Files: src/structs.h, src/globals.h, src/eval.c, src/evalfunc.c, src/evalvars.c, src/testing.c, src/vim9compile.c, src/vim9execute.c, src/viminfo.c, src/if_py_both.h, src/json.c, src/testdir/test_vim9_func.vim *** ../vim-8.2.0516/src/structs.h 2020-04-05 17:07:59.414556253 +0200 --- src/structs.h 2020-04-05 20:52:39.912621416 +0200 *************** *** 1321,1328 **** typedef enum { ! VAR_UNKNOWN = 0, // not set, also used for "any" type ! VAR_VOID, // no value VAR_BOOL, // "v_number" is used: VVAL_TRUE or VVAL_FALSE VAR_SPECIAL, // "v_number" is used: VVAL_NULL or VVAL_NONE VAR_NUMBER, // "v_number" is used --- 1321,1329 ---- typedef enum { ! VAR_UNKNOWN = 0, // not set, any type or "void" allowed ! VAR_ANY, // used for "any" type ! VAR_VOID, // no value (function not returning anything) VAR_BOOL, // "v_number" is used: VVAL_TRUE or VVAL_FALSE VAR_SPECIAL, // "v_number" is used: VVAL_NULL or VVAL_NONE VAR_NUMBER, // "v_number" is used *** ../vim-8.2.0516/src/globals.h 2020-04-05 17:07:59.414556253 +0200 --- src/globals.h 2020-04-05 20:56:05.731770278 +0200 *************** *** 379,385 **** // Commonly used types. ! EXTERN type_T t_any INIT6(VAR_UNKNOWN, 0, 0, 0, NULL, NULL); EXTERN type_T t_void INIT6(VAR_VOID, 0, 0, 0, NULL, NULL); EXTERN type_T t_bool INIT6(VAR_BOOL, 0, 0, 0, NULL, NULL); EXTERN type_T t_special INIT6(VAR_SPECIAL, 0, 0, 0, NULL, NULL); --- 379,386 ---- // Commonly used types. ! EXTERN type_T t_unknown INIT6(VAR_UNKNOWN, 0, 0, 0, NULL, NULL); ! EXTERN type_T t_any INIT6(VAR_ANY, 0, 0, 0, NULL, NULL); EXTERN type_T t_void INIT6(VAR_VOID, 0, 0, 0, NULL, NULL); EXTERN type_T t_bool INIT6(VAR_BOOL, 0, 0, 0, NULL, NULL); EXTERN type_T t_special INIT6(VAR_SPECIAL, 0, 0, 0, NULL, NULL); *************** *** 390,395 **** --- 391,397 ---- EXTERN type_T t_job INIT6(VAR_JOB, 0, 0, 0, NULL, NULL); EXTERN type_T t_channel INIT6(VAR_CHANNEL, 0, 0, 0, NULL, NULL); + EXTERN type_T t_func_unknown INIT6(VAR_FUNC, -1, 0, 0, &t_unknown, NULL); EXTERN type_T t_func_void INIT6(VAR_FUNC, -1, 0, 0, &t_void, NULL); EXTERN type_T t_func_any INIT6(VAR_FUNC, -1, 0, 0, &t_any, NULL); EXTERN type_T t_func_number INIT6(VAR_FUNC, -1, 0, 0, &t_number, NULL); *************** *** 401,408 **** EXTERN type_T t_list_any INIT6(VAR_LIST, 0, 0, 0, &t_any, NULL); EXTERN type_T t_dict_any INIT6(VAR_DICT, 0, 0, 0, &t_any, NULL); ! EXTERN type_T t_list_empty INIT6(VAR_LIST, 0, 0, 0, &t_void, NULL); ! EXTERN type_T t_dict_empty INIT6(VAR_DICT, 0, 0, 0, &t_void, NULL); EXTERN type_T t_list_bool INIT6(VAR_LIST, 0, 0, 0, &t_bool, NULL); EXTERN type_T t_list_number INIT6(VAR_LIST, 0, 0, 0, &t_number, NULL); --- 403,410 ---- EXTERN type_T t_list_any INIT6(VAR_LIST, 0, 0, 0, &t_any, NULL); EXTERN type_T t_dict_any INIT6(VAR_DICT, 0, 0, 0, &t_any, NULL); ! EXTERN type_T t_list_empty INIT6(VAR_LIST, 0, 0, 0, &t_unknown, NULL); ! EXTERN type_T t_dict_empty INIT6(VAR_DICT, 0, 0, 0, &t_unknown, NULL); EXTERN type_T t_list_bool INIT6(VAR_LIST, 0, 0, 0, &t_bool, NULL); EXTERN type_T t_list_number INIT6(VAR_LIST, 0, 0, 0, &t_number, NULL); *** ../vim-8.2.0516/src/eval.c 2020-04-02 18:50:42.419773128 +0200 --- src/eval.c 2020-04-05 21:04:58.161555942 +0200 *************** *** 1272,1277 **** --- 1272,1278 ---- switch (tv1->v_type) { case VAR_UNKNOWN: + case VAR_ANY: case VAR_VOID: case VAR_DICT: case VAR_FUNC: *************** *** 2967,2972 **** --- 2968,2974 ---- emsg(_("E909: Cannot index a special variable")); return FAIL; case VAR_UNKNOWN: + case VAR_ANY: case VAR_VOID: if (evaluate) return FAIL; *************** *** 3073,3078 **** --- 3075,3081 ---- switch (rettv->v_type) { case VAR_UNKNOWN: + case VAR_ANY: case VAR_VOID: case VAR_FUNC: case VAR_PARTIAL: *************** *** 3668,3674 **** } /* ! * Return the function name of the partial. */ char_u * partial_name(partial_T *pt) --- 3671,3677 ---- } /* ! * Return the function name of partial "pt". */ char_u * partial_name(partial_T *pt) *************** *** 3856,3861 **** --- 3859,3865 ---- return tv1->vval.v_string == tv2->vval.v_string; case VAR_UNKNOWN: + case VAR_ANY: case VAR_VOID: break; } *************** *** 4570,4575 **** --- 4574,4580 ---- case VAR_NUMBER: case VAR_UNKNOWN: + case VAR_ANY: case VAR_VOID: *tofree = NULL; r = tv_get_string_buf(tv, numbuf); *************** *** 5422,5427 **** --- 5427,5433 ---- #endif case VAR_NUMBER: case VAR_FLOAT: + case VAR_ANY: case VAR_UNKNOWN: case VAR_VOID: case VAR_BOOL: *************** *** 5486,5491 **** --- 5492,5498 ---- varp->vval.v_channel = NULL; #endif case VAR_UNKNOWN: + case VAR_ANY: case VAR_VOID: break; } *************** *** 5565,5570 **** --- 5572,5578 ---- emsg(_("E974: Using a Blob as a Number")); break; case VAR_UNKNOWN: + case VAR_ANY: case VAR_VOID: internal_error_no_abort("tv_get_number(UNKNOWN)"); break; *************** *** 5619,5624 **** --- 5627,5633 ---- emsg(_("E975: Using a Blob as a Float")); break; case VAR_UNKNOWN: + case VAR_ANY: case VAR_VOID: internal_error_no_abort("tv_get_float(UNKNOWN)"); break; *************** *** 5742,5747 **** --- 5751,5757 ---- #endif break; case VAR_UNKNOWN: + case VAR_ANY: case VAR_VOID: emsg(_(e_inval_string)); break; *************** *** 5891,5896 **** --- 5901,5907 ---- } break; case VAR_UNKNOWN: + case VAR_ANY: case VAR_VOID: internal_error_no_abort("copy_tv(UNKNOWN)"); break; *************** *** 5970,5975 **** --- 5981,5987 ---- ret = FAIL; break; case VAR_UNKNOWN: + case VAR_ANY: case VAR_VOID: internal_error_no_abort("item_copy(UNKNOWN)"); ret = FAIL; *** ../vim-8.2.0516/src/evalfunc.c 2020-04-05 20:20:40.104596563 +0200 --- src/evalfunc.c 2020-04-05 20:59:04.499028317 +0200 *************** *** 2042,2047 **** --- 2042,2048 ---- break; #endif case VAR_UNKNOWN: + case VAR_ANY: case VAR_VOID: internal_error_no_abort("f_empty(UNKNOWN)"); n = TRUE; *************** *** 5217,5222 **** --- 5218,5224 ---- rettv->vval.v_number = dict_len(argvars[0].vval.v_dict); break; case VAR_UNKNOWN: + case VAR_ANY: case VAR_VOID: case VAR_BOOL: case VAR_SPECIAL: *************** *** 8805,8810 **** --- 8807,8813 ---- case VAR_CHANNEL: n = VAR_TYPE_CHANNEL; break; case VAR_BLOB: n = VAR_TYPE_BLOB; break; case VAR_UNKNOWN: + case VAR_ANY: case VAR_VOID: internal_error_no_abort("f_type(UNKNOWN)"); n = -1; *** ../vim-8.2.0516/src/evalvars.c 2020-04-05 18:56:02.233436590 +0200 --- src/evalvars.c 2020-04-05 20:59:11.638998638 +0200 *************** *** 1668,1673 **** --- 1668,1674 ---- switch (tv->v_type) { case VAR_UNKNOWN: + case VAR_ANY: case VAR_VOID: case VAR_NUMBER: case VAR_BOOL: *** ../vim-8.2.0516/src/testing.c 2020-04-01 22:10:56.428201257 +0200 --- src/testing.c 2020-04-05 20:59:29.034926341 +0200 *************** *** 764,769 **** --- 764,770 ---- switch (argvars[0].v_type) { case VAR_UNKNOWN: + case VAR_ANY: case VAR_VOID: case VAR_NUMBER: case VAR_BOOL: *** ../vim-8.2.0516/src/vim9compile.c 2020-04-05 19:09:02.134503484 +0200 --- src/vim9compile.c 2020-04-05 21:29:13.304105938 +0200 *************** *** 249,257 **** type_T *type; // recognize commonly used types ! if (member_type->tt_type == VAR_UNKNOWN) return &t_list_any; ! if (member_type->tt_type == VAR_VOID) return &t_list_empty; if (member_type->tt_type == VAR_BOOL) return &t_list_bool; --- 249,258 ---- type_T *type; // recognize commonly used types ! if (member_type->tt_type == VAR_ANY) return &t_list_any; ! if (member_type->tt_type == VAR_VOID ! || member_type->tt_type == VAR_UNKNOWN) return &t_list_empty; if (member_type->tt_type == VAR_BOOL) return &t_list_bool; *************** *** 277,285 **** type_T *type; // recognize commonly used types ! if (member_type->tt_type == VAR_UNKNOWN) return &t_dict_any; ! if (member_type->tt_type == VAR_VOID) return &t_dict_empty; if (member_type->tt_type == VAR_BOOL) return &t_dict_bool; --- 278,287 ---- type_T *type; // recognize commonly used types ! if (member_type->tt_type == VAR_ANY) return &t_dict_any; ! if (member_type->tt_type == VAR_VOID ! || member_type->tt_type == VAR_UNKNOWN) return &t_dict_empty; if (member_type->tt_type == VAR_BOOL) return &t_dict_bool; *************** *** 482,490 **** static int check_number_or_float(vartype_T type1, vartype_T type2, char_u *op) { ! if (!((type1 == VAR_NUMBER || type1 == VAR_FLOAT || type1 == VAR_UNKNOWN) && (type2 == VAR_NUMBER || type2 == VAR_FLOAT ! || type2 == VAR_UNKNOWN))) { if (*op == '+') emsg(_("E1035: wrong argument type for +")); --- 484,492 ---- static int check_number_or_float(vartype_T type1, vartype_T type2, char_u *op) { ! if (!((type1 == VAR_NUMBER || type1 == VAR_FLOAT || type1 == VAR_ANY) && (type2 == VAR_NUMBER || type2 == VAR_FLOAT ! || type2 == VAR_ANY))) { if (*op == '+') emsg(_("E1035: wrong argument type for +")); *************** *** 515,521 **** // checking. type1 = ((type_T **)stack->ga_data)[stack->ga_len - 2]; type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1]; ! vartype = VAR_UNKNOWN; if (type1->tt_type == type2->tt_type && (type1->tt_type == VAR_NUMBER || type1->tt_type == VAR_LIST --- 517,523 ---- // checking. type1 = ((type_T **)stack->ga_data)[stack->ga_len - 2]; type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1]; ! vartype = VAR_ANY; if (type1->tt_type == type2->tt_type && (type1->tt_type == VAR_NUMBER || type1->tt_type == VAR_LIST *************** *** 528,535 **** switch (*op) { case '+': if (vartype != VAR_LIST && vartype != VAR_BLOB ! && type1->tt_type != VAR_UNKNOWN ! && type2->tt_type != VAR_UNKNOWN && check_number_or_float( type1->tt_type, type2->tt_type, op) == FAIL) return FAIL; --- 530,537 ---- switch (*op) { case '+': if (vartype != VAR_LIST && vartype != VAR_BLOB ! && type1->tt_type != VAR_ANY ! && type2->tt_type != VAR_ANY && check_number_or_float( type1->tt_type, type2->tt_type, op) == FAIL) return FAIL; *************** *** 563,571 **** ? EXPR_MULT : *op == '/'? EXPR_DIV : EXPR_SUB; break; ! case '%': if ((type1->tt_type != VAR_UNKNOWN && type1->tt_type != VAR_NUMBER) ! || (type2->tt_type != VAR_UNKNOWN && type2->tt_type != VAR_NUMBER)) { emsg(_("E1035: % requires number arguments")); --- 565,573 ---- ? EXPR_MULT : *op == '/'? EXPR_DIV : EXPR_SUB; break; ! case '%': if ((type1->tt_type != VAR_ANY && type1->tt_type != VAR_NUMBER) ! || (type2->tt_type != VAR_ANY && type2->tt_type != VAR_NUMBER)) { emsg(_("E1035: % requires number arguments")); *************** *** 579,585 **** } // correct type of result ! if (vartype == VAR_UNKNOWN) { type_T *type = &t_any; --- 581,587 ---- } // correct type of result ! if (vartype == VAR_ANY) { type_T *type = &t_any; *************** *** 614,619 **** --- 616,626 ---- // checking. type1 = ((type_T **)stack->ga_data)[stack->ga_len - 2]->tt_type; type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1]->tt_type; + if (type1 == VAR_UNKNOWN) + type1 = VAR_ANY; + if (type2 == VAR_UNKNOWN) + type2 = VAR_ANY; + if (type1 == type2) { switch (type1) *************** *** 631,637 **** default: isntype = ISN_COMPAREANY; break; } } ! else if (type1 == VAR_UNKNOWN || type2 == VAR_UNKNOWN || ((type1 == VAR_NUMBER || type1 == VAR_FLOAT) && (type2 == VAR_NUMBER || type2 ==VAR_FLOAT))) isntype = ISN_COMPAREANY; --- 638,644 ---- default: isntype = ISN_COMPAREANY; break; } } ! else if (type1 == VAR_ANY || type2 == VAR_ANY || ((type1 == VAR_NUMBER || type1 == VAR_FLOAT) && (type2 == VAR_NUMBER || type2 ==VAR_FLOAT))) isntype = ISN_COMPAREANY; *************** *** 1723,1730 **** return FALSE; switch (type1->tt_type) { - case VAR_VOID: case VAR_UNKNOWN: case VAR_SPECIAL: case VAR_BOOL: case VAR_NUMBER: --- 1730,1738 ---- return FALSE; switch (type1->tt_type) { case VAR_UNKNOWN: + case VAR_ANY: + case VAR_VOID: case VAR_SPECIAL: case VAR_BOOL: case VAR_NUMBER: *************** *** 1785,1790 **** --- 1793,1799 ---- switch (type) { case VAR_UNKNOWN: break; + case VAR_ANY: return "any"; case VAR_VOID: return "void"; case VAR_SPECIAL: return "special"; case VAR_BOOL: return "bool"; *************** *** 1799,1805 **** case VAR_FUNC: return "func"; case VAR_PARTIAL: return "partial"; } ! return "any"; } /* --- 1808,1814 ---- case VAR_FUNC: return "func"; case VAR_PARTIAL: return "partial"; } ! return "unknown"; } /* *************** *** 2396,2402 **** { int ret = OK; ! if (expected->tt_type != VAR_UNKNOWN) { if (expected->tt_type != actual->tt_type) { --- 2405,2411 ---- { int ret = OK; ! if (expected->tt_type != VAR_UNKNOWN && expected->tt_type != VAR_ANY) { if (expected->tt_type != actual->tt_type) { *************** *** 2406,2418 **** } if (expected->tt_type == VAR_DICT || expected->tt_type == VAR_LIST) { ! // void is used for an empty list or dict ! if (actual->tt_member != &t_void) ret = check_type(expected->tt_member, actual->tt_member, FALSE); } else if (expected->tt_type == VAR_FUNC) { ! if (expected->tt_member != &t_any) ret = check_type(expected->tt_member, actual->tt_member, FALSE); if (ret == OK && expected->tt_argcount != -1 && (actual->tt_argcount < expected->tt_min_argcount --- 2415,2428 ---- } if (expected->tt_type == VAR_DICT || expected->tt_type == VAR_LIST) { ! // "unknown" is used for an empty list or dict ! if (actual->tt_member != &t_unknown) ret = check_type(expected->tt_member, actual->tt_member, FALSE); } 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 *************** *** 2436,2442 **** { if (check_type(expected, actual, FALSE)) return OK; ! if (actual->tt_type != VAR_UNKNOWN) { type_mismatch(expected, actual); return FAIL; --- 2446,2452 ---- { if (check_type(expected, actual, FALSE)) return OK; ! if (actual->tt_type != VAR_ANY && actual->tt_type != VAR_UNKNOWN) { type_mismatch(expected, actual); return FAIL; *************** *** 3642,3648 **** { // "set_return_type" cannot be TRUE, only used for a lambda which // always has an argument. ! if (cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_VOID) { emsg(_("E1003: Missing return value")); return NULL; --- 3652,3659 ---- { // "set_return_type" cannot be TRUE, only used for a lambda which // always has an argument. ! if (cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_VOID ! && cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_UNKNOWN) { emsg(_("E1003: Missing return value")); return NULL; *************** *** 3936,3942 **** } if (oplen == 3 && !heredoc && dest != dest_global ! && type->tt_type != VAR_STRING && type->tt_type != VAR_UNKNOWN) { emsg(_("E1019: Can only concatenate to string")); goto theend; --- 3947,3953 ---- } if (oplen == 3 && !heredoc && dest != dest_global ! && type->tt_type != VAR_STRING && type->tt_type != VAR_ANY) { emsg(_("E1019: Can only concatenate to string")); goto theend; *************** *** 4115,4120 **** --- 4126,4132 ---- break; case VAR_NUMBER: case VAR_UNKNOWN: + case VAR_ANY: case VAR_VOID: case VAR_SPECIAL: // cannot happen generate_PUSHNR(cctx, 0); *************** *** 4903,4909 **** drop_scope(cctx); return NULL; } ! if (vartype->tt_member->tt_type != VAR_UNKNOWN) { lvar_T *lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + var_idx; --- 4915,4921 ---- drop_scope(cctx); return NULL; } ! if (vartype->tt_member->tt_type != VAR_ANY) { lvar_T *lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + var_idx; *** ../vim-8.2.0516/src/vim9execute.c 2020-04-05 17:07:59.414556253 +0200 --- src/vim9execute.c 2020-04-05 21:02:17.074227176 +0200 *************** *** 2239,2244 **** --- 2239,2245 ---- case VAR_BLOB: return tv->vval.v_blob != NULL && tv->vval.v_blob->bv_ga.ga_len > 0; case VAR_UNKNOWN: + case VAR_ANY: case VAR_VOID: break; } *** ../vim-8.2.0516/src/viminfo.c 2020-03-23 22:12:15.496961030 +0100 --- src/viminfo.c 2020-04-05 21:02:33.234159874 +0200 *************** *** 1344,1349 **** --- 1344,1350 ---- case VAR_SPECIAL: s = "XPL"; break; case VAR_UNKNOWN: + case VAR_ANY: case VAR_VOID: case VAR_FUNC: case VAR_PARTIAL: *** ../vim-8.2.0516/src/if_py_both.h 2020-04-02 18:50:42.423773112 +0200 --- src/if_py_both.h 2020-04-05 21:02:40.294130478 +0200 *************** *** 6390,6395 **** --- 6390,6396 ---- (char*) tv->vval.v_blob->bv_ga.ga_data, (Py_ssize_t) tv->vval.v_blob->bv_ga.ga_len); case VAR_UNKNOWN: + case VAR_ANY: case VAR_VOID: case VAR_CHANNEL: case VAR_JOB: *** ../vim-8.2.0516/src/json.c 2020-02-29 17:38:08.866485874 +0100 --- src/json.c 2020-04-05 21:03:09.222009967 +0200 *************** *** 351,356 **** --- 351,357 ---- break; #endif case VAR_UNKNOWN: + case VAR_ANY: case VAR_VOID: internal_error_no_abort("json_encode_item()"); return FAIL; *** ../vim-8.2.0516/src/testdir/test_vim9_func.vim 2020-04-05 17:07:59.418556237 +0200 --- src/testdir/test_vim9_func.vim 2020-04-05 21:33:50.235007998 +0200 *************** *** 386,391 **** --- 386,412 ---- Ref1 = FuncNoArgNoRet Ref1() assert_equal(11, funcResult) + + let Ref2: func + funcResult = 0 + Ref2 = FuncNoArgNoRet + Ref2() + assert_equal(11, funcResult) + + funcResult = 0 + Ref2 = FuncOneArgNoRet + Ref2(12) + assert_equal(12, funcResult) + + funcResult = 0 + Ref2 = FuncNoArgRetNumber + assert_equal(1234, Ref2()) + assert_equal(22, funcResult) + + funcResult = 0 + Ref2 = FuncOneArgRetNumber + assert_equal(13, Ref2(13)) + assert_equal(13, funcResult) enddef def Test_func_type_fails() *** ../vim-8.2.0516/src/version.c 2020-04-05 20:20:40.104596563 +0200 --- src/version.c 2020-04-05 21:34:15.006909207 +0200 *************** *** 740,741 **** --- 740,743 ---- { /* Add new patch number below this line */ + /**/ + 517, /**/ -- The Law, in its majestic equality, forbids the rich, as well as the poor, to sleep under the bridges, to beg in the streets, and to steal bread. -- Anatole France /// 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 ///