mirror of
https://github.com/vim/vim.git
synced 2025-07-26 11:04:33 -04:00
patch 9.1.0914: Vim9: compile_assignment() is too long
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>
This commit is contained in:
parent
65be834c30
commit
85ee742f1e
@ -704,6 +704,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
914,
|
||||||
/**/
|
/**/
|
||||||
913,
|
913,
|
||||||
/**/
|
/**/
|
||||||
|
@ -2583,6 +2583,156 @@ push_default_value(
|
|||||||
return r;
|
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:
|
* Compile declaration and assignment:
|
||||||
* "let name"
|
* "let name"
|
||||||
@ -2625,39 +2775,21 @@ compile_assignment(
|
|||||||
long start_lnum = SOURCING_LNUM;
|
long start_lnum = SOURCING_LNUM;
|
||||||
|
|
||||||
int has_arg_is_set_prefix = STRNCMP(arg, "ifargisset ", 11) == 0;
|
int has_arg_is_set_prefix = STRNCMP(arg, "ifargisset ", 11) == 0;
|
||||||
if (has_arg_is_set_prefix)
|
if (has_arg_is_set_prefix &&
|
||||||
{
|
compile_assignment_obj_new_arg(&arg, cctx) == FAIL)
|
||||||
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;
|
goto theend;
|
||||||
}
|
|
||||||
|
|
||||||
// Skip over the "varname" or "[varname, varname]" to get to any "=".
|
// Skip over the "varname" or "[varname, varname]" to get to any "=".
|
||||||
p = skip_var_list(arg, TRUE, &var_count, &semicolon, TRUE);
|
p = skip_var_list(arg, TRUE, &var_count, &semicolon, TRUE);
|
||||||
if (p == NULL)
|
if (p == NULL)
|
||||||
return *arg == '[' ? arg : NULL;
|
return *arg == '[' ? arg : NULL;
|
||||||
|
|
||||||
|
|
||||||
if (eap->cmdidx == CMD_increment || eap->cmdidx == CMD_decrement)
|
if (eap->cmdidx == CMD_increment || eap->cmdidx == CMD_decrement)
|
||||||
{
|
{
|
||||||
if (VIM_ISWHITE(eap->cmd[2]))
|
if (incdec_op_translate(eap, &op, &oplen, &incdec) == FAIL)
|
||||||
{
|
|
||||||
semsg(_(e_no_white_space_allowed_after_str_str),
|
|
||||||
eap->cmdidx == CMD_increment ? "++" : "--", eap->cmd);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
op = (char_u *)(eap->cmdidx == CMD_increment ? "+=" : "-=");
|
|
||||||
oplen = 2;
|
|
||||||
incdec = TRUE;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sp = p;
|
sp = p;
|
||||||
@ -2678,73 +2810,19 @@ compile_assignment(
|
|||||||
|
|
||||||
if (heredoc)
|
if (heredoc)
|
||||||
{
|
{
|
||||||
list_T *l;
|
p = heredoc_assign_stmt_end_get(p, eap, cctx);
|
||||||
|
if (p == NULL)
|
||||||
// [let] varname =<< [trim] {end}
|
|
||||||
eap->ea_getline = exarg_getline;
|
|
||||||
eap->cookie = cctx;
|
|
||||||
l = heredoc_get(eap, op + 3, FALSE, TRUE);
|
|
||||||
if (l == NULL)
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
list_free(l);
|
|
||||||
p += STRLEN(p);
|
|
||||||
end = p;
|
end = p;
|
||||||
}
|
}
|
||||||
else if (var_count > 0)
|
else if (var_count > 0)
|
||||||
{
|
{
|
||||||
char_u *wp;
|
// "[var, var] = expr"
|
||||||
|
p = compile_list_assignment(p, op, oplen, var_count, semicolon,
|
||||||
// for "[var, var] = expr" evaluate the expression here, loop over the
|
instr, &rhs_type, cctx);
|
||||||
// list of variables below.
|
if (p == NULL)
|
||||||
// A line break may follow the "=".
|
goto theend;
|
||||||
|
|
||||||
wp = op + oplen;
|
|
||||||
if (may_get_next_line_error(wp, &p, cctx) == FAIL)
|
|
||||||
return FAIL;
|
|
||||||
if (compile_expr0(&p, cctx) == FAIL)
|
|
||||||
return NULL;
|
|
||||||
end = p;
|
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user