summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2020-08-10 23:09:37 +0200
committerBram Moolenaar <Bram@vim.org>2020-08-10 23:09:37 +0200
commit59eccb92e3c68f65525e08d2113213ff7d7ed00a (patch)
treefbeea20f8863f5fb8a4ba6e1a691061dd21e2a6a
parent8294d49937b99067522fda8a9399bb9533e3c44e (diff)
downloadvim-git-59eccb92e3c68f65525e08d2113213ff7d7ed00a.tar.gz
patch 8.2.1419: Vim9: not operator applied too earlyv8.2.1419
Problem: Vim9: not operator applied too early. Solution: Implement the "numeric_only" argument. (closes #6680)
-rw-r--r--src/testdir/test_vim9_expr.vim5
-rw-r--r--src/version.c2
-rw-r--r--src/vim9compile.c44
3 files changed, 35 insertions, 16 deletions
diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim
index f831b5abe..22ac442bc 100644
--- a/src/testdir/test_vim9_expr.vim
+++ b/src/testdir/test_vim9_expr.vim
@@ -1744,7 +1744,7 @@ def Test_expr7_call()
assert_equal('yes', 'yes'->Echo())
assert_equal('yes', 'yes'
->s:Echo4Arg())
- assert_equal(1, !range(5)->empty())
+ assert_equal(true, !range(5)->empty())
assert_equal([0, 1, 2], --3->range())
call CheckDefFailure(["let x = 'yes'->Echo"], 'E107:')
@@ -1782,6 +1782,9 @@ def Test_expr7_not()
assert_equal(true, !test_void())
assert_equal(true, !test_unknown())
+
+ assert_equal(false, ![1, 2, 3]->reverse())
+ assert_equal(true, ![]->reverse())
END
CheckDefSuccess(lines)
CheckScriptSuccess(['vim9script'] + lines)
diff --git a/src/version.c b/src/version.c
index bfd5070c4..990b945ab 100644
--- a/src/version.c
+++ b/src/version.c
@@ -755,6 +755,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 1419,
+/**/
1418,
/**/
1417,
diff --git a/src/vim9compile.c b/src/vim9compile.c
index 81206b3ac..d327b4855 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -2723,11 +2723,12 @@ compile_get_register(char_u **arg, cctx_T *cctx)
/*
* Apply leading '!', '-' and '+' to constant "rettv".
+ * When "numeric_only" is TRUE do not apply '!'.
*/
static int
-apply_leader(typval_T *rettv, char_u *start, char_u *end)
+apply_leader(typval_T *rettv, int numeric_only, char_u *start, char_u **end)
{
- char_u *p = end;
+ char_u *p = *end;
// this works from end to start
while (p > start)
@@ -2762,6 +2763,11 @@ apply_leader(typval_T *rettv, char_u *start, char_u *end)
rettv->vval.v_number = val;
}
}
+ else if (numeric_only)
+ {
+ ++p;
+ break;
+ }
else
{
int v = tv2bool(rettv);
@@ -2772,6 +2778,7 @@ apply_leader(typval_T *rettv, char_u *start, char_u *end)
rettv->vval.v_number = v ? VVAL_FALSE : VVAL_TRUE;
}
}
+ *end = p;
return OK;
}
@@ -2860,11 +2867,12 @@ get_compare_type(char_u *p, int *len, int *type_is)
/*
* Compile code to apply '-', '+' and '!'.
+ * When "numeric_only" is TRUE do not apply '!'.
*/
static int
-compile_leader(cctx_T *cctx, char_u *start, char_u *end)
+compile_leader(cctx_T *cctx, int numeric_only, char_u *start, char_u **end)
{
- char_u *p = end;
+ char_u *p = *end;
// this works from end to start
while (p > start)
@@ -2890,6 +2898,11 @@ compile_leader(cctx_T *cctx, char_u *start, char_u *end)
if (isn == NULL)
return FAIL;
}
+ else if (numeric_only)
+ {
+ ++p;
+ break;
+ }
else
{
int invert = TRUE;
@@ -2903,6 +2916,7 @@ compile_leader(cctx_T *cctx, char_u *start, char_u *end)
return FAIL;
}
}
+ *end = p;
return OK;
}
@@ -2914,10 +2928,12 @@ compile_leader(cctx_T *cctx, char_u *start, char_u *end)
compile_subscript(
char_u **arg,
cctx_T *cctx,
- char_u **start_leader,
- char_u *end_leader,
+ char_u *start_leader,
+ char_u **end_leader,
ppconst_T *ppconst)
{
+ char_u *name_start = *end_leader;
+
for (;;)
{
char_u *p = skipwhite(*arg);
@@ -2959,7 +2975,7 @@ compile_subscript(
*arg = skipwhite(p + 1);
if (compile_arguments(arg, cctx, &argcount) == FAIL)
return FAIL;
- if (generate_PCALL(cctx, argcount, end_leader, type, TRUE) == FAIL)
+ if (generate_PCALL(cctx, argcount, name_start, type, TRUE) == FAIL)
return FAIL;
}
else if (*p == '-' && p[1] == '>')
@@ -2972,9 +2988,8 @@ compile_subscript(
// something->method()
// Apply the '!', '-' and '+' first:
// -1.0->func() works like (-1.0)->func()
- if (compile_leader(cctx, *start_leader, end_leader) == FAIL)
+ if (compile_leader(cctx, TRUE, start_leader, end_leader) == FAIL)
return FAIL;
- *start_leader = end_leader; // don't apply again later
p += 2;
*arg = skipwhite(p);
@@ -3329,13 +3344,12 @@ compile_expr7(
if (rettv->v_type != VAR_UNKNOWN && used_before == ppconst->pp_used)
{
- // apply the '!', '-' and '+' before the constant
- if (apply_leader(rettv, start_leader, end_leader) == FAIL)
+ // apply the '-' and '+' before the constant, but not '!'
+ if (apply_leader(rettv, TRUE, start_leader, &end_leader) == FAIL)
{
clear_tv(rettv);
return FAIL;
}
- start_leader = end_leader; // don't apply again below
if (cctx->ctx_skip == SKIP_YES)
clear_tv(rettv);
@@ -3373,18 +3387,18 @@ compile_expr7(
// Handle following "[]", ".member", etc.
// Then deal with prefixed '-', '+' and '!', if not done already.
- if (compile_subscript(arg, cctx, &start_leader, end_leader,
+ if (compile_subscript(arg, cctx, start_leader, &end_leader,
ppconst) == FAIL)
return FAIL;
if (ppconst->pp_used > 0)
{
// apply the '!', '-' and '+' before the constant
rettv = &ppconst->pp_tv[ppconst->pp_used - 1];
- if (apply_leader(rettv, start_leader, end_leader) == FAIL)
+ if (apply_leader(rettv, FALSE, start_leader, &end_leader) == FAIL)
return FAIL;
return OK;
}
- if (compile_leader(cctx, start_leader, end_leader) == FAIL)
+ if (compile_leader(cctx, FALSE, start_leader, &end_leader) == FAIL)
return FAIL;
return OK;
}