1
0
forked from aniani/vim

patch 9.1.1278: Vim9: too long functions in vim9type.c

Problem:  Vim9: too long functions in vim9type.c
Solution: refactor into separate functions
          (Yegappan Lakshmanan)

closes: #17056

Signed-off-by: Yegappan Lakshmanan <yegappan@yahoo.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
Yegappan Lakshmanan 2025-04-05 15:57:12 +02:00 committed by Christian Brabandt
parent 2f5a8c0b5b
commit d22f43111b
No known key found for this signature in database
GPG Key ID: F3F92DA383FDDE09
2 changed files with 214 additions and 141 deletions

View File

@ -704,6 +704,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
1278,
/**/
1277,
/**/

View File

@ -1174,6 +1174,122 @@ check_tuple_type_maybe(
return OK;
}
/*
* Check if the expected and actual types match for a function
* Returns OK if "expected" and "actual" are matching function types.
* Returns FAIL if "expected" and "actual" are different types.
* Returns MAYBE when a runtime type check is needed.
*/
static int
check_func_type_maybe(
type_T *expected,
type_T *actual,
where_T where)
{
int ret = OK;
// If the return type is unknown it can be anything, including
// nothing, thus there is no point in checking.
if (expected->tt_member != &t_unknown)
{
if (actual->tt_member != NULL
&& actual->tt_member != &t_unknown)
{
where_T func_where = where;
func_where.wt_kind = WT_METHOD_RETURN;
ret = check_type_maybe(expected->tt_member,
actual->tt_member, FALSE,
func_where);
}
else
ret = MAYBE;
}
if (ret != FAIL
&& ((expected->tt_flags & TTFLAG_VARARGS)
!= (actual->tt_flags & TTFLAG_VARARGS))
&& expected->tt_argcount != -1)
ret = FAIL;
if (ret != FAIL && expected->tt_argcount != -1
&& actual->tt_min_argcount != -1
&& (actual->tt_argcount == -1
|| (actual->tt_argcount < expected->tt_min_argcount
|| actual->tt_argcount > expected->tt_argcount)))
ret = FAIL;
if (ret != FAIL && expected->tt_args != NULL
&& actual->tt_args != NULL)
{
int i;
for (i = 0; i < expected->tt_argcount
&& i < actual->tt_argcount; ++i)
{
where_T func_where = where;
func_where.wt_kind = WT_METHOD_ARG;
// Allow for using "any" argument type, lambda's have them.
if (actual->tt_args[i] != &t_any && check_type(
expected->tt_args[i], actual->tt_args[i], FALSE,
func_where) == FAIL)
{
ret = FAIL;
break;
}
}
}
if (ret == OK && expected->tt_argcount >= 0
&& actual->tt_argcount == -1)
// check the argument count at runtime
ret = MAYBE;
return ret;
}
/*
* Check if the expected and actual types match for an object
* Returns OK if "expected" and "actual" are matching object types.
* Returns FAIL if "expected" and "actual" are different types.
* Returns MAYBE when a runtime type check is needed.
*/
static int
check_object_type_maybe(
type_T *expected,
type_T *actual,
where_T where)
{
int ret = OK;
if (actual->tt_type == VAR_ANY)
return MAYBE; // use runtime type check
if (actual->tt_type != VAR_OBJECT)
return FAIL; // don't use tt_class
if (actual->tt_class == NULL) // null object
return OK;
// t_object_any matches any object except for an enum item
if (expected == &t_object_any && !IS_ENUM(actual->tt_class))
return OK;
// For object method arguments, do a invariant type check in
// an extended class. For all others, do a covariance type check.
if (where.wt_kind == WT_METHOD_ARG)
{
if (actual->tt_class != expected->tt_class)
ret = FAIL;
}
else if (!class_instance_of(actual->tt_class, expected->tt_class))
{
// Check if this is an up-cast, if so we'll have to check the type at
// runtime.
if (where.wt_kind == WT_CAST &&
class_instance_of(expected->tt_class, actual->tt_class))
ret = MAYBE;
else
ret = FAIL;
}
return ret;
}
/*
* Check if the expected and actual types match.
* Does not allow for assigning "any" to a specific type.
@ -1246,91 +1362,9 @@ check_type_maybe(
else if (expected->tt_type == VAR_TUPLE && actual != &t_any)
ret = check_tuple_type_maybe(expected, actual, where);
else if (expected->tt_type == VAR_FUNC && actual != &t_any)
{
// If the return type is unknown it can be anything, including
// nothing, thus there is no point in checking.
if (expected->tt_member != &t_unknown)
{
if (actual->tt_member != NULL
&& actual->tt_member != &t_unknown)
{
where_T func_where = where;
func_where.wt_kind = WT_METHOD_RETURN;
ret = check_type_maybe(expected->tt_member,
actual->tt_member, FALSE,
func_where);
}
else
ret = MAYBE;
}
if (ret != FAIL
&& ((expected->tt_flags & TTFLAG_VARARGS)
!= (actual->tt_flags & TTFLAG_VARARGS))
&& expected->tt_argcount != -1)
ret = FAIL;
if (ret != FAIL && expected->tt_argcount != -1
&& actual->tt_min_argcount != -1
&& (actual->tt_argcount == -1
|| (actual->tt_argcount < expected->tt_min_argcount
|| actual->tt_argcount > expected->tt_argcount)))
ret = FAIL;
if (ret != FAIL && expected->tt_args != NULL
&& actual->tt_args != NULL)
{
int i;
for (i = 0; i < expected->tt_argcount
&& i < actual->tt_argcount; ++i)
{
where_T func_where = where;
func_where.wt_kind = WT_METHOD_ARG;
// Allow for using "any" argument type, lambda's have them.
if (actual->tt_args[i] != &t_any && check_type(
expected->tt_args[i], actual->tt_args[i], FALSE,
func_where) == FAIL)
{
ret = FAIL;
break;
}
}
}
if (ret == OK && expected->tt_argcount >= 0
&& actual->tt_argcount == -1)
// check the argument count at runtime
ret = MAYBE;
}
ret = check_func_type_maybe(expected, actual, where);
else if (expected->tt_type == VAR_OBJECT)
{
if (actual->tt_type == VAR_ANY)
return MAYBE; // use runtime type check
if (actual->tt_type != VAR_OBJECT)
return FAIL; // don't use tt_class
if (actual->tt_class == NULL) // null object
return OK;
// t_object_any matches any object except for an enum item
if (expected == &t_object_any && !IS_ENUM(actual->tt_class))
return OK;
// For object method arguments, do a invariant type check in
// an extended class. For all others, do a covariance type check.
if (where.wt_kind == WT_METHOD_ARG)
{
if (actual->tt_class != expected->tt_class)
ret = FAIL;
}
else if (!class_instance_of(actual->tt_class, expected->tt_class))
{
// Check if this is an up-cast, if so we'll have to check the type at
// runtime.
if (where.wt_kind == WT_CAST &&
class_instance_of(expected->tt_class, actual->tt_class))
ret = MAYBE;
else
ret = FAIL;
}
}
ret = check_object_type_maybe(expected, actual, where);
if (ret == FAIL && give_msg)
type_mismatch_where(expected, actual, where);
@ -1412,23 +1446,12 @@ check_argument_types(
}
/*
* Skip over a type definition and return a pointer to just after it.
* When "optional" is TRUE then a leading "?" is accepted.
* Skip over type in list<type>, dict<type> or tuple<type>.
* Returns a pointer to the character after the type. "syn_error" is set to
* TRUE on syntax error.
*/
char_u *
skip_type(char_u *start, int optional)
{
char_u *p = start;
if (optional && *p == '?')
++p;
// Also skip over "." for imported classes: "import.ClassName".
while (ASCII_ISALNUM(*p) || *p == '_' || *p == '.')
++p;
// Skip over "<type>"; this is permissive about white space.
if (*skipwhite(p) == '<')
static char_u *
skip_member_type(char_u *start, char_u *p, int *syn_error)
{
if (STRNCMP("tuple", start, 5) == 0)
{
@ -1442,7 +1465,10 @@ skip_type(char_u *start, int optional)
p += 3;
p = skip_type(p, TRUE);
if (p == sp)
{
*syn_error = TRUE;
return p; // syntax error
}
if (*p == ',')
p = skipwhite(p + 1);
}
@ -1457,9 +1483,16 @@ skip_type(char_u *start, int optional)
if (*p == '>')
++p;
}
return p;
}
else if ((*p == '(' || (*p == ':' && VIM_ISWHITE(p[1])))
&& STRNCMP("func", start, 4) == 0)
/*
* Skip over a function type. Returns a pointer to the character after the
* type. "syn_error" is set to TRUE on syntax error.
*/
static char_u *
skip_func_type(char_u *p, int *syn_error)
{
if (*p == '(')
{
@ -1473,7 +1506,10 @@ skip_type(char_u *start, int optional)
p += 3;
p = skip_type(p, TRUE);
if (p == sp)
{
*syn_error = TRUE;
return p; // syntax error
}
if (*p == ',')
p = skipwhite(p + 1);
}
@ -1490,6 +1526,41 @@ skip_type(char_u *start, int optional)
// handle func: return_type
p = skip_type(skipwhite(p + 1), FALSE);
}
return p;
}
/*
* Skip over a type definition and return a pointer to just after it.
* When "optional" is TRUE then a leading "?" is accepted.
*/
char_u *
skip_type(char_u *start, int optional)
{
char_u *p = start;
int syn_error = FALSE;
if (optional && *p == '?')
++p;
// Also skip over "." for imported classes: "import.ClassName".
while (ASCII_ISALNUM(*p) || *p == '_' || *p == '.')
++p;
// Skip over "<type>"; this is permissive about white space.
if (*skipwhite(p) == '<')
{
p = skip_member_type(start, p, &syn_error);
if (syn_error)
return p;
}
else if ((*p == '(' || (*p == ':' && VIM_ISWHITE(p[1])))
&& STRNCMP("func", start, 4) == 0)
{
// skip over function type
p = skip_func_type(p, &syn_error);
if (syn_error)
return p;
}
return p;