Compare commits

...

29 Commits

Author SHA1 Message Date
Bram Moolenaar
17dd519633 patch 8.2.4141: Vim9 builtin functions test fails
Problem:    Vim9 builtin functions test fails.
Solution:   Add "scriptversion" item to maparg() result.
2022-01-18 21:42:37 +00:00
Bram Moolenaar
a9528b39a6 patch 8.2.4140: maparg() does not indicate the type of script
Problem:    maparg() does not indicate the type of script where it was defined.
Solution:   Add "scriptversion".
2022-01-18 20:51:35 +00:00
Bram Moolenaar
94075b2b0e patch 8.2.4139: using freed memory in expression abbreviation
Problem:    Using freed memory if an expression abbreviation deletes the
            abbreviation.
Solution:   Do not access the pointer after evaluating the expression.
2022-01-18 20:30:39 +00:00
Bram Moolenaar
ef7aadbe36 patch 8.2.4138: Vim9: no error for return with argument when invalid
Problem:    Vim9: no error for return with argument when the function does not
            return anything.
Solution:   Give an error for the invalid argument. (issue #9497)
2022-01-18 18:46:07 +00:00
Bram Moolenaar
d02dce2bb5 patch 8.2.4137: Vim9: calling import with and without method is inconsistent
Problem:    Vim9: calling import with and without method is inconsistent.
Solution:   Set a flag that a parenthsis follows to compile_load_scriptvar().
            Add some more tests.  Improve error message.
2022-01-18 17:43:04 +00:00
Bram Moolenaar
fd218c8a36 patch 8.2.4136: Vim9: the "autoload" argument of ":vim9script" is not useful
Problem:    Vim9: the "autoload" argument of ":vim9script" is not useful.
Solution:   Remove the argument. (closes #9555)
2022-01-18 16:26:24 +00:00
Bram Moolenaar
6079da7cfb patch 8.2.4135: Vim9: ":scriptnames" shows unloaded imported autoload script
Problem:    Vim9: ":scriptnames" shows unloaded imported autoload script.
Solution:   Mark the unloaded script with "A". (closes #9552)
2022-01-18 14:16:59 +00:00
Bram Moolenaar
113b8dc111 patch 8.2.4134: MS-Windows: test for import with absolute path fails
Problem:    MS-Windows: test for import with absolute path fails.
Solution:   Handle path starting with slash as an absolute path.
2022-01-18 13:43:58 +00:00
Bram Moolenaar
840f16202e patch 8.2.4133: output of ":scriptnames" goes into the message history
Problem:    output of ":scriptnames" goes into the message history, while this
            des not happen for other commands, such as ":ls".
Solution:   Use msg_outtrans() instead of smsg(). (closes #9551)
2022-01-18 13:34:05 +00:00
Bram Moolenaar
1836d61578 patch 8.2.4132: Vim9: wrong error message when autoload script can't be found
Problem:    Vim9: wrong error message when autoload script can't be found.
Solution:   Correct check for using autoload with wrong name.
2022-01-18 13:14:47 +00:00
Bram Moolenaar
cbbc48f64b patch 8.2.4131: Vim9: calling function in autoload import does not work
Problem:    Vim9: calling function in autoload import does not work in a :def
            function.
Solution:   When a variable is not found and a PCALL follows use a funcref.
            (closes #9550)
2022-01-18 12:58:28 +00:00
K.Takata
31dcc8de46 patch 8.2.4130: MS-Windows: MSVC build may have libraries duplicated
Problem:    MS-Windows: MSVC build may have libraries duplicated.
Solution:   Improve the MSVC Makefile. (Ken Takata, closes #9547)
2022-01-18 11:34:57 +00:00
Bram Moolenaar
1247126956 patch 8.2.4129: building with +sound but without +eval fails
Problem:    Building with +sound but without +eval fails. (Dominique Pellé)
Solution:   Disable canberra in tiny and small build. (closes #9548)
2022-01-18 11:11:25 +00:00
Bram Moolenaar
64283d5e1f patch 8.2.4128: crash when method cannot be found
Problem:    Crash when method cannot be found. (Christian J. Robinson)
Solution:   Don't mix up pointer names.
2022-01-18 10:37:29 +00:00
Bram Moolenaar
78f60322f7 patch 8.2.4127: build failure without the +eval feature
Problem:    Build failure without the +eval feature.
Solution:   Add #ifdef.
2022-01-17 22:16:33 +00:00
Bram Moolenaar
afa76e1cf2 patch 8.2.4126: crash on exit when built with dynamic Tcl
Problem:    Crash on exit when built with dynamic Tcl and EXITFREE is defined.
            (Dominique Pellé)
Solution:   Only call Tcl_Finalize() when initialized. (closes #9546)
2022-01-17 21:34:38 +00:00
Bram Moolenaar
b3d9ceed2b patch 8.2.4125: completion tests fail
Problem:    Completion tests fail.
Solution:   Disable error messages while dereferencing the function name.
2022-01-17 21:13:28 +00:00
Bram Moolenaar
6389baa669 patch 8.2.4124: Vim9: method in compiled function may not see script item
Problem:    Vim9: method in compiled function may not see script item.
Solution:   Make sure not to skip to the next line. (closes #9496)
2022-01-17 20:50:40 +00:00
Bram Moolenaar
15d1635e50 patch 8.2.4123: complete function cannot be import.Name
Problem:    Complete function cannot be import.Name.
Solution:   Dereference the function name if needed.  Also: do not see
            "import.Name" as a builtin function. (closes #9541)
2022-01-17 20:09:08 +00:00
Bram Moolenaar
3f3597be3f patch 8.2.4122: ":command Cmd" does not show custom completion argument
Problem:    ":command Cmd" does not show custom completion argument.
Solution:   Show the completion argument when using ":verbose".
2022-01-17 19:06:56 +00:00
Bram Moolenaar
262898ae43 patch 8.2.4121: Visual test fails on MS-Windows
Problem:    Visual test fails on MS-Windows.
Solution:   Set 'isprint' so that the character used is not printable.
2022-01-17 17:52:22 +00:00
Bram Moolenaar
9f8c304c8a patch 8.2.4120: block insert goes over the end of the line
Problem:    Block insert goes over the end of the line.
Solution:   Handle invalid byte better.  Fix inserting the wrong text.
2022-01-17 17:30:21 +00:00
Dominique Pelle
e8741a73e2 patch 8.2.4119: build failure when disabling the channel feature
Problem:    Build failure when disabling the channel feature.
Solution:   Adjust #ifdef. (Dominique Pellé, closes #9545)
2022-01-17 11:23:45 +00:00
Bram Moolenaar
0023f82a76 patch 8.2.4118: using UNUSED for argument that is used
Problem:    Using UNUSED for argument that is used.
Solution:   Remove UNUSED.
2022-01-16 21:54:19 +00:00
Bram Moolenaar
47036b6bd7 patch 8.2.4117: Vim9: wrong white space error after using imported item
Problem:    Vim9: wrong white space error after using imported item.
Solution:   Don't skip over white space. (closes #9544)
2022-01-16 21:18:53 +00:00
Bram Moolenaar
c73499351a patch 8.2.4116: Vim9: cannot use a method with a complex expression in :def
Problem:    Vim9: cannot use a method with a complex expression in a :def
            function.
Solution:   Implement compiling the expression.
2022-01-16 20:59:39 +00:00
Bram Moolenaar
c665dabdf4 patch 8.2.4115: cannot use a method with a complex expression
Problem:    Cannot use a method with a complex expression.
Solution:   Evaluate the expression after "->" and use the result.
2022-01-16 19:38:07 +00:00
Bram Moolenaar
c84287d6d8 patch 8.2.4114: Vim9: type checking for a funcref does not work for method
Problem:    Vim9: type checking for a funcref does not work for when it is
            used in a method.
Solution:   Pass the base to where the type is checked.
2022-01-16 18:06:21 +00:00
Bram Moolenaar
dc98776f89 patch 8.2.4113: typo on DOCMD_RANGEOK results in not recognizing command
Problem:    Typo on DOCMD_RANGEOK results in not recognizing command.
Solution:   Correct the typo. (closes #9539)
2022-01-16 15:52:35 +00:00
32 changed files with 866 additions and 283 deletions

View File

@@ -5247,6 +5247,8 @@ maparg({name} [, {mode} [, {abbr} [, {dict}]]]) *maparg()*
(|mapmode-ic|)
"sid" The script local ID, used for <sid> mappings
(|<SID>|).
"scriptversion" The version of the script. 999999 for
|Vim9| script.
"lnum" The line number in "sid", zero if unknown.
"nowait" Do not wait for other, longer mappings.
(|:map-<nowait>|).

View File

@@ -365,12 +365,11 @@ For writing a Vim script, see chapter 41 of the user manual |usr_41.txt|.
Vim version, or update Vim to a newer version. See
|vimscript-version| for what changed between versions.
:vim9s[cript] [noclear] [autoload] *:vim9s* *:vim9script*
:vim9s[cript] [noclear] *:vim9s* *:vim9script*
Marks a script file as containing |Vim9-script|
commands. Also see |vim9-namespace|.
Must be the first command in the file.
For [noclear] see |vim9-reload|.
For [autoload] see |vim9-autoload|.
Without the |+eval| feature this changes the syntax
for some commands.
See |:vim9cmd| for executing one command with Vim9
@@ -378,8 +377,11 @@ For writing a Vim script, see chapter 41 of the user manual |usr_41.txt|.
*:scr* *:scriptnames*
:scr[iptnames] List all sourced script names, in the order they were
first sourced. The number is used for the script ID
|<SID>|.
first encountered. The number is used for the script
ID |<SID>|.
For a script that was used with `import autoload` but
was not actually sourced yet an "A" is shown after the
script ID.
{not available when compiled without the |+eval|
feature}

View File

@@ -1,4 +1,4 @@
*vim9.txt* For Vim version 8.2. Last change: 2022 Jan 15
*vim9.txt* For Vim version 8.2. Last change: 2022 Jan 18
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -1523,17 +1523,18 @@ actually needed. Using the autoload mechanism is recommended:
directory.
2. In the autoload script put the bulk of the code. >
vim9script autoload
vim9script
export def Stuff(arg: string)
...
< This goes in .../autoload/for/search.vim.
Adding "autoload" to `:vim9script` has the effect that "for#search#" will
be prefixed to every exported item. The prefix is obtained from the file
name, as you would to manually in a legacy autoload script. Thus the
exported function can be found with "for#search#Stuff", but you would
normally use `import autoload` and not need to specify the prefix.
Putting the "search.vim" script under the "/autoload/for/" directory has
the effect that "for#search#" will be prefixed to every exported item. The
prefix is obtained from the file name, as you would to manually in a
legacy autoload script. Thus the exported function can be found with
"for#search#Stuff", but you would normally use `import autoload` and not
use the prefix.
You can split up the functionality and import other scripts from the
autoload script as you like. This way you can share code between plugins.

View File

@@ -508,7 +508,8 @@ NETBEANS_LIB = WSock32.lib Ws2_32.lib
# gdi32.lib and comdlg32.lib for printing support
# ole32.lib and uuid.lib are needed for FEAT_SHORTCUT
CON_LIB = oldnames.lib kernel32.lib advapi32.lib shell32.lib gdi32.lib \
comdlg32.lib ole32.lib netapi32.lib uuid.lib /machine:$(CPU)
comdlg32.lib ole32.lib netapi32.lib uuid.lib user32.lib \
/machine:$(CPU)
!if "$(DELAYLOAD)" == "yes"
CON_LIB = $(CON_LIB) /DELAYLOAD:comdlg32.dll /DELAYLOAD:ole32.dll DelayImp.lib
!endif
@@ -671,6 +672,7 @@ CFLAGS = $(CFLAGS) /fsanitize=address
!endif
!ifdef NODEBUG
VIM = vim
! if "$(OPTIMIZE)" == "SPACE"
OPTFLAG = /O1
@@ -701,7 +703,9 @@ LIBC = msvcrt.lib
LIBC = libcmt.lib
CFLAGS = $(CFLAGS) /Zl /MT
! endif
!else # DEBUG
VIM = vimd
! if ("$(CPU)" == "i386") || ("$(CPU)" == "ix86")
DEBUGINFO = /ZI
@@ -721,6 +725,7 @@ LIBC = $(LIBC) msvcrtd.lib
LIBC = $(LIBC) libcmtd.lib
CFLAGS = $(CFLAGS) /Zl /MTd
! endif
!endif # DEBUG
!if "$(CL)" == "/D_USING_V110_SDK71_"
@@ -910,9 +915,7 @@ GUI_OBJ = \
$(OUTDIR)\gui_beval.obj \
$(OUTDIR)\gui_w32.obj
GUI_LIB = \
gdi32.lib version.lib $(IME_LIB) \
winspool.lib comctl32.lib advapi32.lib shell32.lib netapi32.lib \
/machine:$(CPU)
version.lib $(IME_LIB) winspool.lib comctl32.lib
!else
SUBSYSTEM = console
CUI_INCL = iscygpty.h
@@ -1320,11 +1323,11 @@ conflags = $(conflags) /map /mapinfo:lines
!ENDIF
LINKARGS1 = $(linkdebug) $(conflags)
LINKARGS2 = $(CON_LIB) $(GUI_LIB) $(NODEFAULTLIB) $(LIBC) $(OLE_LIB) user32.lib \
LINKARGS2 = $(CON_LIB) $(GUI_LIB) $(NODEFAULTLIB) $(LIBC) $(OLE_LIB) \
$(LUA_LIB) $(MZSCHEME_LIB) $(PERL_LIB) $(PYTHON_LIB) $(PYTHON3_LIB) $(RUBY_LIB) \
$(TCL_LIB) $(SOUND_LIB) $(NETBEANS_LIB) $(XPM_LIB) $(SOD_LIB) $(LINK_PDB)
# Report link time code generation progress if used.
# Report link time code generation progress if used.
!ifdef NODEBUG
! if $(MSVC_MAJOR) >= 8
! if "$(OPTIMIZE)" != "SPACE"

32
src/auto/configure vendored
View File

@@ -5256,6 +5256,12 @@ esac
if test "x$features" = "xtiny" -o "x$features" = "xsmall"; then
has_eval=no
else
has_eval=yes
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking --with-compiledby argument" >&5
$as_echo_n "checking --with-compiledby argument... " >&6; }
@@ -5333,7 +5339,7 @@ fi
$as_echo "$enable_luainterp" >&6; }
if test "$enable_luainterp" = "yes" -o "$enable_luainterp" = "dynamic"; then
if test "x$features" = "xtiny" -o "x$features" = "xsmall"; then
if test "$has_eval" = "no"; then
as_fn_error $? "cannot use Lua with tiny or small features" "$LINENO" 5
fi
@@ -6103,7 +6109,7 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_perlinterp" >&5
$as_echo "$enable_perlinterp" >&6; }
if test "$enable_perlinterp" = "yes" -o "$enable_perlinterp" = "dynamic"; then
if test "x$features" = "xtiny" -o "x$features" = "xsmall"; then
if test "$has_eval" = "no"; then
as_fn_error $? "cannot use Perl with tiny or small features" "$LINENO" 5
fi
@@ -6308,7 +6314,7 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_pythoninterp" >&5
$as_echo "$enable_pythoninterp" >&6; }
if test "$enable_pythoninterp" = "yes" -o "$enable_pythoninterp" = "dynamic"; then
if test "x$features" = "xtiny" -o "x$features" = "xsmall"; then
if test "$has_eval" = "no"; then
as_fn_error $? "cannot use Python with tiny or small features" "$LINENO" 5
fi
@@ -6659,7 +6665,7 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_python3interp" >&5
$as_echo "$enable_python3interp" >&6; }
if test "$enable_python3interp" = "yes" -o "$enable_python3interp" = "dynamic"; then
if test "x$features" = "xtiny" -o "x$features" = "xsmall"; then
if test "$has_eval" = "no"; then
as_fn_error $? "cannot use Python with tiny or small features" "$LINENO" 5
fi
@@ -7587,7 +7593,7 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_rubyinterp" >&5
$as_echo "$enable_rubyinterp" >&6; }
if test "$enable_rubyinterp" = "yes" -o "$enable_rubyinterp" = "dynamic"; then
if test "x$features" = "xtiny" -o "x$features" = "xsmall"; then
if test "$has_eval" = "no"; then
as_fn_error $? "cannot use Ruby with tiny or small features" "$LINENO" 5
fi
@@ -7765,7 +7771,7 @@ else
fi
if test "$enable_netbeans" = "yes"; then
if test "x$features" = "xtiny" -o "x$features" = "xsmall"; then
if test "$has_eval" = "no"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: cannot use NetBeans with tiny or small features" >&5
$as_echo "cannot use NetBeans with tiny or small features" >&6; }
enable_netbeans="no"
@@ -7788,7 +7794,7 @@ else
fi
if test "$enable_channel" = "yes"; then
if test "x$features" = "xtiny" -o "x$features" = "xsmall"; then
if test "$has_eval" = "no"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: cannot use channels with tiny or small features" >&5
$as_echo "cannot use channels with tiny or small features" >&6; }
enable_channel="no"
@@ -8092,7 +8098,7 @@ else
fi
if test "$enable_terminal" = "yes" || test "$enable_terminal" = "auto" -a "x$features" = "xhuge" ; then
if test "x$features" = "xtiny" -o "x$features" = "xsmall"; then
if test "$has_eval" = "no"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: cannot use terminal emulator with tiny or small features" >&5
$as_echo "cannot use terminal emulator with tiny or small features" >&6; }
enable_terminal="no"
@@ -13051,8 +13057,14 @@ $as_echo "Defaulting to no" >&6; }
enable_canberra="no"
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_canberra" >&5
if test "$enable_canberra" = "yes" -a "$has_eval" = "no"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: cannot use sound with tiny or small features" >&5
$as_echo "cannot use sound with tiny or small features" >&6; }
enable_canberra="no"
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_canberra" >&5
$as_echo "$enable_canberra" >&6; }
fi
fi
if test "$enable_canberra" = "yes"; then
if test "x$PKG_CONFIG" != "xno"; then
@@ -13067,7 +13079,7 @@ if test "$enable_canberra" = "yes"; then
$as_echo_n "checking for libcanberra... " >&6; }
ac_save_CFLAGS="$CFLAGS"
ac_save_LIBS="$LIBS"
if `echo "$CFLAGS" | grep -v "$canberra_cflags" >/dev/null`; then
if `echo "$CFLAGS" | grep -v "$canberra_cflags" 2>/dev/null`; then
CFLAGS="$CFLAGS $canberra_cflags"
fi
LIBS="$LIBS $canberra_lib"

View File

@@ -540,6 +540,12 @@ esac
AC_SUBST(dovimdiff)
AC_SUBST(dogvimdiff)
if test "x$features" = "xtiny" -o "x$features" = "xsmall"; then
has_eval=no
else
has_eval=yes
fi
AC_MSG_CHECKING(--with-compiledby argument)
AC_ARG_WITH(compiledby, [ --with-compiledby=NAME name to show in :version message],
compiledby="$withval"; AC_MSG_RESULT($withval),
@@ -585,7 +591,7 @@ AC_ARG_ENABLE(luainterp,
AC_MSG_RESULT($enable_luainterp)
if test "$enable_luainterp" = "yes" -o "$enable_luainterp" = "dynamic"; then
if test "x$features" = "xtiny" -o "x$features" = "xsmall"; then
if test "$has_eval" = "no"; then
AC_MSG_ERROR([cannot use Lua with tiny or small features])
fi
@@ -1072,7 +1078,7 @@ AC_ARG_ENABLE(perlinterp,
[enable_perlinterp="no"])
AC_MSG_RESULT($enable_perlinterp)
if test "$enable_perlinterp" = "yes" -o "$enable_perlinterp" = "dynamic"; then
if test "x$features" = "xtiny" -o "x$features" = "xsmall"; then
if test "$has_eval" = "no"; then
AC_MSG_ERROR([cannot use Perl with tiny or small features])
fi
AC_SUBST(vi_cv_path_perl)
@@ -1221,7 +1227,7 @@ AC_ARG_ENABLE(pythoninterp,
[enable_pythoninterp="no"])
AC_MSG_RESULT($enable_pythoninterp)
if test "$enable_pythoninterp" = "yes" -o "$enable_pythoninterp" = "dynamic"; then
if test "x$features" = "xtiny" -o "x$features" = "xsmall"; then
if test "$has_eval" = "no"; then
AC_MSG_ERROR([cannot use Python with tiny or small features])
fi
@@ -1456,7 +1462,7 @@ AC_ARG_ENABLE(python3interp,
[enable_python3interp="no"])
AC_MSG_RESULT($enable_python3interp)
if test "$enable_python3interp" = "yes" -o "$enable_python3interp" = "dynamic"; then
if test "x$features" = "xtiny" -o "x$features" = "xsmall"; then
if test "$has_eval" = "no"; then
AC_MSG_ERROR([cannot use Python with tiny or small features])
fi
@@ -1969,7 +1975,7 @@ AC_ARG_ENABLE(rubyinterp,
[enable_rubyinterp="no"])
AC_MSG_RESULT($enable_rubyinterp)
if test "$enable_rubyinterp" = "yes" -o "$enable_rubyinterp" = "dynamic"; then
if test "x$features" = "xtiny" -o "x$features" = "xsmall"; then
if test "$has_eval" = "no"; then
AC_MSG_ERROR([cannot use Ruby with tiny or small features])
fi
@@ -2082,7 +2088,7 @@ AC_ARG_ENABLE(netbeans,
[ --disable-netbeans Disable NetBeans integration support.],
, [enable_netbeans="yes"])
if test "$enable_netbeans" = "yes"; then
if test "x$features" = "xtiny" -o "x$features" = "xsmall"; then
if test "$has_eval" = "no"; then
AC_MSG_RESULT([cannot use NetBeans with tiny or small features])
enable_netbeans="no"
else
@@ -2097,7 +2103,7 @@ AC_ARG_ENABLE(channel,
[ --disable-channel Disable process communication support.],
, [enable_channel="yes"])
if test "$enable_channel" = "yes"; then
if test "x$features" = "xtiny" -o "x$features" = "xsmall"; then
if test "$has_eval" = "no"; then
AC_MSG_RESULT([cannot use channels with tiny or small features])
enable_channel="no"
else
@@ -2205,7 +2211,7 @@ AC_ARG_ENABLE(terminal,
[ --enable-terminal Enable terminal emulation support.],
, [enable_terminal="auto"])
if test "$enable_terminal" = "yes" || test "$enable_terminal" = "auto" -a "x$features" = "xhuge" ; then
if test "x$features" = "xtiny" -o "x$features" = "xsmall"; then
if test "$has_eval" = "no"; then
AC_MSG_RESULT([cannot use terminal emulator with tiny or small features])
enable_terminal="no"
else
@@ -3794,7 +3800,12 @@ if test "$enable_canberra" = "maybe"; then
enable_canberra="no"
fi
else
AC_MSG_RESULT($enable_canberra)
if test "$enable_canberra" = "yes" -a "$has_eval" = "no"; then
AC_MSG_RESULT([cannot use sound with tiny or small features])
enable_canberra="no"
else
AC_MSG_RESULT($enable_canberra)
fi
fi
if test "$enable_canberra" = "yes"; then
if test "x$PKG_CONFIG" != "xno"; then
@@ -3808,7 +3819,7 @@ if test "$enable_canberra" = "yes"; then
AC_MSG_CHECKING(for libcanberra)
ac_save_CFLAGS="$CFLAGS"
ac_save_LIBS="$LIBS"
if `echo "$CFLAGS" | grep -v "$canberra_cflags" >/dev/null`; then
if `echo "$CFLAGS" | grep -v "$canberra_cflags" 2>/dev/null`; then
CFLAGS="$CFLAGS $canberra_cflags"
fi
LIBS="$LIBS $canberra_lib"

View File

@@ -3208,8 +3208,9 @@ EXTERN char e_cannot_import_dot_vim_without_using_as[]
INIT(= N_("E1261: Cannot import .vim without using \"as\""));
EXTERN char e_cannot_import_same_script_twice_str[]
INIT(= N_("E1262: Cannot import the same script twice: %s"));
EXTERN char e_using_autoload_in_script_not_under_autoload_directory[]
INIT(= N_("E1263: Using autoload in a script not under an autoload directory"));
// E1263 unused
EXTERN char e_autoload_import_cannot_use_absolute_or_relative_path[]
INIT(= N_("E1264: Autoload import cannot use absolute or relative path: %s"));
EXTERN char e_cannot_use_partial_here[]
INIT(= N_("E1265: Cannot use a partial here"));
#endif

View File

@@ -625,6 +625,63 @@ eval_expr(char_u *arg, exarg_T *eap)
return tv;
}
/*
* "*arg" points to what can be a function name in the form of "import.Name" or
* "Funcref". Return the name of the function. Set "tofree" to something that
* was allocated.
* If "verbose" is FALSE no errors are given.
* Return NULL for any failure.
*/
static char_u *
deref_function_name(
char_u **arg,
char_u **tofree,
evalarg_T *evalarg,
int verbose)
{
typval_T ref;
char_u *name = *arg;
ref.v_type = VAR_UNKNOWN;
if (eval7(arg, &ref, evalarg, FALSE) == FAIL)
return NULL;
if (*skipwhite(*arg) != NUL)
{
if (verbose)
semsg(_(e_trailing_characters_str), *arg);
name = NULL;
}
else if (ref.v_type == VAR_FUNC && ref.vval.v_string != NULL)
{
name = ref.vval.v_string;
ref.vval.v_string = NULL;
*tofree = name;
}
else if (ref.v_type == VAR_PARTIAL && ref.vval.v_partial != NULL)
{
if (ref.vval.v_partial->pt_argc > 0
|| ref.vval.v_partial->pt_dict != NULL)
{
if (verbose)
emsg(_(e_cannot_use_partial_here));
name = NULL;
}
else
{
name = vim_strsave(partial_name(ref.vval.v_partial));
*tofree = name;
}
}
else
{
if (verbose)
semsg(_(e_not_callable_type_str), name);
name = NULL;
}
clear_tv(&ref);
return name;
}
/*
* Call some Vim script function and return the result in "*rettv".
* Uses argv[0] to argv[argc - 1] for the function arguments. argv[argc]
@@ -640,15 +697,29 @@ call_vim_function(
{
int ret;
funcexe_T funcexe;
char_u *arg;
char_u *name;
char_u *tofree = NULL;
rettv->v_type = VAR_UNKNOWN; // clear_tv() uses this
CLEAR_FIELD(funcexe);
funcexe.fe_firstline = curwin->w_cursor.lnum;
funcexe.fe_lastline = curwin->w_cursor.lnum;
funcexe.fe_evaluate = TRUE;
ret = call_func(func, -1, rettv, argc, argv, &funcexe);
// The name might be "import.Func" or "Funcref".
arg = func;
++emsg_off;
name = deref_function_name(&arg, &tofree, &EVALARG_EVALUATE, FALSE);
--emsg_off;
if (name == NULL)
name = func;
ret = call_func(name, -1, rettv, argc, argv, &funcexe);
if (ret == FAIL)
clear_tv(rettv);
vim_free(tofree);
return ret;
}
@@ -3948,6 +4019,7 @@ eval_method(
char_u *name;
long len;
char_u *alias;
char_u *tofree = NULL;
typval_T base = *rettv;
int ret = OK;
int evaluate = evalarg != NULL
@@ -3968,67 +4040,32 @@ eval_method(
}
else
{
if (**arg == '.')
char_u *paren;
// If there is no "(" immediately following, but there is further on,
// it can be "import.Func()", "dict.Func()", "list[nr]", etc.
// Does not handle anything where "(" is part of the expression.
*arg = skipwhite(*arg);
if (**arg != '(' && alias == NULL
&& (paren = vim_strchr(*arg, '(')) != NULL)
{
int len2;
char_u *fname;
int idx;
imported_T *import = find_imported(name, len, TRUE,
evalarg == NULL ? NULL : evalarg->eval_cctx);
type_T *type;
char_u *deref;
// value->import.func()
if (import != NULL)
*arg = name;
*paren = NUL;
deref = deref_function_name(arg, &tofree, evalarg, verbose);
if (deref == NULL)
{
name = NULL;
++*arg;
fname = *arg;
len2 = get_name_len(arg, &alias, evaluate, TRUE);
if (len2 <= 0)
{
if (verbose)
emsg(_(e_missing_name_after_dot));
ret = FAIL;
}
else if (evaluate)
{
int cc = fname[len2];
ufunc_T *ufunc;
fname[len2] = NUL;
idx = find_exported(import->imp_sid, fname, &ufunc, &type,
evalarg->eval_cctx, verbose);
fname[len2] = cc;
if (idx >= 0)
{
scriptitem_T *si = SCRIPT_ITEM(import->imp_sid);
svar_T *sv =
((svar_T *)si->sn_var_vals.ga_data) + idx;
if (sv->sv_tv->v_type == VAR_FUNC
&& sv->sv_tv->vval.v_string != NULL)
{
name = sv->sv_tv->vval.v_string;
len = STRLEN(name);
}
else
{
// TODO: how about a partial?
if (verbose)
semsg(_(e_not_callable_type_str), fname);
ret = FAIL;
}
}
else if (ufunc != NULL)
{
name = ufunc->uf_name;
len = STRLEN(name);
}
else
ret = FAIL;
}
*arg = name + len;
ret = FAIL;
}
else
{
name = deref;
len = STRLEN(name);
}
*paren = '(';
}
if (ret == OK)
@@ -4057,6 +4094,7 @@ eval_method(
// evaluating the arguments is possible (see test55).
if (evaluate)
clear_tv(&base);
vim_free(tofree);
return ret;
}
@@ -5998,7 +6036,6 @@ handle_subscript(
idx = find_exported(rettv->vval.v_number, exp_name, &ufunc, &type,
evalarg->eval_cctx, verbose);
**arg = cc;
*arg = skipwhite(*arg);
if (idx < 0 && ufunc == NULL)
{

View File

@@ -248,14 +248,6 @@ vim_tcl_init(char *arg)
#endif
}
#if defined(EXITFREE) || defined(PROTO)
void
vim_tcl_finalize(void)
{
Tcl_Finalize();
}
#endif
#if defined(DYNAMIC_TCL) || defined(PROTO)
static int stubs_initialized = FALSE;
@@ -285,6 +277,17 @@ tcl_enabled(int verbose)
}
return stubs_initialized;
}
#endif
#if defined(EXITFREE) || defined(PROTO)
void
vim_tcl_finalize(void)
{
# ifdef DYNAMIC_TCL
if (stubs_initialized)
# endif
Tcl_Finalize();
}
#endif
void

View File

@@ -222,11 +222,12 @@ map_add(
#ifdef FEAT_EVAL
int expr,
scid_T sid, // -1 to use current_sctx
int scriptversion,
linenr_T lnum,
#endif
int simplified)
{
mapblock_T *mp = ALLOC_ONE(mapblock_T);
mapblock_T *mp = ALLOC_CLEAR_ONE(mapblock_T);
if (mp == NULL)
return FAIL;
@@ -259,11 +260,11 @@ map_add(
mp->m_simplified = simplified;
#ifdef FEAT_EVAL
mp->m_expr = expr;
if (sid >= 0)
if (sid > 0)
{
mp->m_script_ctx.sc_sid = sid;
mp->m_script_ctx.sc_lnum = lnum;
mp->m_script_ctx.sc_version = in_vim9script() ? SCRIPT_VERSION_VIM9 : 0;
mp->m_script_ctx.sc_version = scriptversion;
}
else
{
@@ -844,7 +845,7 @@ do_map(
if (map_add(map_table, abbr_table, keys, rhs, orig_rhs,
noremap, nowait, silent, mode, abbrev,
#ifdef FEAT_EVAL
expr, /* sid */ -1, /* lnum */ 0,
expr, /* sid */ -1, /* scriptversion */ 0, /* lnum */ 0,
#endif
did_simplify && keyround == 1) == FAIL)
{
@@ -1515,6 +1516,12 @@ check_abbr(
}
if (mp != NULL)
{
int noremap;
int silent;
#ifdef FEAT_EVAL
int expr;
#endif
// Found a match:
// Insert the rest of the abbreviation in typebuf.tb_buf[].
// This goes from end to start.
@@ -1567,8 +1574,14 @@ check_abbr(
// insert the last typed char
(void)ins_typebuf(tb, 1, 0, TRUE, mp->m_silent);
}
// copy values here, calling eval_map_expr() may make "mp" invalid!
noremap = mp->m_noremap;
silent = mp->m_silent;
#ifdef FEAT_EVAL
if (mp->m_expr)
expr = mp->m_expr;
if (expr)
s = eval_map_expr(mp, c);
else
#endif
@@ -1576,11 +1589,11 @@ check_abbr(
if (s != NULL)
{
// insert the to string
(void)ins_typebuf(s, mp->m_noremap, 0, TRUE, mp->m_silent);
(void)ins_typebuf(s, noremap, 0, TRUE, silent);
// no abbrev. for these chars
typebuf.tb_no_abbr_cnt += (int)STRLEN(s) + j + 1;
#ifdef FEAT_EVAL
if (mp->m_expr)
if (expr)
vim_free(s);
#endif
}
@@ -1590,7 +1603,7 @@ check_abbr(
if (has_mbyte)
len = clen; // Delete characters instead of bytes
while (len-- > 0) // delete the from string
(void)ins_typebuf(tb, 1, 0, TRUE, mp->m_silent);
(void)ins_typebuf(tb, 1, 0, TRUE, silent);
return TRUE;
}
}
@@ -1601,6 +1614,7 @@ check_abbr(
/*
* Evaluate the RHS of a mapping or abbreviations and take care of escaping
* special characters.
* Careful: after this "mp" will be invalid if the mapping was deleted.
*/
char_u *
eval_map_expr(
@@ -2289,6 +2303,8 @@ get_maparg(typval_T *argvars, typval_T *rettv, int exact)
dict_add_number(dict, "expr", mp->m_expr ? 1L : 0L);
dict_add_number(dict, "silent", mp->m_silent ? 1L : 0L);
dict_add_number(dict, "sid", (long)mp->m_script_ctx.sc_sid);
dict_add_number(dict, "scriptversion",
(long)mp->m_script_ctx.sc_version);
dict_add_number(dict, "lnum", (long)mp->m_script_ctx.sc_lnum);
dict_add_number(dict, "buffer", (long)buffer_local);
dict_add_number(dict, "nowait", mp->m_nowait ? 1L : 0L);
@@ -2358,6 +2374,7 @@ f_mapset(typval_T *argvars, typval_T *rettv UNUSED)
int silent;
int buffer;
scid_T sid;
int scriptversion;
linenr_T lnum;
mapblock_T **map_table = maphash;
mapblock_T **abbr_table = &first_abbr;
@@ -2403,6 +2420,7 @@ f_mapset(typval_T *argvars, typval_T *rettv UNUSED)
expr = dict_get_number(d, (char_u *)"expr") != 0;
silent = dict_get_number(d, (char_u *)"silent") != 0;
sid = dict_get_number(d, (char_u *)"sid");
scriptversion = dict_get_number(d, (char_u *)"scriptversion");
lnum = dict_get_number(d, (char_u *)"lnum");
buffer = dict_get_number(d, (char_u *)"buffer");
nowait = dict_get_number(d, (char_u *)"nowait") != 0;
@@ -2433,10 +2451,11 @@ f_mapset(typval_T *argvars, typval_T *rettv UNUSED)
vim_free(arg);
(void)map_add(map_table, abbr_table, lhsraw, rhs, orig_rhs, noremap,
nowait, silent, mode, is_abbr, expr, sid, lnum, 0);
nowait, silent, mode, is_abbr, expr, sid, scriptversion, lnum, 0);
if (lhsrawalt != NULL)
(void)map_add(map_table, abbr_table, lhsrawalt, rhs, orig_rhs, noremap,
nowait, silent, mode, is_abbr, expr, sid, lnum, 1);
nowait, silent, mode, is_abbr, expr, sid, scriptversion,
lnum, 1);
vim_free(keys_buf);
vim_free(arg_buf);
}

View File

@@ -2902,7 +2902,6 @@ mch_parse_cmd(char_u *cmd, int use_shcf, char ***argv, int *argc)
return OK;
}
# if defined(FEAT_JOB_CHANNEL) || defined(PROTO)
/*
* Build "argv[argc]" from the string "cmd".
* "argv[argc]" is set to NULL;
@@ -2929,6 +2928,7 @@ build_argv_from_string(char_u *cmd, char ***argv, int *argc)
return OK;
}
# if defined(FEAT_JOB_CHANNEL) || defined(PROTO)
/*
* Build "argv[argc]" from the list "l".
* "argv[argc]" is set to NULL;

View File

@@ -536,24 +536,29 @@ block_insert(
if (b_insert)
{
off = (*mb_head_off)(oldp, oldp + offset + spaces);
spaces -= off;
count -= off;
}
else
{
off = (*mb_off_next)(oldp, oldp + offset);
offset += off;
// spaces fill the gap, the character that's at the edge moves
// right
off = (*mb_head_off)(oldp, oldp + offset);
offset -= off;
}
spaces -= off;
count -= off;
}
if (spaces < 0) // can happen when the cursor was moved
spaces = 0;
newp = alloc(STRLEN(oldp) + s_len + count + 1);
// Make sure the allocated size matches what is actually copied below.
newp = alloc(STRLEN(oldp) + spaces + s_len
+ (spaces > 0 && !bdp->is_short ? ts_val - spaces : 0)
+ count + 1);
if (newp == NULL)
continue;
// copy up to shifted part
mch_memmove(newp, oldp, (size_t)(offset));
mch_memmove(newp, oldp, (size_t)offset);
oldp += offset;
// insert pre-padding
@@ -564,14 +569,21 @@ block_insert(
mch_memmove(newp + startcol, s, (size_t)s_len);
offset += s_len;
if (spaces && !bdp->is_short)
if (spaces > 0 && !bdp->is_short)
{
// insert post-padding
vim_memset(newp + offset + spaces, ' ', (size_t)(ts_val - spaces));
// We're splitting a TAB, don't copy it.
oldp++;
// We allowed for that TAB, remember this now
count++;
if (*oldp == TAB)
{
// insert post-padding
vim_memset(newp + offset + spaces, ' ',
(size_t)(ts_val - spaces));
// we're splitting a TAB, don't copy it
oldp++;
// We allowed for that TAB, remember this now
count++;
}
else
// Not a TAB, no extra spaces
count = spaces;
}
if (spaces > 0)
@@ -1598,7 +1610,7 @@ op_insert(oparg_T *oap, long count1)
oap->start_vcol = t;
}
else if (oap->op_type == OP_APPEND
&& oap->end.col + oap->end.coladd
&& oap->start.col + oap->start.coladd
>= curbuf->b_op_start_orig.col
+ curbuf->b_op_start_orig.coladd)
{

View File

@@ -12,12 +12,11 @@ type_T *typval2type(typval_T *tv, int copyID, garray_T *type_gap, int flags);
type_T *typval2type_vimvar(typval_T *tv, garray_T *type_gap);
int check_typval_arg_type(type_T *expected, typval_T *actual_tv, char *func_name, int arg_idx);
int check_typval_type(type_T *expected, typval_T *actual_tv, where_T where);
void type_mismatch(type_T *expected, type_T *actual);
void arg_type_mismatch(type_T *expected, type_T *actual, int arg_idx);
void type_mismatch_where(type_T *expected, type_T *actual, where_T where);
int check_type(type_T *expected, type_T *actual, int give_msg, where_T where);
int check_type_maybe(type_T *expected, type_T *actual, int give_msg, where_T where);
int check_argument_types(type_T *type, typval_T *argvars, int argcount, char_u *name);
int check_argument_types(type_T *type, typval_T *argvars, int argcount, typval_T *base_tv, char_u *name);
char_u *skip_type(char_u *start, int optional);
type_T *parse_type(char_u **arg, garray_T *type_gap, int give_error);
int equal_type(type_T *type1, type_T *type2, int flags);

View File

@@ -1648,12 +1648,22 @@ ex_scriptnames(exarg_T *eap)
}
for (i = 1; i <= script_items.ga_len && !got_int; ++i)
if (SCRIPT_ITEM(i)->sn_name != NULL)
{
scriptitem_T *si = SCRIPT_ITEM(i);
if (si->sn_name != NULL)
{
home_replace(NULL, SCRIPT_ITEM(i)->sn_name,
NameBuff, MAXPATHL, TRUE);
smsg("%3d: %s", i, NameBuff);
home_replace(NULL, si->sn_name, NameBuff, MAXPATHL, TRUE);
vim_snprintf((char *)IObuff, IOSIZE, "%3d%s: %s",
i,
si->sn_state == SN_STATE_NOT_LOADED ? " A" : "",
NameBuff);
msg_putchar('\n');
msg_outtrans(IObuff);
out_flush(); // output one line at a time
ui_breakcheck();
}
}
}
# if defined(BACKSLASH_IN_FILENAME) || defined(PROTO)

View File

@@ -18,26 +18,30 @@ func Test_maparg()
call assert_equal("is<F4>foo", maparg('foo<C-V>'))
call assert_equal({'silent': 0, 'noremap': 0, 'script': 0, 'lhs': 'foo<C-V>',
\ 'lhsraw': "foo\x80\xfc\x04V", 'lhsrawalt': "foo\x16",
\ 'mode': ' ', 'nowait': 0, 'expr': 0, 'sid': sid, 'lnum': lnum + 1,
\ 'mode': ' ', 'nowait': 0, 'expr': 0, 'sid': sid, 'scriptversion': 1,
\ 'lnum': lnum + 1,
\ 'rhs': 'is<F4>foo', 'buffer': 0},
\ maparg('foo<C-V>', '', 0, 1))
call assert_equal({'silent': 1, 'noremap': 1, 'script': 1, 'lhs': 'bar',
\ 'lhsraw': 'bar', 'mode': 'v',
\ 'nowait': 0, 'expr': 1, 'sid': sid, 'lnum': lnum + 2,
\ 'nowait': 0, 'expr': 1, 'sid': sid, 'scriptversion': 1,
\ 'lnum': lnum + 2,
\ 'rhs': 'isbar', 'buffer': 1},
\ 'bar'->maparg('', 0, 1))
let lnum = expand('<sflnum>')
map <buffer> <nowait> foo bar
call assert_equal({'silent': 0, 'noremap': 0, 'script': 0, 'lhs': 'foo',
\ 'lhsraw': 'foo', 'mode': ' ',
\ 'nowait': 1, 'expr': 0, 'sid': sid, 'lnum': lnum + 1, 'rhs': 'bar',
\ 'nowait': 1, 'expr': 0, 'sid': sid, 'scriptversion': 1,
\ 'lnum': lnum + 1, 'rhs': 'bar',
\ 'buffer': 1},
\ maparg('foo', '', 0, 1))
let lnum = expand('<sflnum>')
tmap baz foo
call assert_equal({'silent': 0, 'noremap': 0, 'script': 0, 'lhs': 'baz',
\ 'lhsraw': 'baz', 'mode': 't',
\ 'nowait': 0, 'expr': 0, 'sid': sid, 'lnum': lnum + 1, 'rhs': 'foo',
\ 'nowait': 0, 'expr': 0, 'sid': sid, 'scriptversion': 1,
\ 'lnum': lnum + 1, 'rhs': 'foo',
\ 'buffer': 0},
\ maparg('baz', 't', 0, 1))

View File

@@ -704,6 +704,11 @@ func Test_mapcomplete()
mapclear
endfunc
func GetAbbrText()
unabbr hola
return 'hello'
endfunc
" Test for <expr> in abbreviation
func Test_expr_abbr()
new
@@ -719,7 +724,14 @@ func Test_expr_abbr()
call assert_equal('', getline(1))
unabbr <expr> hte
close!
" evaluating the expression deletes the abbreviation
abbr <expr> hola GetAbbrText()
call assert_equal('GetAbbrText()', maparg('hola', 'i', '1'))
call feedkeys("ahola \<Esc>", 'xt')
call assert_equal('hello ', getline('.'))
call assert_equal('', maparg('hola', 'i', '1'))
bwipe!
endfunc
" Test for storing mappings in different modes in a vimrc file
@@ -1411,6 +1423,22 @@ func Test_map_script_cmd_restore()
unlet g:result
endfunc
func Test_map_script_cmd_finds_func()
let lines =<< trim END
vim9script
onoremap <F3> <ScriptCmd>Func()<CR>
def Func()
g:func_called = 'yes'
enddef
END
call CheckScriptSuccess(lines)
call feedkeys("y\<F3>\<Esc>", 'xtc')
call assert_equal('yes', g:func_called)
ounmap <F3>
unlet g:func_called
endfunc
" Test for using <script> with a map to remap characters in rhs
func Test_script_local_remap()
new

View File

@@ -23,6 +23,10 @@ func Test_scriptnames()
bwipe
call delete('Xscripting')
let msgs = execute('messages')
scriptnames
call assert_equal(msgs, execute('messages'))
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@@ -589,10 +589,10 @@ func Test_command_list()
\ execute('command DoCmd'))
" Test output in verbose mode.
command! DoCmd :
command! -nargs=+ -complete=customlist,SomeFunc DoCmd :ls
call assert_match("^\n"
\ .. " Name Args Address Complete Definition\n"
\ .. " DoCmd 0 :\n"
\ .. " DoCmd + customlist,SomeFunc :ls\n"
\ .. "\tLast set from .*/test_usercommands.vim line \\d\\+$",
\ execute('verbose command DoCmd'))

View File

@@ -2278,6 +2278,7 @@ def Test_maparg()
nowait: 0,
expr: 0,
sid: SID(),
scriptversion: 999999,
rhs: 'bar',
buffer: 0})
unmap foo

View File

@@ -1717,7 +1717,7 @@ let g:dict_one = #{one: 1}
let $TESTVAR = 'testvar'
" type casts
def Test_expr7t()
def Test_expr7()
var lines =<< trim END
var ls: list<string> = ['a', <string>g:string_empty]
var ln: list<number> = [<number>g:anint, <number>g:thefour]
@@ -1743,7 +1743,7 @@ def Test_expr7t()
enddef
" test low level expression
def Test_expr7_number()
def Test_expr8_number()
# number constant
var lines =<< trim END
assert_equal(0, 0)
@@ -1756,7 +1756,7 @@ def Test_expr7_number()
CheckDefAndScriptSuccess(lines)
enddef
def Test_expr7_float()
def Test_expr8_float()
# float constant
if !has('float')
MissingFeature 'float'
@@ -1771,7 +1771,7 @@ def Test_expr7_float()
endif
enddef
def Test_expr7_blob()
def Test_expr8_blob()
# blob constant
var lines =<< trim END
assert_equal(g:blob_empty, 0z)
@@ -1803,7 +1803,7 @@ def Test_expr7_blob()
CheckDefAndScriptFailure(["var x = 0z123"], 'E973:', 1)
enddef
def Test_expr7_string()
def Test_expr8_string()
# string constant
var lines =<< trim END
assert_equal(g:string_empty, '')
@@ -1820,7 +1820,7 @@ def Test_expr7_string()
CheckDefAndScriptFailure(["var x = 'abc"], 'E115:', 1)
enddef
def Test_expr7_vimvar()
def Test_expr8_vimvar()
v:errors = []
var errs: list<string> = v:errors
CheckDefFailure(['var errs: list<number> = v:errors'], 'E1012:')
@@ -1845,7 +1845,7 @@ def Test_expr7_vimvar()
bwipe!
enddef
def Test_expr7_special()
def Test_expr8_special()
# special constant
var lines =<< trim END
assert_equal(g:special_true, true)
@@ -1882,7 +1882,7 @@ def Test_expr7_special()
CheckDefAndScriptFailure(['v:none = 22'], 'E46:', 1)
enddef
def Test_expr7_list()
def Test_expr8_list()
# list
var lines =<< trim END
assert_equal(g:list_empty, [])
@@ -1955,7 +1955,7 @@ def Test_expr7_list()
CheckDefAndScriptFailure(lines + ['echo numbers[a :b]'], 'E1004:', 4)
enddef
def Test_expr7_list_vim9script()
def Test_expr8_list_vim9script()
var lines =<< trim END
var l = [
11,
@@ -2043,7 +2043,7 @@ def LambdaUsingArg(x: number): func
x == 2
enddef
def Test_expr7_lambda()
def Test_expr8_lambda()
var lines =<< trim END
var La = () => 'result'
# comment
@@ -2129,7 +2129,7 @@ def Test_expr7_lambda()
CheckDefAndScriptSuccess(lines)
enddef
def Test_expr7_lambda_block()
def Test_expr8_lambda_block()
var lines =<< trim END
var Func = (s: string): string => {
return 'hello ' .. s
@@ -2209,7 +2209,7 @@ def NewLambdaUsingArg(x: number): func
x == 2
enddef
def Test_expr7_new_lambda()
def Test_expr8_new_lambda()
var lines =<< trim END
var La = () => 'result'
assert_equal('result', La())
@@ -2294,7 +2294,7 @@ def Test_expr7_new_lambda()
CheckDefAndScriptFailure(['var Fx = (a) => [0', ' 1]'], 'E696:', 2)
enddef
def Test_expr7_lambda_vim9script()
def Test_expr8_lambda_vim9script()
var lines =<< trim END
var v = 10->((a) =>
a
@@ -2313,7 +2313,7 @@ def Test_expr7_lambda_vim9script()
CheckDefAndScriptSuccess(lines)
enddef
def Test_expr7_funcref()
def Test_expr8_funcref()
var lines =<< trim END
def RetNumber(): number
return 123
@@ -2350,7 +2350,7 @@ enddef
let g:test_space_dict = {'': 'empty', ' ': 'space'}
let g:test_hash_dict = #{one: 1, two: 2}
def Test_expr7_dict()
def Test_expr8_dict()
# dictionary
var lines =<< trim END
assert_equal(g:dict_empty, {})
@@ -2461,7 +2461,7 @@ def Test_expr7_dict()
CheckDefExecAndScriptFailure(['{}[getftype("file")]'], 'E716: Key not present in Dictionary: ""', 1)
enddef
def Test_expr7_dict_vim9script()
def Test_expr8_dict_vim9script()
var lines =<< trim END
var d = {
['one']:
@@ -2592,7 +2592,7 @@ def Test_expr7_dict_vim9script()
CheckScriptSuccess(lines)
enddef
def Test_expr7_dict_in_block()
def Test_expr8_dict_in_block()
var lines =<< trim END
vim9script
command MyCommand {
@@ -2615,7 +2615,7 @@ def Test_expr7_dict_in_block()
delcommand YourCommand
enddef
def Test_expr7_call_2bool()
def Test_expr8_call_2bool()
var lines =<< trim END
vim9script
@@ -2663,7 +2663,7 @@ def Test_expr_member()
CheckDefExecAndScriptFailure(["var d: dict<number>", "d = g:list_empty"], 'E1012: Type mismatch; expected dict<number> but got list<unknown>', 2)
enddef
def Test_expr7_any_index_slice()
def Test_expr8_any_index_slice()
var lines =<< trim END
# getting the one member should clear the list only after getting the item
assert_equal('bbb', ['aaa', 'bbb', 'ccc'][1])
@@ -2817,7 +2817,7 @@ def SetSomeVar()
b:someVar = &fdm
enddef
def Test_expr7_option()
def Test_expr8_option()
var lines =<< trim END
# option
set ts=11
@@ -2844,7 +2844,7 @@ def Test_expr7_option()
CheckDefAndScriptSuccess(lines)
enddef
def Test_expr7_environment()
def Test_expr8_environment()
var lines =<< trim END
# environment variable
assert_equal('testvar', $TESTVAR)
@@ -2856,7 +2856,7 @@ def Test_expr7_environment()
CheckDefAndScriptFailure(["$"], ['E1002:', 'E15:'], 1)
enddef
def Test_expr7_register()
def Test_expr8_register()
var lines =<< trim END
@a = 'register a'
assert_equal('register a', @a)
@@ -2882,7 +2882,7 @@ def Test_expr7_register()
enddef
" This is slow when run under valgrind.
def Test_expr7_namespace()
def Test_expr8_namespace()
var lines =<< trim END
g:some_var = 'some'
assert_equal('some', get(g:, 'some_var'))
@@ -2911,7 +2911,7 @@ def Test_expr7_namespace()
CheckDefAndScriptSuccess(lines)
enddef
def Test_expr7_namespace_loop_def()
def Test_expr8_namespace_loop_def()
var lines =<< trim END
# check using g: in a for loop more than DO_NOT_FREE_CNT times
var exists = 0
@@ -2930,8 +2930,8 @@ def Test_expr7_namespace_loop_def()
enddef
" NOTE: this is known to be slow. To skip use:
" :let $TEST_SKIP_PAT = 'Test_expr7_namespace_loop_script'
def Test_expr7_namespace_loop_script()
" :let $TEST_SKIP_PAT = 'Test_expr8_namespace_loop_script'
def Test_expr8_namespace_loop_script()
var lines =<< trim END
vim9script
# check using g: in a for loop more than DO_NOT_FREE_CNT times
@@ -2950,7 +2950,7 @@ def Test_expr7_namespace_loop_script()
CheckScriptSuccess(lines)
enddef
def Test_expr7_parens()
def Test_expr8_parens()
# (expr)
var lines =<< trim END
assert_equal(4, (6 * 4) / 6)
@@ -2982,7 +2982,7 @@ def Test_expr7_parens()
CheckDefAndScriptSuccess(lines)
enddef
def Test_expr7_negate_add()
def Test_expr8_negate_add()
var lines =<< trim END
assert_equal(-99, -99)
assert_equal(-99, - 99)
@@ -3031,7 +3031,7 @@ def LegacyReturn(): string
legacy return #{key: 'ok'}.key
enddef
def Test_expr7_legacy_script()
def Test_expr8_legacy_script()
var lines =<< trim END
let s:legacy = 'legacy'
def GetLocal(): string
@@ -3065,7 +3065,7 @@ def s:Echo4Arg(arg: any): string
return arg
enddef
def Test_expr7_call()
def Test_expr8_call()
var lines =<< trim END
assert_equal('yes', 'yes'->Echo())
assert_equal(true, !range(5)->empty())
@@ -3098,7 +3098,7 @@ def Test_expr7_call()
delete('Xruntime', 'rf')
enddef
def Test_expr7_method_call()
def Test_expr8_method_call()
var lines =<< trim END
new
setline(1, ['first', 'last'])
@@ -3139,6 +3139,34 @@ def Test_expr7_method_call()
END
CheckDefAndScriptSuccess(lines)
lines =<< trim END
def SetNumber(n: number)
g:number = n
enddef
const Setit = SetNumber
len('text')->Setit()
assert_equal(4, g:number)
const SetFuncref = funcref(SetNumber)
len('longer')->SetFuncref()
assert_equal(6, g:number)
const SetList = [SetNumber, SetFuncref]
len('xx')->SetList[0]()
assert_equal(2, g:number)
len('xxx')->SetList[1]()
assert_equal(3, g:number)
const SetDict = {key: SetNumber}
len('xxxx')->SetDict['key']()
assert_equal(4, g:number)
len('xxxxx')->SetDict.key()
assert_equal(5, g:number)
unlet g:number
END
CheckDefAndScriptSuccess(lines)
lines =<< trim END
def RetVoid()
enddef
@@ -3147,7 +3175,7 @@ def Test_expr7_method_call()
CheckDefExecFailure(lines, 'E1013:')
enddef
def Test_expr7_method_call_linebreak()
def Test_expr8_method_call_linebreak()
# this was giving an error when skipping over the expression
var lines =<< trim END
vim9script
@@ -3163,8 +3191,42 @@ def Test_expr7_method_call_linebreak()
CheckScriptSuccess(lines)
enddef
def Test_expr8_method_call_import()
var lines =<< trim END
vim9script
export def Square(items: list<number>): list<number>
return map(items, (_, i) => i * i)
enddef
END
call writefile(lines, 'Xsquare.vim')
def Test_expr7_not()
lines =<< trim END
vim9script
import './Xsquare.vim'
def Test(): list<number>
return range(5)
->Xsquare.Square()
->map((_, i) => i * 10)
enddef
assert_equal([0, 10, 40, 90, 160], Test())
END
CheckScriptSuccess(lines)
lines =<< trim END
vim9script
import './Xsquare.vim'
echo range(5)->Xsquare.NoSuchFunc()
END
CheckScriptFailure(lines, 'E1048: Item not found in script: NoSuchFunc')
delete('Xsquare.vim')
enddef
def Test_expr8_not()
var lines =<< trim END
assert_equal(true, !'')
assert_equal(true, ![])
@@ -3216,7 +3278,7 @@ enddef
let g:anumber = 42
def Test_expr7_negate()
def Test_expr8_negate()
var lines =<< trim END
var nr = 1
assert_equal(-1, -nr)
@@ -3225,7 +3287,7 @@ def Test_expr7_negate()
CheckDefAndScriptSuccess(lines)
enddef
func Test_expr7_fails()
func Test_expr8_fails()
call CheckDefFailure(["var x = (12"], "E1097:", 3)
call CheckScriptFailure(['vim9script', "var x = (12"], 'E110:', 2)
@@ -3285,7 +3347,7 @@ func CallMe2(one, two)
return a:one .. a:two
endfunc
def Test_expr7_trailing()
def Test_expr8_trailing()
var lines =<< trim END
# user function call
assert_equal(123, g:CallMe(123))
@@ -3321,7 +3383,7 @@ def Test_expr7_trailing()
CheckDefAndScriptSuccess(lines)
enddef
def Test_expr7_string_subscript()
def Test_expr8_string_subscript()
var lines =<< trim END
var text = 'abcdef'
assert_equal('f', text[-1])
@@ -3420,7 +3482,7 @@ def Test_expr7_string_subscript()
CheckDefAndScriptFailure(lines, ['E1012: Type mismatch; expected number but got string', 'E1030: Using a String as a Number: "2"'], 1)
enddef
def Test_expr7_list_subscript()
def Test_expr8_list_subscript()
var lines =<< trim END
var list = [0, 1, 2, 3, 4]
assert_equal(0, list[0])
@@ -3463,7 +3525,7 @@ def Test_expr7_list_subscript()
CheckDefAndScriptSuccess(lines)
enddef
def Test_expr7_dict_subscript()
def Test_expr8_dict_subscript()
var lines =<< trim END
var l = [{lnum: 2}, {lnum: 1}]
var res = l[0].lnum > l[1].lnum
@@ -3484,7 +3546,7 @@ def Test_expr7_dict_subscript()
CheckDefAndScriptSuccess(lines)
enddef
def Test_expr7_blob_subscript()
def Test_expr8_blob_subscript()
var lines =<< trim END
var b = 0z112233
assert_equal(0x11, b[0])
@@ -3496,7 +3558,7 @@ def Test_expr7_blob_subscript()
CheckDefAndScriptSuccess(lines)
enddef
def Test_expr7_subscript_linebreak()
def Test_expr8_subscript_linebreak()
var lines =<< trim END
var range = range(
3)
@@ -3539,7 +3601,7 @@ def Test_expr7_subscript_linebreak()
CheckDefAndScriptFailure(lines, ['E1127:', 'E116:'], 2)
enddef
func Test_expr7_trailing_fails()
func Test_expr8_trailing_fails()
call CheckDefAndScriptFailure(['var l = [2]', 'l->((ll) => add(ll, 8))'], 'E107:', 2)
call CheckDefAndScriptFailure(['var l = [2]', 'l->((ll) => add(ll, 8)) ()'], 'E274:', 2)
endfunc

View File

@@ -341,6 +341,20 @@ def Test_return_something()
ReturnString()->assert_equal('string')
ReturnNumber()->assert_equal(123)
assert_fails('ReturnGlobal()', 'E1012: Type mismatch; expected number but got string', '', 1, 'ReturnGlobal')
var lines =<< trim END
vim9script
def Msg()
echomsg 'in Msg()...'
enddef
def Func()
return Msg()
enddef
defcompile
END
CheckScriptFailure(lines, 'E1096:')
enddef
def Test_check_argument_type()

View File

@@ -69,6 +69,7 @@ def Test_vim9_import_export()
g:imported_name = expo.exp_name
expo.exp_name ..= ' Doe'
expo.exp_name = expo.exp_name .. ' Maar'
g:imported_name_appended = expo.exp_name
g:exported_later = expo.exported
@@ -97,7 +98,7 @@ def Test_vim9_import_export()
assert_equal('Exported', g:imported_func)
assert_equal('Exported', g:funcref_result)
assert_equal('John', g:imported_name)
assert_equal('John Doe', g:imported_name_appended)
assert_equal('John Doe Maar', g:imported_name_appended)
assert_false(exists('g:name'))
Undo_export_script_lines()
@@ -579,6 +580,29 @@ def Test_use_import_in_mapping()
nunmap <F3>
enddef
def Test_use_import_in_completion()
var lines =<< trim END
vim9script
export def Complete(..._): list<string>
return ['abcd']
enddef
END
writefile(lines, 'Xscript.vim')
lines =<< trim END
vim9script
import './Xscript.vim'
command -nargs=1 -complete=customlist,Xscript.Complete Cmd echo 'ok'
feedkeys(":Cmd ab\<Tab>\<C-B>#\<CR>", 'xnt')
assert_equal('#Cmd abcd', @:)
END
CheckScriptSuccess(lines)
delcommand Cmd
delete('Xscript.vim')
enddef
def Test_export_fails()
CheckScriptFailure(['export var some = 123'], 'E1042:')
CheckScriptFailure(['vim9script', 'export var g:some'], 'E1022:')
@@ -1172,9 +1196,9 @@ def Test_vim9script_autoload()
var save_rtp = &rtp
exe 'set rtp^=' .. getcwd() .. '/Xdir'
# when using "vim9script autoload" prefix is not needed
# when the path has "/autoload/" prefix is not needed
var lines =<< trim END
vim9script autoload
vim9script
g:prefixed_loaded += 1
export def Gettest(): string
@@ -1232,13 +1256,147 @@ def Test_vim9script_autoload()
&rtp = save_rtp
enddef
def Test_import_autoload_not_exported()
mkdir('Xdir/autoload', 'p')
var save_rtp = &rtp
exe 'set rtp^=' .. getcwd() .. '/Xdir'
# error when using an item that is not exported from an autoload script
var exportLines =<< trim END
vim9script
var notExported = 123
def NotExport()
echo 'nop'
enddef
END
writefile(exportLines, 'Xdir/autoload/notExport1.vim')
var lines =<< trim END
vim9script
import autoload 'notExport1.vim'
echo notExport1.notFound
END
CheckScriptFailure(lines, 'E1048: Item not found in script: notFound')
lines =<< trim END
vim9script
import autoload 'notExport1.vim'
echo notExport1.notExported
END
CheckScriptFailure(lines, 'E1049: Item not exported in script: notExported')
lines =<< trim END
vim9script
import autoload 'notExport1.vim'
echo notExport1.NotFunc()
END
CheckScriptFailure(lines, 'E1048: Item not found in script: NotFunc')
lines =<< trim END
vim9script
import autoload 'notExport1.vim'
echo notExport1.NotExport()
END
CheckScriptFailure(lines, 'E1049: Item not exported in script: NotExport')
lines =<< trim END
vim9script
import autoload 'notExport1.vim'
echo 'text'->notExport1.NotFunc()
END
CheckScriptFailure(lines, 'E1048: Item not found in script: NotFunc')
lines =<< trim END
vim9script
import autoload 'notExport1.vim'
echo 'text'->notExport1.NotExport()
END
CheckScriptFailure(lines, 'E1049: Item not exported in script: NotExport')
# using a :def function we use a different autoload script every time so that
# the function is compiled without the script loaded
writefile(exportLines, 'Xdir/autoload/notExport2.vim')
lines =<< trim END
vim9script
import autoload 'notExport2.vim'
def Testit()
echo notExport2.notFound
enddef
Testit()
END
CheckScriptFailure(lines, 'E1048: Item not found in script: notExport2#notFound')
writefile(exportLines, 'Xdir/autoload/notExport3.vim')
lines =<< trim END
vim9script
import autoload 'notExport3.vim'
def Testit()
echo notExport3.notExported
enddef
Testit()
END
# don't get E1049 because it is too complicated to figure out
CheckScriptFailure(lines, 'E1048: Item not found in script: notExport3#notExported')
writefile(exportLines, 'Xdir/autoload/notExport4.vim')
lines =<< trim END
vim9script
import autoload 'notExport4.vim'
def Testit()
echo notExport4.NotFunc()
enddef
Testit()
END
CheckScriptFailure(lines, 'E117: Unknown function: notExport4#NotFunc')
writefile(exportLines, 'Xdir/autoload/notExport5.vim')
lines =<< trim END
vim9script
import autoload 'notExport5.vim'
def Testit()
echo notExport5.NotExport()
enddef
Testit()
END
CheckScriptFailure(lines, 'E117: Unknown function: notExport5#NotExport')
writefile(exportLines, 'Xdir/autoload/notExport6.vim')
lines =<< trim END
vim9script
import autoload 'notExport6.vim'
def Testit()
echo 'text'->notExport6.NotFunc()
enddef
Testit()
END
CheckScriptFailure(lines, 'E117: Unknown function: notExport6#NotFunc')
writefile(exportLines, 'Xdir/autoload/notExport7.vim')
lines =<< trim END
vim9script
import autoload 'notExport7.vim'
def Testit()
echo 'text'->notExport7.NotExport()
enddef
Testit()
END
CheckScriptFailure(lines, 'E117: Unknown function: notExport7#NotExport')
delete('Xdir', 'rf')
&rtp = save_rtp
enddef
def Test_vim9script_autoload_call()
mkdir('Xdir/autoload', 'p')
var save_rtp = &rtp
exe 'set rtp^=' .. getcwd() .. '/Xdir'
var lines =<< trim END
vim9script autoload
vim9script
export def RetArg(arg: string): string
return arg
enddef
export def Getother()
g:result = 'other'
@@ -1249,6 +1407,13 @@ def Test_vim9script_autoload_call()
lines =<< trim END
vim9script
import autoload 'another.vim'
# compile this before 'another.vim' is loaded
def CallAnother()
assert_equal('foo', 'foo'->another.RetArg())
enddef
CallAnother()
call another.Getother()
assert_equal('other', g:result)
END
@@ -1265,7 +1430,7 @@ def Test_import_autoload_postponed()
exe 'set rtp^=' .. getcwd() .. '/Xdir'
var lines =<< trim END
vim9script autoload
vim9script
g:loaded_postponed = 'true'
export var variable = 'bla'
@@ -1302,7 +1467,7 @@ def Test_import_autoload_override()
test_override('autoload', 1)
var lines =<< trim END
vim9script autoload
vim9script
g:loaded_override = 'true'
export var variable = 'bla'
@@ -1337,7 +1502,7 @@ def Test_autoload_mapping()
exe 'set rtp^=' .. getcwd() .. '/Xdir'
var lines =<< trim END
vim9script autoload
vim9script
g:toggle_loaded = 'yes'
@@ -1362,10 +1527,12 @@ def Test_autoload_mapping()
CheckScriptSuccess(lines)
assert_false(exists("g:toggle_loaded"))
assert_false(exists("g:toggle_called"))
assert_match('\d A: \f*[/\\]toggle.vim', execute('scriptnames'))
feedkeys("tt", 'xt')
assert_equal('yes', g:toggle_loaded)
assert_equal('yes', g:toggle_called)
assert_match('\d: \f*[/\\]toggle.vim', execute('scriptnames'))
feedkeys("xx", 'xt')
assert_equal('yes', g:doit_called)
@@ -1386,7 +1553,13 @@ def Test_vim9script_autoload_fails()
vim9script autoload
var n = 0
END
CheckScriptFailure(lines, 'E1263:')
CheckScriptFailure(lines, 'E475: Invalid argument: autoload')
lines =<< trim END
vim9script noclear noclear
var n = 0
END
CheckScriptFailure(lines, 'E983: Duplicate argument: noclear')
enddef
def Test_import_autoload_fails()
@@ -1398,9 +1571,21 @@ def Test_import_autoload_fails()
lines =<< trim END
vim9script
import autoload 'doesNotExist.vim'
import autoload './doesNotExist.vim'
END
CheckScriptFailure(lines, 'E1264:')
lines =<< trim END
vim9script
import autoload '/dir/doesNotExist.vim'
END
CheckScriptFailure(lines, 'E1264:')
lines =<< trim END
vim9script
import autoload 'doesNotExist.vim'
END
CheckScriptFailure(lines, 'E1053: Could not import "doesNotExist.vim"')
enddef
" test disassembling an auto-loaded function starting with "debug"
@@ -1467,7 +1652,7 @@ enddef
" test using a autoloaded file that is case sensitive
def Test_vim9_autoload_case_sensitive()
var lines =<< trim END
vim9script autoload
vim9script
export def CaseSensitive(): string
return 'done'
enddef

View File

@@ -1278,6 +1278,17 @@ func Test_visual_block_ctrl_w_f()
au! BufNew
endfunc
func Test_visual_block_append_invalid_char()
" this was going over the end of the line
set isprint=@,161-255
new
call setline(1, [' let xxx', 'xxxxxˆ', 'xxxxxxxxxxx'])
exe "normal 0\<C-V>jjA-\<Esc>"
call assert_equal([' - let xxx', 'xxxxx -ˆ', 'xxxxxxxx-xxx'], getline(1, 3))
bwipe!
set isprint&
endfunc
func Test_visual_reselect_with_count()
" this was causing an illegal memory access
let lines =<< trim END

View File

@@ -123,10 +123,10 @@ static struct
char_u *
find_ucmd(
exarg_T *eap,
char_u *p, // end of the command (possibly including count)
int *full, // set to TRUE for a full match
expand_T *xp, // used for completion, NULL otherwise
int *complp UNUSED) // completion flags or NULL
char_u *p, // end of the command (possibly including count)
int *full, // set to TRUE for a full match
expand_T *xp, // used for completion, NULL otherwise
int *complp) // completion flags or NULL
{
int len = (int)(p - eap->cmd);
int j, k, matchlen = 0;
@@ -548,6 +548,15 @@ uc_list(char_u *name, size_t name_len)
{
STRCPY(IObuff + len, command_complete[j].name);
len += (int)STRLEN(IObuff + len);
#ifdef FEAT_EVAL
if (p_verbose > 0 && cmd->uc_compl_arg != NULL
&& STRLEN(cmd->uc_compl_arg) < 200)
{
IObuff[len] = ',';
STRCPY(IObuff + len + 1, cmd->uc_compl_arg);
len += (int)STRLEN(IObuff + len);
}
#endif
break;
}

View File

@@ -3119,18 +3119,30 @@ free_all_functions(void)
/*
* Return TRUE if "name" looks like a builtin function name: starts with a
* lower case letter and doesn't contain AUTOLOAD_CHAR or ':'.
* lower case letter, doesn't contain AUTOLOAD_CHAR or ':', no "." after the
* name.
* "len" is the length of "name", or -1 for NUL terminated.
*/
int
builtin_function(char_u *name, int len)
{
char_u *p;
int i;
if (!ASCII_ISLOWER(name[0]) || name[1] == ':')
return FALSE;
p = vim_strchr(name, AUTOLOAD_CHAR);
return p == NULL || (len > 0 && p > name + len);
for (i = 0; name[i] != NUL && (len < 0 || i < len); ++i)
{
if (name[i] == AUTOLOAD_CHAR)
return FALSE;
if (!eval_isnamec(name[i]))
{
// "name.something" is not a builtin function
if (name[i] == '.')
return FALSE;
break;
}
}
return TRUE;
}
int
@@ -3386,7 +3398,8 @@ call_func(
&& funcexe->fe_evaluate)
{
// Check that the argument types are OK for the types of the funcref.
if (check_argument_types(funcexe->fe_check_type, argvars, argcount,
if (check_argument_types(funcexe->fe_check_type,
argvars, argcount, funcexe->fe_basetv,
(name != NULL) ? name : funcname) == FAIL)
error = FCERR_OTHER;
}

View File

@@ -750,6 +750,64 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
4141,
/**/
4140,
/**/
4139,
/**/
4138,
/**/
4137,
/**/
4136,
/**/
4135,
/**/
4134,
/**/
4133,
/**/
4132,
/**/
4131,
/**/
4130,
/**/
4129,
/**/
4128,
/**/
4127,
/**/
4126,
/**/
4125,
/**/
4124,
/**/
4123,
/**/
4122,
/**/
4121,
/**/
4120,
/**/
4119,
/**/
4118,
/**/
4117,
/**/
4116,
/**/
4115,
/**/
4114,
/**/
4113,
/**/
4112,
/**/

View File

@@ -1074,7 +1074,7 @@ extern int (*dyn_libintl_wputenv)(const wchar_t *envstring);
#define DOCMD_KEYTYPED 0x08 // don't reset KeyTyped
#define DOCMD_EXCRESET 0x10 // reset exception environment (for debugging)
#define DOCMD_KEEPLINE 0x20 // keep typed line for repeating with "."
#define DOCMD_RANGEOK 0240 // can use a range without ":" in Vim9 script
#define DOCMD_RANGEOK 0x40 // can use a range without ":" in Vim9 script
// flags for beginline()
#define BL_WHITE 1 // cursor on first non-white in the line

View File

@@ -2196,6 +2196,11 @@ compile_return(char_u *arg, int check_return_type, int legacy, cctx_T *cctx)
if (*p != NUL && *p != '|' && *p != '\n')
{
if (cctx->ctx_ufunc->uf_ret_type->tt_type == VAR_VOID)
{
emsg(_(e_returning_value_in_function_without_return_type));
return NULL;
}
if (legacy)
{
int save_flags = cmdmod.cmod_flags;
@@ -2231,13 +2236,6 @@ compile_return(char_u *arg, int check_return_type, int legacy, cctx_T *cctx)
}
else
{
if (cctx->ctx_ufunc->uf_ret_type->tt_type == VAR_VOID
&& stack_type->tt_type != VAR_VOID
&& stack_type->tt_type != VAR_UNKNOWN)
{
emsg(_(e_returning_value_in_function_without_return_type));
return NULL;
}
if (need_type(stack_type, cctx->ctx_ufunc->uf_ret_type, -1,
0, cctx, FALSE, FALSE) == FAIL)
return NULL;

View File

@@ -2200,10 +2200,12 @@ exec_instructions(ectx_T *ectx)
case ISN_LOADW:
case ISN_LOADT:
{
dictitem_T *di = NULL;
hashtab_T *ht = NULL;
char namespace;
dictitem_T *di = NULL;
hashtab_T *ht = NULL;
char namespace;
if (GA_GROW_FAILS(&ectx->ec_stack, 1))
goto theend;
switch (iptr->isn_type)
{
case ISN_LOADG:
@@ -2227,9 +2229,12 @@ exec_instructions(ectx_T *ectx)
}
di = find_var_in_ht(ht, 0, iptr->isn_arg.string, TRUE);
if (di == NULL && ht == get_globvar_ht())
if (di == NULL && ht == get_globvar_ht()
&& vim_strchr(iptr->isn_arg.string,
AUTOLOAD_CHAR) != NULL)
{
// may need to load autoload script
// Global variable has an autoload name, may still need
// to load the script.
if (script_autoload(iptr->isn_arg.string, FALSE))
di = find_var_in_ht(ht, 0,
iptr->isn_arg.string, TRUE);
@@ -2240,14 +2245,19 @@ exec_instructions(ectx_T *ectx)
if (di == NULL)
{
SOURCING_LNUM = iptr->isn_lnum;
semsg(_(e_undefined_variable_char_str),
if (vim_strchr(iptr->isn_arg.string,
AUTOLOAD_CHAR) != NULL)
// no check if the item exists in the script but
// isn't exported, it is too complicated
semsg(_(e_item_not_found_in_script_str),
iptr->isn_arg.string);
else
semsg(_(e_undefined_variable_char_str),
namespace, iptr->isn_arg.string);
goto on_error;
}
else
{
if (GA_GROW_FAILS(&ectx->ec_stack, 1))
goto theend;
copy_tv(&di->di_tv, STACK_TV_BOT(0));
++ectx->ec_stack.ga_len;
}

View File

@@ -21,6 +21,9 @@
# include "vim9.h"
#endif
// flag passed from compile_subscript() to compile_load_scriptvar()
static int paren_follows_after_expr = 0;
/*
* Generate code for any ppconst entries.
*/
@@ -277,7 +280,6 @@ compile_load_scriptvar(
int done = FALSE;
int res = OK;
// TODO: if this is an autoload import do something else.
// Need to lookup the member.
if (*p != '.')
{
@@ -306,7 +308,7 @@ compile_load_scriptvar(
// autoload script must be loaded later, access by the autoload
// name.
if (cc == '(')
if (cc == '(' || paren_follows_after_expr)
res = generate_PUSHFUNC(cctx, auto_name, &t_func_any);
else
res = generate_LOAD(cctx, ISN_LOADG, 0, auto_name, &t_any);
@@ -1583,6 +1585,8 @@ compile_parenthesis(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
return ret;
}
static int compile_expr8(char_u **arg, cctx_T *cctx, ppconst_T *ppconst);
/*
* Compile whatever comes after "name" or "name()".
* Advances "*arg" only when something was recognized.
@@ -1651,13 +1655,15 @@ compile_subscript(
}
else if (*p == '-' && p[1] == '>')
{
char_u *pstart = p;
char_u *pstart = p;
int alt;
char_u *paren;
// something->method()
if (generate_ppconst(cctx, ppconst) == FAIL)
return FAIL;
ppconst->pp_is_const = FALSE;
// something->method()
// Apply the '!', '-' and '+' first:
// -1.0->func() works like (-1.0)->func()
if (compile_leader(cctx, TRUE, start_leader, end_leader) == FAIL)
@@ -1666,7 +1672,48 @@ compile_subscript(
p += 2;
*arg = skipwhite(p);
// No line break supported right after "->".
// Three alternatives handled here:
// 1. "base->name(" only a name, use compile_call()
// 2. "base->(expr)(" evaluate "expr", then use PCALL
// 3. "base->expr(" Same, find the end of "expr" by "("
if (**arg == '(')
alt = 2;
else
{
// alternative 1 or 3
p = *arg;
if (!eval_isnamec1(*p))
{
semsg(_(e_trailing_characters_str), pstart);
return FAIL;
}
if (ASCII_ISALPHA(*p) && p[1] == ':')
p += 2;
for ( ; eval_isnamec(*p); ++p)
;
if (*p == '(')
{
// alternative 1
alt = 1;
if (compile_call(arg, p - *arg, cctx, ppconst, 1) == FAIL)
return FAIL;
}
else
{
// Must be alternative 3, find the "(". Only works within
// one line.
alt = 3;
paren = vim_strchr(p, '(');
if (paren == NULL)
{
semsg(_(e_missing_parenthesis_str), *arg);
return FAIL;
}
}
}
if (alt != 1)
{
int argcount = 1;
garray_T *stack = &cctx->ctx_type_stack;
@@ -1676,16 +1723,40 @@ compile_subscript(
int expr_isn_end;
int arg_isn_count;
// Funcref call: list->(Refs[2])(arg)
// or lambda: list->((arg) => expr)(arg)
//
// Fist compile the function expression.
if (compile_parenthesis(arg, cctx, ppconst) == FAIL)
return FAIL;
if (alt == 2)
{
// Funcref call: list->(Refs[2])(arg)
// or lambda: list->((arg) => expr)(arg)
//
// Fist compile the function expression.
if (compile_parenthesis(arg, cctx, ppconst) == FAIL)
return FAIL;
}
else
{
int fail;
int save_len = cctx->ctx_ufunc->uf_lines.ga_len;
// Remember the next instruction index, where the instructions
// for arguments are being written.
expr_isn_end = cctx->ctx_instr.ga_len;
*paren = NUL;
// instead of using LOADG for "import.Func" use PUSHFUNC
++paren_follows_after_expr;
// do not look in the next line
cctx->ctx_ufunc->uf_lines.ga_len = 1;
fail = compile_expr8(arg, cctx, ppconst) == FAIL
|| *skipwhite(*arg) != NUL;
*paren = '(';
--paren_follows_after_expr;
cctx->ctx_ufunc->uf_lines.ga_len = save_len;
if (fail)
{
semsg(_(e_invalid_expression_str), pstart);
return FAIL;
}
}
// Compile the arguments.
if (**arg != '(')
@@ -1696,6 +1767,11 @@ compile_subscript(
semsg(_(e_missing_parenthesis_str), *arg);
return FAIL;
}
// Remember the next instruction index, where the instructions
// for arguments are being written.
expr_isn_end = cctx->ctx_instr.ga_len;
*arg = skipwhite(*arg + 1);
if (compile_arguments(arg, cctx, &argcount, FALSE) == FAIL)
return FAIL;
@@ -1742,27 +1818,7 @@ compile_subscript(
if (generate_PCALL(cctx, argcount, p - 2, type, FALSE) == FAIL)
return FAIL;
}
else
{
// method call: list->method()
p = *arg;
if (!eval_isnamec1(*p))
{
semsg(_(e_trailing_characters_str), pstart);
return FAIL;
}
if (ASCII_ISALPHA(*p) && p[1] == ':')
p += 2;
for ( ; eval_isnamec(*p); ++p)
;
if (*p != '(')
{
semsg(_(e_missing_parenthesis_str), *arg);
return FAIL;
}
if (compile_call(arg, p - *arg, cctx, ppconst, 1) == FAIL)
return FAIL;
}
if (keeping_dict)
{
keeping_dict = FALSE;

View File

@@ -69,7 +69,6 @@ ex_vim9script(exarg_T *eap UNUSED)
int sid = current_sctx.sc_sid;
scriptitem_T *si;
int found_noclear = FALSE;
int found_autoload = FALSE;
char_u *p;
if (!getline_equal(eap->getline, eap->cookie, getsourceline))
@@ -96,20 +95,6 @@ ex_vim9script(exarg_T *eap UNUSED)
}
found_noclear = TRUE;
}
else if (STRNCMP(p, "autoload", 8) == 0 && IS_WHITE_OR_NUL(p[8]))
{
if (found_autoload)
{
semsg(_(e_duplicate_argument_str), p);
return;
}
found_autoload = TRUE;
if (script_name_after_autoload(si) == NULL)
{
emsg(_(e_using_autoload_in_script_not_under_autoload_directory));
return;
}
}
else
{
semsg(_(e_invalid_argument_str), eap->arg);
@@ -411,7 +396,7 @@ handle_import(
int ret = FAIL;
char_u *as_name = NULL;
typval_T tv;
int sid = -1;
int sid = -2;
int res;
long start_lnum = SOURCING_LNUM;
garray_T *import_gap;
@@ -468,7 +453,13 @@ handle_import(
vim_free(from_name);
}
}
else if (mch_isFullName(tv.vval.v_string))
else if (mch_isFullName(tv.vval.v_string)
#ifdef BACKSLASH_IN_FILENAME
// On MS-Windows omitting the drive is still handled like an
// absolute path, not using 'runtimepath'.
|| *tv.vval.v_string == '/' || *tv.vval.v_string == '\\'
#endif
)
{
// Absolute path: "/tmp/name.vim"
if (is_autoload)
@@ -519,7 +510,7 @@ handle_import(
if (res == FAIL || sid <= 0)
{
semsg(_(is_autoload && sid <= 0
semsg(_(is_autoload && sid == -2
? e_autoload_import_cannot_use_absolute_or_relative_path
: e_could_not_import_str), tv.vval.v_string);
goto erret;
@@ -716,22 +707,36 @@ find_exported(
sprintf((char *)funcname + 3, "%ld_%s", (long)sid, name);
}
*ufunc = find_func(funcname, FALSE);
if (funcname != buffer)
vim_free(funcname);
if (*ufunc == NULL)
{
if (verbose)
semsg(_(e_item_not_found_in_script_str), name);
return -1;
{
ufunc_T *alt_ufunc = NULL;
if (script->sn_autoload_prefix != NULL)
{
// try find the function by the script-local name
funcname[0] = K_SPECIAL;
funcname[1] = KS_EXTRA;
funcname[2] = (int)KE_SNR;
sprintf((char *)funcname + 3, "%ld_%s", (long)sid, name);
alt_ufunc = find_func(funcname, FALSE);
}
if (alt_ufunc != NULL)
semsg(_(e_item_not_exported_in_script_str), name);
else
semsg(_(e_item_not_found_in_script_str), name);
}
}
else if (((*ufunc)->uf_flags & FC_EXPORT) == 0)
{
if (verbose)
semsg(_(e_item_not_exported_in_script_str), name);
*ufunc = NULL;
return -1;
}
if (funcname != buffer)
vim_free(funcname);
}
return idx;

View File

@@ -687,6 +687,7 @@ check_type_maybe(
/*
* Check that the arguments of "type" match "argvars[argcount]".
* "base_tv" is from "expr->Func()".
* Return OK/FAIL.
*/
int
@@ -694,19 +695,21 @@ check_argument_types(
type_T *type,
typval_T *argvars,
int argcount,
typval_T *base_tv,
char_u *name)
{
int varargs = (type->tt_flags & TTFLAG_VARARGS) ? 1 : 0;
int i;
int totcount = argcount + (base_tv == NULL ? 0 : 1);
if (type->tt_type != VAR_FUNC && type->tt_type != VAR_PARTIAL)
return OK; // just in case
if (argcount < type->tt_min_argcount - varargs)
if (totcount < type->tt_min_argcount - varargs)
{
semsg(_(e_not_enough_arguments_for_function_str), name);
return FAIL;
}
if (!varargs && type->tt_argcount >= 0 && argcount > type->tt_argcount)
if (!varargs && type->tt_argcount >= 0 && totcount > type->tt_argcount)
{
semsg(_(e_too_many_arguments_for_function_str), name);
return FAIL;
@@ -715,15 +718,25 @@ check_argument_types(
return OK; // cannot check
for (i = 0; i < argcount; ++i)
for (i = 0; i < totcount; ++i)
{
type_T *expected;
type_T *expected;
typval_T *tv;
if (base_tv != NULL)
{
if (i == 0)
tv = base_tv;
else
tv = &argvars[i - 1];
}
else
tv = &argvars[i];
if (varargs && i >= type->tt_argcount - 1)
expected = type->tt_args[type->tt_argcount - 1]->tt_member;
else
expected = type->tt_args[i];
if (check_typval_arg_type(expected, &argvars[i], NULL, i + 1) == FAIL)
if (check_typval_arg_type(expected, tv, NULL, i + 1) == FAIL)
return FAIL;
}
return OK;