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:
parent
2f5a8c0b5b
commit
d22f43111b
@ -704,6 +704,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
1278,
|
||||
/**/
|
||||
1277,
|
||||
/**/
|
||||
|
275
src/vim9type.c
275
src/vim9type.c
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user