comparison src/vim9compile.c @ 24606:a4fda40e0bb9 v8.2.2842

patch 8.2.2842: Vim9: skip argument to searchpair() is not compiled Commit: https://github.com/vim/vim/commit/f18332fb9e2e4208a97d800f096b02c6681780e7 Author: Bram Moolenaar <Bram@vim.org> Date: Fri May 7 17:55:55 2021 +0200 patch 8.2.2842: Vim9: skip argument to searchpair() is not compiled Problem: Vim9: skip argument to searchpair() is not compiled. Solution: Add VAR_INSTR.
author Bram Moolenaar <Bram@vim.org>
date Fri, 07 May 2021 18:00:04 +0200
parents 033b43570140
children cb031f421ece
comparison
equal deleted inserted replaced
24605:f5484f767f70 24606:a4fda40e0bb9
613 case VAR_PARTIAL: 613 case VAR_PARTIAL:
614 case VAR_LIST: 614 case VAR_LIST:
615 case VAR_DICT: 615 case VAR_DICT:
616 case VAR_JOB: 616 case VAR_JOB:
617 case VAR_CHANNEL: 617 case VAR_CHANNEL:
618 case VAR_INSTR:
618 to_string_error((*type)->tt_type); 619 to_string_error((*type)->tt_type);
619 return FAIL; 620 return FAIL;
620 } 621 }
621 622
622 *type = &t_string; 623 *type = &t_string;
3095 semsg(_(e_variable_not_found_str), name); 3096 semsg(_(e_variable_not_found_str), name);
3096 vim_free(name); 3097 vim_free(name);
3097 return res; 3098 return res;
3098 } 3099 }
3099 3100
3101 static void
3102 clear_instr_ga(garray_T *gap)
3103 {
3104 int idx;
3105
3106 for (idx = 0; idx < gap->ga_len; ++idx)
3107 delete_instr(((isn_T *)gap->ga_data) + idx);
3108 ga_clear(gap);
3109 }
3110
3111 /*
3112 * Compile a string in a ISN_PUSHS instruction into an ISN_INSTR.
3113 * Returns FAIL if compilation fails.
3114 */
3115 static int
3116 compile_string(isn_T *isn, cctx_T *cctx)
3117 {
3118 char_u *s = isn->isn_arg.string;
3119 garray_T save_ga = cctx->ctx_instr;
3120 int expr_res;
3121 int trailing_error;
3122 int instr_count;
3123 isn_T *instr = NULL;
3124
3125 // Temporarily reset the list of instructions so that the jump labels are
3126 // correct.
3127 cctx->ctx_instr.ga_len = 0;
3128 cctx->ctx_instr.ga_maxlen = 0;
3129 cctx->ctx_instr.ga_data = NULL;
3130 expr_res = compile_expr0(&s, cctx);
3131 s = skipwhite(s);
3132 trailing_error = *s != NUL;
3133
3134 if (expr_res == FAIL || trailing_error)
3135 {
3136 if (trailing_error)
3137 semsg(_(e_trailing_arg), s);
3138 clear_instr_ga(&cctx->ctx_instr);
3139 cctx->ctx_instr = save_ga;
3140 return FAIL;
3141 }
3142
3143 // Move the generated instructions into the ISN_INSTR instruction, then
3144 // restore the list of instructions.
3145 instr_count = cctx->ctx_instr.ga_len;
3146 instr = cctx->ctx_instr.ga_data;
3147 instr[instr_count].isn_type = ISN_FINISH;
3148
3149 cctx->ctx_instr = save_ga;
3150 vim_free(isn->isn_arg.string);
3151 isn->isn_type = ISN_INSTR;
3152 isn->isn_arg.instr = instr;
3153 return OK;
3154 }
3155
3100 /* 3156 /*
3101 * Compile the argument expressions. 3157 * Compile the argument expressions.
3102 * "arg" points to just after the "(" and is advanced to after the ")" 3158 * "arg" points to just after the "(" and is advanced to after the ")"
3103 */ 3159 */
3104 static int 3160 static int
3105 compile_arguments(char_u **arg, cctx_T *cctx, int *argcount) 3161 compile_arguments(char_u **arg, cctx_T *cctx, int *argcount, int is_searchpair)
3106 { 3162 {
3107 char_u *p = *arg; 3163 char_u *p = *arg;
3108 char_u *whitep = *arg; 3164 char_u *whitep = *arg;
3109 int must_end = FALSE; 3165 int must_end = FALSE;
3166 int instr_count;
3110 3167
3111 for (;;) 3168 for (;;)
3112 { 3169 {
3113 if (may_get_next_line(whitep, &p, cctx) == FAIL) 3170 if (may_get_next_line(whitep, &p, cctx) == FAIL)
3114 goto failret; 3171 goto failret;
3121 { 3178 {
3122 semsg(_(e_missing_comma_before_argument_str), p); 3179 semsg(_(e_missing_comma_before_argument_str), p);
3123 return FAIL; 3180 return FAIL;
3124 } 3181 }
3125 3182
3183 instr_count = cctx->ctx_instr.ga_len;
3126 if (compile_expr0(&p, cctx) == FAIL) 3184 if (compile_expr0(&p, cctx) == FAIL)
3127 return FAIL; 3185 return FAIL;
3128 ++*argcount; 3186 ++*argcount;
3187
3188 if (is_searchpair && *argcount == 5
3189 && cctx->ctx_instr.ga_len == instr_count + 1)
3190 {
3191 isn_T *isn = ((isn_T *)cctx->ctx_instr.ga_data) + instr_count;
3192
3193 // {skip} argument of searchpair() can be compiled if not empty
3194 if (isn->isn_type == ISN_PUSHS && *isn->isn_arg.string != NUL)
3195 compile_string(isn, cctx);
3196 }
3129 3197
3130 if (*p != ',' && *skipwhite(p) == ',') 3198 if (*p != ',' && *skipwhite(p) == ',')
3131 { 3199 {
3132 semsg(_(e_no_white_space_allowed_before_str_str), ",", p); 3200 semsg(_(e_no_white_space_allowed_before_str_str), ",", p);
3133 p = skipwhite(p); 3201 p = skipwhite(p);
3173 char_u *tofree = NULL; 3241 char_u *tofree = NULL;
3174 int error = FCERR_NONE; 3242 int error = FCERR_NONE;
3175 ufunc_T *ufunc = NULL; 3243 ufunc_T *ufunc = NULL;
3176 int res = FAIL; 3244 int res = FAIL;
3177 int is_autoload; 3245 int is_autoload;
3246 int is_searchpair;
3178 3247
3179 // we can evaluate "has('name')" at compile time 3248 // we can evaluate "has('name')" at compile time
3180 if (varlen == 3 && STRNCMP(*arg, "has", 3) == 0) 3249 if (varlen == 3 && STRNCMP(*arg, "has", 3) == 0)
3181 { 3250 {
3182 char_u *s = skipwhite(*arg + varlen + 1); 3251 char_u *s = skipwhite(*arg + varlen + 1);
3214 return FAIL; 3283 return FAIL;
3215 } 3284 }
3216 vim_strncpy(namebuf, *arg, varlen); 3285 vim_strncpy(namebuf, *arg, varlen);
3217 name = fname_trans_sid(namebuf, fname_buf, &tofree, &error); 3286 name = fname_trans_sid(namebuf, fname_buf, &tofree, &error);
3218 3287
3288 // we handle the "skip" argument of searchpair() differently
3289 is_searchpair = (varlen == 10 && STRNCMP(*arg, "searchpair", 10) == 0);
3290
3219 *arg = skipwhite(*arg + varlen + 1); 3291 *arg = skipwhite(*arg + varlen + 1);
3220 if (compile_arguments(arg, cctx, &argcount) == FAIL) 3292 if (compile_arguments(arg, cctx, &argcount, is_searchpair) == FAIL)
3221 goto theend; 3293 goto theend;
3222 3294
3223 is_autoload = vim_strchr(name, AUTOLOAD_CHAR) != NULL; 3295 is_autoload = vim_strchr(name, AUTOLOAD_CHAR) != NULL;
3224 if (ASCII_ISLOWER(*name) && name[1] != ':' && !is_autoload) 3296 if (ASCII_ISLOWER(*name) && name[1] != ':' && !is_autoload)
3225 { 3297 {
4025 4097
4026 // funcref(arg) 4098 // funcref(arg)
4027 type = ((type_T **)stack->ga_data)[stack->ga_len - 1]; 4099 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
4028 4100
4029 *arg = skipwhite(p + 1); 4101 *arg = skipwhite(p + 1);
4030 if (compile_arguments(arg, cctx, &argcount) == FAIL) 4102 if (compile_arguments(arg, cctx, &argcount, FALSE) == FAIL)
4031 return FAIL; 4103 return FAIL;
4032 if (generate_PCALL(cctx, argcount, name_start, type, TRUE) == FAIL) 4104 if (generate_PCALL(cctx, argcount, name_start, type, TRUE) == FAIL)
4033 return FAIL; 4105 return FAIL;
4034 } 4106 }
4035 else if (*p == '-' && p[1] == '>') 4107 else if (*p == '-' && p[1] == '>')
4078 else 4150 else
4079 semsg(_(e_missing_paren), *arg); 4151 semsg(_(e_missing_paren), *arg);
4080 return FAIL; 4152 return FAIL;
4081 } 4153 }
4082 *arg = skipwhite(*arg + 1); 4154 *arg = skipwhite(*arg + 1);
4083 if (compile_arguments(arg, cctx, &argcount) == FAIL) 4155 if (compile_arguments(arg, cctx, &argcount, FALSE) == FAIL)
4084 return FAIL; 4156 return FAIL;
4085 4157
4086 // Move the instructions for the arguments to before the 4158 // Move the instructions for the arguments to before the
4087 // instructions of the expression and move the type of the 4159 // instructions of the expression and move the type of the
4088 // expression after the argument types. This is what ISN_PCALL 4160 // expression after the argument types. This is what ISN_PCALL
6726 case VAR_NUMBER: 6798 case VAR_NUMBER:
6727 case VAR_UNKNOWN: 6799 case VAR_UNKNOWN:
6728 case VAR_ANY: 6800 case VAR_ANY:
6729 case VAR_PARTIAL: 6801 case VAR_PARTIAL:
6730 case VAR_VOID: 6802 case VAR_VOID:
6803 case VAR_INSTR:
6731 case VAR_SPECIAL: // cannot happen 6804 case VAR_SPECIAL: // cannot happen
6732 generate_PUSHNR(cctx, 0); 6805 generate_PUSHNR(cctx, 0);
6733 break; 6806 break;
6734 } 6807 }
6735 } 6808 }
8534 8607
8535 return nextcmd; 8608 return nextcmd;
8536 } 8609 }
8537 8610
8538 8611
8539 static void
8540 clear_instr_ga(garray_T *gap)
8541 {
8542 int idx;
8543
8544 for (idx = 0; idx < gap->ga_len; ++idx)
8545 delete_instr(((isn_T *)gap->ga_data) + idx);
8546 ga_clear(gap);
8547 }
8548
8549 /* 8612 /*
8550 * :s/pat/repl/ 8613 * :s/pat/repl/
8551 */ 8614 */
8552 static char_u * 8615 static char_u *
8553 compile_substitute(char_u *arg, exarg_T *eap, cctx_T *cctx) 8616 compile_substitute(char_u *arg, exarg_T *eap, cctx_T *cctx)
8566 garray_T save_ga = cctx->ctx_instr; 8629 garray_T save_ga = cctx->ctx_instr;
8567 char_u *end; 8630 char_u *end;
8568 int expr_res; 8631 int expr_res;
8569 int trailing_error; 8632 int trailing_error;
8570 int instr_count; 8633 int instr_count;
8571 isn_T *instr = NULL; 8634 isn_T *instr;
8572 isn_T *isn; 8635 isn_T *isn;
8573 8636
8574 cmd += 3; 8637 cmd += 3;
8575 end = skip_substitute(cmd, delimiter); 8638 end = skip_substitute(cmd, delimiter);
8576 8639
8577 // Temporarily reset the list of instructions so that the jumps 8640 // Temporarily reset the list of instructions so that the jump
8578 // labels are correct. 8641 // labels are correct.
8579 cctx->ctx_instr.ga_len = 0; 8642 cctx->ctx_instr.ga_len = 0;
8580 cctx->ctx_instr.ga_maxlen = 0; 8643 cctx->ctx_instr.ga_maxlen = 0;
8581 cctx->ctx_instr.ga_data = NULL; 8644 cctx->ctx_instr.ga_data = NULL;
8582 expr_res = compile_expr0(&cmd, cctx); 8645 expr_res = compile_expr0(&cmd, cctx);
8590 { 8653 {
8591 if (trailing_error) 8654 if (trailing_error)
8592 semsg(_(e_trailing_arg), cmd); 8655 semsg(_(e_trailing_arg), cmd);
8593 clear_instr_ga(&cctx->ctx_instr); 8656 clear_instr_ga(&cctx->ctx_instr);
8594 cctx->ctx_instr = save_ga; 8657 cctx->ctx_instr = save_ga;
8595 vim_free(instr);
8596 return NULL; 8658 return NULL;
8597 } 8659 }
8598 8660
8599 // Move the generated instructions into the ISN_SUBSTITUTE 8661 // Move the generated instructions into the ISN_SUBSTITUTE
8600 // instructions, then restore the list of instructions before 8662 // instructions, then restore the list of instructions before
9547 { 9609 {
9548 int idx; 9610 int idx;
9549 isn_T *list = isn->isn_arg.subs.subs_instr; 9611 isn_T *list = isn->isn_arg.subs.subs_instr;
9550 9612
9551 vim_free(isn->isn_arg.subs.subs_cmd); 9613 vim_free(isn->isn_arg.subs.subs_cmd);
9614 for (idx = 0; list[idx].isn_type != ISN_FINISH; ++idx)
9615 delete_instr(list + idx);
9616 vim_free(list);
9617 }
9618 break;
9619
9620 case ISN_INSTR:
9621 {
9622 int idx;
9623 isn_T *list = isn->isn_arg.instr;
9624
9552 for (idx = 0; list[idx].isn_type != ISN_FINISH; ++idx) 9625 for (idx = 0; list[idx].isn_type != ISN_FINISH; ++idx)
9553 delete_instr(list + idx); 9626 delete_instr(list + idx);
9554 vim_free(list); 9627 vim_free(list);
9555 } 9628 }
9556 break; 9629 break;