mirror of
https://github.com/vim/vim.git
synced 2025-09-24 03:44:06 -04:00
patch 8.2.1247: Vim9: cannot index a character in a string
Problem: Vim9: cannot index a character in a string. Solution: Add ISN_STRINDEX instruction. (closes #6478)
This commit is contained in:
@@ -1509,6 +1509,15 @@ def Test_expr7_trailing()
|
|||||||
assert_equal(123, d.key)
|
assert_equal(123, d.key)
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
|
def Test_expr7_subscript()
|
||||||
|
let text = 'abcdef'
|
||||||
|
assert_equal('', text[-1])
|
||||||
|
assert_equal('a', text[0])
|
||||||
|
assert_equal('e', text[4])
|
||||||
|
assert_equal('f', text[5])
|
||||||
|
assert_equal('', text[6])
|
||||||
|
enddef
|
||||||
|
|
||||||
def Test_expr7_subscript_linebreak()
|
def Test_expr7_subscript_linebreak()
|
||||||
let range = range(
|
let range = range(
|
||||||
3)
|
3)
|
||||||
|
@@ -754,6 +754,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 */
|
||||||
|
/**/
|
||||||
|
1247,
|
||||||
/**/
|
/**/
|
||||||
1246,
|
1246,
|
||||||
/**/
|
/**/
|
||||||
|
@@ -111,7 +111,8 @@ typedef enum {
|
|||||||
|
|
||||||
// expression operations
|
// expression operations
|
||||||
ISN_CONCAT,
|
ISN_CONCAT,
|
||||||
ISN_INDEX, // [expr] list index
|
ISN_STRINDEX, // [expr] string index
|
||||||
|
ISN_LISTINDEX, // [expr] list index
|
||||||
ISN_SLICE, // drop isn_arg.number items from start of list
|
ISN_SLICE, // drop isn_arg.number items from start of list
|
||||||
ISN_GETITEM, // push list item, isn_arg.number is the index
|
ISN_GETITEM, // push list item, isn_arg.number is the index
|
||||||
ISN_MEMBER, // dict[member]
|
ISN_MEMBER, // dict[member]
|
||||||
|
@@ -3752,6 +3752,7 @@ compile_subscript(
|
|||||||
|
|
||||||
// list index: list[123]
|
// list index: list[123]
|
||||||
// dict member: dict[key]
|
// dict member: dict[key]
|
||||||
|
// string index: text[123]
|
||||||
// TODO: blob index
|
// TODO: blob index
|
||||||
// TODO: more arguments
|
// TODO: more arguments
|
||||||
// TODO: recognize list or dict at runtime
|
// TODO: recognize list or dict at runtime
|
||||||
@@ -3799,11 +3800,17 @@ compile_subscript(
|
|||||||
if (generate_instr_drop(cctx, ISN_MEMBER, 1) == FAIL)
|
if (generate_instr_drop(cctx, ISN_MEMBER, 1) == FAIL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
|
else if (vtype == VAR_STRING)
|
||||||
|
{
|
||||||
|
*typep = &t_number;
|
||||||
|
if (generate_instr_drop(cctx, ISN_STRINDEX, 1) == FAIL)
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
else if (vtype == VAR_LIST || *typep == &t_any)
|
else if (vtype == VAR_LIST || *typep == &t_any)
|
||||||
{
|
{
|
||||||
if ((*typep)->tt_type == VAR_LIST)
|
if ((*typep)->tt_type == VAR_LIST)
|
||||||
*typep = (*typep)->tt_member;
|
*typep = (*typep)->tt_member;
|
||||||
if (generate_instr_drop(cctx, ISN_INDEX, 1) == FAIL)
|
if (generate_instr_drop(cctx, ISN_LISTINDEX, 1) == FAIL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -7542,7 +7549,8 @@ delete_instr(isn_T *isn)
|
|||||||
case ISN_EXECCONCAT:
|
case ISN_EXECCONCAT:
|
||||||
case ISN_EXECUTE:
|
case ISN_EXECUTE:
|
||||||
case ISN_FOR:
|
case ISN_FOR:
|
||||||
case ISN_INDEX:
|
case ISN_LISTINDEX:
|
||||||
|
case ISN_STRINDEX:
|
||||||
case ISN_GETITEM:
|
case ISN_GETITEM:
|
||||||
case ISN_SLICE:
|
case ISN_SLICE:
|
||||||
case ISN_MEMBER:
|
case ISN_MEMBER:
|
||||||
|
@@ -2122,7 +2122,44 @@ call_def_function(
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ISN_INDEX:
|
case ISN_STRINDEX:
|
||||||
|
{
|
||||||
|
char_u *s;
|
||||||
|
varnumber_T n;
|
||||||
|
char_u *res;
|
||||||
|
|
||||||
|
// string index: string is at stack-2, index at stack-1
|
||||||
|
tv = STACK_TV_BOT(-2);
|
||||||
|
if (tv->v_type != VAR_STRING)
|
||||||
|
{
|
||||||
|
emsg(_(e_stringreq));
|
||||||
|
goto on_error;
|
||||||
|
}
|
||||||
|
s = tv->vval.v_string;
|
||||||
|
|
||||||
|
tv = STACK_TV_BOT(-1);
|
||||||
|
if (tv->v_type != VAR_NUMBER)
|
||||||
|
{
|
||||||
|
emsg(_(e_number_exp));
|
||||||
|
goto on_error;
|
||||||
|
}
|
||||||
|
n = tv->vval.v_number;
|
||||||
|
|
||||||
|
// The resulting variable is a string of a single
|
||||||
|
// character. If the index is too big or negative the
|
||||||
|
// result is empty.
|
||||||
|
if (n < 0 || n >= (varnumber_T)STRLEN(s))
|
||||||
|
res = NULL;
|
||||||
|
else
|
||||||
|
res = vim_strnsave(s + n, 1);
|
||||||
|
--ectx.ec_stack.ga_len;
|
||||||
|
tv = STACK_TV_BOT(-1);
|
||||||
|
vim_free(tv->vval.v_string);
|
||||||
|
tv->vval.v_string = res;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ISN_LISTINDEX:
|
||||||
{
|
{
|
||||||
list_T *list;
|
list_T *list;
|
||||||
varnumber_T n;
|
varnumber_T n;
|
||||||
@@ -2947,7 +2984,8 @@ ex_disassemble(exarg_T *eap)
|
|||||||
|
|
||||||
// expression operations
|
// expression operations
|
||||||
case ISN_CONCAT: smsg("%4d CONCAT", current); break;
|
case ISN_CONCAT: smsg("%4d CONCAT", current); break;
|
||||||
case ISN_INDEX: smsg("%4d INDEX", current); break;
|
case ISN_STRINDEX: smsg("%4d STRINDEX", current); break;
|
||||||
|
case ISN_LISTINDEX: smsg("%4d LISTINDEX", current); break;
|
||||||
case ISN_SLICE: smsg("%4d SLICE %lld",
|
case ISN_SLICE: smsg("%4d SLICE %lld",
|
||||||
current, iptr->isn_arg.number); break;
|
current, iptr->isn_arg.number); break;
|
||||||
case ISN_GETITEM: smsg("%4d ITEM %lld",
|
case ISN_GETITEM: smsg("%4d ITEM %lld",
|
||||||
|
Reference in New Issue
Block a user