patch 9.1.1278: Vim9: too long functions in vim9type.c Commit: https://github.com/vim/vim/commit/d22f43111b6bef8c146a8fe7f871f478fbb4a96f Author: Yegappan Lakshmanan <yegap...@yahoo.com> Date: Sat Apr 5 15:57:12 2025 +0200
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 <yegap...@yahoo.com> Signed-off-by: Christian Brabandt <c...@256bit.org> diff --git a/src/version.c b/src/version.c index 971133b2a..883367da1 100644 --- a/src/version.c +++ b/src/version.c @@ -704,6 +704,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1278, /**/ 1277, /**/ diff --git a/src/vim9type.c b/src/vim9type.c index a3881c9b1..a90c0cc1c 100644 --- a/src/vim9type.c +++ b/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); @@ -1411,6 +1445,91 @@ check_argument_types( return OK; } +/* + * 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. + */ + static char_u * +skip_member_type(char_u *start, char_u *p, int *syn_error) +{ + if (STRNCMP("tuple", start, 5) == 0) + { + // handle tuple<{type1}, {type2}, ....<type>> + p = skipwhite(p + 1); + while (*p != '>' && *p != NUL) + { + char_u *sp = p; + + if (STRNCMP(p, "...", 3) == 0) + p += 3; + p = skip_type(p, TRUE); + if (p == sp) + { + *syn_error = TRUE; + return p; // syntax error + } + if (*p == ',') + p = skipwhite(p + 1); + } + if (*p == '>') + p++; + } + else + { + p = skipwhite(p); + p = skip_type(skipwhite(p + 1), FALSE); + p = skipwhite(p); + if (*p == '>') + ++p; + } + + return p; +} + +/* + * 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 == '(') + { + // handle func(args): type + ++p; + while (*p != ')' && *p != NUL) + { + char_u *sp = p; + + if (STRNCMP(p, "...", 3) == 0) + p += 3; + p = skip_type(p, TRUE); + if (p == sp) + { + *syn_error = TRUE; + return p; // syntax error + } + if (*p == ',') + p = skipwhite(p + 1); + } + if (*p == ')') + { + if (p[1] == ':') + p = skip_type(skipwhite(p + 2), FALSE); + else + ++p; + } + } + else + { + // 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. @@ -1418,7 +1537,8 @@ check_argument_types( char_u * skip_type(char_u *start, int optional) { - char_u *p = start; + char_u *p = start; + int syn_error = FALSE; if (optional && *p == '?') ++p; @@ -1430,66 +1550,17 @@ skip_type(char_u *start, int optional) // Skip over "<type>"; this is permissive about white space. if (*skipwhite(p) == '<') { - if (STRNCMP("tuple", start, 5) == 0) - { - // handle tuple<{type1}, {type2}, ....<type>> - p = skipwhite(p + 1); - while (*p != '>' && *p != NUL) - { - char_u *sp = p; - - if (STRNCMP(p, "...", 3) == 0) - p += 3; - p = skip_type(p, TRUE); - if (p == sp) - return p; // syntax error - if (*p == ',') - p = skipwhite(p + 1); - } - if (*p == '>') - p++; - } - else - { - p = skipwhite(p); - p = skip_type(skipwhite(p + 1), FALSE); - p = skipwhite(p); - if (*p == '>') - ++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) { - if (*p == '(') - { - // handle func(args): type - ++p; - while (*p != ')' && *p != NUL) - { - char_u *sp = p; - - if (STRNCMP(p, "...", 3) == 0) - p += 3; - p = skip_type(p, TRUE); - if (p == sp) - return p; // syntax error - if (*p == ',') - p = skipwhite(p + 1); - } - if (*p == ')') - { - if (p[1] == ':') - p = skip_type(skipwhite(p + 2), FALSE); - else - ++p; - } - } - else - { - // handle func: return_type - p = skip_type(skipwhite(p + 1), FALSE); - } + // skip over function type + p = skip_func_type(p, &syn_error); + if (syn_error) + return p; } return p; -- -- You received this message from the "vim_dev" maillist. Do not top-post! Type your reply below the text you are replying to. For more information, visit http://www.vim.org/maillist.php --- You received this message because you are subscribed to the Google Groups "vim_dev" group. To unsubscribe from this group and stop receiving emails from it, send an email to vim_dev+unsubscr...@googlegroups.com. To view this discussion visit https://groups.google.com/d/msgid/vim_dev/E1u1447-0024Mj-1l%40256bit.org.