forked from aniani/vim
patch 8.2.2219: Vim9: method call with expression not supported
Problem: Vim9: method call with expression not supported. Solution: Implement expr->(expr)().
This commit is contained in:
parent
fc0e8f5c3e
commit
7e3682068b
@ -2560,6 +2560,39 @@ def Test_expr7_call()
|
||||
delete('Xruntime', 'rf')
|
||||
enddef
|
||||
|
||||
def Test_expr7_method_call()
|
||||
new
|
||||
setline(1, ['first', 'last'])
|
||||
'second'->append(1)
|
||||
"third"->append(2)
|
||||
assert_equal(['first', 'second', 'third', 'last'], getline(1, '$'))
|
||||
bwipe!
|
||||
|
||||
var bufnr = bufnr()
|
||||
var loclist = [{bufnr: bufnr, lnum: 42, col: 17, text: 'wrong'}]
|
||||
loclist->setloclist(0)
|
||||
assert_equal([{bufnr: bufnr,
|
||||
lnum: 42,
|
||||
col: 17,
|
||||
text: 'wrong',
|
||||
pattern: '',
|
||||
valid: 1,
|
||||
vcol: 0,
|
||||
nr: 0,
|
||||
type: '',
|
||||
module: ''}
|
||||
], getloclist(0))
|
||||
|
||||
var result: bool = get({n: 0}, 'n', 0)
|
||||
assert_equal(false, result)
|
||||
|
||||
assert_equal('+string+', 'string'->((s) => '+' .. s .. '+')())
|
||||
assert_equal('-text-', 'text'->((s, c) => c .. s .. c)('-'))
|
||||
|
||||
var Join = (l) => join(l, 'x')
|
||||
assert_equal('axb', ['a', 'b']->(Join)())
|
||||
enddef
|
||||
|
||||
|
||||
def Test_expr7_not()
|
||||
var lines =<< trim END
|
||||
@ -2852,33 +2885,6 @@ def Test_expr7_subscript_linebreak()
|
||||
one)
|
||||
enddef
|
||||
|
||||
def Test_expr7_method_call()
|
||||
new
|
||||
setline(1, ['first', 'last'])
|
||||
'second'->append(1)
|
||||
"third"->append(2)
|
||||
assert_equal(['first', 'second', 'third', 'last'], getline(1, '$'))
|
||||
bwipe!
|
||||
|
||||
var bufnr = bufnr()
|
||||
var loclist = [{bufnr: bufnr, lnum: 42, col: 17, text: 'wrong'}]
|
||||
loclist->setloclist(0)
|
||||
assert_equal([{bufnr: bufnr,
|
||||
lnum: 42,
|
||||
col: 17,
|
||||
text: 'wrong',
|
||||
pattern: '',
|
||||
valid: 1,
|
||||
vcol: 0,
|
||||
nr: 0,
|
||||
type: '',
|
||||
module: ''}
|
||||
], getloclist(0))
|
||||
|
||||
var result: bool = get({n: 0}, 'n', 0)
|
||||
assert_equal(false, result)
|
||||
enddef
|
||||
|
||||
func Test_expr7_trailing_fails()
|
||||
call CheckDefFailure(['var l = [2]', 'l->{l -> add(l, 8)}'], 'E107:', 2)
|
||||
call CheckDefFailure(['var l = [2]', 'l->{l -> add(l, 8)} ()'], 'E274:', 2)
|
||||
|
@ -750,6 +750,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
2219,
|
||||
/**/
|
||||
2218,
|
||||
/**/
|
||||
|
@ -2817,9 +2817,8 @@ compile_call(
|
||||
&& compile_load(&p, namebuf + varlen, cctx, FALSE, FALSE) == OK)
|
||||
{
|
||||
garray_T *stack = &cctx->ctx_type_stack;
|
||||
type_T *type;
|
||||
type_T *type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
|
||||
|
||||
type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
|
||||
res = generate_PCALL(cctx, argcount, namebuf, type, FALSE);
|
||||
goto theend;
|
||||
}
|
||||
@ -3429,6 +3428,19 @@ get_compare_type(char_u *p, int *len, int *type_is)
|
||||
return type;
|
||||
}
|
||||
|
||||
/*
|
||||
* Skip over an expression, ignoring most errors.
|
||||
*/
|
||||
static void
|
||||
skip_expr_cctx(char_u **arg, cctx_T *cctx)
|
||||
{
|
||||
evalarg_T evalarg;
|
||||
|
||||
CLEAR_FIELD(evalarg);
|
||||
evalarg.eval_cctx = cctx;
|
||||
skip_expr(arg, &evalarg);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compile code to apply '-', '+' and '!'.
|
||||
* When "numeric_only" is TRUE do not apply '!'.
|
||||
@ -3487,6 +3499,38 @@ compile_leader(cctx_T *cctx, int numeric_only, char_u *start, char_u **end)
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compile "(expression)": recursive!
|
||||
* Return FAIL/OK.
|
||||
*/
|
||||
static int
|
||||
compile_parenthesis(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
|
||||
{
|
||||
int ret;
|
||||
|
||||
*arg = skipwhite(*arg + 1);
|
||||
if (ppconst->pp_used <= PPSIZE - 10)
|
||||
{
|
||||
ret = compile_expr1(arg, cctx, ppconst);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not enough space in ppconst, flush constants.
|
||||
if (generate_ppconst(cctx, ppconst) == FAIL)
|
||||
return FAIL;
|
||||
ret = compile_expr0(arg, cctx);
|
||||
}
|
||||
*arg = skipwhite(*arg);
|
||||
if (**arg == ')')
|
||||
++*arg;
|
||||
else if (ret == OK)
|
||||
{
|
||||
emsg(_(e_missing_close));
|
||||
ret = FAIL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compile whatever comes after "name" or "name()".
|
||||
* Advances "*arg" only when something was recognized.
|
||||
@ -3572,10 +3616,42 @@ compile_subscript(
|
||||
}
|
||||
else if (**arg == '(')
|
||||
{
|
||||
// Funcref call: list->(Refs[2])()
|
||||
// or lambda: list->((arg) => expr)()
|
||||
// TODO: make this work
|
||||
if (compile_lambda_call(arg, cctx) == FAIL)
|
||||
int argcount = 1;
|
||||
char_u *expr;
|
||||
garray_T *stack;
|
||||
type_T *type;
|
||||
|
||||
// Funcref call: list->(Refs[2])(arg)
|
||||
// or lambda: list->((arg) => expr)(arg)
|
||||
// Fist compile the arguments.
|
||||
expr = *arg;
|
||||
*arg = skipwhite(*arg + 1);
|
||||
skip_expr_cctx(arg, cctx);
|
||||
*arg = skipwhite(*arg);
|
||||
if (**arg != ')')
|
||||
{
|
||||
semsg(_(e_missing_paren), *arg);
|
||||
return FAIL;
|
||||
}
|
||||
++*arg;
|
||||
if (**arg != '(')
|
||||
{
|
||||
semsg(_(e_missing_paren), *arg);
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
*arg = skipwhite(*arg + 1);
|
||||
if (compile_arguments(arg, cctx, &argcount) == FAIL)
|
||||
return FAIL;
|
||||
|
||||
// Compile the function expression.
|
||||
if (compile_parenthesis(&expr, cctx, ppconst) == FAIL)
|
||||
return FAIL;
|
||||
|
||||
stack = &cctx->ctx_type_stack;
|
||||
type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
|
||||
if (generate_PCALL(cctx, argcount,
|
||||
(char_u *)"[expression]", type, FALSE) == FAIL)
|
||||
return FAIL;
|
||||
}
|
||||
else
|
||||
@ -3998,28 +4074,7 @@ compile_expr7(
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// (expression): recursive!
|
||||
*arg = skipwhite(*arg + 1);
|
||||
if (ppconst->pp_used <= PPSIZE - 10)
|
||||
{
|
||||
ret = compile_expr1(arg, cctx, ppconst);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not enough space in ppconst, flush constants.
|
||||
if (generate_ppconst(cctx, ppconst) == FAIL)
|
||||
return FAIL;
|
||||
ret = compile_expr0(arg, cctx);
|
||||
}
|
||||
*arg = skipwhite(*arg);
|
||||
if (**arg == ')')
|
||||
++*arg;
|
||||
else if (ret == OK)
|
||||
{
|
||||
emsg(_(e_missing_close));
|
||||
ret = FAIL;
|
||||
}
|
||||
ret = compile_parenthesis(arg, cctx, ppconst);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -4597,7 +4652,7 @@ compile_expr2(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
|
||||
* end:
|
||||
*/
|
||||
static int
|
||||
compile_expr1(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
|
||||
compile_expr1(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
|
||||
{
|
||||
char_u *p;
|
||||
int ppconst_used = ppconst->pp_used;
|
||||
@ -4606,11 +4661,7 @@ compile_expr1(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
|
||||
// Ignore all kinds of errors when not producing code.
|
||||
if (cctx->ctx_skip == SKIP_YES)
|
||||
{
|
||||
evalarg_T evalarg;
|
||||
|
||||
CLEAR_FIELD(evalarg);
|
||||
evalarg.eval_cctx = cctx;
|
||||
skip_expr(arg, &evalarg);
|
||||
skip_expr_cctx(arg, cctx);
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user