mirror of
https://github.com/vim/vim.git
synced 2025-09-23 03:43:49 -04:00
patch 8.2.3704: Vim9: cannot use a list declaration in a :def function
Problem: Vim9: cannot use a list declaration in a :def function. Solution: Make it work.
This commit is contained in:
@@ -420,12 +420,11 @@ similar to how a function argument can be ignored: >
|
||||
To ignore any remaining items: >
|
||||
[a, b; _] = longList
|
||||
|
||||
< *E1092*
|
||||
Declaring more than one variable at a time, using the unpack notation, is
|
||||
currently not supported: >
|
||||
var [v1, v2] = GetValues() # Error!
|
||||
That is because the type needs to be inferred from the list item type, which
|
||||
isn't that easy.
|
||||
possible. Each variable can have a type or infer it from the value: >
|
||||
var [v1: number, v2] = GetValues()
|
||||
Use this only when there is a list with values, declaring one variable per
|
||||
line is much easier to read and change later.
|
||||
|
||||
|
||||
Constants ~
|
||||
|
@@ -366,8 +366,7 @@ EXTERN char e_cannot_assign_to_argument[]
|
||||
INIT(= N_("E1090: Cannot assign to argument %s"));
|
||||
EXTERN char e_function_is_not_compiled_str[]
|
||||
INIT(= N_("E1091: Function is not compiled: %s"));
|
||||
EXTERN char e_cannot_use_list_for_declaration[]
|
||||
INIT(= N_("E1092: Cannot use a list for a declaration"));
|
||||
// E1092 unused
|
||||
EXTERN char e_expected_nr_items_but_got_nr[]
|
||||
INIT(= N_("E1093: Expected %d items but got %d"));
|
||||
EXTERN char e_import_can_only_be_used_in_script[]
|
||||
|
@@ -732,7 +732,6 @@ def Test_assignment_list()
|
||||
assert_equal(['sdf', 'asdf', 'end'], list3)
|
||||
|
||||
CheckDefExecFailure(['var ll = [1, 2, 3]', 'll[-4] = 6'], 'E684:')
|
||||
CheckDefExecFailure(['var [v1, v2] = [1, 2]'], 'E1092:')
|
||||
|
||||
# type becomes list<any>
|
||||
var somelist = rand() > 0 ? [1, 2, 3] : ['a', 'b', 'c']
|
||||
@@ -753,6 +752,60 @@ def Test_assignment_list()
|
||||
CheckDefExecAndScriptFailure(lines, 'E1012:', 5)
|
||||
enddef
|
||||
|
||||
def Test_list_declaration()
|
||||
var [v1, v2] = [1, 2]
|
||||
v1 += 3
|
||||
assert_equal(4, v1)
|
||||
v2 *= 3
|
||||
assert_equal(6, v2)
|
||||
|
||||
var lines =<< trim END
|
||||
var [v1, v2] = [1]
|
||||
END
|
||||
CheckDefExecAndScriptFailure2(lines, 'E1093: Expected 2 items but got 1', 'E688:')
|
||||
lines =<< trim END
|
||||
var testlist = [1]
|
||||
var [v1, v2] = testlist
|
||||
END
|
||||
CheckDefExecAndScriptFailure2(lines, 'E1093: Expected 2 items but got 1', 'E688:')
|
||||
lines =<< trim END
|
||||
var [v1, v2] = [1, 2, 3]
|
||||
END
|
||||
CheckDefExecAndScriptFailure2(lines, 'E1093: Expected 2 items but got 3', 'E687:')
|
||||
lines =<< trim END
|
||||
var testlist = [1, 2, 3]
|
||||
var [v1, v2] = testlist
|
||||
END
|
||||
CheckDefExecAndScriptFailure2(lines, 'E1093: Expected 2 items but got 3', 'E687:')
|
||||
|
||||
var [vnr, vstr] = [123, 'text']
|
||||
vnr += 3
|
||||
assert_equal(126, vnr)
|
||||
vstr ..= 'end'
|
||||
assert_equal('textend', vstr)
|
||||
|
||||
var [vnr2: number, vstr2: string] = [123, 'text']
|
||||
vnr2 += 3
|
||||
assert_equal(126, vnr2)
|
||||
vstr2 ..= 'end'
|
||||
assert_equal('textend', vstr2)
|
||||
|
||||
var [vnr3: number; vlist: list<string>] = [123, 'foo', 'bar']
|
||||
vnr3 += 5
|
||||
assert_equal(128, vnr3)
|
||||
assert_equal(['foo', 'bar'], vlist)
|
||||
|
||||
lines =<< trim END
|
||||
var [vnr2: number, vstr2: number] = [123, 'text']
|
||||
END
|
||||
CheckDefExecAndScriptFailure2(lines, 'E1163: Variable 2: type mismatch, expected number but got string', 'E1012: Type mismatch; expected number but got string')
|
||||
lines =<< trim END
|
||||
var testlist = [234, 'text']
|
||||
var [vnr2: number, vstr2: number] = testlist
|
||||
END
|
||||
CheckDefExecAndScriptFailure2(lines, 'E1163: Variable 2: type mismatch, expected number but got string', 'E1012: Type mismatch; expected number but got string')
|
||||
enddef
|
||||
|
||||
def PartFuncBool(b: bool): string
|
||||
return 'done'
|
||||
enddef
|
||||
|
@@ -753,6 +753,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
3704,
|
||||
/**/
|
||||
3703,
|
||||
/**/
|
||||
|
@@ -144,6 +144,7 @@ typedef struct {
|
||||
// any "[expr]" or ".name"
|
||||
char_u *lhs_dest_end; // end of the destination, including
|
||||
// "[expr]" or ".name".
|
||||
char_u *lhs_end; // end including any type
|
||||
|
||||
int lhs_has_index; // has "[expr]" or ".name"
|
||||
|
||||
@@ -6299,6 +6300,7 @@ compile_lhs(
|
||||
--lhs->lhs_dest_end;
|
||||
if (is_decl && var_end == var_start + 2 && var_end[-1] == ':')
|
||||
--var_end;
|
||||
lhs->lhs_end = lhs->lhs_dest_end;
|
||||
|
||||
// compute the length of the destination without "[expr]" or ".name"
|
||||
lhs->lhs_varlen = var_end - var_start;
|
||||
@@ -6435,7 +6437,7 @@ compile_lhs(
|
||||
}
|
||||
}
|
||||
|
||||
// handle "a:name" as a name, not index "name" on "a"
|
||||
// handle "a:name" as a name, not index "name" in "a"
|
||||
if (lhs->lhs_varlen > 1 || var_start[lhs->lhs_varlen] != ':')
|
||||
var_end = lhs->lhs_dest_end;
|
||||
|
||||
@@ -6456,6 +6458,7 @@ compile_lhs(
|
||||
if (lhs->lhs_type == NULL)
|
||||
return FAIL;
|
||||
lhs->lhs_has_type = TRUE;
|
||||
lhs->lhs_end = p;
|
||||
}
|
||||
else if (lhs->lhs_lvar != NULL)
|
||||
lhs->lhs_type = lhs->lhs_lvar->lv_type;
|
||||
@@ -6896,13 +6899,6 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
||||
if (p == NULL)
|
||||
return *arg == '[' ? arg : NULL;
|
||||
|
||||
if (var_count > 0 && is_decl)
|
||||
{
|
||||
// TODO: should we allow this, and figure out type inference from list
|
||||
// members?
|
||||
emsg(_(e_cannot_use_list_for_declaration));
|
||||
return NULL;
|
||||
}
|
||||
lhs.lhs_name = NULL;
|
||||
|
||||
sp = p;
|
||||
@@ -7330,7 +7326,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
||||
cctx->ctx_lnum = save_lnum;
|
||||
|
||||
if (var_idx + 1 < var_count)
|
||||
var_start = skipwhite(lhs.lhs_dest_end + 1);
|
||||
var_start = skipwhite(lhs.lhs_end + 1);
|
||||
}
|
||||
|
||||
// For "[var, var] = expr" drop the "expr" value.
|
||||
|
Reference in New Issue
Block a user