summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2020-04-07 20:53:39 +0200
committerBram Moolenaar <Bram@vim.org>2020-04-07 20:53:39 +0200
commitec5929d0fe7e90f953fa5b019486c0c4e5826d92 (patch)
tree67cd19b5170a373c3bea0f4a9fe142fd2f78017b
parent86b9a3e8cd24335195dbe377b98bed1ba291268d (diff)
downloadvim-git-ec5929d0fe7e90f953fa5b019486c0c4e5826d92.tar.gz
patch 8.2.0527: Vim9: function types insufficiently testedv8.2.0527
Problem: Vim9: function types insufficiently tested. Solution: Add more tests. Fix white space check. Add "test_vim9" target.
-rw-r--r--src/Makefile2
-rw-r--r--src/testdir/Make_all.mak23
-rw-r--r--src/testdir/Makefile10
-rw-r--r--src/testdir/test_vim9_func.vim35
-rw-r--r--src/version.c2
-rw-r--r--src/vim9compile.c65
6 files changed, 101 insertions, 36 deletions
diff --git a/src/Makefile b/src/Makefile
index 704721b5f..c32ea0840 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -2301,7 +2301,7 @@ test1 \
# export TEST_FILTER=Test_terminal_wipe_buffer
# A partial match also works:
# export TEST_FILTER=wipe_buffer
-$(NEW_TESTS):
+$(NEW_TESTS) test_vim9:
cd testdir; $(MAKE) $@ VIMPROG=../$(VIMTESTTARGET) $(GUI_TESTARG) SCRIPTSOURCE=../$(SCRIPTSOURCE)
newtests:
diff --git a/src/testdir/Make_all.mak b/src/testdir/Make_all.mak
index 8ca783168..63d97e862 100644
--- a/src/testdir/Make_all.mak
+++ b/src/testdir/Make_all.mak
@@ -43,6 +43,19 @@ SCRIPTS_WIN32 =
# Tests for the GUI.
SCRIPTS_GUI =
+# Tests for Vim9 script.
+TEST_VIM9 = \
+ test_vim9_disassemble \
+ test_vim9_expr \
+ test_vim9_func \
+ test_vim9_script
+
+TEST_VIM9_RES = \
+ test_vim9_disassemble.res \
+ test_vim9_expr.res \
+ test_vim9_func.res \
+ test_vim9_script.res
+
# Individual tests, including the ones part of test_alot.
# Please keep sorted up to test_alot.
NEW_TESTS = \
@@ -272,10 +285,7 @@ NEW_TESTS = \
test_utf8 \
test_utf8_comparisons \
test_vartabs \
- test_vim9_disassemble \
- test_vim9_expr \
- test_vim9_func \
- test_vim9_script \
+ $(TEST_VIM9) \
test_viminfo \
test_vimscript \
test_virtualedit \
@@ -482,10 +492,7 @@ NEW_TESTS_RES = \
test_user_func.res \
test_usercommands.res \
test_vartabs.res \
- test_vim9_disassemble.res \
- test_vim9_expr.res \
- test_vim9_func.res \
- test_vim9_script.res \
+ $(TEST_VIM9_RES) \
test_viminfo.res \
test_vimscript.res \
test_virtualedit.res \
diff --git a/src/testdir/Makefile b/src/testdir/Makefile
index 746c84993..b2eaecbf4 100644
--- a/src/testdir/Makefile
+++ b/src/testdir/Makefile
@@ -79,6 +79,16 @@ $(NEW_TESTS):
exit 1; \
fi
+# Run only tests specific for Vim9 script
+test_vim9:
+ rm -f test_vim9_*.res test.log messages
+ @MAKEFLAGS=--no-print-directory $(MAKE) -f Makefile $(TEST_VIM9_RES) VIMPROG=$(VIMPROG) XXDPROG=$(XXDPROG) SCRIPTSOURCE=$(SCRIPTSOURCE)
+ @cat messages
+ @MAKEFLAGS=--no-print-directory $(MAKE) -f Makefile report VIMPROG=$(VIMPROG) XXDPROG=$(XXDPROG) SCRIPTSOURCE=$(SCRIPTSOURCE)
+ @if test -f test.log; then \
+ exit 1; \
+ fi
+
RM_ON_RUN = test.out X* viminfo
RM_ON_START = tiny.vim small.vim mbyte.vim mzscheme.vim test.ok benchmark.out
RUN_VIM = VIMRUNTIME=$(SCRIPTSOURCE) $(VALGRIND) $(VIMPROG) -f $(GUI_FLAG) -u unix.vim $(NO_INITS) -s dotest.in
diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim
index 5554b2d7e..fb2180fc9 100644
--- a/src/testdir/test_vim9_func.vim
+++ b/src/testdir/test_vim9_func.vim
@@ -373,6 +373,11 @@ def FuncNoArgRetNumber(): number
return 1234
enddef
+def FuncNoArgRetString(): string
+ funcResult = 45
+ return 'text'
+enddef
+
def FuncOneArgNoRet(arg: number)
funcResult = arg
enddef
@@ -382,6 +387,10 @@ def FuncOneArgRetNumber(arg: number): number
return arg
enddef
+def FuncOneArgRetString(arg: string): string
+ return arg
+enddef
+
def FuncOneArgRetAny(arg: any): any
return arg
enddef
@@ -415,6 +424,32 @@ def Test_func_type()
assert_equal(13, funcResult)
enddef
+def Test_func_type_part()
+ let RefVoid: func: void
+ RefVoid = FuncNoArgNoRet
+ RefVoid = FuncOneArgNoRet
+ CheckDefFailure(['let RefVoid: func: void', 'RefVoid = FuncNoArgRetNumber'], 'E1013: type mismatch, expected func() but got func(): number')
+ CheckDefFailure(['let RefVoid: func: void', 'RefVoid = FuncNoArgRetString'], 'E1013: type mismatch, expected func() but got func(): string')
+
+ let RefAny: func(): any
+ RefAny = FuncNoArgRetNumber
+ RefAny = FuncNoArgRetString
+ CheckDefFailure(['let RefAny: func(): any', 'RefAny = FuncNoArgNoRet'], 'E1013: type mismatch, expected func(): any but got func()')
+ CheckDefFailure(['let RefAny: func(): any', 'RefAny = FuncOneArgNoRet'], 'E1013: type mismatch, expected func(): any but got func(number)')
+
+ let RefNr: func: number
+ RefNr = FuncNoArgRetNumber
+ RefNr = FuncOneArgRetNumber
+ CheckDefFailure(['let RefNr: func: number', 'RefNr = FuncNoArgNoRet'], 'E1013: type mismatch, expected func(): number but got func()')
+ CheckDefFailure(['let RefNr: func: number', 'RefNr = FuncNoArgRetString'], 'E1013: type mismatch, expected func(): number but got func(): string')
+
+ let RefStr: func: string
+ RefStr = FuncNoArgRetString
+ RefStr = FuncOneArgRetString
+ CheckDefFailure(['let RefStr: func: string', 'RefStr = FuncNoArgNoRet'], 'E1013: type mismatch, expected func(): string but got func()')
+ CheckDefFailure(['let RefStr: func: string', 'RefStr = FuncNoArgRetNumber'], 'E1013: type mismatch, expected func(): string but got func(): number')
+enddef
+
def Test_func_type_fails()
CheckDefFailure(['let ref1: func()'], 'E704:')
diff --git a/src/version.c b/src/version.c
index bcf333b8d..f08ca11d3 100644
--- a/src/version.c
+++ b/src/version.c
@@ -739,6 +739,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 527,
+/**/
526,
/**/
525,
diff --git a/src/vim9compile.c b/src/vim9compile.c
index 359007a38..18fbdd36e 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -314,6 +314,11 @@ get_func_type(type_T *ret_type, int argcount, garray_T *type_gap)
// recognize commonly used types
if (argcount <= 0)
{
+ if (ret_type == &t_unknown)
+ {
+ // (argcount == 0) is not possible
+ return &t_func_unknown;
+ }
if (ret_type == &t_void)
{
if (argcount == 0)
@@ -350,6 +355,7 @@ get_func_type(type_T *ret_type, int argcount, garray_T *type_gap)
return &t_any;
type->tt_type = VAR_FUNC;
type->tt_member = ret_type;
+ type->tt_argcount = argcount;
type->tt_args = NULL;
return type;
}
@@ -1589,7 +1595,7 @@ parse_type(char_u **arg, garray_T *type_gap)
if (len == 4 && STRNCMP(*arg, "func", len) == 0)
{
type_T *type;
- type_T *ret_type = &t_any;
+ type_T *ret_type = &t_unknown;
int argcount = -1;
int flags = 0;
int first_optional = -1;
@@ -1657,7 +1663,7 @@ parse_type(char_u **arg, garray_T *type_gap)
{
// parse return type
++*arg;
- if (!VIM_ISWHITE(*p))
+ if (!VIM_ISWHITE(**arg))
semsg(_(e_white_after), ":");
*arg = skipwhite(*arg);
ret_type = parse_type(arg, type_gap);
@@ -2405,7 +2411,10 @@ check_type(type_T *expected, type_T *actual, int give_msg)
{
int ret = OK;
- if (expected->tt_type != VAR_UNKNOWN && expected->tt_type != VAR_ANY)
+ // When expected is "unknown" we accept any actual type.
+ // When expected is "any" we accept any actual type except "void".
+ if (expected->tt_type != VAR_UNKNOWN
+ && (expected->tt_type != VAR_ANY || actual->tt_type == VAR_VOID))
{
if (expected->tt_type != actual->tt_type)
{
@@ -2421,8 +2430,7 @@ check_type(type_T *expected, type_T *actual, int give_msg)
}
else if (expected->tt_type == VAR_FUNC)
{
- if (expected->tt_member != &t_any
- && expected->tt_member != &t_unknown)
+ if (expected->tt_member != &t_unknown)
ret = check_type(expected->tt_member, actual->tt_member, FALSE);
if (ret == OK && expected->tt_argcount != -1
&& (actual->tt_argcount < expected->tt_min_argcount
@@ -4044,36 +4052,39 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
if (r == FAIL)
goto theend;
- stack = &cctx->ctx_type_stack;
- stacktype = stack->ga_len == 0 ? &t_void
- : ((type_T **)stack->ga_data)[stack->ga_len - 1];
- if (idx >= 0 && (is_decl || !has_type))
+ if (cctx->ctx_skip != TRUE)
{
- lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
- if (new_local && !has_type)
+ stack = &cctx->ctx_type_stack;
+ stacktype = stack->ga_len == 0 ? &t_void
+ : ((type_T **)stack->ga_data)[stack->ga_len - 1];
+ if (idx >= 0 && (is_decl || !has_type))
{
- if (stacktype->tt_type == VAR_VOID)
- {
- emsg(_("E1031: Cannot use void value"));
- goto theend;
- }
- else
+ lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
+ if (new_local && !has_type)
{
- // An empty list or dict has a &t_void member, for a
- // variable that implies &t_any.
- if (stacktype == &t_list_empty)
- lvar->lv_type = &t_list_any;
- else if (stacktype == &t_dict_empty)
- lvar->lv_type = &t_dict_any;
+ if (stacktype->tt_type == VAR_VOID)
+ {
+ emsg(_("E1031: Cannot use void value"));
+ goto theend;
+ }
else
- lvar->lv_type = stacktype;
+ {
+ // An empty list or dict has a &t_void member, for a
+ // variable that implies &t_any.
+ if (stacktype == &t_list_empty)
+ lvar->lv_type = &t_list_any;
+ else if (stacktype == &t_dict_empty)
+ lvar->lv_type = &t_dict_any;
+ else
+ lvar->lv_type = stacktype;
+ }
}
+ else if (need_type(stacktype, lvar->lv_type, -1, cctx) == FAIL)
+ goto theend;
}
- else if (need_type(stacktype, lvar->lv_type, -1, cctx) == FAIL)
+ else if (*p != '=' && check_type(type, stacktype, TRUE) == FAIL)
goto theend;
}
- else if (*p != '=' && check_type(type, stacktype, TRUE) == FAIL)
- goto theend;
}
else if (cmdidx == CMD_const)
{