Patch 8.2.1865

7 views
Skip to first unread message

Bram Moolenaar

unread,
Oct 19, 2020, 1:03:56 PM10/19/20
to vim...@googlegroups.com

Patch 8.2.1865
Problem: Vim9: add() does not check type of argument.
Solution: Inline the add() call. (closes #7160)
Files: src/vim9.h, src/vim9compile.c, src/vim9execute.c, src/errors.h,
src/testdir/test_vim9_func.vim,
src/testdir/test_vim9_disassemble.vim


*** ../vim-8.2.1864/src/vim9.h 2020-10-03 22:51:42.890813408 +0200
--- src/vim9.h 2020-10-19 18:14:27.963998794 +0200
***************
*** 96,103 ****
ISN_ENDTRY, // take entry off from ec_trystack

// more expression operations
! ISN_ADDLIST,
! ISN_ADDBLOB,

// operation with two arguments; isn_arg.op.op_type is exptype_T
ISN_OPNR,
--- 96,103 ----
ISN_ENDTRY, // take entry off from ec_trystack

// more expression operations
! ISN_ADDLIST, // add two lists
! ISN_ADDBLOB, // add two blobs

// operation with two arguments; isn_arg.op.op_type is exptype_T
ISN_OPNR,
***************
*** 120,125 ****
--- 120,126 ----
ISN_CONCAT,
ISN_STRINDEX, // [expr] string index
ISN_STRSLICE, // [expr:expr] string slice
+ ISN_LISTAPPEND, // append to a list, like add()
ISN_LISTINDEX, // [expr] list index
ISN_LISTSLICE, // [expr:expr] list slice
ISN_ANYINDEX, // [expr] runtime index
*** ../vim-8.2.1864/src/vim9compile.c 2020-10-19 16:07:37.193322741 +0200
--- src/vim9compile.c 2020-10-19 18:35:28.577344915 +0200
***************
*** 1495,1500 ****
--- 1495,1526 ----
}

/*
+ * Generate an ISN_LISTAPPEND instruction. Works like add().
+ * Argument count is already checked.
+ */
+ static int
+ generate_LISTAPPEND(cctx_T *cctx)
+ {
+ garray_T *stack = &cctx->ctx_type_stack;
+ type_T *list_type;
+ type_T *item_type;
+ type_T *expected;
+
+ // Caller already checked that list_type is a list.
+ list_type = ((type_T **)stack->ga_data)[stack->ga_len - 2];
+ item_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
+ expected = list_type->tt_member;
+ if (need_type(item_type, expected, -1, cctx, FALSE, FALSE) == FAIL)
+ return FAIL;
+
+ if (generate_instr(cctx, ISN_LISTAPPEND) == NULL)
+ return FAIL;
+
+ --stack->ga_len; // drop the argument
+ return OK;
+ }
+
+ /*
* Generate an ISN_DCALL or ISN_UCALL instruction.
* Return FAIL if the number of arguments is wrong.
*/
***************
*** 2537,2543 ****
// builtin function
idx = find_internal_func(name);
if (idx >= 0)
! res = generate_BCALL(cctx, idx, argcount, argcount_init == 1);
else
semsg(_(e_unknownfunc), namebuf);
goto theend;
--- 2563,2587 ----
// builtin function
idx = find_internal_func(name);
if (idx >= 0)
! {
! if (STRCMP(name, "add") == 0 && argcount == 2)
! {
! garray_T *stack = &cctx->ctx_type_stack;
! type_T *type = ((type_T **)stack->ga_data)[
! stack->ga_len - 2];
!
! // TODO: also check for VAR_BLOB
! if (type->tt_type == VAR_LIST)
! {
! // inline "add(list, item)" so that the type can be checked
! res = generate_LISTAPPEND(cctx);
! idx = -1;
! }
! }
!
! if (idx >= 0)
! res = generate_BCALL(cctx, idx, argcount, argcount_init == 1);
! }
else
semsg(_(e_unknownfunc), namebuf);
goto theend;
***************
*** 7656,7661 ****
--- 7700,7706 ----
case ISN_FOR:
case ISN_GETITEM:
case ISN_JUMP:
+ case ISN_LISTAPPEND:
case ISN_LISTINDEX:
case ISN_LISTSLICE:
case ISN_LOAD:
*** ../vim-8.2.1864/src/vim9execute.c 2020-10-17 22:58:17.913317608 +0200
--- src/vim9execute.c 2020-10-19 18:59:06.617794199 +0200
***************
*** 2095,2100 ****
--- 2095,2101 ----
|| *skipwhite(tv->vval.v_string) == NUL)
{
vim_free(tv->vval.v_string);
+ SOURCING_LNUM = iptr->isn_lnum;
emsg(_(e_throw_with_empty_string));
goto failed;
}
***************
*** 2282,2287 ****
--- 2283,2289 ----
typval_T *tv1 = STACK_TV_BOT(-2);
typval_T *tv2 = STACK_TV_BOT(-1);

+ // add two lists or blobs
if (iptr->isn_type == ISN_ADDLIST)
eval_addlist(tv1, tv2);
else
***************
*** 2291,2296 ****
--- 2293,2317 ----
}
break;

+ case ISN_LISTAPPEND:
+ {
+ typval_T *tv1 = STACK_TV_BOT(-2);
+ typval_T *tv2 = STACK_TV_BOT(-1);
+ list_T *l = tv1->vval.v_list;
+
+ // add an item to a list
+ if (l == NULL)
+ {
+ SOURCING_LNUM = iptr->isn_lnum;
+ emsg(_(e_cannot_add_to_null_list));
+ goto on_error;
+ }
+ if (list_append_tv(l, tv2) == FAIL)
+ goto failed;
+ --ectx.ec_stack.ga_len;
+ }
+ break;
+
// Computation with two arguments of unknown type
case ISN_OPANY:
{
***************
*** 3410,3415 ****
--- 3431,3437 ----
case ISN_CONCAT: smsg("%4d CONCAT", current); break;
case ISN_STRINDEX: smsg("%4d STRINDEX", current); break;
case ISN_STRSLICE: smsg("%4d STRSLICE", current); break;
+ case ISN_LISTAPPEND: smsg("%4d LISTAPPEND", current); break;
case ISN_LISTINDEX: smsg("%4d LISTINDEX", current); break;
case ISN_LISTSLICE: smsg("%4d LISTSLICE", current); break;
case ISN_ANYINDEX: smsg("%4d ANYINDEX", current); break;
*** ../vim-8.2.1864/src/errors.h 2020-10-16 23:16:43.459258200 +0200
--- src/errors.h 2020-10-19 18:36:55.749148167 +0200
***************
*** 282,285 ****
--- 282,287 ----
INIT(= N_("E1128: } without {"));
EXTERN char e_throw_with_empty_string[]
INIT(= N_("E1129: Throw with empty string"));
+ EXTERN char e_cannot_add_to_null_list[]
+ INIT(= N_("E1130: Cannot add to null list"));
#endif
*** ../vim-8.2.1864/src/testdir/test_vim9_func.vim 2020-10-17 19:29:47.526935795 +0200
--- src/testdir/test_vim9_func.vim 2020-10-19 18:58:15.089922991 +0200
***************
*** 1772,1777 ****
--- 1772,1795 ----
list2str(l, true)->assert_equal(s)
enddef

+ def Test_list_add()
+ var l: list<number> # defaults to empty list
+ add(l, 9)
+ assert_equal([9], l)
+
+ var lines =<< trim END
+ var l: list<number>
+ add(l, "x")
+ END
+ CheckDefFailure(lines, 'E1012:', 2)
+
+ lines =<< trim END
+ var l: list<number> = test_null_list()
+ add(l, 123)
+ END
+ CheckDefExecFailure(lines, 'E1130:', 2)
+ enddef
+
def SID(): number
return expand('<SID>')
->matchstr('<SNR>\zs\d\+\ze_$')
*** ../vim-8.2.1864/src/testdir/test_vim9_disassemble.vim 2020-10-10 14:12:58.024646147 +0200
--- src/testdir/test_vim9_disassemble.vim 2020-10-19 18:53:39.646630997 +0200
***************
*** 273,278 ****
--- 273,306 ----
res)
enddef

+ def s:ListAdd()
+ var l: list<number> = []
+ add(l, 123)
+ add(l, g:aNumber)
+ enddef
+
+ def Test_disassemble_list_add()
+ var res = execute('disass s:ListAdd')
+ assert_match('<SNR>\d*_ListAdd\_s*' ..
+ 'var l: list<number> = []\_s*' ..
+ '\d NEWLIST size 0\_s*' ..
+ '\d STORE $0\_s*' ..
+ 'add(l, 123)\_s*' ..
+ '\d LOAD $0\_s*' ..
+ '\d PUSHNR 123\_s*' ..
+ '\d LISTAPPEND\_s*' ..
+ '\d DROP\_s*' ..
+ 'add(l, g:aNumber)\_s*' ..
+ '\d LOAD $0\_s*' ..
+ '\d\+ LOADG g:aNumber\_s*' ..
+ '\d\+ CHECKTYPE number stack\[-1\]\_s*' ..
+ '\d\+ LISTAPPEND\_s*' ..
+ '\d\+ DROP\_s*' ..
+ '\d\+ PUSHNR 0\_s*' ..
+ '\d\+ RETURN',
+ res)
+ enddef
+
def s:ScriptFuncUnlet()
g:somevar = "value"
unlet g:somevar
***************
*** 803,809 ****
'res->add(i)\_s*' ..
'\d LOAD $0\_s*' ..
'\d LOAD $2\_s*' ..
! '\d\+ BCALL add(argc 2)\_s*' ..
'\d\+ DROP\_s*' ..
'endfor\_s*' ..
'\d\+ JUMP -> \d\+\_s*' ..
--- 831,837 ----
'res->add(i)\_s*' ..
'\d LOAD $0\_s*' ..
'\d LOAD $2\_s*' ..
! '\d\+ LISTAPPEND\_s*' ..
'\d\+ DROP\_s*' ..
'endfor\_s*' ..
'\d\+ JUMP -> \d\+\_s*' ..
*** ../vim-8.2.1864/src/version.c 2020-10-19 16:07:37.193322741 +0200
--- src/version.c 2020-10-19 18:24:34.546489681 +0200
***************
*** 752,753 ****
--- 752,755 ----
{ /* Add new patch number below this line */
+ /**/
+ 1865,
/**/

--
The primary purpose of the DATA statement is to give names to constants;
instead of referring to pi as 3.141592653589793 at every appearance, the
variable PI can be given that value with a DATA statement and used instead
of the longer form of the constant. This also simplifies modifying the
program, should the value of pi change.
-- FORTRAN manual for Xerox Computers

/// Bram Moolenaar -- Br...@Moolenaar.net -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///

Bram Moolenaar

unread,
Oct 19, 2020, 2:22:11 PM10/19/20
to vim...@googlegroups.com

Patch 8.2.1865
Problem: Vim9: add() does not check type of argument.
Solution: Inline the add() call. (closes #7160)
Files: src/vim9.h, src/vim9compile.c, src/vim9execute.c, src/errors.h,
src/testdir/test_vim9_func.vim,
src/testdir/test_vim9_disassemble.vim


*** ../vim-8.2.1865/src/blob.c 2020-01-26 15:52:33.015833276 +0100
--- src/blob.c 2020-10-19 20:19:57.100712463 +0200
***************
*** 80,85 ****
--- 80,86 ----
len = 0;
}
to->vval.v_blob->bv_ga.ga_len = len;
+ to->vval.v_blob->bv_ga.ga_maxlen = len;
}
return ret;
}
*** ../vim-8.2.1865/src/testdir/test_vim9_func.vim 2020-10-19 19:02:36.857261645 +0200
--- src/testdir/test_vim9_func.vim 2020-10-19 20:19:36.504772125 +0200
***************
*** 1790,1795 ****
--- 1790,1801 ----
CheckDefExecFailure(lines, 'E1130:', 2)
enddef

+ def Test_blob_add()
+ var b: blob = 0z12
+ add(b, 0x34)
+ assert_equal(0z1234, b)
+ enddef
+
def SID(): number
return expand('<SID>')
->matchstr('<SNR>\zs\d\+\ze_$')
*** ../vim-8.2.1865/src/version.c 2020-10-19 19:02:36.857261645 +0200
--- src/version.c 2020-10-19 20:18:04.793039621 +0200
***************
*** 752,753 ****
--- 752,755 ----
{ /* Add new patch number below this line */
+ /**/
+ 1866,
/**/

--
I AM THANKFUL...
...for a lawn that needs mowing, windows that need cleaning
and gutters that need fixing because it means I have a home.
Reply all
Reply to author
Forward
0 new messages