To: vim_dev@googlegroups.com Subject: Patch 8.2.1867 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.1867 Problem: Vim9: argument to add() not checked for blob. Solution: Add the BLOBAPPEND instruction. 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.1866/src/vim9.h 2020-10-19 19:02:36.853261655 +0200 --- src/vim9.h 2020-10-19 20:23:16.084142073 +0200 *************** *** 126,131 **** --- 126,132 ---- ISN_ANYINDEX, // [expr] runtime index ISN_ANYSLICE, // [expr:expr] runtime slice ISN_SLICE, // drop isn_arg.number items from start of list + ISN_BLOBAPPEND, // append to a blob, like add() ISN_GETITEM, // push list item, isn_arg.number is the index ISN_MEMBER, // dict[member] ISN_STRINGMEMBER, // dict.member using isn_arg.string *** ../vim-8.2.1866/src/vim9compile.c 2020-10-19 19:02:36.857261645 +0200 --- src/vim9compile.c 2020-10-19 20:39:10.545495598 +0200 *************** *** 1521,1526 **** --- 1521,1548 ---- } /* + * Generate an ISN_BLOBAPPEND instruction. Works like add(). + * Argument count is already checked. + */ + static int + generate_BLOBAPPEND(cctx_T *cctx) + { + garray_T *stack = &cctx->ctx_type_stack; + type_T *item_type; + + // Caller already checked that blob_type is a blob. + item_type = ((type_T **)stack->ga_data)[stack->ga_len - 1]; + if (need_type(item_type, &t_number, -1, cctx, FALSE, FALSE) == FAIL) + return FAIL; + + if (generate_instr(cctx, ISN_BLOBAPPEND) == 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. */ *************** *** 2570,2582 **** 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) --- 2592,2609 ---- type_T *type = ((type_T **)stack->ga_data)[ stack->ga_len - 2]; if (type->tt_type == VAR_LIST) { // inline "add(list, item)" so that the type can be checked res = generate_LISTAPPEND(cctx); idx = -1; } + else if (type->tt_type == VAR_BLOB) + { + // inline "add(blob, nr)" so that the type can be checked + res = generate_BLOBAPPEND(cctx); + idx = -1; + } } if (idx >= 0) *************** *** 5421,5427 **** generate_PUSHS(cctx, NULL); break; case VAR_BLOB: ! generate_PUSHBLOB(cctx, NULL); break; case VAR_FUNC: generate_PUSHFUNC(cctx, NULL, &t_func_void); --- 5448,5454 ---- generate_PUSHS(cctx, NULL); break; case VAR_BLOB: ! generate_PUSHBLOB(cctx, blob_alloc()); break; case VAR_FUNC: generate_PUSHFUNC(cctx, NULL, &t_func_void); *************** *** 7675,7680 **** --- 7702,7708 ---- case ISN_ANYINDEX: case ISN_ANYSLICE: case ISN_BCALL: + case ISN_BLOBAPPEND: case ISN_CATCH: case ISN_CHECKLEN: case ISN_CHECKNR: *** ../vim-8.2.1866/src/vim9execute.c 2020-10-19 19:02:36.857261645 +0200 --- src/vim9execute.c 2020-10-19 20:31:23.638775112 +0200 *************** *** 2312,2317 **** --- 2312,2340 ---- } break; + case ISN_BLOBAPPEND: + { + typval_T *tv1 = STACK_TV_BOT(-2); + typval_T *tv2 = STACK_TV_BOT(-1); + blob_T *b = tv1->vval.v_blob; + int error = FALSE; + varnumber_T n; + + // add a number to a blob + if (b == NULL) + { + SOURCING_LNUM = iptr->isn_lnum; + emsg(_(e_cannot_add_to_null_blob)); + goto on_error; + } + n = tv_get_number_chk(tv2, &error); + if (error) + goto on_error; + ga_append(&b->bv_ga, (int)n); + --ectx.ec_stack.ga_len; + } + break; + // Computation with two arguments of unknown type case ISN_OPANY: { *************** *** 3432,3437 **** --- 3455,3461 ---- 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_BLOBAPPEND: smsg("%4d BLOBAPPEND", 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.1866/src/errors.h 2020-10-19 19:02:36.857261645 +0200 --- src/errors.h 2020-10-19 20:28:56.595184155 +0200 *************** *** 284,287 **** --- 284,289 ---- INIT(= N_("E1129: Throw with empty string")); EXTERN char e_cannot_add_to_null_list[] INIT(= N_("E1130: Cannot add to null list")); + EXTERN char e_cannot_add_to_null_blob[] + INIT(= N_("E1131: Cannot add to null blob")); #endif *** ../vim-8.2.1866/src/testdir/test_vim9_func.vim 2020-10-19 20:20:59.892531346 +0200 --- src/testdir/test_vim9_func.vim 2020-10-19 20:34:41.466227816 +0200 *************** *** 1791,1799 **** enddef def Test_blob_add() ! var b: blob = 0z12 ! add(b, 0x34) ! assert_equal(0z1234, b) enddef def SID(): number --- 1791,1815 ---- enddef def Test_blob_add() ! var b1: blob = 0z12 ! add(b1, 0x34) ! assert_equal(0z1234, b1) ! ! var b2: blob # defaults to empty blob ! add(b2, 0x67) ! assert_equal(0z67, b2) ! ! var lines =<< trim END ! var b: blob ! add(b, "x") ! END ! CheckDefFailure(lines, 'E1012:', 2) ! ! lines =<< trim END ! var b: blob = test_null_blob() ! add(b, 123) ! END ! CheckDefExecFailure(lines, 'E1131:', 2) enddef def SID(): number *** ../vim-8.2.1866/src/testdir/test_vim9_disassemble.vim 2020-10-19 19:02:36.857261645 +0200 --- src/testdir/test_vim9_disassemble.vim 2020-10-19 20:42:37.773018704 +0200 *************** *** 301,306 **** --- 301,334 ---- res) enddef + def s:BlobAdd() + var b: blob = 0z + add(b, 123) + add(b, g:aNumber) + enddef + + def Test_disassemble_blob_add() + var res = execute('disass s:BlobAdd') + assert_match('\d*_BlobAdd\_s*' .. + 'var b: blob = 0z\_s*' .. + '\d PUSHBLOB 0z\_s*' .. + '\d STORE $0\_s*' .. + 'add(b, 123)\_s*' .. + '\d LOAD $0\_s*' .. + '\d PUSHNR 123\_s*' .. + '\d BLOBAPPEND\_s*' .. + '\d DROP\_s*' .. + 'add(b, g:aNumber)\_s*' .. + '\d LOAD $0\_s*' .. + '\d\+ LOADG g:aNumber\_s*' .. + '\d\+ CHECKTYPE number stack\[-1\]\_s*' .. + '\d\+ BLOBAPPEND\_s*' .. + '\d\+ DROP\_s*' .. + '\d\+ PUSHNR 0\_s*' .. + '\d\+ RETURN', + res) + enddef + def s:ScriptFuncUnlet() g:somevar = "value" unlet g:somevar *** ../vim-8.2.1866/src/version.c 2020-10-19 20:20:59.892531346 +0200 --- src/version.c 2020-10-19 20:24:02.828009395 +0200 *************** *** 752,753 **** --- 752,755 ---- { /* Add new patch number below this line */ + /**/ + 1867, /**/ -- A fool learns from his mistakes, a wise man from someone else's. /// Bram Moolenaar -- Bram@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 ///