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.

Raspunde prin e-mail lui