Mercurial > vim
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; |