mirror of
https://github.com/vim/vim.git
synced 2025-09-25 03:54:15 -04:00
patch 8.2.2757: Vim9: blob tests for legacy and Vim9 script are separate
Problem: Vim9: blob tests for legacy and Vim9 script are separate. Solution: Add CheckLegacyAndVim9Success(). Make blob index assign work.
This commit is contained in:
22
src/blob.c
22
src/blob.c
@@ -336,6 +336,28 @@ blob_slice_or_index(
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set bytes "n1" to "n2" (inclusive) in "dest" to the value of "src".
|
||||||
|
* Caller must make sure "src" is a blob.
|
||||||
|
* Returns FAIL if the number of bytes does not match.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
blob_set_range(blob_T *dest, long n1, long n2, typval_T *src)
|
||||||
|
{
|
||||||
|
int il, ir;
|
||||||
|
|
||||||
|
if (n2 - n1 + 1 != blob_len(src->vval.v_blob))
|
||||||
|
{
|
||||||
|
emsg(_("E972: Blob value does not have the right number of bytes"));
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ir = 0;
|
||||||
|
for (il = n1; il <= n2; il++)
|
||||||
|
blob_set(dest, il, blob_get(src->vval.v_blob, ir++));
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* "remove({blob})" function
|
* "remove({blob})" function
|
||||||
*/
|
*/
|
||||||
|
@@ -399,3 +399,5 @@ EXTERN char e_variable_arguments_type_must_be_list_str[]
|
|||||||
INIT(= N_("E1180: Variable arguments type must be a list: %s"));
|
INIT(= N_("E1180: Variable arguments type must be a list: %s"));
|
||||||
EXTERN char e_cannot_use_underscore_here[]
|
EXTERN char e_cannot_use_underscore_here[]
|
||||||
INIT(= N_("E1181: Cannot use an underscore here"));
|
INIT(= N_("E1181: Cannot use an underscore here"));
|
||||||
|
EXTERN char e_blob_required[]
|
||||||
|
INIT(= N_("E1182: Blob required"));
|
||||||
|
15
src/eval.c
15
src/eval.c
@@ -1319,24 +1319,13 @@ set_var_lval(
|
|||||||
|
|
||||||
if (lp->ll_range && rettv->v_type == VAR_BLOB)
|
if (lp->ll_range && rettv->v_type == VAR_BLOB)
|
||||||
{
|
{
|
||||||
int il, ir;
|
|
||||||
|
|
||||||
if (lp->ll_empty2)
|
if (lp->ll_empty2)
|
||||||
lp->ll_n2 = blob_len(lp->ll_blob) - 1;
|
lp->ll_n2 = blob_len(lp->ll_blob) - 1;
|
||||||
|
|
||||||
if (lp->ll_n2 - lp->ll_n1 + 1 != blob_len(rettv->vval.v_blob))
|
if (blob_set_range(lp->ll_blob, lp->ll_n1, lp->ll_n2,
|
||||||
{
|
rettv) == FAIL)
|
||||||
emsg(_("E972: Blob value does not have the right number of bytes"));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (lp->ll_empty2)
|
|
||||||
lp->ll_n2 = blob_len(lp->ll_blob);
|
|
||||||
|
|
||||||
ir = 0;
|
|
||||||
for (il = lp->ll_n1; il <= lp->ll_n2; il++)
|
|
||||||
blob_set(lp->ll_blob, il,
|
|
||||||
blob_get(rettv->vval.v_blob, ir++));
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
val = (int)tv_get_number_chk(rettv, &error);
|
val = (int)tv_get_number_chk(rettv, &error);
|
||||||
|
@@ -3429,22 +3429,25 @@ find_ex_command(
|
|||||||
// "varname.key" is an expression.
|
// "varname.key" is an expression.
|
||||||
|| (*p == '.' && ASCII_ISALPHA(p[1]))))
|
|| (*p == '.' && ASCII_ISALPHA(p[1]))))
|
||||||
{
|
{
|
||||||
char_u *after = p;
|
char_u *after = eap->cmd;
|
||||||
|
|
||||||
// When followed by "=" or "+=" then it is an assignment.
|
// When followed by "=" or "+=" then it is an assignment.
|
||||||
|
// Skip over the whole thing, it can be:
|
||||||
|
// name.member = val
|
||||||
|
// name[a : b] = val
|
||||||
|
// name[idx] = val
|
||||||
|
// name[idx].member = val
|
||||||
|
// etc.
|
||||||
|
eap->cmdidx = CMD_eval;
|
||||||
++emsg_silent;
|
++emsg_silent;
|
||||||
if (*after == '.')
|
|
||||||
after = skipwhite(after + 1);
|
|
||||||
if (skip_expr(&after, NULL) == OK)
|
if (skip_expr(&after, NULL) == OK)
|
||||||
|
{
|
||||||
after = skipwhite(after);
|
after = skipwhite(after);
|
||||||
else
|
|
||||||
after = (char_u *)"";
|
|
||||||
if (*after == '=' || (*after != NUL && after[1] == '=')
|
if (*after == '=' || (*after != NUL && after[1] == '=')
|
||||||
|| (after[0] == '.' && after[1] == '.'
|
|| (after[0] == '.' && after[1] == '.'
|
||||||
&& after[2] == '='))
|
&& after[2] == '='))
|
||||||
eap->cmdidx = CMD_var;
|
eap->cmdidx = CMD_var;
|
||||||
else
|
}
|
||||||
eap->cmdidx = CMD_eval;
|
|
||||||
--emsg_silent;
|
--emsg_silent;
|
||||||
return eap->cmd;
|
return eap->cmd;
|
||||||
}
|
}
|
||||||
|
@@ -14,5 +14,6 @@ int write_blob(FILE *fd, blob_T *blob);
|
|||||||
char_u *blob2string(blob_T *blob, char_u **tofree, char_u *numbuf);
|
char_u *blob2string(blob_T *blob, char_u **tofree, char_u *numbuf);
|
||||||
blob_T *string2blob(char_u *str);
|
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);
|
int blob_slice_or_index(blob_T *blob, int is_range, varnumber_T n1, varnumber_T n2, int exclusive, typval_T *rettv);
|
||||||
|
int blob_set_range(blob_T *dest, long n1, long n2, typval_T *src);
|
||||||
void blob_remove(typval_T *argvars, typval_T *rettv);
|
void blob_remove(typval_T *argvars, typval_T *rettv);
|
||||||
/* vim: set ft=c : */
|
/* vim: set ft=c : */
|
||||||
|
@@ -1,5 +1,7 @@
|
|||||||
" Tests for the Blob types
|
" Tests for the Blob types
|
||||||
|
|
||||||
|
source vim9.vim
|
||||||
|
|
||||||
func TearDown()
|
func TearDown()
|
||||||
" Run garbage collection after every test
|
" Run garbage collection after every test
|
||||||
call test_garbagecollect_now()
|
call test_garbagecollect_now()
|
||||||
@@ -9,73 +11,81 @@ endfunc
|
|||||||
|
|
||||||
" Blob creation from constant
|
" Blob creation from constant
|
||||||
func Test_blob_create()
|
func Test_blob_create()
|
||||||
let b = 0zDEADBEEF
|
let lines =<< trim END
|
||||||
|
VAR b = 0zDEADBEEF
|
||||||
call assert_equal(v:t_blob, type(b))
|
call assert_equal(v:t_blob, type(b))
|
||||||
call assert_equal(4, len(b))
|
call assert_equal(4, len(b))
|
||||||
call assert_equal(0xDE, b[0])
|
call assert_equal(0xDE, b[0])
|
||||||
call assert_equal(0xAD, b[1])
|
call assert_equal(0xAD, b[1])
|
||||||
call assert_equal(0xBE, b[2])
|
call assert_equal(0xBE, b[2])
|
||||||
call assert_equal(0xEF, b[3])
|
call assert_equal(0xEF, b[3])
|
||||||
call assert_fails('let x = b[4]')
|
call assert_fails('VAR x = b[4]')
|
||||||
|
|
||||||
call assert_equal(0xDE, get(b, 0))
|
call assert_equal(0xDE, get(b, 0))
|
||||||
call assert_equal(0xEF, get(b, 3))
|
call assert_equal(0xEF, get(b, 3))
|
||||||
|
|
||||||
call assert_fails('let b = 0z1', 'E973:')
|
call assert_fails('VAR b = 0z1', 'E973:')
|
||||||
call assert_fails('let b = 0z1x', 'E973:')
|
call assert_fails('VAR b = 0z1x', 'E973:')
|
||||||
call assert_fails('let b = 0z12345', 'E973:')
|
call assert_fails('VAR b = 0z12345', 'E973:')
|
||||||
|
|
||||||
call assert_equal(0z, test_null_blob())
|
call assert_equal(0z, test_null_blob())
|
||||||
|
|
||||||
let b = 0z001122.33445566.778899.aabbcc.dd
|
LET b = 0z001122.33445566.778899.aabbcc.dd
|
||||||
call assert_equal(0z00112233445566778899aabbccdd, b)
|
call assert_equal(0z00112233445566778899aabbccdd, b)
|
||||||
call assert_fails('let b = 0z1.1')
|
call assert_fails('VAR b = 0z1.1')
|
||||||
call assert_fails('let b = 0z.')
|
call assert_fails('VAR b = 0z.')
|
||||||
call assert_fails('let b = 0z001122.')
|
call assert_fails('VAR b = 0z001122.')
|
||||||
call assert_fails('call get("", 1)', 'E896:')
|
call assert_fails('call get("", 1)', 'E896:')
|
||||||
call assert_equal(0, len(test_null_blob()))
|
call assert_equal(0, len(test_null_blob()))
|
||||||
|
END
|
||||||
|
call CheckLegacyAndVim9Success(lines)
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
" assignment to a blob
|
" assignment to a blob
|
||||||
func Test_blob_assign()
|
func Test_blob_assign()
|
||||||
let b = 0zDEADBEEF
|
let lines =<< trim END
|
||||||
let b2 = b[1:2]
|
VAR b = 0zDEADBEEF
|
||||||
|
VAR b2 = b[1 : 2]
|
||||||
call assert_equal(0zADBE, b2)
|
call assert_equal(0zADBE, b2)
|
||||||
|
|
||||||
let bcopy = b[:]
|
VAR bcopy = b[:]
|
||||||
call assert_equal(b, bcopy)
|
call assert_equal(b, bcopy)
|
||||||
call assert_false(b is bcopy)
|
call assert_false(b is bcopy)
|
||||||
|
|
||||||
let b = 0zDEADBEEF
|
LET b = 0zDEADBEEF
|
||||||
let b2 = b
|
LET b2 = b
|
||||||
call assert_true(b is b2)
|
call assert_true(b is b2)
|
||||||
let b[:] = 0z11223344
|
LET b[:] = 0z11223344
|
||||||
call assert_equal(0z11223344, b)
|
call assert_equal(0z11223344, b)
|
||||||
call assert_equal(0z11223344, b2)
|
call assert_equal(0z11223344, b2)
|
||||||
call assert_true(b is b2)
|
call assert_true(b is b2)
|
||||||
|
|
||||||
let b = 0zDEADBEEF
|
LET b = 0zDEADBEEF
|
||||||
let b[3:] = 0z66
|
LET b[3 :] = 0z66
|
||||||
call assert_equal(0zDEADBE66, b)
|
call assert_equal(0zDEADBE66, b)
|
||||||
let b[:1] = 0z8899
|
LET b[: 1] = 0z8899
|
||||||
call assert_equal(0z8899BE66, b)
|
call assert_equal(0z8899BE66, b)
|
||||||
|
|
||||||
call assert_fails('let b[2:3] = 0z112233', 'E972:')
|
LET b = 0zDEADBEEF
|
||||||
call assert_fails('let b[2:3] = 0z11', 'E972:')
|
LET b += 0z99
|
||||||
call assert_fails('let b[3:2] = 0z', 'E979:')
|
|
||||||
|
|
||||||
let b = 0zDEADBEEF
|
|
||||||
let b += 0z99
|
|
||||||
call assert_equal(0zDEADBEEF99, b)
|
call assert_equal(0zDEADBEEF99, b)
|
||||||
|
|
||||||
call assert_fails('let b .= 0z33', 'E734:')
|
VAR l = [0z12]
|
||||||
call assert_fails('let b .= "xx"', 'E734:')
|
VAR m = deepcopy(l)
|
||||||
call assert_fails('let b += "xx"', 'E734:')
|
LET m[0] = 0z34 #" E742 or E741 should not occur.
|
||||||
call assert_fails('let b[1:1] .= 0z55', 'E734:')
|
END
|
||||||
|
call CheckLegacyAndVim9Success(lines)
|
||||||
|
|
||||||
let l = [0z12]
|
" TODO: move to above once it works
|
||||||
let m = deepcopy(l)
|
let b = 0zDEADBEEF
|
||||||
let m[0] = 0z34 " E742 or E741 should not occur.
|
call assert_fails('let b[2 : 3] = 0z112233', 'E972:')
|
||||||
|
call assert_fails('let b[2 : 3] = 0z11', 'E972:')
|
||||||
|
call assert_fails('let b[3 : 2] = 0z', 'E979:')
|
||||||
|
|
||||||
|
call assert_fails('let b ..= 0z33', 'E734:')
|
||||||
|
call assert_fails('let b ..= "xx"', 'E734:')
|
||||||
|
call assert_fails('let b += "xx"', 'E734:')
|
||||||
|
call assert_fails('let b[1 : 1] ..= 0z55', 'E734:')
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Test_blob_get_range()
|
func Test_blob_get_range()
|
||||||
|
@@ -133,3 +133,38 @@ def CheckDefExecAndScriptFailure2(
|
|||||||
CheckDefExecFailure(lines, errorDef, lnum)
|
CheckDefExecFailure(lines, errorDef, lnum)
|
||||||
CheckScriptFailure(['vim9script'] + lines, errorScript, lnum + 1)
|
CheckScriptFailure(['vim9script'] + lines, errorScript, lnum + 1)
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
|
|
||||||
|
" Check that "lines" inside a legacy function has no error.
|
||||||
|
func CheckLegacySuccess(lines)
|
||||||
|
let cwd = getcwd()
|
||||||
|
let fname = 'XlegacySuccess' .. s:sequence
|
||||||
|
let s:sequence += 1
|
||||||
|
call writefile(['func Func()'] + a:lines + ['endfunc'], fname)
|
||||||
|
try
|
||||||
|
exe 'so ' .. fname
|
||||||
|
call Func()
|
||||||
|
delfunc! Func
|
||||||
|
finally
|
||||||
|
call chdir(cwd)
|
||||||
|
call delete(fname)
|
||||||
|
endtry
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" Execute "lines" in a legacy function, :def function and Vim9 script.
|
||||||
|
" Use 'VAR' for a declaration.
|
||||||
|
" Use 'LET' for an assignment
|
||||||
|
" Use ' #"' for a comment
|
||||||
|
def CheckLegacyAndVim9Success(lines: list<string>)
|
||||||
|
var legacylines = lines->mapnew((_, v) =>
|
||||||
|
v->substitute('\<VAR\>', 'let', 'g')
|
||||||
|
->substitute('\<LET\>', 'let', 'g')
|
||||||
|
->substitute('#"', ' "', 'g'))
|
||||||
|
CheckLegacySuccess(legacylines)
|
||||||
|
|
||||||
|
var vim9lines = lines->mapnew((_, v) =>
|
||||||
|
v->substitute('\<VAR\>', 'var', 'g')
|
||||||
|
->substitute('\<LET ', '', 'g'))
|
||||||
|
CheckDefSuccess(vim9lines)
|
||||||
|
CheckScriptSuccess(['vim9script'] + vim9lines)
|
||||||
|
enddef
|
||||||
|
@@ -750,6 +750,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
2757,
|
||||||
/**/
|
/**/
|
||||||
2756,
|
2756,
|
||||||
/**/
|
/**/
|
||||||
|
@@ -57,6 +57,8 @@ typedef enum {
|
|||||||
ISN_STORENR, // store number into local variable isn_arg.storenr.stnr_idx
|
ISN_STORENR, // store number into local variable isn_arg.storenr.stnr_idx
|
||||||
ISN_STOREINDEX, // store into list or dictionary, type isn_arg.vartype,
|
ISN_STOREINDEX, // store into list or dictionary, type isn_arg.vartype,
|
||||||
// value/index/variable on stack
|
// value/index/variable on stack
|
||||||
|
ISN_STORERANGE, // store into blob,
|
||||||
|
// value/index 1/index 2/variable on stack
|
||||||
|
|
||||||
ISN_UNLET, // unlet variable isn_arg.unlet.ul_name
|
ISN_UNLET, // unlet variable isn_arg.unlet.ul_name
|
||||||
ISN_UNLETENV, // unlet environment variable isn_arg.unlet.ul_name
|
ISN_UNLETENV, // unlet environment variable isn_arg.unlet.ul_name
|
||||||
|
@@ -6064,37 +6064,47 @@ compile_lhs(
|
|||||||
compile_assign_index(
|
compile_assign_index(
|
||||||
char_u *var_start,
|
char_u *var_start,
|
||||||
lhs_T *lhs,
|
lhs_T *lhs,
|
||||||
int is_assign,
|
|
||||||
int *range,
|
int *range,
|
||||||
cctx_T *cctx)
|
cctx_T *cctx)
|
||||||
{
|
{
|
||||||
size_t varlen = lhs->lhs_varlen;
|
size_t varlen = lhs->lhs_varlen;
|
||||||
char_u *p;
|
char_u *p;
|
||||||
int r = OK;
|
int r = OK;
|
||||||
|
int need_white_before = TRUE;
|
||||||
|
int empty_second;
|
||||||
|
|
||||||
p = var_start + varlen;
|
p = var_start + varlen;
|
||||||
if (*p == '[')
|
if (*p == '[')
|
||||||
{
|
{
|
||||||
p = skipwhite(p + 1);
|
p = skipwhite(p + 1);
|
||||||
|
if (*p == ':')
|
||||||
|
{
|
||||||
|
// empty first index, push zero
|
||||||
|
r = generate_PUSHNR(cctx, 0);
|
||||||
|
need_white_before = FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
r = compile_expr0(&p, cctx);
|
r = compile_expr0(&p, cctx);
|
||||||
|
|
||||||
if (r == OK && *skipwhite(p) == ':')
|
if (r == OK && *skipwhite(p) == ':')
|
||||||
{
|
{
|
||||||
// unlet var[idx : idx]
|
// unlet var[idx : idx]
|
||||||
if (is_assign)
|
// blob[idx : idx] = value
|
||||||
{
|
|
||||||
semsg(_(e_cannot_use_range_with_assignment_str), p);
|
|
||||||
return FAIL;
|
|
||||||
}
|
|
||||||
*range = TRUE;
|
*range = TRUE;
|
||||||
p = skipwhite(p);
|
p = skipwhite(p);
|
||||||
if (!IS_WHITE_OR_NUL(p[-1]) || !IS_WHITE_OR_NUL(p[1]))
|
empty_second = *skipwhite(p + 1) == ']';
|
||||||
|
if ((need_white_before && !IS_WHITE_OR_NUL(p[-1]))
|
||||||
|
|| (!empty_second && !IS_WHITE_OR_NUL(p[1])))
|
||||||
{
|
{
|
||||||
semsg(_(e_white_space_required_before_and_after_str_at_str),
|
semsg(_(e_white_space_required_before_and_after_str_at_str),
|
||||||
":", p);
|
":", p);
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
p = skipwhite(p + 1);
|
p = skipwhite(p + 1);
|
||||||
|
if (*p == ']')
|
||||||
|
// empty second index, push "none"
|
||||||
|
r = generate_PUSHSPEC(cctx, VVAL_NONE);
|
||||||
|
else
|
||||||
r = compile_expr0(&p, cctx);
|
r = compile_expr0(&p, cctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6175,8 +6185,14 @@ compile_assign_unlet(
|
|||||||
garray_T *stack = &cctx->ctx_type_stack;
|
garray_T *stack = &cctx->ctx_type_stack;
|
||||||
int range = FALSE;
|
int range = FALSE;
|
||||||
|
|
||||||
if (compile_assign_index(var_start, lhs, is_assign, &range, cctx) == FAIL)
|
if (compile_assign_index(var_start, lhs, &range, cctx) == FAIL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
|
if (is_assign && range && lhs->lhs_type != &t_blob
|
||||||
|
&& lhs->lhs_type != &t_any)
|
||||||
|
{
|
||||||
|
semsg(_(e_cannot_use_range_with_assignment_str), var_start);
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
if (lhs->lhs_type == &t_any)
|
if (lhs->lhs_type == &t_any)
|
||||||
{
|
{
|
||||||
@@ -6213,9 +6229,17 @@ compile_assign_unlet(
|
|||||||
if (compile_load_lhs(lhs, var_start, rhs_type, cctx) == FAIL)
|
if (compile_load_lhs(lhs, var_start, rhs_type, cctx) == FAIL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
|
|
||||||
if (dest_type == VAR_LIST || dest_type == VAR_DICT || dest_type == VAR_ANY)
|
if (dest_type == VAR_LIST || dest_type == VAR_DICT
|
||||||
|
|| dest_type == VAR_BLOB || dest_type == VAR_ANY)
|
||||||
{
|
{
|
||||||
if (is_assign)
|
if (is_assign)
|
||||||
|
{
|
||||||
|
if (range)
|
||||||
|
{
|
||||||
|
if (generate_instr_drop(cctx, ISN_STORERANGE, 4) == NULL)
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
isn_T *isn = generate_instr_drop(cctx, ISN_STOREINDEX, 3);
|
isn_T *isn = generate_instr_drop(cctx, ISN_STOREINDEX, 3);
|
||||||
|
|
||||||
@@ -6223,6 +6247,7 @@ compile_assign_unlet(
|
|||||||
return FAIL;
|
return FAIL;
|
||||||
isn->isn_arg.vartype = dest_type;
|
isn->isn_arg.vartype = dest_type;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else if (range)
|
else if (range)
|
||||||
{
|
{
|
||||||
if (generate_instr_drop(cctx, ISN_UNLETRANGE, 3) == NULL)
|
if (generate_instr_drop(cctx, ISN_UNLETRANGE, 3) == NULL)
|
||||||
@@ -6443,8 +6468,14 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
|||||||
// Get member from list or dict. First compile the
|
// Get member from list or dict. First compile the
|
||||||
// index value.
|
// index value.
|
||||||
if (compile_assign_index(var_start, &lhs,
|
if (compile_assign_index(var_start, &lhs,
|
||||||
TRUE, &range, cctx) == FAIL)
|
&range, cctx) == FAIL)
|
||||||
goto theend;
|
goto theend;
|
||||||
|
if (range)
|
||||||
|
{
|
||||||
|
semsg(_(e_cannot_use_range_with_assignment_str),
|
||||||
|
var_start);
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
// Get the member.
|
// Get the member.
|
||||||
if (compile_member(FALSE, cctx) == FAIL)
|
if (compile_member(FALSE, cctx) == FAIL)
|
||||||
@@ -9315,6 +9346,7 @@ delete_instr(isn_T *isn)
|
|||||||
case ISN_SLICE:
|
case ISN_SLICE:
|
||||||
case ISN_STORE:
|
case ISN_STORE:
|
||||||
case ISN_STOREINDEX:
|
case ISN_STOREINDEX:
|
||||||
|
case ISN_STORERANGE:
|
||||||
case ISN_STORENR:
|
case ISN_STORENR:
|
||||||
case ISN_STOREOUTER:
|
case ISN_STOREOUTER:
|
||||||
case ISN_STOREREG:
|
case ISN_STOREREG:
|
||||||
|
@@ -2219,6 +2219,10 @@ call_def_function(
|
|||||||
clear_tv(tv);
|
clear_tv(tv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (status == OK && dest_type == VAR_BLOB)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
status = FAIL;
|
status = FAIL;
|
||||||
@@ -2236,6 +2240,60 @@ call_def_function(
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// store value in blob range
|
||||||
|
case ISN_STORERANGE:
|
||||||
|
{
|
||||||
|
typval_T *tv_idx1 = STACK_TV_BOT(-3);
|
||||||
|
typval_T *tv_idx2 = STACK_TV_BOT(-2);
|
||||||
|
typval_T *tv_dest = STACK_TV_BOT(-1);
|
||||||
|
int status = OK;
|
||||||
|
|
||||||
|
// Stack contains:
|
||||||
|
// -4 value to be stored
|
||||||
|
// -3 first index or "none"
|
||||||
|
// -2 second index or "none"
|
||||||
|
// -1 destination blob
|
||||||
|
tv = STACK_TV_BOT(-4);
|
||||||
|
if (tv_dest->v_type != VAR_BLOB)
|
||||||
|
{
|
||||||
|
status = FAIL;
|
||||||
|
emsg(_(e_blob_required));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
varnumber_T n1;
|
||||||
|
varnumber_T n2;
|
||||||
|
int error = FALSE;
|
||||||
|
|
||||||
|
n1 = tv_get_number_chk(tv_idx1, &error);
|
||||||
|
if (error)
|
||||||
|
status = FAIL;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (tv_idx2->v_type == VAR_SPECIAL
|
||||||
|
&& tv_idx2->vval.v_number == VVAL_NONE)
|
||||||
|
n2 = blob_len(tv_dest->vval.v_blob) - 1;
|
||||||
|
else
|
||||||
|
n2 = tv_get_number_chk(tv_idx2, &error);
|
||||||
|
if (error)
|
||||||
|
status = FAIL;
|
||||||
|
else
|
||||||
|
status = blob_set_range(tv_dest->vval.v_blob,
|
||||||
|
n1, n2, tv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clear_tv(tv_idx1);
|
||||||
|
clear_tv(tv_idx2);
|
||||||
|
clear_tv(tv_dest);
|
||||||
|
ectx.ec_stack.ga_len -= 4;
|
||||||
|
clear_tv(tv);
|
||||||
|
|
||||||
|
if (status == FAIL)
|
||||||
|
goto on_error;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
// load or store variable or argument from outer scope
|
// load or store variable or argument from outer scope
|
||||||
case ISN_LOADOUTER:
|
case ISN_LOADOUTER:
|
||||||
case ISN_STOREOUTER:
|
case ISN_STOREOUTER:
|
||||||
@@ -4362,6 +4420,10 @@ ex_disassemble(exarg_T *eap)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ISN_STORERANGE:
|
||||||
|
smsg("%4d STORERANGE", current);
|
||||||
|
break;
|
||||||
|
|
||||||
// constants
|
// constants
|
||||||
case ISN_PUSHNR:
|
case ISN_PUSHNR:
|
||||||
smsg("%4d PUSHNR %lld", current,
|
smsg("%4d PUSHNR %lld", current,
|
||||||
|
Reference in New Issue
Block a user