Patch 8.2.3314
Problem: Behavior of exists() in a :def function is unpredictable.
Solution: Add exists_compiled().
Files: runtime/doc/eval.txt, runtime/doc/usr_41.txt, src/evalfunc.c,
src/errors.h, src/vim9compile.c, src/testdir/test_vim9_builtin.vim
*** ../vim-8.2.3313/runtime/doc/eval.txt 2021-07-31 12:43:19.464837526
+0200
--- runtime/doc/eval.txt 2021-08-08 14:12:05.788745542 +0200
***************
*** 2545,2550 ****
--- 2561,2567 ----
execute({command}) String execute {command} and get the output
exepath({expr}) String full path of the command {expr}
exists({expr}) Number |TRUE| if {expr} exists
+ exists_compiled({expr}) Number |TRUE| if {expr} exists at
compile time
exp({expr}) Float exponential of {expr}
expand({expr} [, {nosuf} [, {list}]])
any expand special keywords in {expr}
***************
*** 4421,4426 ****
--- 4446,4455 ----
exists({expr}) The result is a Number, which is |TRUE| if {expr} is
defined,
zero otherwise.
+ Note: In a compiled |:def| function the evaluation is done at
+ runtime. Use `exists_compiled()` to evaluate the expression
+ at compile time.
+
For checking for a supported feature use |has()|.
For checking if a file exists use |filereadable()|.
***************
*** 4508,4515 ****
Can also be used as a |method|: >
Varname()->exists()
! exp({expr}) *exp()*
Return the exponential of {expr} as a |Float| in the range
[0, inf].
{expr} must evaluate to a |Float| or a |Number|.
--- 4539,4561 ----
Can also be used as a |method|: >
Varname()->exists()
+ <
+
+ exists_compiled({expr})
*exists()*
+ Like `exists()` but evaluated at compile time. This is useful
+ to skip a block where a function is used that would otherwise
+ give an error: >
+ if exists_compiled('*ThatFunction')
+ ThatFunction('works')
+ endif
+ < If `exists()` were used then a compilation error would be
+ given if ThatFunction() is not defined.
! {expr} must be a literal string. *E1232*
! Can only be used in a |:def| function. *E1233*
!
!
! exp({expr}) *exp()*
Return the exponential of {expr} as a |Float| in the range
[0, inf].
{expr} must evaluate to a |Float| or a |Number|.
***************
*** 8394,8399 ****
--- 8485,8492 ----
Lists are represented as Vim |List| type.
Dictionaries are represented as Vim |Dictionary| type with
keys converted to strings.
+ Note that in a `:def` function local variables are not visible
+ to {expr}.
Can also be used as a |method|: >
GetExpr()->py3eval()
***************
*** 8409,8414 ****
--- 8502,8509 ----
Lists are represented as Vim |List| type.
Dictionaries are represented as Vim |Dictionary| type,
non-string keys result in error.
+ Note that in a `:def` function local variables are not visible
+ to {expr}.
Can also be used as a |method|: >
GetExpr()->pyeval()
*** ../vim-8.2.3313/runtime/doc/usr_41.txt 2021-07-26 21:54:00.051491580
+0200
--- runtime/doc/usr_41.txt 2021-08-08 14:24:42.486586832 +0200
***************
*** 1174,1179 ****
--- 1182,1188 ----
state() get current busy state
visualmode() last visual mode used
exists() check if a variable, function, etc. exists
+ exists_compiled() like exists() but check at compile time
has() check if a feature is supported in Vim
changenr() return number of most recent change
cscope_connection() check if a cscope connection exists
*** ../vim-8.2.3313/src/evalfunc.c 2021-08-06 21:34:34.626972208 +0200
--- src/evalfunc.c 2021-08-08 14:06:52.869871446 +0200
***************
*** 49,54 ****
--- 49,55 ----
static void f_eval(typval_T *argvars, typval_T *rettv);
static void f_eventhandler(typval_T *argvars, typval_T *rettv);
static void f_execute(typval_T *argvars, typval_T *rettv);
+ static void f_exists_compiled(typval_T *argvars, typval_T *rettv);
static void f_expand(typval_T *argvars, typval_T *rettv);
static void f_expandcmd(typval_T *argvars, typval_T *rettv);
static void f_feedkeys(typval_T *argvars, typval_T *rettv);
***************
*** 1329,1334 ****
--- 1330,1337 ----
ret_string, f_exepath},
{"exists", 1, 1, FEARG_1, arg1_string,
ret_number_bool, f_exists},
+ {"exists_compiled", 1, 1, FEARG_1, arg1_string,
+ ret_number_bool, f_exists_compiled},
{"exp", 1, 1, FEARG_1, arg1_float_or_nr,
ret_float, FLOAT_FUNC(f_exp)},
{"expand", 1, 3, FEARG_1, arg3_string_bool_bool,
***************
*** 3626,3631 ****
--- 3629,3640 ----
rettv->vval.v_number = n;
}
+ static void
+ f_exists_compiled(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
+ {
+ emsg(_(e_exists_compiled_can_only_be_used_in_def_function));
+ }
+
/*
* "expand()" function
*/
*** ../vim-8.2.3313/src/errors.h 2021-08-05 20:39:59.354053658 +0200
--- src/errors.h 2021-08-08 14:11:59.188767184 +0200
***************
*** 646,648 ****
--- 646,652 ----
INIT(= N_("E1230: Encryption: sodium_mlock() failed"));
EXTERN char e_cannot_use_bar_to_separate_commands_here_str[]
INIT(= N_("E1231: Cannot use a bar to separate commands here: %s"));
+ EXTERN char e_argument_of_exists_compiled_must_be_literal_string[]
+ INIT(= N_("E1232: Argument of exists_compiled() must be a literal
string"));
+ EXTERN char e_exists_compiled_can_only_be_used_in_def_function[]
+ INIT(= N_("E1233: exists_compiled() can only be used in a :def
function"));
*** ../vim-8.2.3313/src/vim9compile.c 2021-08-07 18:12:35.495528716 +0200
--- src/vim9compile.c 2021-08-08 14:10:34.985049746 +0200
***************
*** 3415,3423 ****
int is_searchpair;
// We can evaluate "has('name')" at compile time.
! // We can evaluate some "exists()" values at compile time.
if ((varlen == 3 && STRNCMP(*arg, "has", 3) == 0)
! || (varlen == 6 && STRNCMP(*arg, "exists", 6) == 0))
{
char_u *s = skipwhite(*arg + varlen + 1);
typval_T argvars[2];
--- 3415,3423 ----
int is_searchpair;
// We can evaluate "has('name')" at compile time.
! // We always evaluate "exists_compiled()" at compile time.
if ((varlen == 3 && STRNCMP(*arg, "has", 3) == 0)
! || (varlen == 15 && STRNCMP(*arg, "exists_compiled", 6) == 0))
{
char_u *s = skipwhite(*arg + varlen + 1);
typval_T argvars[2];
***************
*** 3431,3438 ****
s = skipwhite(s);
if (*s == ')' && argvars[0].v_type == VAR_STRING
&& ((is_has && !dynamic_feature(argvars[0].vval.v_string))
! || (!is_has && vim_strchr((char_u *)"+&:*",
! *argvars[0].vval.v_string))))
{
typval_T *tv = &ppconst->pp_tv[ppconst->pp_used];
--- 3431,3437 ----
s = skipwhite(s);
if (*s == ')' && argvars[0].v_type == VAR_STRING
&& ((is_has && !dynamic_feature(argvars[0].vval.v_string))
! || !is_has))
{
typval_T *tv = &ppconst->pp_tv[ppconst->pp_used];
***************
*** 3449,3454 ****
--- 3448,3458 ----
return OK;
}
clear_tv(&argvars[0]);
+ if (!is_has)
+ {
+ emsg(_(e_argument_of_exists_compiled_must_be_literal_string));
+ return FAIL;
+ }
}
if (generate_ppconst(cctx, ppconst) == FAIL)
*** ../vim-8.2.3313/src/testdir/test_vim9_builtin.vim 2021-08-05
22:48:08.524435481 +0200
--- src/testdir/test_vim9_builtin.vim 2021-08-08 14:23:06.726837390 +0200
***************
*** 793,834 ****
CheckDefAndScriptFailure2(['exists(10)'], 'E1013: Argument 1: type
mismatch, expected string but got number', 'E1174: String required for argument
1')
call assert_equal(1, exists('&tabstop'))
! if exists('+newoption')
if &newoption == 'ok'
endif
endif
! if exists('&newoption')
if &newoption == 'ok'
endif
endif
! if exists('+tabstop')
assert_equal(8, &tabstop)
else
assert_report('tabstop option not existing?')
endif
! if exists('&tabstop')
assert_equal(8, &tabstop)
else
assert_report('tabstop option not existing?')
endif
! if exists(':DoSomeCommand') >= 2
DoSomeCommand
endif
assert_equal(4, g:didSomeCommand)
! if exists(':NoSuchCommand') >= 2
NoSuchCommand
endif
var found = false
! if exists('*CheckScriptSuccess')
found = true
endif
assert_true(found)
! if exists('*NoSuchFunction')
NoSuchFunction()
endif
! if exists('*no_such_function')
no_such_function()
endif
enddef
--- 793,849 ----
CheckDefAndScriptFailure2(['exists(10)'], 'E1013: Argument 1: type
mismatch, expected string but got number', 'E1174: String required for argument
1')
call assert_equal(1, exists('&tabstop'))
! var lines =<< trim END
! if exists('+newoption')
! if &newoption == 'ok'
! endif
! endif
! END
! CheckDefFailure(lines, 'E113:')
! CheckScriptSuccess(lines)
! enddef
!
! def Test_exists_compiled()
! call assert_equal(1, exists_compiled('&tabstop'))
! CheckDefAndScriptFailure2(['exists_compiled(10)'], 'E1232:', 'E1233:')
! CheckDefAndScriptFailure2(['exists_compiled(v:progname)'], 'E1232:',
'E1233:')
!
! if exists_compiled('+newoption')
if &newoption == 'ok'
endif
endif
! if exists_compiled('&newoption')
if &newoption == 'ok'
endif
endif
! if exists_compiled('+tabstop')
assert_equal(8, &tabstop)
else
assert_report('tabstop option not existing?')
endif
! if exists_compiled('&tabstop')
assert_equal(8, &tabstop)
else
assert_report('tabstop option not existing?')
endif
! if exists_compiled(':DoSomeCommand') >= 2
DoSomeCommand
endif
assert_equal(4, g:didSomeCommand)
! if exists_compiled(':NoSuchCommand') >= 2
NoSuchCommand
endif
var found = false
! if exists_compiled('*CheckScriptSuccess')
found = true
endif
assert_true(found)
! if exists_compiled('*NoSuchFunction')
NoSuchFunction()
endif
! if exists_compiled('*no_such_function')
no_such_function()
endif
enddef
*** ../vim-8.2.3313/src/version.c 2021-08-07 22:35:49.038237945 +0200
--- src/version.c 2021-08-08 14:28:28.978007619 +0200
***************
*** 757,758 ****
--- 757,760 ----
{ /* Add new patch number below this line */
+ /**/
+ 3314,
/**/
--
I'm sure that I asked CBuilder to do a "full" install. Looks like I got
a "fool" install, instead. Charles E Campbell, Jr, PhD
/// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/vim_dev/202108081243.178ChrXb2107491%40masaka.moolenaar.net.