Patch 8.2.5003
Problem: Cannot do bitwise shifts.
Solution: Add the >> and << operators. (Yegappan Lakshmanan, closes #8457)
Files: runtime/doc/eval.txt, src/errors.h, src/eval.c, src/structs.h,
src/vim.h, src/vim9execute.c, src/vim9expr.c,
src/testdir/test_expr.vim, src/testdir/test_vim9_disassemble.vim,
src/testdir/test_vim9_expr.vim
*** ../vim-8.2.5002/runtime/doc/eval.txt 2022-05-22 14:48:26.327247291 +0100
--- runtime/doc/eval.txt 2022-05-22 19:06:51.564142481 +0100
***************
*** 868,900 ****
expr5 isnot expr5 different |List|, |Dictionary| or |Blob|
instance
! |expr5| expr6
! expr6 + expr6 ... number addition, list or blob concatenation
! expr6 - expr6 ... number subtraction
! expr6 . expr6 ... string concatenation
! expr6 .. expr6 ... string concatenation
|expr6| expr7
! expr7 * expr7 ... number multiplication
! expr7 / expr7 ... number division
! expr7 % expr7 ... number modulo
|expr7| expr8
! <type>expr8 type check and conversion (|Vim9| only)
|expr8| expr9
! ! expr8 logical NOT
! - expr8 unary minus
! + expr8 unary plus
|expr9| expr10
! expr9[expr1] byte of a String or item of a |List|
! expr9[expr1 : expr1] substring of a String or sublist of a |List|
!
expr9.name entry in a |Dictionary|
! expr9(expr1, ...) function call with |Funcref| variable
! expr9->name(expr1, ...) |method| call
! |expr10| number number constant
"string" string constant, backslash is special
'string' string constant, ' is doubled
[expr1, ...] |List|
--- 868,903 ----
expr5 isnot expr5 different |List|, |Dictionary| or |Blob|
instance
! |expr5| expr6 << expr6 bitwise left shift
! expr6 >> expr6 bitwise right shift
|expr6| expr7
! expr7 + expr7 ... number addition, list or blob concatenation
! expr7 - expr7 ... number subtraction
! expr7 . expr7 ... string concatenation
! expr7 .. expr7 ... string concatenation
|expr7| expr8
! expr8 * expr8 ... number multiplication
! expr8 / expr8 ... number division
! expr8 % expr8 ... number modulo
|expr8| expr9
! <type>expr9 type check and conversion (|Vim9| only)
|expr9| expr10
! ! expr9 logical NOT
! - expr9 unary minus
! + expr9 unary plus
!
! |expr10| expr11
! expr10[expr1] byte of a String or item of a |List|
! expr10[expr1 : expr1] substring of a String or sublist of a |List|
!
expr10.name entry in a |Dictionary|
! expr10(expr1, ...) function call with |Funcref| variable
! expr10->name(expr1, ...) |method| call
! |expr11| number number constant
"string" string constant, backslash is special
'string' string constant, ' is doubled
[expr1, ...] |List|
***************
*** 1128,1141 ****
"foo\nbar" =~ "\\n" evaluates to 0
! expr5 and expr6 *expr5* *expr6* *E1036* *E1051*
---------------
! expr6 + expr6 Number addition, |List| or |Blob| concatenation *expr-+*
! expr6 - expr6 Number subtraction *expr--*
! expr6 . expr6 String concatenation *expr-.*
! expr6 .. expr6 String concatenation *expr-..*
! For |Lists| only "+" is possible and then both expr6 must be a list. The
result is a new list with the two lists Concatenated.
For String concatenation ".." is preferred, since "." is ambiguous, it is also
--- 1131,1156 ----
"foo\nbar" =~ "\\n" evaluates to 0
! expr5 *expr5* *bitwise-shift*
! -----
! expr6 << expr6 bitwise left shift *expr-<<*
! expr6 >> expr6 bitwise right shift *expr->>*
! *E1282* *E1283*
! The "<<" and ">>" operators can be used to perform bitwise left or right shift
! of the left operand by the number of bits specified by the right operand. The
! operands must be positive numbers. The topmost bit (sign bit) is always
! cleared for ">>". If the right operand (shift amount) is more than the
! maximum number of bits in a number (|v:numbersize|) the result is zero.
!
!
! expr6 and expr7 *expr6* *expr7* *E1036* *E1051*
---------------
! expr7 + expr7 Number addition, |List| or |Blob| concatenation *expr-+*
! expr7 - expr7 Number subtraction *expr--*
! expr7 . expr7 String concatenation *expr-.*
! expr7 .. expr7 String concatenation *expr-..*
! For |Lists| only "+" is possible and then both expr7 must be a list. The
result is a new list with the two lists Concatenated.
For String concatenation ".." is preferred, since "." is ambiguous, it is also
***************
*** 1147,1155 ****
types: Number, Float, Special and Bool. For other types |string()| should be
used.
! expr7 * expr7 Number multiplication *expr-star*
! expr7 / expr7 Number division *expr-/*
! expr7 % expr7 Number modulo *expr-%*
In legacy script, for all operators except "." and "..", Strings are converted
to Numbers.
--- 1162,1170 ----
types: Number, Float, Special and Bool. For other types |string()| should be
used.
! expr8 * expr8 Number multiplication *expr-star*
! expr8 / expr8 Number division *expr-/*
! expr8 % expr8 Number modulo *expr-%*
In legacy script, for all operators except "." and "..", Strings are converted
to Numbers.
***************
*** 1191,1208 ****
".", ".." and "%" do not work for Float. *E804* *E1035*
! expr7 *expr7*
-----
! <type>expr8
This is only available in |Vim9| script, see |type-casting|.
! expr8 *expr8*
-----
! ! expr8 logical NOT *expr-!*
! - expr8 unary minus *expr-unary--*
! + expr8 unary plus *expr-unary-+*
For '!' |TRUE| becomes |FALSE|, |FALSE| becomes |TRUE| (one).
For '-' the sign of the number is changed.
--- 1206,1223 ----
".", ".." and "%" do not work for Float. *E804* *E1035*
! expr8 *expr8*
-----
! <type>expr9
This is only available in |Vim9| script, see |type-casting|.
! expr9 *expr9*
-----
! ! expr9 logical NOT *expr-!*
! - expr9 unary minus *expr-unary--*
! + expr9 unary plus *expr-unary-+*
For '!' |TRUE| becomes |FALSE|, |FALSE| becomes |TRUE| (one).
For '-' the sign of the number is changed.
***************
*** 1224,1244 ****
--9 == 9
! expr9 *expr9*
! -----
! This expression is either |expr10| or a sequence of the alternatives below,
in any order. E.g., these are all possible:
! expr9[expr1].name
!
expr9.name[expr1]
! expr9(expr1, ...)[expr1].name
! expr9->(expr1, ...)[expr1]
Evaluation is always from left to right.
! expr9[expr1] item of String or |List| *expr-[]* *E111*
*E909* *subscript* *E1062*
In legacy Vim script:
! If expr9 is a Number or String this results in a String that contains the
! expr1'th single byte from expr9. expr9 is used as a String (a number is
automatically converted to a String), expr1 as a Number. This doesn't
recognize multibyte encodings, see `byteidx()` for an alternative, or use
`split()` to turn the string into a list of characters. Example, to get the
--- 1239,1259 ----
--9 == 9
! expr10 *expr10*
! ------
! This expression is either |expr11| or a sequence of the alternatives below,
in any order. E.g., these are all possible:
! expr10[expr1].name
!
expr10.name[expr1]
! expr10(expr1, ...)[expr1].name
! expr10->(expr1, ...)[expr1]
Evaluation is always from left to right.
! expr10[expr1] item of String or |List| *expr-[]* *E111*
*E909* *subscript* *E1062*
In legacy Vim script:
! If expr10 is a Number or String this results in a String that contains the
! expr1'th single byte from expr10. expr10 is used as a String (a number is
automatically converted to a String), expr1 as a Number. This doesn't
recognize multibyte encodings, see `byteidx()` for an alternative, or use
`split()` to turn the string into a list of characters. Example, to get the
***************
*** 1246,1253 ****
:let c = getline(".")[col(".") - 1]
In |Vim9| script: *E1147* *E1148*
! If expr9 is a String this results in a String that contains the expr1'th
! single character (including any composing characters) from expr9. To use byte
indexes use |strpart()|.
Index zero gives the first byte or character. Careful: text column numbers
--- 1261,1268 ----
:let c = getline(".")[col(".") - 1]
In |Vim9| script: *E1147* *E1148*
! If expr10 is a String this results in a String that contains the expr1'th
! single character (including any composing characters) from expr10. To use byte
indexes use |strpart()|.
Index zero gives the first byte or character. Careful: text column numbers
***************
*** 1258,1264 ****
compatibility). Use [-1:] to get the last byte or character.
In Vim9 script a negative index is used like with a list: count from the end.
! If expr9 is a |List| then it results the item at index expr1. See |list-index|
for possible index values. If the index is out of range this results in an
error. Example: >
:let item = mylist[-1] " get last item
--- 1273,1279 ----
compatibility). Use [-1:] to get the last byte or character.
In Vim9 script a negative index is used like with a list: count from the end.
! If expr10 is a |List| then it results the item at index expr1. See |list-index|
for possible index values. If the index is out of range this results in an
error. Example: >
:let item = mylist[-1] " get last item
***************
*** 1268,1281 ****
error.
! expr9[expr1a : expr1b] substring or sublist *expr-[:]*
! If expr9 is a String this results in the substring with the bytes or
! characters from expr1a to and including expr1b. expr9 is used as a String,
expr1a and expr1b are used as a Number.
In legacy Vim script the indexes are byte indexes. This doesn't recognize
! multibyte encodings, see |byteidx()| for computing the indexes. If expr9 is
a Number it is first converted to a String.
In Vim9 script the indexes are character indexes and include composing
--- 1283,1296 ----
error.
! expr10[expr1a : expr1b] substring or sublist *expr-[:]*
! If expr10 is a String this results in the substring with the bytes or
! characters from expr1a to and including expr1b. expr10 is used as a String,
expr1a and expr1b are used as a Number.
In legacy Vim script the indexes are byte indexes. This doesn't recognize
! multibyte encodings, see |byteidx()| for computing the indexes. If expr10 is
a Number it is first converted to a String.
In Vim9 script the indexes are character indexes and include composing
***************
*** 1302,1321 ****
:let s = s[:-3] " remove last two bytes
<
*slice*
! If expr9 is a |List| this results in a new |List| with the items indicated by
the indexes expr1a and expr1b. This works like with a String, as explained
just above. Also see |sublist| below. Examples: >
:let l = mylist[:3] " first four items
:let l = mylist[4:4] " List with one item
:let l = mylist[:] " shallow copy of a List
! If expr9 is a |Blob| this results in a new |Blob| with the bytes in the
indexes expr1a and expr1b, inclusive. Examples: >
:let b = 0zDEADBEEF
:let bs = b[1:2] " 0zADBE
:let bs = b[:] " copy of 0zDEADBEEF
! Using expr9[expr1] or expr9[expr1a : expr1b] on a |Funcref| results in an
error.
Watch out for confusion between a namespace and a variable followed by a colon
--- 1317,1336 ----
:let s = s[:-3] " remove last two bytes
<
*slice*
! If expr10 is a |List| this results in a new |List| with the items indicated by
the indexes expr1a and expr1b. This works like with a String, as explained
just above. Also see |sublist| below. Examples: >
:let l = mylist[:3] " first four items
:let l = mylist[4:4] " List with one item
:let l = mylist[:] " shallow copy of a List
! If expr10 is a |Blob| this results in a new |Blob| with the bytes in the
indexes expr1a and expr1b, inclusive. Examples: >
:let b = 0zDEADBEEF
:let bs = b[1:2] " 0zADBE
:let bs = b[:] " copy of 0zDEADBEEF
! Using expr10[expr1] or expr10[expr1a : expr1b] on a |Funcref| results in an
error.
Watch out for confusion between a namespace and a variable followed by a colon
***************
*** 1324,1334 ****
mylist[s:] " uses namespace s:, error!
!
expr9.name entry in a |Dictionary| *expr-entry*
*E1203* *E1229*
! If expr9 is a |Dictionary| and it is followed by a dot, then the following
name will be used as a key in the |Dictionary|. This is just like:
! expr9[name].
The name must consist of alphanumeric characters, just like a variable name,
but it may start with a number. Curly braces cannot be used.
--- 1339,1349 ----
mylist[s:] " uses namespace s:, error!
!
expr10.name entry in a |Dictionary| *expr-entry*
*E1203* *E1229*
! If expr10 is a |Dictionary| and it is followed by a dot, then the following
name will be used as a key in the |Dictionary|. This is just like:
! expr10[name].
The name must consist of alphanumeric characters, just like a variable name,
but it may start with a number. Curly braces cannot be used.
***************
*** 1345,1361 ****
always put spaces around the dot for String concatenation.
! expr9(expr1, ...) |Funcref| function call *E1085*
! When expr9 is a |Funcref| type variable, invoke the function it refers to.
! expr9->name([args]) method call *method* *->*
! expr9->{lambda}([args])
*E260* *E276* *E1265*
For methods that are also available as global functions this is the same as: >
! name(expr9 [, args])
! There can also be methods specifically for the type of "expr9".
This allows for chaining, passing the value that one method returns to the
next method: >
--- 1360,1376 ----
always put spaces around the dot for String concatenation.
! expr10(expr1, ...) |Funcref| function call *E1085*
! When expr10 is a |Funcref| type variable, invoke the function it refers to.
! expr10->name([args]) method call *method* *->*
! expr10->{lambda}([args])
*E260* *E276* *E1265*
For methods that are also available as global functions this is the same as: >
! name(expr10 [, args])
! There can also be methods specifically for the type of "expr10".
This allows for chaining, passing the value that one method returns to the
next method: >
***************
*** 1364,1370 ****
Example of using a lambda: >
GetPercentage()->{x -> x * 100}()->printf('%d%%')
<
! When using -> the |expr8| operators will be applied first, thus: >
-1.234->string()
Is equivalent to: >
(-1.234)->string()
--- 1379,1385 ----
Example of using a lambda: >
GetPercentage()->{x -> x * 100}()->printf('%d%%')
<
! When using -> the |expr9| operators will be applied first, thus: >
-1.234->string()
Is equivalent to: >
(-1.234)->string()
***************
*** 1393,1399 ****
(.
! *expr10*
number
------
number number constant *expr-number*
--- 1408,1414 ----
(.
! *expr11*
number
------
number number constant *expr-number*
*** ../vim-8.2.5002/src/errors.h 2022-05-18 15:03:58.171540249 +0100
--- src/errors.h 2022-05-22 18:57:17.987843294 +0100
***************
*** 3279,3281 ****
--- 3279,3287 ----
#endif
EXTERN char e_atom_engine_must_be_at_start_of_pattern[]
INIT(= N_("E1281: Atom '\\%%#=%c' must be at the start of the pattern"));
+ #ifdef FEAT_EVAL
+ EXTERN char e_bitshift_ops_must_be_number[]
+ INIT(= N_("E1282: bitshift operands must be numbers"));
+ EXTERN char e_bitshift_ops_must_be_postive[]
+ INIT(= N_("E1283: bitshift amount must be a positive number"));
+ #endif
*** ../vim-8.2.5002/src/eval.c 2022-05-10 13:24:17.632706901 +0100
--- src/eval.c 2022-05-22 19:13:18.984315611 +0100
***************
*** 49,58 ****
static int eval3(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
static int eval4(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
static int eval5(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
! static int eval6(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int want_string);
! static int eval7t(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int want_string);
static int eval7(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int want_string);
! static int eval7_leader(typval_T *rettv, int numeric_only, char_u *start_leader, char_u **end_leaderp);
static int free_unref_items(int copyID);
static char_u *make_expanded_name(char_u *in_start, char_u *expr_start, char_u *expr_end, char_u *in_end);
--- 49,59 ----
static int eval3(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
static int eval4(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
static int eval5(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
! static int eval6(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
static int eval7(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int want_string);
! static int eval8(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int want_string);
! static int eval9(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int want_string);
! static int eval9_leader(typval_T *rettv, int numeric_only, char_u *start_leader, char_u **end_leaderp);
static int free_unref_items(int copyID);
static char_u *make_expanded_name(char_u *in_start, char_u *expr_start, char_u *expr_end, char_u *in_end);
***************
*** 638,644 ****
char_u *name = *arg;
ref.v_type = VAR_UNKNOWN;
! if (eval7(arg, &ref, evalarg, FALSE) == FAIL)
{
dictitem_T *v;
--- 639,645 ----
char_u *name = *arg;
ref.v_type = VAR_UNKNOWN;
! if (eval9(arg, &ref, evalarg, FALSE) == FAIL)
{
dictitem_T *v;
***************
*** 2591,2597 ****
int getnext;
/*
! * Get the first variable.
*/
if (eval3(arg, rettv, evalarg) == FAIL)
return FAIL;
--- 2592,2598 ----
int getnext;
/*
! * Get the first expression.
*/
if (eval3(arg, rettv, evalarg) == FAIL)
return FAIL;
***************
*** 2717,2723 ****
int getnext;
/*
! * Get the first variable.
*/
if (eval4(arg, rettv, evalarg) == FAIL)
return FAIL;
--- 2718,2724 ----
int getnext;
/*
! * Get the first expression.
*/
if (eval4(arg, rettv, evalarg) == FAIL)
return FAIL;
***************
*** 2856,2867 ****
int type_is = FALSE;
/*
! * Get the first variable.
*/
if (eval5(arg, rettv, evalarg) == FAIL)
return FAIL;
p = eval_next_non_blank(*arg, evalarg, &getnext);
type = get_compare_type(p, &len, &type_is);
/*
--- 2857,2869 ----
int type_is = FALSE;
/*
! * Get the first expression.
*/
if (eval5(arg, rettv, evalarg) == FAIL)
return FAIL;
p = eval_next_non_blank(*arg, evalarg, &getnext);
+
type = get_compare_type(p, &len, &type_is);
/*
***************
*** 2991,2997 ****
}
/*
! * Handle fourth level expression:
* + number addition, concatenation of list or blob
* - number subtraction
* . string concatenation (if script version is 1)
--- 2993,3112 ----
}
/*
! * Handle the bitwise left/right shift operator expression:
! * var1 << var2
! * var1 >> var2
! *
! * "arg" must point to the first non-white of the expression.
! * "arg" is advanced to just after the recognized expression.
! *
! * Return OK or FAIL.
! */
! static int
! eval5(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
! {
! /*
! * Get the first expression.
! */
! if (eval6(arg, rettv, evalarg) == FAIL)
! return FAIL;
!
! /*
! * Repeat computing, until no '<<' or '>>' is following.
! */
! for (;;)
! {
! char_u *p;
! int getnext;
! exprtype_T type;
! int evaluate;
! typval_T var2;
! int vim9script;
!
! p = eval_next_non_blank(*arg, evalarg, &getnext);
! if (p[0] == '<' && p[1] == '<')
! type = EXPR_LSHIFT;
! else if (p[0] == '>' && p[1] == '>')
! type = EXPR_RSHIFT;
! else
! return OK;
!
! // Handle a bitwise left or right shift operator
! if (rettv->v_type != VAR_NUMBER)
! {
! // left operand should be a number
! emsg(_(e_bitshift_ops_must_be_number));
! clear_tv(rettv);
! return FAIL;
! }
!
! evaluate = evalarg == NULL ? 0 : (evalarg->eval_flags & EVAL_EVALUATE);
! vim9script = in_vim9script();
! if (getnext)
! {
! *arg = eval_next_line(*arg, evalarg);
! p = *arg;
! }
! else if (evaluate && vim9script && !VIM_ISWHITE(**arg))
! {
! error_white_both(*arg, 2);
! clear_tv(rettv);
! return FAIL;
! }
!
! /*
! * Get the second variable.
! */
! if (evaluate && vim9script && !IS_WHITE_OR_NUL(p[2]))
! {
! error_white_both(p, 2);
! clear_tv(rettv);
! return FAIL;
! }
! *arg = skipwhite_and_linebreak(p + 2, evalarg);
! if (eval6(arg, &var2, evalarg) == FAIL)
! {
! clear_tv(rettv);
! return FAIL;
! }
!
! if (var2.v_type != VAR_NUMBER || var2.vval.v_number < 0)
! {
! // right operand should be a positive number
! if (var2.v_type != VAR_NUMBER)
! emsg(_(e_bitshift_ops_must_be_number));
! else
! emsg(_(e_bitshift_ops_must_be_postive));
! clear_tv(rettv);
! clear_tv(&var2);
! return FAIL;
! }
!
! if (evaluate)
! {
! if (var2.vval.v_number > MAX_LSHIFT_BITS)
! // shifting more bits than we have always results in zero
! rettv->vval.v_number = 0;
! else if (type == EXPR_LSHIFT)
! rettv->vval.v_number =
! rettv->vval.v_number << var2.vval.v_number;
! else
! {
! rettv->vval.v_number =
! rettv->vval.v_number >> var2.vval.v_number;
! // clear the topmost sign bit
! rettv->vval.v_number &= ~((uvarnumber_T)1 << MAX_LSHIFT_BITS);
! }
! }
!
! clear_tv(&var2);
! }
!
! return OK;
! }
!
! /*
! * Handle fifth level expression:
* + number addition, concatenation of list or blob
* - number subtraction
* . string concatenation (if script version is 1)
***************
*** 3003,3014 ****
* Return OK or FAIL.
*/
static int
! eval5(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
{
/*
! * Get the first variable.
*/
! if (eval6(arg, rettv, evalarg, FALSE) == FAIL)
return FAIL;
/*
--- 3118,3129 ----
* Return OK or FAIL.
*/
static int
! eval6(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
{
/*
! * Get the first expression.
*/
! if (eval7(arg, rettv, evalarg, FALSE) == FAIL)
return FAIL;
/*
***************
*** 3086,3092 ****
return FAIL;
}
*arg = skipwhite_and_linebreak(*arg + oplen, evalarg);
! if (eval6(arg, &var2, evalarg, !vim9script && op == '.') == FAIL)
{
clear_tv(rettv);
return FAIL;
--- 3201,3207 ----
return FAIL;
}
*arg = skipwhite_and_linebreak(*arg + oplen, evalarg);
! if (eval7(arg, &var2, evalarg, !vim9script && op == '.') == FAIL)
{
clear_tv(rettv);
return FAIL;
***************
*** 3221,3227 ****
}
/*
! * Handle fifth level expression:
* * number multiplication
* / number division
* % number modulo
--- 3336,3342 ----
}
/*
! * Handle sixth level expression:
* * number multiplication
* / number division
* % number modulo
***************
*** 3232,3238 ****
* Return OK or FAIL.
*/
static int
! eval6(
char_u **arg,
typval_T *rettv,
evalarg_T *evalarg,
--- 3347,3353 ----
* Return OK or FAIL.
*/
static int
! eval7(
char_u **arg,
typval_T *rettv,
evalarg_T *evalarg,
***************
*** 3243,3251 ****
#endif
/*
! * Get the first variable.
*/
! if (eval7t(arg, rettv, evalarg, want_string) == FAIL)
return FAIL;
/*
--- 3358,3366 ----
#endif
/*
! * Get the first expression.
*/
! if (eval8(arg, rettv, evalarg, want_string) == FAIL)
return FAIL;
/*
***************
*** 3318,3324 ****
return FAIL;
}
*arg = skipwhite_and_linebreak(*arg + 1, evalarg);
! if (eval7t(arg, &var2, evalarg, FALSE) == FAIL)
return FAIL;
if (evaluate)
--- 3433,3439 ----
return FAIL;
}
*arg = skipwhite_and_linebreak(*arg + 1, evalarg);
! if (eval8(arg, &var2, evalarg, FALSE) == FAIL)
return FAIL;
if (evaluate)
***************
*** 3415,3421 ****
* Return OK or FAIL.
*/
static int
! eval7t(
char_u **arg,
typval_T *rettv,
evalarg_T *evalarg,
--- 3530,3536 ----
* Return OK or FAIL.
*/
static int
! eval8(
char_u **arg,
typval_T *rettv,
evalarg_T *evalarg,
***************
*** 3453,3459 ****
*arg = skipwhite_and_linebreak(*arg, evalarg);
}
! res = eval7(arg, rettv, evalarg, want_string);
if (want_type != NULL && evaluate)
{
--- 3568,3574 ----
*arg = skipwhite_and_linebreak(*arg, evalarg);
}
! res = eval9(arg, rettv, evalarg, want_string);
if (want_type != NULL && evaluate)
{
***************
*** 3642,3648 ****
* Return OK or FAIL.
*/
static int
! eval7(
char_u **arg,
typval_T *rettv,
evalarg_T *evalarg,
--- 3757,3763 ----
* Return OK or FAIL.
*/
static int
! eval9(
char_u **arg,
typval_T *rettv,
evalarg_T *evalarg,
***************
*** 3720,3726 ****
// "->" follows.
if (ret == OK && evaluate && end_leader > start_leader
&& rettv->v_type != VAR_BLOB)
! ret = eval7_leader(rettv, TRUE, start_leader, &end_leader);
break;
/*
--- 3835,3841 ----
// "->" follows.
if (ret == OK && evaluate && end_leader > start_leader
&& rettv->v_type != VAR_BLOB)
! ret = eval9_leader(rettv, TRUE, start_leader, &end_leader);
break;
/*
***************
*** 3920,3938 ****
* Apply logical NOT and unary '-', from right to left, ignore '+'.
*/
if (ret == OK && evaluate && end_leader > start_leader)
! ret = eval7_leader(rettv, FALSE, start_leader, &end_leader);
--recurse;
return ret;
}
/*
! * Apply the leading "!" and "-" before an eval7 expression to "rettv".
* When "numeric_only" is TRUE only handle "+" and "-".
* Adjusts "end_leaderp" until it is at "start_leader".
*/
static int
! eval7_leader(
typval_T *rettv,
int numeric_only,
char_u *start_leader,
--- 4035,4053 ----
* Apply logical NOT and unary '-', from right to left, ignore '+'.
*/
if (ret == OK && evaluate && end_leader > start_leader)
! ret = eval9_leader(rettv, FALSE, start_leader, &end_leader);
--recurse;
return ret;
}
/*
! * Apply the leading "!" and "-" before an eval9 expression to "rettv".
* When "numeric_only" is TRUE only handle "+" and "-".
* Adjusts "end_leaderp" until it is at "start_leader".
*/
static int
! eval9_leader(
typval_T *rettv,
int numeric_only,
char_u *start_leader,
*** ../vim-8.2.5002/src/structs.h 2022-05-21 20:16:51.011567174 +0100
--- src/structs.h 2022-05-22 18:25:44.089073531 +0100
***************
*** 4152,4157 ****
--- 4152,4159 ----
EXPR_MULT, // *
EXPR_DIV, // /
EXPR_REM, // %
+ EXPR_LSHIFT, // <<
+ EXPR_RSHIFT, // >>
// used with ISN_ADDLIST
EXPR_COPY, // create new list
EXPR_APPEND, // append to first list
*** ../vim-8.2.5002/src/vim.h 2022-05-09 20:09:19.294641425 +0100
--- src/vim.h 2022-05-22 18:25:44.089073531 +0100
***************
*** 2808,2811 ****
--- 2808,2812 ----
#define FFED_IS_GLOBAL 1 // "g:" was used
#define FFED_NO_GLOBAL 2 // only check for script-local functions
+ #define MAX_LSHIFT_BITS (varnumber_T)((sizeof(uvarnumber_T) * 8) - 1)
#endif // VIM__H
*** ../vim-8.2.5002/src/vim9execute.c 2022-05-21 21:55:49.456619728 +0100
--- src/vim9execute.c 2022-05-22 18:56:02.543796783 +0100
***************
*** 4055,4060 ****
--- 4055,4071 ----
varnumber_T res = 0;
int div_zero = FALSE;
+ if (iptr->isn_arg.op.op_type == EXPR_LSHIFT
+ || iptr->isn_arg.op.op_type == EXPR_RSHIFT)
+ {
+ if (arg2 < 0)
+ {
+ SOURCING_LNUM = iptr->isn_lnum;
+ emsg(_(e_bitshift_ops_must_be_postive));
+ goto on_error;
+ }
+ }
+
switch (iptr->isn_arg.op.op_type)
{
case EXPR_MULT: res = arg1 * arg2; break;
***************
*** 4077,4082 ****
--- 4088,4108 ----
case EXPR_GEQUAL: res = arg1 >= arg2; break;
case EXPR_SMALLER: res = arg1 < arg2; break;
case EXPR_SEQUAL: res = arg1 <= arg2; break;
+ case EXPR_LSHIFT: if (arg2 > MAX_LSHIFT_BITS)
+ res = 0;
+ else
+ res = arg1 << arg2;
+ break;
+ case EXPR_RSHIFT: if (arg2 > MAX_LSHIFT_BITS)
+ res = 0;
+ else
+ {
+ res = arg1 >> arg2;
+ // clear the topmost sign bit
+ res &= ~((uvarnumber_T)1
+ << MAX_LSHIFT_BITS);
+ }
+ break;
default: break;
}
***************
*** 6016,6021 ****
--- 6042,6049 ----
case EXPR_REM: what = "%"; break;
case EXPR_SUB: what = "-"; break;
case EXPR_ADD: what = "+"; break;
+ case EXPR_LSHIFT: what = "<<"; break;
+ case EXPR_RSHIFT: what = ">>"; break;
default: what = "???"; break;
}
switch (iptr->isn_type)
*** ../vim-8.2.5002/src/vim9expr.c 2022-05-17 15:03:29.702610338 +0100
--- src/vim9expr.c 2022-05-22 18:57:10.663838875 +0100
***************
*** 1748,1754 ****
return ret;
}
! static int compile_expr8(char_u **arg, cctx_T *cctx, ppconst_T *ppconst);
/*
* Compile whatever comes after "name" or "name()".
--- 1748,1754 ----
return ret;
}
! static int compile_expr9(char_u **arg, cctx_T *cctx, ppconst_T *ppconst);
/*
* Compile whatever comes after "name" or "name()".
***************
*** 1909,1915 ****
// 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;
--- 1909,1915 ----
// do not look in the next line
cctx->ctx_ufunc->uf_lines.ga_len = 1;
! fail = compile_expr9(arg, cctx, ppconst) == FAIL
|| *skipwhite(*arg) != NUL;
*paren = '(';
--paren_follows_after_expr;
***************
*** 2143,2149 ****
* trailing ->name() method call
*/
static int
! compile_expr8(
char_u **arg,
cctx_T *cctx,
ppconst_T *ppconst)
--- 2143,2149 ----
* trailing ->name() method call
*/
static int
! compile_expr9(
char_u **arg,
cctx_T *cctx,
ppconst_T *ppconst)
***************
*** 2389,2398 ****
}
/*
! * <type>expr8: runtime type check / conversion
*/
static int
! compile_expr7(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
{
type_T *want_type = NULL;
--- 2389,2398 ----
}
/*
! * <type>expr9: runtime type check / conversion
*/
static int
! compile_expr8(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
{
type_T *want_type = NULL;
***************
*** 2417,2423 ****
return FAIL;
}
! if (compile_expr8(arg, cctx, ppconst) == FAIL)
return FAIL;
if (want_type != NULL)
--- 2417,2423 ----
return FAIL;
}
! if (compile_expr9(arg, cctx, ppconst) == FAIL)
return FAIL;
if (want_type != NULL)
***************
*** 2444,2457 ****
* % number modulo
*/
static int
! compile_expr6(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
{
char_u *op;
char_u *next;
int ppconst_used = ppconst->pp_used;
// get the first expression
! if (compile_expr7(arg, cctx, ppconst) == FAIL)
return FAIL;
/*
--- 2444,2457 ----
* % number modulo
*/
static int
! compile_expr7(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
{
char_u *op;
char_u *next;
int ppconst_used = ppconst->pp_used;
// get the first expression
! if (compile_expr8(arg, cctx, ppconst) == FAIL)
return FAIL;
/*
***************
*** 2477,2483 ****
return FAIL;
// get the second expression
! if (compile_expr7(arg, cctx, ppconst) == FAIL)
return FAIL;
if (ppconst->pp_used == ppconst_used + 2
--- 2477,2483 ----
return FAIL;
// get the second expression
! if (compile_expr8(arg, cctx, ppconst) == FAIL)
return FAIL;
if (ppconst->pp_used == ppconst_used + 2
***************
*** 2522,2528 ****
* .. string concatenation
*/
static int
! compile_expr5(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
{
char_u *op;
char_u *next;
--- 2522,2528 ----
* .. string concatenation
*/
static int
! compile_expr6(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
{
char_u *op;
char_u *next;
***************
*** 2530,2536 ****
int ppconst_used = ppconst->pp_used;
// get the first variable
! if (compile_expr6(arg, cctx, ppconst) == FAIL)
return FAIL;
/*
--- 2530,2536 ----
int ppconst_used = ppconst->pp_used;
// get the first variable
! if (compile_expr7(arg, cctx, ppconst) == FAIL)
return FAIL;
/*
***************
*** 2562,2568 ****
return FAIL;
// get the second expression
! if (compile_expr6(arg, cctx, ppconst) == FAIL)
return FAIL;
if (ppconst->pp_used == ppconst_used + 2
--- 2562,2568 ----
return FAIL;
// get the second expression
! if (compile_expr7(arg, cctx, ppconst) == FAIL)
return FAIL;
if (ppconst->pp_used == ppconst_used + 2
***************
*** 2621,2626 ****
--- 2621,2756 ----
}
/*
+ * expr6a >> expr6b
+ * expr6a << expr6b
+ *
+ * Produces instructions:
+ * OPNR bitwise left or right shift
+ */
+ static int
+ compile_expr5(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
+ {
+ exprtype_T type = EXPR_UNKNOWN;
+ char_u *p;
+ char_u *next;
+ int len = 2;
+ int ppconst_used = ppconst->pp_used;
+ typval_T *tv1;
+ typval_T *tv2;
+ isn_T *isn;
+
+ // get the first variable
+ if (compile_expr6(arg, cctx, ppconst) == FAIL)
+ return FAIL;
+
+ /*
+ * Repeat computing, until no "+", "-" or ".." is following.
+ */
+ for (;;)
+ {
+ type = EXPR_UNKNOWN;
+
+ p = may_peek_next_line(cctx, *arg, &next);
+ if (p[0] == '<' && p[1] == '<')
+ type = EXPR_LSHIFT;
+ else if (p[0] == '>' && p[1] == '>')
+ type = EXPR_RSHIFT;
+
+ if (type == EXPR_UNKNOWN)
+ return OK;
+
+ // Handle a bitwise left or right shift operator
+ if (ppconst->pp_used == ppconst_used + 1)
+ {
+ tv1 = &ppconst->pp_tv[ppconst->pp_used - 1];
+ if (tv1->v_type != VAR_NUMBER)
+ {
+ // left operand should be a number
+ emsg(_(e_bitshift_ops_must_be_number));
+ return FAIL;
+ }
+ }
+ else
+ {
+ type_T *t = get_type_on_stack(cctx, 0);
+
+ if (need_type(t, &t_number, 0, 0, cctx, FALSE, FALSE) == FAIL)
+ {
+ emsg(_(e_bitshift_ops_must_be_number));
+ return FAIL;
+ }
+ }
+
+ if (next != NULL)
+ {
+ *arg = next_line_from_context(cctx, TRUE);
+ p = skipwhite(*arg);
+ }
+
+ if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[len]))
+ {
+ error_white_both(p, len);
+ return FAIL;
+ }
+
+ // get the second variable
+ if (may_get_next_line_error(p + len, arg, cctx) == FAIL)
+ return FAIL;
+
+ if (compile_expr6(arg, cctx, ppconst) == FAIL)
+ return FAIL;
+
+ if (ppconst->pp_used == ppconst_used + 2)
+ {
+ // Both sides are a constant, compute the result now.
+ tv2 = &ppconst->pp_tv[ppconst->pp_used - 1];
+ if (tv2->v_type != VAR_NUMBER || tv2->vval.v_number < 0)
+ {
+ // right operand should be a positive number
+ if (tv2->v_type != VAR_NUMBER)
+ emsg(_(e_bitshift_ops_must_be_number));
+ else
+ emsg(_(e_bitshift_ops_must_be_postive));
+ return FAIL;
+ }
+
+ if (tv2->vval.v_number > MAX_LSHIFT_BITS)
+ tv1->vval.v_number = 0;
+ else if (type == EXPR_LSHIFT)
+ tv1->vval.v_number = tv1->vval.v_number << tv2->vval.v_number;
+ else
+ {
+ tv1->vval.v_number = tv1->vval.v_number >> tv2->vval.v_number;
+ // clear the topmost sign bit
+ tv1->vval.v_number &= ~((uvarnumber_T)1 << MAX_LSHIFT_BITS);
+ }
+ clear_tv(tv2);
+ --ppconst->pp_used;
+ }
+ else
+ {
+ if (need_type(get_type_on_stack(cctx, 0), &t_number, 0, 0, cctx,
+ FALSE, FALSE) == FAIL)
+ {
+ emsg(_(e_bitshift_ops_must_be_number));
+ return FAIL;
+ }
+
+ generate_ppconst(cctx, ppconst);
+
+ isn = generate_instr_drop(cctx, ISN_OPNR, 1);
+ if (isn == NULL)
+ return FAIL;
+
+ if (isn != NULL)
+ isn->isn_arg.op.op_type = type;
+ }
+ }
+
+ return OK;
+ }
+
+ /*
* expr5a == expr5b
* expr5a =~ expr5b
* expr5a != expr5b
***************
*** 2652,2657 ****
--- 2782,2788 ----
return FAIL;
p = may_peek_next_line(cctx, *arg, &next);
+
type = get_compare_type(p, &len, &type_is);
/*
*** ../vim-8.2.5002/src/testdir/test_expr.vim 2022-05-10 13:24:17.640706898 +0100
--- src/testdir/test_expr.vim 2022-05-22 18:58:54.647899723 +0100
***************
*** 946,949 ****
--- 946,1011 ----
call v9.CheckDefAndScriptSuccess(lines)
endfunc
+ " Test for bitwise left and right shift (<< and >>)
+ func Test_bitwise_shift()
+ let lines =<< trim END
+ call assert_equal(16, 1 << 4)
+ call assert_equal(2, 16 >> 3)
+ call assert_equal(0, 0 << 2)
+ call assert_equal(0, 0 >> 4)
+ call assert_equal(3, 3 << 0)
+ call assert_equal(3, 3 >> 0)
+ call assert_equal(0, 0 >> 4)
+ call assert_equal(0, 999999 >> 100)
+ call assert_equal(0, 999999 << 100)
+ VAR a = 8
+ VAR b = 2
+ call assert_equal(2, a >> b)
+ call assert_equal(32, a << b)
+ #" operator precedence
+ call assert_equal(48, 1 + 2 << 5 - 1)
+ call assert_equal(3, 8 + 4 >> 4 - 2)
+ call assert_true(1 << 2 < 1 << 3)
+ call assert_true(1 << 4 > 1 << 3)
+ VAR val = 0
+ for i in range(0, v:numbersize - 2)
+ LET val = or(val, 1 << i)
+ endfor
+ call assert_equal(v:numbermax, val)
+ LET val = v:numbermax
+ for i in range(0, v:numbersize - 2)
+ LET val = and(val, invert(1 << i))
+ endfor
+ call assert_equal(0, val)
+ #" multiple operators
+ call assert_equal(16, 1 << 2 << 2)
+ call assert_equal(4, 64 >> 2 >> 2)
+ call assert_true(1 << 2 << 2 == 256 >> 2 >> 2)
+ END
+ call v9.CheckLegacyAndVim9Success(lines)
+
+ call v9.CheckLegacyAndVim9Failure(['VAR v = 2 << -1'], ['E1283:', 'E1283:', 'E1283:'])
+ call v9.CheckLegacyAndVim9Failure(['VAR a = 2', 'VAR b = -1', 'VAR v = a << b'], ['E1283:', 'E1283:', 'E1283:'])
+ call v9.CheckLegacyAndVim9Failure(['VAR v = "8" >> 2'], ['E1282:', 'E1282:', 'E1282:'])
+ call v9.CheckLegacyAndVim9Failure(['VAR v = 1 << "2"'], ['E1282:', 'E1282:', 'E1282:'])
+ call v9.CheckLegacyAndVim9Failure(['VAR a = "8"', 'VAR b = 2', 'VAR v = a << b'], ['E1282:', 'E1012:', 'E1282:'])
+ call v9.CheckLegacyAndVim9Failure(['VAR a = 8', 'VAR b = "2"', 'VAR v = a >> b'], ['E1282:', 'E1012:', 'E1282:'])
+ call v9.CheckLegacyAndVim9Failure(['VAR v = ![] << 1'], ['E745:', 'E1012:', 'E1282:'])
+ call v9.CheckLegacyAndVim9Failure(['VAR v = 1 << ![]'], ['E745:', 'E1012:', 'E1282:'])
+ call v9.CheckLegacyAndVim9Failure(['VAR v = ![] >> 1'], ['E745:', 'E1012:', 'E1282:'])
+ call v9.CheckLegacyAndVim9Failure(['VAR v = 1 >> ![]'], ['E745:', 'E1012:', 'E1282:'])
+ call v9.CheckDefAndScriptFailure(['echo 1<< 2'], ['E1004:', 'E1004:'])
+ call v9.CheckDefAndScriptFailure(['echo 1 <<2'], ['E1004:', 'E1004:'])
+ call v9.CheckDefAndScriptFailure(['echo 1>> 2'], ['E1004:', 'E1004:'])
+ call v9.CheckDefAndScriptFailure(['echo 1 >>2'], ['E1004:', 'E1004:'])
+
+ let lines =<< trim END
+ var a = 1
+ <<
+ 4
+ assert_equal(16, a)
+ END
+ call v9.CheckDefAndScriptSuccess(lines)
+ endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
*** ../vim-8.2.5002/src/testdir/test_vim9_disassemble.vim 2022-05-21 15:38:33.094080625 +0100
--- src/testdir/test_vim9_disassemble.vim 2022-05-22 18:25:44.089073531 +0100
***************
*** 2864,2867 ****
--- 2864,2894 ----
instr)
enddef
+ def BitShift()
+ var a = 1 << 2
+ var b = 8 >> 1
+ var c = a << b
+ var d = b << a
+ enddef
+
+ def Test_disassemble_bitshift()
+ var instr = execute('disassemble BitShift')
+ assert_match('BitShift\_s*' ..
+ 'var a = 1 << 2\_s*' ..
+ '0 STORE 4 in $0\_s*' ..
+ 'var b = 8 >> 1\_s*' ..
+ '1 STORE 4 in $1\_s*' ..
+ 'var c = a << b\_s*' ..
+ '2 LOAD $0\_s*' ..
+ '3 LOAD $1\_s*' ..
+ '4 OPNR <<\_s*' ..
+ '5 STORE $2\_s*' ..
+ 'var d = b << a\_s*' ..
+ '6 LOAD $1\_s*' ..
+ '7 LOAD $0\_s*' ..
+ '8 OPNR <<\_s*' ..
+ '9 STORE $3\_s*' ..
+ '10 RETURN void', instr)
+ enddef
+
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
*** ../vim-8.2.5002/src/testdir/test_vim9_expr.vim 2022-05-17 15:03:29.706610336 +0100
--- src/testdir/test_vim9_expr.vim 2022-05-22 18:25:44.089073531 +0100
***************
*** 1483,1490 ****
endif
endfunc
" test addition, subtraction, concatenation
! def Test_expr5()
var lines =<< trim END
assert_equal(66, 60 + 6)
assert_equal(70, 60 +
--- 1483,1495 ----
endif
endfunc
+ " test bitwise left and right shift operators
+ " The tests for this is in test_expr.vim (Test_bitwise_shift)
+ " def Test_expr5()
+ " enddef
+
" test addition, subtraction, concatenation
! def Test_expr6()
var lines =<< trim END
assert_equal(66, 60 + 6)
assert_equal(70, 60 +
***************
*** 1549,1555 ****
v9.CheckDefAndScriptSuccess(lines)
enddef
! def Test_expr5_vim9script()
# check line continuation
var lines =<< trim END
var name = 11
--- 1554,1560 ----
v9.CheckDefAndScriptSuccess(lines)
enddef
! def Test_expr6_vim9script()
# check line continuation
var lines =<< trim END
var name = 11
***************
*** 1698,1704 ****
endfor
enddef
! def Test_expr5_vim9script_channel()
if !has('channel')
MissingFeature 'channel'
else
--- 1703,1709 ----
endfor
enddef
! def Test_expr6_vim9script_channel()
if !has('channel')
MissingFeature 'channel'
else
***************
*** 1713,1719 ****
endif
enddef
! def Test_expr5_float()
if !has('float')
MissingFeature 'float'
else
--- 1718,1724 ----
endif
enddef
! def Test_expr6_float()
if !has('float')
MissingFeature 'float'
else
***************
*** 1741,1747 ****
endif
enddef
! func Test_expr5_fails()
let msg = "White space required before and after '+'"
call v9.CheckDefAndScriptFailure(["var x = 1+2"], msg, 1)
call v9.CheckDefAndScriptFailure(["var x = 1 +2"], msg, 1)
--- 1746,1752 ----
endif
enddef
! func Test_expr6_fails()
let msg = "White space required before and after '+'"
call v9.CheckDefAndScriptFailure(["var x = 1+2"], msg, 1)
call v9.CheckDefAndScriptFailure(["var x = 1 +2"], msg, 1)
***************
*** 1780,1793 ****
call v9.CheckDefAndScriptFailure(['var x = 1 + false'], ['E1051:', 'E1138:'], 1)
endfunc
! func Test_expr5_fails_channel()
CheckFeature channel
call v9.CheckDefAndScriptFailure(["var x = 'a' .. test_null_job()"], ['E1105:', 'E908:'], 1)
call v9.CheckDefAndScriptFailure(["var x = 'a' .. test_null_channel()"], ['E1105:', 'E908:'], 1)
endfunc
! def Test_expr5_list_add()
var lines =<< trim END
# concatenating two lists with same member types is OK
var d = {}
--- 1785,1798 ----
call v9.CheckDefAndScriptFailure(['var x = 1 + false'], ['E1051:', 'E1138:'], 1)
endfunc
! func Test_expr6_fails_channel()
CheckFeature channel
call v9.CheckDefAndScriptFailure(["var x = 'a' .. test_null_job()"], ['E1105:', 'E908:'], 1)
call v9.CheckDefAndScriptFailure(["var x = 'a' .. test_null_channel()"], ['E1105:', 'E908:'], 1)
endfunc
! def Test_expr6_list_add()
var lines =<< trim END
# concatenating two lists with same member types is OK
var d = {}
***************
*** 1818,1824 ****
enddef
" test multiply, divide, modulo
! def Test_expr6()
var lines =<< trim END
assert_equal(36, 6 * 6)
assert_equal(24, 6 *
--- 1823,1829 ----
enddef
" test multiply, divide, modulo
! def Test_expr7()
var lines =<< trim END
assert_equal(36, 6 * 6)
assert_equal(24, 6 *
***************
*** 1890,1896 ****
v9.CheckDefExecAndScriptFailure(lines, 'E1154', 2)
enddef
! def Test_expr6_vim9script()
# check line continuation
var lines =<< trim END
var name = 11
--- 1895,1901 ----
v9.CheckDefExecAndScriptFailure(lines, 'E1154', 2)
enddef
! def Test_expr7_vim9script()
# check line continuation
var lines =<< trim END
var name = 11
***************
*** 1942,1948 ****
v9.CheckDefAndScriptFailure(lines, 'E1004:', 1)
enddef
! def Test_expr6_float()
if !has('float')
MissingFeature 'float'
else
--- 1947,1953 ----
v9.CheckDefAndScriptFailure(lines, 'E1004:', 1)
enddef
! def Test_expr7_float()
if !has('float')
MissingFeature 'float'
else
***************
*** 1975,1981 ****
endif
enddef
! func Test_expr6_fails()
let msg = "White space required before and after '*'"
call v9.CheckDefAndScriptFailure(["var x = 1*2"], msg, 1)
call v9.CheckDefAndScriptFailure(["var x = 1 *2"], msg, 1)
--- 1980,1986 ----
endif
enddef
! func Test_expr7_fails()
let msg = "White space required before and after '*'"
call v9.CheckDefAndScriptFailure(["var x = 1*2"], msg, 1)
call v9.CheckDefAndScriptFailure(["var x = 1 *2"], msg, 1)
***************
*** 2019,2025 ****
endfor
endfunc
! func Test_expr6_float_fails()
CheckFeature float
call v9.CheckDefAndScriptFailure(["var x = 1.0 % 2"], ['E1035:', 'E804:'], 1)
endfunc
--- 2024,2030 ----
endfor
endfunc
! func Test_expr7_float_fails()
CheckFeature float
call v9.CheckDefAndScriptFailure(["var x = 1.0 % 2"], ['E1035:', 'E804:'], 1)
endfunc
***************
*** 2053,2059 ****
let $TESTVAR = 'testvar'
" type casts
! 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]
--- 2058,2064 ----
let $TESTVAR = 'testvar'
" type casts
! def Test_expr8()
var lines =<< trim END
var ls: list<string> = ['a', <string>g:string_empty]
var ln: list<number> = [<number>g:anint, <number>g:thefour]
***************
*** 2079,2085 ****
enddef
" test low level expression
! def Test_expr8_number()
# number constant
var lines =<< trim END
assert_equal(0, 0)
--- 2084,2090 ----
enddef
" test low level expression
! def Test_expr9_number()
# number constant
var lines =<< trim END
assert_equal(0, 0)
***************
*** 2092,2098 ****
v9.CheckDefAndScriptSuccess(lines)
enddef
! def Test_expr8_float()
# float constant
if !has('float')
MissingFeature 'float'
--- 2097,2103 ----
v9.CheckDefAndScriptSuccess(lines)
enddef
! def Test_expr9_float()
# float constant
if !has('float')
MissingFeature 'float'
***************
*** 2107,2113 ****
endif
enddef
! def Test_expr8_blob()
# blob constant
var lines =<< trim END
assert_equal(g:blob_empty, 0z)
--- 2112,2118 ----
endif
enddef
! def Test_expr9_blob()
# blob constant
var lines =<< trim END
assert_equal(g:blob_empty, 0z)
***************
*** 2139,2145 ****
v9.CheckDefAndScriptFailure(["var x = 0z123"], 'E973:', 1)
enddef
! def Test_expr8_string()
# string constant
var lines =<< trim END
assert_equal(g:string_empty, '')
--- 2144,2150 ----
v9.CheckDefAndScriptFailure(["var x = 0z123"], 'E973:', 1)
enddef
! def Test_expr9_string()
# string constant
var lines =<< trim END
assert_equal(g:string_empty, '')
***************
*** 2180,2186 ****
v9.CheckDefAndScriptSuccess(lines)
enddef
! def Test_expr8_vimvar()
v:errors = []
var errs: list<string> = v:errors
v9.CheckDefFailure(['var errs: list<number> = v:errors'], 'E1012:')
--- 2185,2191 ----
v9.CheckDefAndScriptSuccess(lines)
enddef
! def Test_expr9_vimvar()
v:errors = []
var errs: list<string> = v:errors
v9.CheckDefFailure(['var errs: list<number> = v:errors'], 'E1012:')
***************
*** 2205,2211 ****
bwipe!
enddef
! def Test_expr8_special()
# special constant
var lines =<< trim END
assert_equal(g:special_true, true)
--- 2210,2216 ----
bwipe!
enddef
! def Test_expr9_special()
# special constant
var lines =<< trim END
assert_equal(g:special_true, true)
***************
*** 2242,2248 ****
v9.CheckDefAndScriptFailure(['v:none = 22'], 'E46:', 1)
enddef
! def Test_expr8_list()
# list
var lines =<< trim END
assert_equal(g:list_empty, [])
--- 2247,2253 ----
v9.CheckDefAndScriptFailure(['v:none = 22'], 'E46:', 1)
enddef
! def Test_expr9_list()
# list
var lines =<< trim END
assert_equal(g:list_empty, [])
***************
*** 2320,2326 ****
v9.CheckDefAndScriptFailure(lines + ['echo numbers[a :b]'], 'E1004:', 4)
enddef
! def Test_expr8_list_vim9script()
var lines =<< trim END
var l = [
11,
--- 2325,2331 ----
v9.CheckDefAndScriptFailure(lines + ['echo numbers[a :b]'], 'E1004:', 4)
enddef
! def Test_expr9_list_vim9script()
var lines =<< trim END
var l = [
11,
***************
*** 2408,2414 ****
x == 2
enddef
! def Test_expr8_lambda()
var lines =<< trim END
var La = () => 'result'
# comment
--- 2413,2419 ----
x == 2
enddef
! def Test_expr9_lambda()
var lines =<< trim END
var La = () => 'result'
# comment
***************
*** 2494,2500 ****
v9.CheckDefAndScriptSuccess(lines)
enddef
! def Test_expr8_lambda_block()
var lines =<< trim END
var Func = (s: string): string => {
return 'hello ' .. s
--- 2499,2505 ----
v9.CheckDefAndScriptSuccess(lines)
enddef
! def Test_expr9_lambda_block()
var lines =<< trim END
var Func = (s: string): string => {
return 'hello ' .. s
***************
*** 2574,2580 ****
x == 2
enddef
! def Test_expr8_new_lambda()
var lines =<< trim END
var La = () => 'result'
assert_equal('result', La())
--- 2579,2585 ----
x == 2
enddef
! def Test_expr9_new_lambda()
var lines =<< trim END
var La = () => 'result'
assert_equal('result', La())
***************
*** 2659,2665 ****
v9.CheckDefAndScriptFailure(['var Fx = (a) => [0', ' 1]'], 'E696:', 2)
enddef
! def Test_expr8_lambda_vim9script()
var lines =<< trim END
var v = 10->((a) =>
a
--- 2664,2670 ----
v9.CheckDefAndScriptFailure(['var Fx = (a) => [0', ' 1]'], 'E696:', 2)
enddef
! def Test_expr9_lambda_vim9script()
var lines =<< trim END
var v = 10->((a) =>
a
***************
*** 2678,2684 ****
v9.CheckDefAndScriptSuccess(lines)
enddef
! def Test_expr8funcref()
var lines =<< trim END
def RetNumber(): number
return 123
--- 2683,2689 ----
v9.CheckDefAndScriptSuccess(lines)
enddef
! def Test_expr9funcref()
var lines =<< trim END
def RetNumber(): number
return 123
***************
*** 2730,2736 ****
let g:test_space_dict = {'': 'empty', ' ': 'space'}
let g:test_hash_dict = #{one: 1, two: 2}
! def Test_expr8_dict()
# dictionary
var lines =<< trim END
assert_equal(g:dict_empty, {})
--- 2735,2741 ----
let g:test_space_dict = {'': 'empty', ' ': 'space'}
let g:test_hash_dict = #{one: 1, two: 2}
! def Test_expr9_dict()
# dictionary
var lines =<< trim END
assert_equal(g:dict_empty, {})
***************
*** 2850,2856 ****
v9.CheckDefExecAndScriptFailure(['{}[getftype("file")]'], 'E716: Key not present in Dictionary: ""', 1)
enddef
! def Test_expr8_dict_vim9script()
var lines =<< trim END
var d = {
['one']:
--- 2855,2861 ----
v9.CheckDefExecAndScriptFailure(['{}[getftype("file")]'], 'E716: Key not present in Dictionary: ""', 1)
enddef
! def Test_expr9_dict_vim9script()
var lines =<< trim END
var d = {
['one']:
***************
*** 2981,2987 ****
v9.CheckScriptSuccess(lines)
enddef
! def Test_expr8_dict_in_block()
var lines =<< trim END
vim9script
command MyCommand {
--- 2986,2992 ----
v9.CheckScriptSuccess(lines)
enddef
! def Test_expr9_dict_in_block()
var lines =<< trim END
vim9script
command MyCommand {
***************
*** 3004,3010 ****
delcommand YourCommand
enddef
! def Test_expr8_call_2bool()
var lines =<< trim END
vim9script
--- 3009,3015 ----
delcommand YourCommand
enddef
! def Test_expr9_call_2bool()
var lines =<< trim END
vim9script
***************
*** 3052,3058 ****
v9.CheckDefExecAndScriptFailure(["var d: dict<number>", "d = g:list_empty"], 'E1012: Type mismatch; expected dict<number> but got list<unknown>', 2)
enddef
! 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])
--- 3057,3063 ----
v9.CheckDefExecAndScriptFailure(["var d: dict<number>", "d = g:list_empty"], 'E1012: Type mismatch; expected dict<number> but got list<unknown>', 2)
enddef
! def Test_expr9_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])
***************
*** 3223,3229 ****
b:someVar = &fdm
enddef
! def Test_expr8_option()
var lines =<< trim END
# option
set ts=11
--- 3228,3234 ----
b:someVar = &fdm
enddef
! def Test_expr9_option()
var lines =<< trim END
# option
set ts=11
***************
*** 3250,3256 ****
v9.CheckDefAndScriptSuccess(lines)
enddef
! def Test_expr8_environment()
var lines =<< trim END
# environment variable
assert_equal('testvar', $TESTVAR)
--- 3255,3261 ----
v9.CheckDefAndScriptSuccess(lines)
enddef
! def Test_expr9_environment()
var lines =<< trim END
# environment variable
assert_equal('testvar', $TESTVAR)
***************
*** 3262,3268 ****
v9.CheckDefAndScriptFailure(["$"], ['E1002:', 'E15:'], 1)
enddef
! def Test_expr8_register()
var lines =<< trim END
@a = 'register a'
assert_equal('register a', @a)
--- 3267,3273 ----
v9.CheckDefAndScriptFailure(["$"], ['E1002:', 'E15:'], 1)
enddef
! def Test_expr9_register()
var lines =<< trim END
@a = 'register a'
assert_equal('register a', @a)
***************
*** 3288,3294 ****
enddef
" This is slow when run under valgrind.
! def Test_expr8_namespace()
var lines =<< trim END
g:some_var = 'some'
assert_equal('some', get(g:, 'some_var'))
--- 3293,3299 ----
enddef
" This is slow when run under valgrind.
! def Test_expr9_namespace()
var lines =<< trim END
g:some_var = 'some'
assert_equal('some', get(g:, 'some_var'))
***************
*** 3317,3323 ****
v9.CheckDefAndScriptSuccess(lines)
enddef
! 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
--- 3322,3328 ----
v9.CheckDefAndScriptSuccess(lines)
enddef
! def Test_expr9_namespace_loop_def()
var lines =<< trim END
# check using g: in a for loop more than DO_NOT_FREE_CNT times
var exists = 0
***************
*** 3336,3343 ****
enddef
" NOTE: this is known to be slow. To skip use:
! " :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
--- 3341,3348 ----
enddef
" NOTE: this is known to be slow. To skip use:
! " :let $TEST_SKIP_PAT = 'Test_expr9_namespace_loop_script'
! def Test_expr9_namespace_loop_script()
var lines =<< trim END
vim9script
# check using g: in a for loop more than DO_NOT_FREE_CNT times
***************
*** 3356,3362 ****
v9.CheckScriptSuccess(lines)
enddef
! def Test_expr8_parens()
# (expr)
var lines =<< trim END
assert_equal(4, (6 * 4) / 6)
--- 3361,3367 ----
v9.CheckScriptSuccess(lines)
enddef
! def Test_expr9_parens()
# (expr)
var lines =<< trim END
assert_equal(4, (6 * 4) / 6)
***************
*** 3403,3409 ****
unlet g:result
enddef
! def Test_expr8_negate_add()
var lines =<< trim END
assert_equal(-99, -99)
assert_equal(-99, - 99)
--- 3408,3414 ----
unlet g:result
enddef
! def Test_expr9_negate_add()
var lines =<< trim END
assert_equal(-99, -99)
assert_equal(-99, - 99)
***************
*** 3452,3458 ****
legacy return #{key: 'ok'}.key
enddef
! def Test_expr8_legacy_script()
var lines =<< trim END
let s:legacy = 'legacy'
def GetLocal(): string
--- 3457,3463 ----
legacy return #{key: 'ok'}.key
enddef
! def Test_expr9_legacy_script()
var lines =<< trim END
let s:legacy = 'legacy'
def GetLocal(): string
***************
*** 3495,3501 ****
return arg
enddef
! def Test_expr8_call()
var lines =<< trim END
assert_equal('yes', 'yes'->g:Echo())
assert_equal(true, !range(5)->empty())
--- 3500,3506 ----
return arg
enddef
! def Test_expr9_call()
var lines =<< trim END
assert_equal('yes', 'yes'->g:Echo())
assert_equal(true, !range(5)->empty())
***************
*** 3518,3524 ****
return 'existing'
enddef
! def Test_expr8_call_global()
assert_equal('existing', g:ExistingGlobal())
def g:DefinedLater(): string
--- 3523,3529 ----
return 'existing'
enddef
! def Test_expr9_call_global()
assert_equal('existing', g:ExistingGlobal())
def g:DefinedLater(): string
***************
*** 3532,3538 ****
v9.CheckDefAndScriptFailure(lines, 'E117: Unknown function: ExistingGlobal')
enddef
! def Test_expr8_autoload_var()
var auto_lines =<< trim END
let autofile#var = 'found'
END
--- 3537,3543 ----
v9.CheckDefAndScriptFailure(lines, 'E117: Unknown function: ExistingGlobal')
enddef
! def Test_expr9_autoload_var()
var auto_lines =<< trim END
let autofile#var = 'found'
END
***************
*** 3555,3561 ****
delete('Xruntime', 'rf')
enddef
! def Test_expr8_call_autoload()
var auto_lines =<< trim END
def g:some#func(): string
return 'found'
--- 3560,3566 ----
delete('Xruntime', 'rf')
enddef
! def Test_expr9_call_autoload()
var auto_lines =<< trim END
def g:some#func(): string
return 'found'
***************
*** 3572,3578 ****
delete('Xruntime', 'rf')
enddef
! def Test_expr8_method_call()
var lines =<< trim END
new
setline(1, ['first', 'last'])
--- 3577,3583 ----
delete('Xruntime', 'rf')
enddef
! def Test_expr9_method_call()
var lines =<< trim END
new
setline(1, ['first', 'last'])
***************
*** 3663,3669 ****
v9.CheckDefFailure(lines, 'E15: Invalid expression: "->SetList[0]x()"')
enddef
! def Test_expr8_method_call_linebreak()
# this was giving an error when skipping over the expression
var lines =<< trim END
vim9script
--- 3668,3674 ----
v9.CheckDefFailure(lines, 'E15: Invalid expression: "->SetList[0]x()"')
enddef
! def Test_expr9_method_call_linebreak()
# this was giving an error when skipping over the expression
var lines =<< trim END
vim9script
***************
*** 3679,3685 ****
v9.CheckScriptSuccess(lines)
enddef
! def Test_expr8_method_call_import()
var lines =<< trim END
vim9script
export def Square(items: list<number>): list<number>
--- 3684,3690 ----
v9.CheckScriptSuccess(lines)
enddef
! def Test_expr9_method_call_import()
var lines =<< trim END
vim9script
export def Square(items: list<number>): list<number>
***************
*** 3714,3720 ****
enddef
! def Test_expr8_not()
var lines =<< trim END
assert_equal(true, !'')
assert_equal(true, ![])
--- 3719,3725 ----
enddef
! def Test_expr9_not()
var lines =<< trim END
assert_equal(true, !'')
assert_equal(true, ![])
***************
*** 3766,3772 ****
let g:anumber = 42
! def Test_expr8_negate()
var lines =<< trim END
var nr = 1
assert_equal(-1, -nr)
--- 3771,3777 ----
let g:anumber = 42
! def Test_expr9_negate()
var lines =<< trim END
var nr = 1
assert_equal(-1, -nr)
***************
*** 3775,3781 ****
v9.CheckDefAndScriptSuccess(lines)
enddef
! func Test_expr8_fails()
call v9.CheckDefFailure(["var x = (12"], "E1097:", 3)
call v9.CheckScriptFailure(['vim9script', "var x = (12"], 'E110:', 2)
--- 3780,3786 ----
v9.CheckDefAndScriptSuccess(lines)
enddef
! func Test_expr9_fails()
call v9.CheckDefFailure(["var x = (12"], "E1097:", 3)
call v9.CheckScriptFailure(['vim9script', "var x = (12"], 'E110:', 2)
***************
*** 3837,3843 ****
return a:one .. a:two
endfunc
! def Test_expr8_trailing()
var lines =<< trim END
# user function call
assert_equal(123, g:CallMe(123))
--- 3842,3848 ----
return a:one .. a:two
endfunc
! def Test_expr9_trailing()
var lines =<< trim END
# user function call
assert_equal(123, g:CallMe(123))
***************
*** 3873,3879 ****
v9.CheckDefAndScriptSuccess(lines)
enddef
! def Test_expr8_string_subscript()
var lines =<< trim END
var text = 'abcdef'
assert_equal('f', text[-1])
--- 3878,3884 ----
v9.CheckDefAndScriptSuccess(lines)
enddef
! def Test_expr9_string_subscript()
var lines =<< trim END
var text = 'abcdef'
assert_equal('f', text[-1])
***************
*** 3972,3978 ****
v9.CheckDefAndScriptFailure(lines, ['E1012: Type mismatch; expected number but got string', 'E1030: Using a String as a Number: "2"'], 1)
enddef
! def Test_expr8_list_subscript()
var lines =<< trim END
var list = [0, 1, 2, 3, 4]
assert_equal(0, list[0])
--- 3977,3983 ----
v9.CheckDefAndScriptFailure(lines, ['E1012: Type mismatch; expected number but got string', 'E1030: Using a String as a Number: "2"'], 1)
enddef
! def Test_expr9_list_subscript()
var lines =<< trim END
var list = [0, 1, 2, 3, 4]
assert_equal(0, list[0])
***************
*** 4015,4021 ****
v9.CheckDefAndScriptSuccess(lines)
enddef
! def Test_expr8_dict_subscript()
var lines =<< trim END
var l = [{lnum: 2}, {lnum: 1}]
var res = l[0].lnum > l[1].lnum
--- 4020,4026 ----
v9.CheckDefAndScriptSuccess(lines)
enddef
! def Test_expr9_dict_subscript()
var lines =<< trim END
var l = [{lnum: 2}, {lnum: 1}]
var res = l[0].lnum > l[1].lnum
***************
*** 4036,4042 ****
v9.CheckDefAndScriptSuccess(lines)
enddef
! def Test_expr8_blob_subscript()
var lines =<< trim END
var b = 0z112233
assert_equal(0x11, b[0])
--- 4041,4047 ----
v9.CheckDefAndScriptSuccess(lines)
enddef
! def Test_expr9_blob_subscript()
var lines =<< trim END
var b = 0z112233
assert_equal(0x11, b[0])
***************
*** 4048,4054 ****
v9.CheckDefAndScriptSuccess(lines)
enddef
! def Test_expr8_funcref_subscript()
var lines =<< trim END
var l = function('len')("abc")
assert_equal(3, l)
--- 4053,4059 ----
v9.CheckDefAndScriptSuccess(lines)
enddef
! def Test_expr9_funcref_subscript()
var lines =<< trim END
var l = function('len')("abc")
assert_equal(3, l)
***************
*** 4058,4064 ****
v9.CheckDefAndScriptFailure(["var l = function('len')(xxx)"], ['E1001: Variable not found: xxx', 'E121: Undefined variable: xxx'], 1)
enddef
! def Test_expr8_subscript_linebreak()
var lines =<< trim END
var range = range(
3)
--- 4063,4069 ----
v9.CheckDefAndScriptFailure(["var l = function('len')(xxx)"], ['E1001: Variable not found: xxx', 'E121: Undefined variable: xxx'], 1)
enddef
! def Test_expr9_subscript_linebreak()
var lines =<< trim END
var range = range(
3)
***************
*** 4101,4107 ****
v9.CheckDefAndScriptFailure(lines, ['E1127:', 'E116:'], 2)
enddef
! func Test_expr8_trailing_fails()
call v9.CheckDefAndScriptFailure(['var l = [2]', 'l->((ll) => add(ll, 8))'], 'E107:', 2)
call v9.CheckDefAndScriptFailure(['var l = [2]', 'l->((ll) => add(ll, 8)) ()'], 'E274:', 2)
endfunc
--- 4106,4112 ----
v9.CheckDefAndScriptFailure(lines, ['E1127:', 'E116:'], 2)
enddef
! func Test_expr9_trailing_fails()
call v9.CheckDefAndScriptFailure(['var l = [2]', 'l->((ll) => add(ll, 8))'], 'E107:', 2)
call v9.CheckDefAndScriptFailure(['var l = [2]', 'l->((ll) => add(ll, 8)) ()'], 'E274:', 2)
endfunc
*** ../vim-8.2.5002/src/version.c 2022-05-22 15:35:39.922194215 +0100
--- src/version.c 2022-05-22 19:09:24.436212420 +0100
***************
*** 736,737 ****
--- 736,739 ----
{ /* Add new patch number below this line */
+ /**/
+ 5003,
/**/
--
hundred-and-one symptoms of being an internet addict:
266. You hear most of your jokes via e-mail instead of in person.
/// Bram Moolenaar -- Br...@Moolenaar.net --
http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features --
http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims --
http://ICCF-Holland.org ///