To: vim_dev@googlegroups.com Subject: Patch 8.2.3765 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.3765 Problem: Vim9: cannot use a lambda for 'opfunc' and others. Solution: Convert the lambda to a string. Files: src/vim9compile.c, src/vim9.h, src/vim9execute.c, src/testdir/test_vim9_func.vim, src/testdir/test_vim9_disassemble.vim *** ../vim-8.2.3764/src/vim9compile.c 2021-12-06 11:03:50.954900203 +0000 --- src/vim9compile.c 2021-12-09 12:56:26.816501876 +0000 *************** *** 118,123 **** --- 118,124 ---- typedef enum { dest_local, dest_option, + dest_func_option, dest_env, dest_global, dest_buffer, *************** *** 1412,1426 **** } /* ! * Generate an ISN_STOREOPT instruction */ static int ! generate_STOREOPT(cctx_T *cctx, char_u *name, int opt_flags) { isn_T *isn; RETURN_OK_IF_SKIP(cctx); ! if ((isn = generate_instr_drop(cctx, ISN_STOREOPT, 1)) == NULL) return FAIL; isn->isn_arg.storeopt.so_name = vim_strsave(name); isn->isn_arg.storeopt.so_flags = opt_flags; --- 1413,1431 ---- } /* ! * Generate an ISN_STOREOPT or ISN_STOREFUNCOPT instruction */ static int ! generate_STOREOPT( ! cctx_T *cctx, ! isntype_T isn_type, ! char_u *name, ! int opt_flags) { isn_T *isn; RETURN_OK_IF_SKIP(cctx); ! if ((isn = generate_instr_drop(cctx, isn_type, 1)) == NULL) return FAIL; isn->isn_arg.storeopt.so_name = vim_strsave(name); isn->isn_arg.storeopt.so_flags = opt_flags; *************** *** 5980,5985 **** --- 5985,5991 ---- switch (dest) { case dest_option: + case dest_func_option: generate_LOAD(cctx, ISN_LOADOPT, 0, name, type); break; case dest_global: *************** *** 6094,6099 **** --- 6100,6106 ---- int cc; long numval; getoption_T opt_type; + int opt_p_flags; *dest = dest_option; if (cmdidx == CMD_final || cmdidx == CMD_const) *************** *** 6112,6118 **** cc = *p; *p = NUL; opt_type = get_option_value(skip_option_env_lead(name), ! &numval, NULL, NULL, *option_scope); *p = cc; switch (opt_type) { --- 6119,6125 ---- cc = *p; *p = NUL; opt_type = get_option_value(skip_option_env_lead(name), ! &numval, NULL, &opt_p_flags, *option_scope); *p = cc; switch (opt_type) { *************** *** 6121,6127 **** return FAIL; case gov_string: case gov_hidden_string: ! *type = &t_string; break; case gov_bool: case gov_hidden_bool: --- 6128,6143 ---- return FAIL; case gov_string: case gov_hidden_string: ! if (opt_p_flags & P_FUNC) ! { ! // might be a Funcref, check the type later ! *type = &t_any; ! *dest = dest_func_option; ! } ! else ! { ! *type = &t_string; ! } break; case gov_bool: case gov_hidden_bool: *************** *** 6204,6211 **** switch (dest) { case dest_option: ! return generate_STOREOPT(cctx, skip_option_env_lead(name), ! opt_flags); case dest_global: // include g: with the name, easier to execute that way return generate_STORE(cctx, vim_strchr(name, AUTOLOAD_CHAR) == NULL --- 6220,6230 ---- switch (dest) { case dest_option: ! return generate_STOREOPT(cctx, ISN_STOREOPT, ! skip_option_env_lead(name), opt_flags); ! case dest_func_option: ! return generate_STOREOPT(cctx, ISN_STOREFUNCOPT, ! skip_option_env_lead(name), opt_flags); case dest_global: // include g: with the name, easier to execute that way return generate_STORE(cctx, vim_strchr(name, AUTOLOAD_CHAR) == NULL *************** *** 6468,6474 **** if (lhs->lhs_varlen > 1 || var_start[lhs->lhs_varlen] != ':') var_end = lhs->lhs_dest_end; ! if (lhs->lhs_dest != dest_option) { if (is_decl && *var_end == ':') { --- 6487,6493 ---- if (lhs->lhs_varlen > 1 || var_start[lhs->lhs_varlen] != ':') var_end = lhs->lhs_dest_end; ! if (lhs->lhs_dest != dest_option && lhs->lhs_dest != dest_func_option) { if (is_decl && *var_end == ':') { *************** *** 7223,7229 **** emsg(_(e_const_requires_a_value)); goto theend; } ! else if (!lhs.lhs_has_type || lhs.lhs_dest == dest_option) { emsg(_(e_type_or_initialization_required)); goto theend; --- 7242,7249 ---- emsg(_(e_const_requires_a_value)); goto theend; } ! else if (!lhs.lhs_has_type || lhs.lhs_dest == dest_option ! || lhs.lhs_dest == dest_func_option) { emsg(_(e_type_or_initialization_required)); goto theend; *************** *** 10454,10459 **** --- 10474,10480 ---- break; case ISN_STOREOPT: + case ISN_STOREFUNCOPT: vim_free(isn->isn_arg.storeopt.so_name); break; *** ../vim-8.2.3764/src/vim9.h 2021-12-01 15:22:53.106902067 +0000 --- src/vim9.h 2021-12-09 12:55:58.288530390 +0000 *************** *** 55,61 **** ISN_STORES, // pop into script variable isn_arg.loadstore ISN_STOREOUTER, // pop variable into outer scope isn_arg.outer ISN_STORESCRIPT, // pop into script variable isn_arg.script ! ISN_STOREOPT, // pop into option isn_arg.string ISN_STOREENV, // pop into environment variable isn_arg.string ISN_STOREREG, // pop into register isn_arg.number // ISN_STOREOTHER, // pop into other script variable isn_arg.other. --- 55,62 ---- ISN_STORES, // pop into script variable isn_arg.loadstore ISN_STOREOUTER, // pop variable into outer scope isn_arg.outer ISN_STORESCRIPT, // pop into script variable isn_arg.script ! ISN_STOREOPT, // pop into option isn_arg.storeopt ! ISN_STOREFUNCOPT, // pop into option isn_arg.storeopt ISN_STOREENV, // pop into environment variable isn_arg.string ISN_STOREREG, // pop into register isn_arg.number // ISN_STOREOTHER, // pop into other script variable isn_arg.other. *************** *** 291,297 **** varnumber_T stnr_val; } storenr_T; ! // arguments to ISN_STOREOPT typedef struct { char_u *so_name; int so_flags; --- 292,298 ---- varnumber_T stnr_val; } storenr_T; ! // arguments to ISN_STOREOPT and ISN_STOREFUNCOPT typedef struct { char_u *so_name; int so_flags; *** ../vim-8.2.3764/src/vim9execute.c 2021-12-06 15:06:49.331517808 +0000 --- src/vim9execute.c 2021-12-09 13:45:48.520873653 +0000 *************** *** 2336,2345 **** --- 2336,2349 ---- // store option case ISN_STOREOPT: + case ISN_STOREFUNCOPT: { + char_u *opt_name = iptr->isn_arg.storeopt.so_name; + int opt_flags = iptr->isn_arg.storeopt.so_flags; long n = 0; char_u *s = NULL; char *msg; + callback_T cb = {NULL, NULL, 0}; --ectx->ec_stack.ga_len; tv = STACK_TV_BOT(0); *************** *** 2349,2359 **** if (s == NULL) s = (char_u *)""; } else // must be VAR_NUMBER, CHECKTYPE makes sure n = tv->vval.v_number; ! msg = set_option_value(iptr->isn_arg.storeopt.so_name, ! n, s, iptr->isn_arg.storeopt.so_flags); clear_tv(tv); if (msg != NULL) { --- 2353,2374 ---- if (s == NULL) s = (char_u *)""; } + else if (iptr->isn_type == ISN_STOREFUNCOPT) + { + SOURCING_LNUM = iptr->isn_lnum; + cb = get_callback(tv); + if (cb.cb_name == NULL || *cb.cb_name == NUL) + { + clear_tv(tv); + free_callback(&cb); + goto on_error; + } + s = cb.cb_name; + } else // must be VAR_NUMBER, CHECKTYPE makes sure n = tv->vval.v_number; ! msg = set_option_value(opt_name, n, s, opt_flags); clear_tv(tv); if (msg != NULL) { *************** *** 2361,2366 **** --- 2376,2383 ---- emsg(_(msg)); goto on_error; } + if (cb.cb_name != NULL) + free_callback(&cb); } break; *************** *** 5335,5341 **** } break; case ISN_STOREOPT: ! smsg("%s%4d STOREOPT &%s", pfx, current, iptr->isn_arg.storeopt.so_name); break; case ISN_STOREENV: --- 5352,5360 ---- } break; case ISN_STOREOPT: ! case ISN_STOREFUNCOPT: ! smsg("%s%4d %s &%s", pfx, current, ! iptr->isn_type == ISN_STOREOPT ? "STOREOPT" : "STOREFUNCOPT", iptr->isn_arg.storeopt.so_name); break; case ISN_STOREENV: *** ../vim-8.2.3764/src/testdir/test_vim9_func.vim 2021-12-02 16:38:46.243764499 +0000 --- src/testdir/test_vim9_func.vim 2021-12-09 13:31:23.326010989 +0000 *************** *** 1202,1207 **** --- 1202,1229 ---- CheckScriptSuccess(lines) enddef + def Test_set_opfunc_to_lambda() + var lines =<< trim END + vim9script + nnoremap CountSpaces() .. '_' + def CountSpaces(type = ''): string + if type == '' + &operatorfunc = (t) => CountSpaces(t) + return 'g@' + endif + normal! '[V']y + g:result = getreg('"')->count(' ') + return '' + enddef + new + 'a b c d e'->setline(1) + feedkeys("\", 'x') + assert_equal(4, g:result) + bwipe! + END + CheckScriptSuccess(lines) + enddef + " Default arg and varargs def MyDefVarargs(one: string, two = 'foo', ...rest: list): string var res = one .. ',' .. two *** ../vim-8.2.3764/src/testdir/test_vim9_disassemble.vim 2021-12-01 17:37:56.440650135 +0000 --- src/testdir/test_vim9_disassemble.vim 2021-12-09 14:20:13.686239069 +0000 *************** *** 316,321 **** --- 316,322 ---- w:windowvar = 'wv' t:tabpagevar = 'tv' &tabstop = 8 + &opfunc = (t) => len(t) $ENVVAR = 'ev' @z = 'rv' enddef *************** *** 343,354 **** ' STOREW w:windowvar.*' .. 't:tabpagevar = ''tv''.*' .. ' STORET t:tabpagevar.*' .. ! '&tabstop = 8.*' .. ! ' STOREOPT &tabstop.*' .. ! '$ENVVAR = ''ev''.*' .. ! ' STOREENV $ENVVAR.*' .. '@z = ''rv''.*' .. ! ' STOREREG @z.*', res) enddef --- 344,360 ---- ' STOREW w:windowvar.*' .. 't:tabpagevar = ''tv''.*' .. ' STORET t:tabpagevar.*' .. ! '&tabstop = 8\_s*' .. ! '\d\+ PUSHNR 8\_s*' .. ! '\d\+ STOREOPT &tabstop\_s*' .. ! '&opfunc = (t) => len(t)\_s*' .. ! '\d\+ FUNCREF \d\+\_s*' .. ! '\d\+ STOREFUNCOPT &opfunc\_s*' .. ! '$ENVVAR = ''ev''\_s*' .. ! '\d\+ PUSHS "ev"\_s*' .. ! '\d\+ STOREENV $ENVVAR\_s*' .. '@z = ''rv''.*' .. ! '\d\+ STOREREG @z.*', res) enddef *** ../vim-8.2.3764/src/version.c 2021-12-09 11:57:19.163557374 +0000 --- src/version.c 2021-12-09 13:01:50.124143869 +0000 *************** *** 755,756 **** --- 755,758 ---- { /* Add new patch number below this line */ + /**/ + 3765, /**/ -- hundred-and-one symptoms of being an internet addict: 14. You start introducing yourself as "Jim at I-I-Net dot net dot au" /// 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 ///