patch 9.1.1577: Vim9: no generic support yet
Problem: Vim9: no generic support yet
Solution: Add support for generic functions, funcrefs and object/class
methods (Yegappan Lakshmanan).
closes: #17313
Signed-off-by: Yegappan Lakshmanan <yegappan@yahoo.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
committed by
Christian Brabandt
parent
b486ed8266
commit
3416cee36f
70
src/eval.c
70
src/eval.c
@ -1620,12 +1620,12 @@ get_lval_tuple(
|
||||
* The method index, method function pointer and method type are returned in
|
||||
* "lp".
|
||||
*/
|
||||
static void
|
||||
static int
|
||||
get_lval_oc_method(
|
||||
lval_T *lp,
|
||||
class_T *cl,
|
||||
char_u *key,
|
||||
char_u *key_end,
|
||||
char_u **key_end,
|
||||
vartype_T v_type)
|
||||
{
|
||||
// Look for a method with this name.
|
||||
@ -1637,8 +1637,13 @@ get_lval_oc_method(
|
||||
ufunc_T *fp;
|
||||
|
||||
fp = method_lookup(cl, round == 1 ? VAR_CLASS : VAR_OBJECT,
|
||||
key, key_end - key, &m_idx);
|
||||
key, *key_end - key, &m_idx);
|
||||
lp->ll_oi = m_idx;
|
||||
|
||||
// process generic method (if present)
|
||||
if (fp && (fp = eval_generic_func(fp, key, key_end)) == NULL)
|
||||
return FAIL;
|
||||
|
||||
if (fp != NULL)
|
||||
{
|
||||
lp->ll_ufunc = fp;
|
||||
@ -1646,6 +1651,8 @@ get_lval_oc_method(
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1711,7 +1718,7 @@ get_lval_oc_variable(
|
||||
get_lval_class_or_obj(
|
||||
lval_T *lp,
|
||||
char_u *key,
|
||||
char_u *key_end,
|
||||
char_u **key_end,
|
||||
vartype_T v_type,
|
||||
class_T *cl_exec,
|
||||
int flags,
|
||||
@ -1747,19 +1754,20 @@ get_lval_class_or_obj(
|
||||
lp->ll_valtype = NULL;
|
||||
|
||||
if (flags & GLV_PREFER_FUNC)
|
||||
get_lval_oc_method(lp, cl, key, key_end, v_type);
|
||||
if (get_lval_oc_method(lp, cl, key, key_end, v_type) == FAIL)
|
||||
return FAIL;
|
||||
|
||||
// Look for object/class member variable
|
||||
if (lp->ll_valtype == NULL)
|
||||
{
|
||||
if (get_lval_oc_variable(lp, cl, key, key_end, v_type, cl_exec, flags)
|
||||
if (get_lval_oc_variable(lp, cl, key, *key_end, v_type, cl_exec, flags)
|
||||
== FAIL)
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
if (lp->ll_valtype == NULL)
|
||||
{
|
||||
member_not_found_msg(cl, v_type, key, key_end - key);
|
||||
member_not_found_msg(cl, v_type, key, *key_end - key);
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
@ -2039,7 +2047,7 @@ get_lval_subscript(
|
||||
}
|
||||
else // v_type == VAR_CLASS || v_type == VAR_OBJECT
|
||||
{
|
||||
if (get_lval_class_or_obj(lp, key, p, v_type, cl_exec, flags,
|
||||
if (get_lval_class_or_obj(lp, key, &p, v_type, cl_exec, flags,
|
||||
quiet) == FAIL)
|
||||
goto done;
|
||||
}
|
||||
@ -2213,7 +2221,7 @@ get_lval(
|
||||
// parse the type after the name
|
||||
lp->ll_type = parse_type(&tp,
|
||||
&SCRIPT_ITEM(current_sctx.sc_sid)->sn_type_list,
|
||||
!quiet);
|
||||
NULL, NULL, !quiet);
|
||||
if (lp->ll_type == NULL && !quiet)
|
||||
return NULL;
|
||||
lp->ll_name_end = tp;
|
||||
@ -3179,6 +3187,8 @@ eval_func(
|
||||
funcexe.fe_basetv = basetv;
|
||||
funcexe.fe_check_type = type;
|
||||
funcexe.fe_found_var = found_var;
|
||||
if (evalarg != NULL)
|
||||
funcexe.fe_cctx = evalarg->eval_cctx;
|
||||
ret = get_func_tv(s, len, rettv, arg, evalarg, &funcexe);
|
||||
}
|
||||
vim_free(s);
|
||||
@ -4725,7 +4735,7 @@ eval8(
|
||||
{
|
||||
++*arg;
|
||||
ga_init2(&type_list, sizeof(type_T *), 10);
|
||||
want_type = parse_type(arg, &type_list, TRUE);
|
||||
want_type = parse_type(arg, &type_list, NULL, NULL, TRUE);
|
||||
if (want_type == NULL && (evaluate || **arg != '>'))
|
||||
{
|
||||
clear_type_list(&type_list);
|
||||
@ -4973,7 +4983,7 @@ eval9_nested_expr(
|
||||
|
||||
if (vim9script)
|
||||
{
|
||||
ret = get_lambda_tv(arg, rettv, TRUE, evalarg);
|
||||
ret = get_lambda_tv(arg, rettv, TRUE, evalarg, NULL);
|
||||
if (ret == OK && evaluate)
|
||||
{
|
||||
ufunc_T *ufunc = rettv->vval.v_partial->pt_func;
|
||||
@ -5062,7 +5072,8 @@ eval9_var_func_name(
|
||||
semsg(_(e_cannot_use_s_colon_in_vim9_script_str), s);
|
||||
ret = FAIL;
|
||||
}
|
||||
else if ((vim9script ? **arg : *skipwhite(*arg)) == '(')
|
||||
else if ((vim9script ? **arg : *skipwhite(*arg)) == '('
|
||||
|| (vim9script && generic_func_call(arg)))
|
||||
{
|
||||
// "name(..." recursive!
|
||||
*arg = skipwhite(*arg);
|
||||
@ -5079,6 +5090,12 @@ eval9_var_func_name(
|
||||
*name_start = s;
|
||||
ret = eval_variable(s, len, 0, rettv, NULL,
|
||||
EVAL_VAR_VERBOSE + EVAL_VAR_IMPORT);
|
||||
|
||||
// skip the generic function arguments (if present)
|
||||
// they are already processed by eval_variable
|
||||
if (ret == OK && vim9script && **arg == '<'
|
||||
&& rettv->v_type == VAR_FUNC)
|
||||
ret = skip_generic_func_type_args(arg);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -5230,7 +5247,7 @@ eval9(
|
||||
case '{': if (vim9script)
|
||||
ret = NOTDONE;
|
||||
else
|
||||
ret = get_lambda_tv(arg, rettv, vim9script, evalarg);
|
||||
ret = get_lambda_tv(arg, rettv, vim9script, evalarg, NULL);
|
||||
if (ret == NOTDONE)
|
||||
ret = eval_dict(arg, rettv, evalarg, FALSE);
|
||||
break;
|
||||
@ -5438,6 +5455,8 @@ call_func_rettv(
|
||||
funcexe.fe_partial = pt;
|
||||
funcexe.fe_selfdict = selfdict;
|
||||
funcexe.fe_basetv = basetv;
|
||||
if (evalarg != NULL)
|
||||
funcexe.fe_cctx = evalarg->eval_cctx;
|
||||
ret = get_func_tv(s, -1, rettv, arg, evalarg, &funcexe);
|
||||
|
||||
theend:
|
||||
@ -5471,7 +5490,7 @@ eval_lambda(
|
||||
if (**arg == '{')
|
||||
{
|
||||
// ->{lambda}()
|
||||
ret = get_lambda_tv(arg, rettv, FALSE, evalarg);
|
||||
ret = get_lambda_tv(arg, rettv, FALSE, evalarg, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -5663,6 +5682,15 @@ eval_index(
|
||||
;
|
||||
if (keylen == 0)
|
||||
return FAIL;
|
||||
if (vim9script && key[keylen] == '<')
|
||||
{
|
||||
// skip generic type arguments
|
||||
char_u *p = &key[keylen];
|
||||
|
||||
if (skip_generic_func_type_args(&p) == FAIL)
|
||||
return FAIL;
|
||||
keylen = p - key;
|
||||
}
|
||||
*arg = key + keylen;
|
||||
}
|
||||
else
|
||||
@ -7374,7 +7402,19 @@ handle_subscript(
|
||||
else
|
||||
{
|
||||
rettv->v_type = VAR_FUNC;
|
||||
rettv->vval.v_string = vim_strnsave(ufunc->uf_name, ufunc->uf_namelen);
|
||||
if (**arg == '<')
|
||||
{
|
||||
char_u *s = get_generic_func_name(ufunc, arg);
|
||||
if (s != NULL)
|
||||
rettv->vval.v_string = s;
|
||||
else
|
||||
ret = FAIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
rettv->vval.v_string =
|
||||
vim_strnsave(ufunc->uf_name, ufunc->uf_namelen);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user