0
0
mirror of https://github.com/vim/vim.git synced 2025-11-16 23:24:03 -05:00

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:
Yegappan Lakshmanan
2025-07-21 21:36:08 +02:00
committed by Christian Brabandt
parent b486ed8266
commit 3416cee36f
35 changed files with 5905 additions and 161 deletions

View File

@@ -101,7 +101,7 @@ copy_type_deep_rec(type_T *type, garray_T *type_gap, garray_T *seen_types)
* Make a deep copy of "type".
* When allocation fails returns "type".
*/
static type_T *
type_T *
copy_type_deep(type_T *type, garray_T *type_gap)
{
garray_T seen_types;
@@ -342,7 +342,10 @@ get_list_type(type_T *member_type, garray_T *type_gap)
type_T *type;
// recognize commonly used types
if (member_type == NULL || member_type->tt_type == VAR_ANY)
// A generic type is t_any initially before being set to a concrete type
// later. So don't use the static t_list_any for a generic type.
if (member_type == NULL || (member_type->tt_type == VAR_ANY
&& !IS_GENERIC_TYPE(member_type)))
return &t_list_any;
if (member_type->tt_type == VAR_VOID
|| member_type->tt_type == VAR_UNKNOWN)
@@ -810,7 +813,29 @@ fp_typval2type(typval_T *tv, garray_T *type_gap)
type_gap);
}
else
ufunc = find_func(name, FALSE);
{
// Check if name contains "<". If it does, then replace "<" with
// NUL and lookup the function and then look up the specific
// generic function using the supplied types.
char_u *p = generic_func_find_open_bracket(name);
if (p == NULL)
ufunc = find_func(name, FALSE);
else
{
// generic function
char_u cc = *p;
*p = NUL;
ufunc = find_func(name, FALSE);
*p = cc;
if (ufunc != NULL && IS_GENERIC_FUNC(ufunc))
{
ufunc = find_generic_func(ufunc, name, &p);
if (ufunc == NULL)
return NULL;
}
}
}
}
if (ufunc != NULL)
{
@@ -1582,7 +1607,9 @@ parse_type_member(
type_T *type,
garray_T *type_gap,
int give_error,
char *info)
char *info,
ufunc_T *ufunc,
cctx_T *cctx)
{
char_u *arg_start = *arg;
type_T *member_type;
@@ -1601,7 +1628,7 @@ parse_type_member(
}
*arg = skipwhite(*arg + 1);
member_type = parse_type(arg, type_gap, give_error);
member_type = parse_type(arg, type_gap, ufunc, cctx, give_error);
if (member_type == NULL)
return NULL;
@@ -1625,7 +1652,13 @@ parse_type_member(
* Return NULL for failure.
*/
static type_T *
parse_type_func(char_u **arg, size_t len, garray_T *type_gap, int give_error)
parse_type_func(
char_u **arg,
size_t len,
garray_T *type_gap,
int give_error,
ufunc_T *ufunc,
cctx_T *cctx)
{
char_u *p;
type_T *type;
@@ -1665,7 +1698,7 @@ parse_type_func(char_u **arg, size_t len, garray_T *type_gap, int give_error)
return NULL;
}
type = parse_type(&p, type_gap, give_error);
type = parse_type(&p, type_gap, ufunc, cctx, give_error);
if (type == NULL)
return NULL;
if ((flags & TTFLAG_VARARGS) != 0 && type->tt_type != VAR_LIST)
@@ -1725,7 +1758,7 @@ parse_type_func(char_u **arg, size_t len, garray_T *type_gap, int give_error)
if (!VIM_ISWHITE(**arg) && give_error)
semsg(_(e_white_space_required_after_str_str), ":", *arg - 1);
*arg = skipwhite(*arg);
ret_type = parse_type(arg, type_gap, give_error);
ret_type = parse_type(arg, type_gap, ufunc, cctx, give_error);
if (ret_type == NULL)
return NULL;
}
@@ -1755,7 +1788,12 @@ parse_type_func(char_u **arg, size_t len, garray_T *type_gap, int give_error)
* Return NULL for failure.
*/
static type_T *
parse_type_tuple(char_u **arg, garray_T *type_gap, int give_error)
parse_type_tuple(
char_u **arg,
garray_T *type_gap,
int give_error,
ufunc_T *ufunc,
cctx_T *cctx)
{
char_u *p;
type_T *type;
@@ -1792,7 +1830,7 @@ parse_type_tuple(char_u **arg, garray_T *type_gap, int give_error)
p += 3;
}
type = parse_type(&p, type_gap, give_error);
type = parse_type(&p, type_gap, ufunc, cctx, give_error);
if (type == NULL)
goto on_err;
@@ -1865,7 +1903,11 @@ on_err:
* Return NULL for failure.
*/
static type_T *
parse_type_object(char_u **arg, garray_T *type_gap, int give_error)
parse_type_object(
char_u **arg,
garray_T *type_gap,
int give_error,
cctx_T *cctx)
{
char_u *arg_start = *arg;
type_T *object_type;
@@ -1889,7 +1931,7 @@ parse_type_object(char_u **arg, garray_T *type_gap, int give_error)
// skip spaces following "object<"
*arg = skipwhite(*arg + 1);
object_type = parse_type(arg, type_gap, give_error);
object_type = parse_type(arg, type_gap, NULL, cctx, give_error);
if (object_type == NULL)
return NULL;
@@ -1926,7 +1968,9 @@ parse_type_user_defined(
char_u **arg,
size_t len,
garray_T *type_gap,
int give_error)
int give_error,
ufunc_T *ufunc,
cctx_T *cctx)
{
int did_emsg_before = did_emsg;
typval_T tv;
@@ -1968,6 +2012,14 @@ parse_type_user_defined(
clear_tv(&tv);
}
// Check whether it is a generic type
type_T *type = find_generic_type(*arg, len, ufunc, cctx);
if (type != NULL)
{
*arg += len;
return type;
}
if (give_error && (did_emsg == did_emsg_before))
{
char_u *p = skip_type(*arg, FALSE);
@@ -1987,7 +2039,12 @@ parse_type_user_defined(
* Return NULL for failure.
*/
type_T *
parse_type(char_u **arg, garray_T *type_gap, int give_error)
parse_type(
char_u **arg,
garray_T *type_gap,
ufunc_T *ufunc,
cctx_T *cctx,
int give_error)
{
char_u *p = *arg;
size_t len;
@@ -2029,8 +2086,9 @@ parse_type(char_u **arg, garray_T *type_gap, int give_error)
if (len == 4 && STRNCMP(*arg, "dict", len) == 0)
{
*arg += len;
return parse_type_member(arg, &t_dict_any,
type_gap, give_error, "dict");
return parse_type_member(arg, &t_dict_any, type_gap,
give_error, "dict", ufunc,
cctx);
}
break;
case 'f':
@@ -2040,7 +2098,8 @@ parse_type(char_u **arg, garray_T *type_gap, int give_error)
return &t_float;
}
if (len == 4 && STRNCMP(*arg, "func", len) == 0)
return parse_type_func(arg, len, type_gap, give_error);
return parse_type_func(arg, len, type_gap, give_error, ufunc,
cctx);
break;
case 'j':
if (len == 3 && STRNCMP(*arg, "job", len) == 0)
@@ -2053,8 +2112,9 @@ parse_type(char_u **arg, garray_T *type_gap, int give_error)
if (len == 4 && STRNCMP(*arg, "list", len) == 0)
{
*arg += len;
return parse_type_member(arg, &t_list_any,
type_gap, give_error, "list");
return parse_type_member(arg, &t_list_any, type_gap,
give_error, "list", ufunc,
cctx);
}
break;
case 'n':
@@ -2068,7 +2128,7 @@ parse_type(char_u **arg, garray_T *type_gap, int give_error)
if (len == 6 && STRNCMP(*arg, "object", len) == 0)
{
*arg += len;
return parse_type_object(arg, type_gap, give_error);
return parse_type_object(arg, type_gap, give_error, cctx);
}
break;
case 's':
@@ -2082,7 +2142,8 @@ parse_type(char_u **arg, garray_T *type_gap, int give_error)
if (len == 5 && STRNCMP(*arg, "tuple", len) == 0)
{
*arg += len;
return parse_type_tuple(arg, type_gap, give_error);
return parse_type_tuple(arg, type_gap, give_error, ufunc,
cctx);
}
break;
case 'v':
@@ -2095,7 +2156,8 @@ parse_type(char_u **arg, garray_T *type_gap, int give_error)
}
// User defined type
return parse_type_user_defined(arg, len, type_gap, give_error);
return parse_type_user_defined(arg, len, type_gap, give_error, ufunc,
cctx);
}
/*