]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.1.0914: Vim9: compile_assignment() is too long v9.1.0914
authorYegappan Lakshmanan <yegappan@yahoo.com>
Sun, 8 Dec 2024 09:15:35 +0000 (10:15 +0100)
committerChristian Brabandt <cb@256bit.org>
Sun, 8 Dec 2024 09:15:35 +0000 (10:15 +0100)
Problem:  Vim9: compile_assignment() is too long
Solution: refactor compile_assignment() into smaller functions
          (Yegappan Lakshmanan)

closes: #16186

Signed-off-by: Yegappan Lakshmanan <yegappan@yahoo.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
src/version.c
src/vim9compile.c

index 1333d9dea0fdc7994120a3e8693e3d5f78c26778..1ae3f53369d97a2678c7d6656ef48ad89dbbd815 100644 (file)
@@ -704,6 +704,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    914,
 /**/
     913,
 /**/
index ea305b7b34bb5213e7f2d1d507a2f6493c641af5..e75462f0b4b109ac0a0101a73b420e9605c2e461 100644 (file)
@@ -2583,6 +2583,156 @@ push_default_value(
     return r;
 }
 
+/*
+ * Compile an object member variable assignment in the argument passed to a
+ * class new() method.
+ *
+ * Instruction format:
+ *
+ *     ifargisset <n> this.<varname> = <value>
+ *
+ * where <n> is the object member variable index.
+ *
+ * Generates the ISN_JUMP_IF_ARG_NOT_SET instruction to skip the assignment if
+ * the value is passed as an argument to the new() method call.
+ *
+ * Returns OK on success.
+ */
+    static int
+compile_assignment_obj_new_arg(char_u **argp, cctx_T *cctx)
+{
+    char_u *arg = *argp;
+
+    arg += 11;     // skip "ifargisset"
+    int def_idx = getdigits(&arg);
+    arg = skipwhite(arg);
+
+    // Use a JUMP_IF_ARG_NOT_SET instruction to skip if the value was not
+    // given and the default value is "v:none".
+    int off = STACK_FRAME_SIZE + (cctx->ctx_ufunc->uf_va_name != NULL
+                                                               ? 1 : 0);
+    int count = cctx->ctx_ufunc->uf_def_args.ga_len;
+    if (generate_JUMP_IF_ARG(cctx, ISN_JUMP_IF_ARG_NOT_SET,
+                                       def_idx - count - off) == FAIL)
+       return FAIL;
+
+    *argp = arg;
+    return OK;
+}
+
+/*
+ * Convert the increment (++) or decrement (--) operator to the corresponding
+ * compound operator.
+ *
+ * Returns OK on success and FAIL on syntax error.
+ */
+    static int
+incdec_op_translate(
+    exarg_T    *eap,
+    char_u     **op,
+    int                *oplen,
+    int                *incdec)
+{
+    if (VIM_ISWHITE(eap->cmd[2]))
+    {
+       semsg(_(e_no_white_space_allowed_after_str_str),
+               eap->cmdidx == CMD_increment ? "++" : "--", eap->cmd);
+       return FAIL;
+    }
+    *op = (char_u *)(eap->cmdidx == CMD_increment ? "+=" : "-=");
+    *oplen = 2;
+    *incdec = TRUE;
+
+    return OK;
+}
+
+/*
+ * Parse a heredoc assignment starting at "p".  Returns a pointer to the
+ * beginning of the heredoc content.
+ */
+    static char_u *
+heredoc_assign_stmt_end_get(char_u *p, exarg_T *eap, cctx_T *cctx)
+{
+    // [let] varname =<< [trim] {end}
+    eap->ea_getline = exarg_getline;
+    eap->cookie = cctx;
+
+    list_T *l = heredoc_get(eap, p + 3, FALSE, TRUE);
+    if (l == NULL)
+       return NULL;
+
+    list_free(l);
+    p += STRLEN(p);
+
+    return p;
+}
+
+    static char_u *
+compile_list_assignment(
+    char_u     *p,
+    char_u     *op,
+    int                oplen,
+    int                var_count,
+    int                semicolon,
+    garray_T   *instr,
+    type_T     **rhs_type,
+    cctx_T     *cctx)
+{
+    char_u *wp;
+
+    // for "[var, var] = expr" evaluate the expression here, loop over the
+    // list of variables below.
+    // A line break may follow the "=".
+
+    wp = op + oplen;
+    if (may_get_next_line_error(wp, &p, cctx) == FAIL)
+       return NULL;
+    if (compile_expr0(&p, cctx) == FAIL)
+       return NULL;
+
+    if (cctx->ctx_skip != SKIP_YES)
+    {
+       type_T  *stacktype;
+       int             needed_list_len;
+       int             did_check = FALSE;
+
+       stacktype = cctx->ctx_type_stack.ga_len == 0 ? &t_void
+                                               : get_type_on_stack(cctx, 0);
+       if (stacktype->tt_type == VAR_VOID)
+       {
+           emsg(_(e_cannot_use_void_value));
+           return NULL;
+       }
+       if (need_type(stacktype, &t_list_any, FALSE, -1, 0, cctx, FALSE,
+                                                       FALSE) == FAIL)
+           return NULL;
+       // If a constant list was used we can check the length right here.
+       needed_list_len = semicolon ? var_count - 1 : var_count;
+       if (instr->ga_len > 0)
+       {
+           isn_T       *isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
+
+           if (isn->isn_type == ISN_NEWLIST)
+           {
+               did_check = TRUE;
+               if (semicolon ? isn->isn_arg.number < needed_list_len
+                       : isn->isn_arg.number != needed_list_len)
+               {
+                   semsg(_(e_expected_nr_items_but_got_nr),
+                           needed_list_len, (int)isn->isn_arg.number);
+                   return NULL;
+               }
+           }
+       }
+       if (!did_check)
+           generate_CHECKLEN(cctx, needed_list_len, semicolon);
+       if (stacktype->tt_member != NULL)
+           *rhs_type = stacktype->tt_member;
+    }
+
+    return p;
+}
+
 /*
  * Compile declaration and assignment:
  * "let name"
@@ -2625,38 +2775,20 @@ compile_assignment(
     long       start_lnum = SOURCING_LNUM;
 
     int        has_arg_is_set_prefix = STRNCMP(arg, "ifargisset ", 11) == 0;
-    if (has_arg_is_set_prefix)
-    {
-       arg += 11;
-       int def_idx = getdigits(&arg);
-       arg = skipwhite(arg);
-
-       // Use a JUMP_IF_ARG_NOT_SET instruction to skip if the value was not
-       // given and the default value is "v:none".
-       int off = STACK_FRAME_SIZE + (cctx->ctx_ufunc->uf_va_name != NULL
-                                                                     ? 1 : 0);
-       int count = cctx->ctx_ufunc->uf_def_args.ga_len;
-       if (generate_JUMP_IF_ARG(cctx, ISN_JUMP_IF_ARG_NOT_SET,
-                                               def_idx - count - off) == FAIL)
-           goto theend;
-    }
+    if (has_arg_is_set_prefix &&
+           compile_assignment_obj_new_arg(&arg, cctx) == FAIL)
+       goto theend;
 
     // Skip over the "varname" or "[varname, varname]" to get to any "=".
     p = skip_var_list(arg, TRUE, &var_count, &semicolon, TRUE);
     if (p == NULL)
        return *arg == '[' ? arg : NULL;
 
+
     if (eap->cmdidx == CMD_increment || eap->cmdidx == CMD_decrement)
     {
-       if (VIM_ISWHITE(eap->cmd[2]))
-       {
-           semsg(_(e_no_white_space_allowed_after_str_str),
-                        eap->cmdidx == CMD_increment ? "++" : "--", eap->cmd);
+       if (incdec_op_translate(eap, &op, &oplen, &incdec) == FAIL)
            return NULL;
-       }
-       op = (char_u *)(eap->cmdidx == CMD_increment ? "+=" : "-=");
-       oplen = 2;
-       incdec = TRUE;
     }
     else
     {
@@ -2678,73 +2810,19 @@ compile_assignment(
 
     if (heredoc)
     {
-       list_T     *l;
-
-       // [let] varname =<< [trim] {end}
-       eap->ea_getline = exarg_getline;
-       eap->cookie = cctx;
-       l = heredoc_get(eap, op + 3, FALSE, TRUE);
-       if (l == NULL)
+       p = heredoc_assign_stmt_end_get(p, eap, cctx);
+       if (p == NULL)
            return NULL;
-
-       list_free(l);
-       p += STRLEN(p);
        end = p;
     }
     else if (var_count > 0)
     {
-       char_u *wp;
-
-       // for "[var, var] = expr" evaluate the expression here, loop over the
-       // list of variables below.
-       // A line break may follow the "=".
-
-       wp = op + oplen;
-       if (may_get_next_line_error(wp, &p, cctx) == FAIL)
-           return FAIL;
-       if (compile_expr0(&p, cctx) == FAIL)
-           return NULL;
+       // "[var, var] = expr"
+       p = compile_list_assignment(p, op, oplen, var_count, semicolon,
+                                               instr, &rhs_type, cctx);
+       if (p == NULL)
+           goto theend;
        end = p;
-
-       if (cctx->ctx_skip != SKIP_YES)
-       {
-           type_T      *stacktype;
-           int         needed_list_len;
-           int         did_check = FALSE;
-
-           stacktype = cctx->ctx_type_stack.ga_len == 0 ? &t_void
-                                                 : get_type_on_stack(cctx, 0);
-           if (stacktype->tt_type == VAR_VOID)
-           {
-               emsg(_(e_cannot_use_void_value));
-               goto theend;
-           }
-           if (need_type(stacktype, &t_list_any, FALSE, -1, 0, cctx,
-                                                        FALSE, FALSE) == FAIL)
-               goto theend;
-           // If a constant list was used we can check the length right here.
-           needed_list_len = semicolon ? var_count - 1 : var_count;
-           if (instr->ga_len > 0)
-           {
-               isn_T   *isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
-
-               if (isn->isn_type == ISN_NEWLIST)
-               {
-                   did_check = TRUE;
-                   if (semicolon ? isn->isn_arg.number < needed_list_len
-                           : isn->isn_arg.number != needed_list_len)
-                   {
-                       semsg(_(e_expected_nr_items_but_got_nr),
-                                   needed_list_len, (int)isn->isn_arg.number);
-                       goto theend;
-                   }
-               }
-           }
-           if (!did_check)
-               generate_CHECKLEN(cctx, needed_list_len, semicolon);
-           if (stacktype->tt_member != NULL)
-               rhs_type = stacktype->tt_member;
-       }
     }
 
     /*