To: vim_dev@googlegroups.com Subject: Patch 8.2.2756 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.2756 Problem: Vim9: blob index and slice not implemented yet. Solution: Implement blob index and slice. Files: src/vim9compile.c, src/vim9.h, src/vim9execute.c, src/eval.c, src/blob.c, src/proto/blob.pro, src/testdir/test_vim9_expr.vim *** ../vim-8.2.2755/src/vim9compile.c 2021-04-11 18:24:40.494508509 +0200 --- src/vim9compile.c 2021-04-11 19:06:39.003758433 +0200 *************** *** 2725,2732 **** } else if (vtype == VAR_BLOB) { ! emsg("Sorry, blob index and slice not implemented yet"); ! return FAIL; } else if (vtype == VAR_LIST || *typep == &t_any) { --- 2725,2742 ---- } else if (vtype == VAR_BLOB) { ! if (is_slice) ! { ! *typep = &t_blob; ! if (generate_instr_drop(cctx, ISN_BLOBSLICE, 2) == FAIL) ! return FAIL; ! } ! else ! { ! *typep = &t_number; ! if (generate_instr_drop(cctx, ISN_BLOBINDEX, 1) == FAIL) ! return FAIL; ! } } else if (vtype == VAR_LIST || *typep == &t_any) { *************** *** 4088,4094 **** // list index: list[123] // dict member: dict[key] // string index: text[123] ! // TODO: blob index // TODO: more arguments // TODO: recognize list or dict at runtime if (generate_ppconst(cctx, ppconst) == FAIL) --- 4098,4104 ---- // list index: list[123] // dict member: dict[key] // string index: text[123] ! // blob index: blob[123] // TODO: more arguments // TODO: recognize list or dict at runtime if (generate_ppconst(cctx, ppconst) == FAIL) *************** *** 9241,9246 **** --- 9251,9258 ---- case ISN_ANYSLICE: case ISN_BCALL: case ISN_BLOBAPPEND: + case ISN_BLOBINDEX: + case ISN_BLOBSLICE: case ISN_CATCH: case ISN_CHECKLEN: case ISN_CHECKNR: *** ../vim-8.2.2755/src/vim9.h 2021-03-29 22:14:45.604788424 +0200 --- src/vim9.h 2021-04-11 18:54:03.539798024 +0200 *************** *** 133,138 **** --- 133,140 ---- ISN_LISTAPPEND, // append to a list, like add() ISN_LISTINDEX, // [expr] list index ISN_LISTSLICE, // [expr:expr] list slice + ISN_BLOBINDEX, // [expr] blob index + ISN_BLOBSLICE, // [expr:expr] blob slice ISN_ANYINDEX, // [expr] runtime index ISN_ANYSLICE, // [expr:expr] runtime slice ISN_SLICE, // drop isn_arg.number items from start of list *** ../vim-8.2.2755/src/vim9execute.c 2021-04-10 20:46:43.888862729 +0200 --- src/vim9execute.c 2021-04-11 19:13:19.911301856 +0200 *************** *** 3415,3430 **** case ISN_LISTINDEX: case ISN_LISTSLICE: { ! int is_slice = iptr->isn_type == ISN_LISTSLICE; ! list_T *list; varnumber_T n1, n2; // list index: list is at stack-2, index at stack-1 // list slice: list is at stack-3, indexes at stack-2 and // stack-1 ! tv = is_slice ? STACK_TV_BOT(-3) : STACK_TV_BOT(-2); ! list = tv->vval.v_list; tv = STACK_TV_BOT(-1); n1 = n2 = tv->vval.v_number; --- 3415,3435 ---- case ISN_LISTINDEX: case ISN_LISTSLICE: + case ISN_BLOBINDEX: + case ISN_BLOBSLICE: { ! int is_slice = iptr->isn_type == ISN_LISTSLICE ! || iptr->isn_type == ISN_BLOBSLICE; ! int is_blob = iptr->isn_type == ISN_BLOBINDEX ! || iptr->isn_type == ISN_BLOBSLICE; varnumber_T n1, n2; + typval_T *val_tv; // list index: list is at stack-2, index at stack-1 // list slice: list is at stack-3, indexes at stack-2 and // stack-1 ! // Same for blob. ! val_tv = is_slice ? STACK_TV_BOT(-3) : STACK_TV_BOT(-2); tv = STACK_TV_BOT(-1); n1 = n2 = tv->vval.v_number; *************** *** 3440,3448 **** ectx.ec_stack.ga_len -= is_slice ? 2 : 1; tv = STACK_TV_BOT(-1); SOURCING_LNUM = iptr->isn_lnum; ! if (list_slice_or_index(list, is_slice, n1, n2, FALSE, ! tv, TRUE) == FAIL) ! goto on_error; } break; --- 3445,3462 ---- ectx.ec_stack.ga_len -= is_slice ? 2 : 1; tv = STACK_TV_BOT(-1); SOURCING_LNUM = iptr->isn_lnum; ! if (is_blob) ! { ! if (blob_slice_or_index(val_tv->vval.v_blob, is_slice, ! n1, n2, FALSE, tv) == FAIL) ! goto on_error; ! } ! else ! { ! if (list_slice_or_index(val_tv->vval.v_list, is_slice, ! n1, n2, FALSE, tv, TRUE) == FAIL) ! goto on_error; ! } } break; *************** *** 4688,4693 **** --- 4702,4709 ---- 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_BLOBINDEX: smsg("%4d BLOBINDEX", current); break; + case ISN_BLOBSLICE: smsg("%4d BLOBSLICE", 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; *** ../vim-8.2.2755/src/eval.c 2021-04-10 22:35:40.487360271 +0200 --- src/eval.c 2021-04-11 19:13:42.975271735 +0200 *************** *** 4161,4228 **** break; case VAR_BLOB: ! len = blob_len(rettv->vval.v_blob); ! if (is_range) ! { ! // The resulting variable is a sub-blob. If the indexes ! // are out of range the result is empty. ! if (n1 < 0) ! { ! n1 = len + n1; ! if (n1 < 0) ! n1 = 0; ! } ! if (n2 < 0) ! n2 = len + n2; ! else if (n2 >= len) ! n2 = len - (exclusive ? 0 : 1); ! if (exclusive) ! --n2; ! if (n1 >= len || n2 < 0 || n1 > n2) ! { ! clear_tv(rettv); ! rettv->v_type = VAR_BLOB; ! rettv->vval.v_blob = NULL; ! } ! else ! { ! blob_T *blob = blob_alloc(); ! long i; ! ! if (blob != NULL) ! { ! if (ga_grow(&blob->bv_ga, n2 - n1 + 1) == FAIL) ! { ! blob_free(blob); ! return FAIL; ! } ! blob->bv_ga.ga_len = n2 - n1 + 1; ! for (i = n1; i <= n2; i++) ! blob_set(blob, i - n1, ! blob_get(rettv->vval.v_blob, i)); ! ! clear_tv(rettv); ! rettv_blob_set(rettv, blob); ! } ! } ! } ! else ! { ! // The resulting variable is a byte value. ! // If the index is too big or negative that is an error. ! if (n1 < 0) ! n1 = len + n1; ! if (n1 < len && n1 >= 0) ! { ! int v = blob_get(rettv->vval.v_blob, n1); ! ! clear_tv(rettv); ! rettv->v_type = VAR_NUMBER; ! rettv->vval.v_number = v; ! } ! else ! semsg(_(e_blobidx), n1); ! } break; case VAR_LIST: --- 4161,4168 ---- break; case VAR_BLOB: ! blob_slice_or_index(rettv->vval.v_blob, is_range, n1, n2, ! exclusive, rettv); break; case VAR_LIST: *** ../vim-8.2.2755/src/blob.c 2020-10-19 20:20:59.892531346 +0200 --- src/blob.c 2021-04-11 19:15:26.603132861 +0200 *************** *** 259,264 **** --- 259,341 ---- return NULL; } + int + blob_slice_or_index( + blob_T *blob, + int is_range, + varnumber_T n1, + varnumber_T n2, + int exclusive, + typval_T *rettv) + { + long len = blob_len(blob); + + if (is_range) + { + // The resulting variable is a sub-blob. If the indexes + // are out of range the result is empty. + if (n1 < 0) + { + n1 = len + n1; + if (n1 < 0) + n1 = 0; + } + if (n2 < 0) + n2 = len + n2; + else if (n2 >= len) + n2 = len - (exclusive ? 0 : 1); + if (exclusive) + --n2; + if (n1 >= len || n2 < 0 || n1 > n2) + { + clear_tv(rettv); + rettv->v_type = VAR_BLOB; + rettv->vval.v_blob = NULL; + } + else + { + blob_T *new_blob = blob_alloc(); + long i; + + if (new_blob != NULL) + { + if (ga_grow(&new_blob->bv_ga, n2 - n1 + 1) == FAIL) + { + blob_free(new_blob); + return FAIL; + } + new_blob->bv_ga.ga_len = n2 - n1 + 1; + for (i = n1; i <= n2; i++) + blob_set(new_blob, i - n1, blob_get(blob, i)); + + clear_tv(rettv); + rettv_blob_set(rettv, new_blob); + } + } + } + else + { + // The resulting variable is a byte value. + // If the index is too big or negative that is an error. + if (n1 < 0) + n1 = len + n1; + if (n1 < len && n1 >= 0) + { + int v = blob_get(blob, n1); + + clear_tv(rettv); + rettv->v_type = VAR_NUMBER; + rettv->vval.v_number = v; + } + else + { + semsg(_(e_blobidx), n1); + return FAIL; + } + } + return OK; + } + /* * "remove({blob})" function */ *** ../vim-8.2.2755/src/proto/blob.pro 2020-01-26 15:52:33.023833239 +0100 --- src/proto/blob.pro 2021-04-11 19:16:56.571008077 +0200 *************** *** 13,17 **** --- 13,18 ---- int write_blob(FILE *fd, blob_T *blob); char_u *blob2string(blob_T *blob, char_u **tofree, char_u *numbuf); blob_T *string2blob(char_u *str); + int blob_slice_or_index(blob_T *blob, int is_range, varnumber_T n1, varnumber_T n2, int exclusive, typval_T *rettv); void blob_remove(typval_T *argvars, typval_T *rettv); /* vim: set ft=c : */ *** ../vim-8.2.2755/src/testdir/test_vim9_expr.vim 2021-04-11 18:24:40.494508509 +0200 --- src/testdir/test_vim9_expr.vim 2021-04-11 20:18:30.683569421 +0200 *************** *** 1622,1627 **** --- 1622,1647 ---- assert_equal(g:blob_empty, 0z) assert_equal(g:blob_one, 0z01) assert_equal(g:blob_long, 0z0102.0304) + + var testblob = 0z010203 + assert_equal(0x01, testblob[0]) + assert_equal(0x02, testblob[1]) + assert_equal(0x03, testblob[-1]) + assert_equal(0x02, testblob[-2]) + + assert_equal(0z01, testblob[0 : 0]) + assert_equal(0z0102, testblob[0 : 1]) + assert_equal(0z010203, testblob[0 : 2]) + assert_equal(0z010203, testblob[0 : ]) + assert_equal(0z0203, testblob[1 : ]) + assert_equal(0z0203, testblob[1 : 2]) + assert_equal(0z0203, testblob[1 : -1]) + assert_equal(0z03, testblob[-1 : -1]) + assert_equal(0z02, testblob[-2 : -2]) + + # blob slice accepts out of range + assert_equal(0z, testblob[3 : 3]) + assert_equal(0z, testblob[0 : -4]) END CheckDefAndScriptSuccess(lines) *** ../vim-8.2.2755/src/version.c 2021-04-11 18:24:40.498508499 +0200 --- src/version.c 2021-04-11 20:18:56.519500813 +0200 *************** *** 752,753 **** --- 752,755 ---- { /* Add new patch number below this line */ + /**/ + 2756, /**/ -- From "know your smileys": 2B|^2B Message from Shakespeare /// Bram Moolenaar -- Bram@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 ///